fix(history): show the provider's real session title, not the first prompt - #72
Merged
Conversation
…rompt Claude transcripts carry the CLI's own session name in `ai-title` records (re-emitted as it gets refined). We ignored them and fell back to truncating the first user prompt, so the browser's history list disagreed with what the user sees in Claude Code — e.g. "有个痛点,定时任务触发之后。。运行中的时…" instead of "定时任务运行时无法打开会话". Codex had a related split: the list used `thread_name` but the opened session header fell back to the first prompt, so the two disagreed. Both now prefer the provider's own title consistently. Provider-written titles are third-party data, so route all three through `_provider_title` — Codex/Copilot previously used theirs raw, and 11 of 48 real `session_index.jsonl` entries here exceed the 80-char cap (the longest is 120 chars of leaked prompt scaffolding). Also stop one unreadable transcript from failing the whole listing — these files are written by third-party CLIs, so `_summaries` now skips on any exception rather than only OSError, logging the skip so a vanished session stays diagnosable.
Germey
approved these changes
Jul 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
问题
历史会话抽屉里显示的名字,和用户在 Claude Code 里看到的 session 名字对不上。
原因:三个 provider 都会给会话起名,但代码只读了两个。
~/.codex/session_index.jsonl→thread_name<session>/workspace.yaml→nameai-title记录Claude Code 每个会话都会写若干条
{"type":"ai-title","aiTitle":"…"},随对话推进不断精炼(最后一条为准)。history.py从头到尾没认这个记录类型。实测对照:
改动
ai-title,列表与详情一致;空标题不覆盖已有标题(后写的空值不清空好标题)。_codex_read此前仅在标题为空时才查索引,导致抽屉显示thread_name、点开却显示首条 prompt。_provider_title()(isinstance守卫 +_clean_title),四个取值点全部接上。Codex/Copilot 此前用的是裸值——本机 48 条索引里 11 条超 80 字符,最长一条是 120 字符的提示词脚手架泄漏。_summaries原先只吞OSError,任一 transcript 抛别的异常会让所有会话消失。改为吞Exception并记日志(KeyboardInterrupt仍会传播)。前端无需改动,HistoryDrawer.vue 只是渲染
item.title。验证
真实数据(本机 855 个 transcript):125 个 Codex 会话中超长/非 str 标题 0 个,列表与详情标题全部一致;Claude 侧抽样标题即 CLI 自己的名字。
测试:history 27/27 通过(净增 6 个)。全量 531 passed / 22 failed,干净
origin/main基线为 525 / 22 —— 失败集完全一致(channels/portal 网络超时 + version 元数据,与本改动无关)。ruff check通过。变异测试 14 个变异体全部被杀,含:四个 sanitise 点各一、
_provider_title的两半守卫、Claudeai-title的 last-wins 与 blank-non-clobber、_claude_read覆盖、Codex 详情优先级、except OSError回退、日志行、logger 命名空间。🤖 对抗评审
Codex 额度耗尽(
You've hit your usage limit),回落到 Claudegeneral-purposesubagent。3 轮收敛,共 8 条RISK,全部修复或申辩,无一遗漏。第 1 轮 — 5 条:
isinstance守卫无测试覆盖(可被静默删除);一个坏文件炸掉整个列表;blank-clobber 语义未测;_clean_title对aiTitle形同虚设;Codex 列表/详情标题不一致(评审员用合成 fixture 实证:list 返回thread_name、read 返回首条 prompt)。全部修复。第 2 轮 — 3 条,其中第一条是我在第 1 轮修复中引入的:把 Codex
thread_name提升为权威值时没走_clean_title,泄漏面从列表扩大到详情(评审员在真实session_index.jsonl里找到 120 字符的提示词脚手架);非 strthread_name会把裸 dict 送进前端title: string;except Exception让会话静默消失且无日志。全部修复 → 抽出_provider_title。第 3 轮 — 1 条,又是我上一轮修复引入的:日志 logger 用了
logging.getLogger(__name__)(coding_bridge.history,下划线),而守护进程只配置coding-bridge(连字符)根 logger 且propagate=False——我加的日志既进不了agent.log也进不了 CLS,恰好废掉了它自己的诊断目的。评审员同时指出旧测试用caplog挂在真根 logger 上,对错命名空间无差别(改成正确名字仍 27/27 绿)。已端到端复现(调
logs.setup()后触发跳过,agent.log为空、"sid-bad" in content为False),改用coding-bridge.history并把测试重写为真实跑logs.setup()断言落盘。写完发现全量套件下该测试会挂——别的测试先装了 handler,setup()幂等跳过建文件,log_path指向不存在的文件;已改为借还 handler。变异验证:错误命名空间现在会被测试杀掉(此前不会)。申辩 1 条并被采纳:
_claude_summary里的continue删掉后变异体存活。我主张这是行为等价(下一行即kind in ("user","assistant")守卫),不该也无法被测试区分;评审员独立复现后确认「your rebuttal is correct」——同时验证_claude_read里的同名continue删掉会被杀,二者不对称是对的。🤖 Generated with Claude Code