Skip to content

feat(ui): 对话动作行常驻、用户消息时间戳、回复速度展示 - #40

Merged
SudoUserReal merged 7 commits into
ZCodium-project:mainfrom
yachen4ever:feat/conversation-action-ux
Oct 18, 2026
Merged

SudoUserReal merged 7 commits into
ZCodium-project:mainfrom
yachen4ever:feat/conversation-action-ux

Conversation

@yachen4ever

Copy link
Copy Markdown
Collaborator

Closes #39

改动(5 文件,+56/−19)

  1. 动作行常驻:用户气泡与助手回复的复制/编辑/反馈/fork 动作行去掉 hover 透明门控——远控(无 hover)、触屏与大屏场景都出现过入口不可发现的问题(v4 迁移时旧 UserMessage 的常显分支被漏掉,RowView 内的注释自己也记录了这一点);TurnGroup 轮尾与 hook 动作行同步统一。
  2. 用户消息补时间戳:row.createdAt 已在行载荷(rowBaseFields),用 assistant 动作栏同款 formatMessageTimeLabel 相对日判定,在动作行内展示(text-ui-sm subtle)。
  3. 回复速度展示:session-debug 轮次补 prefill 吞吐两个字段(prefillDurationMs / prefillTokensPerSecond = inputTokens / TTFT 秒),助手动作栏按「row 创建后首个完成的模型轮」关联展示 ↑prefill ↓decode tok/s。

实现说明

  • 速度数据全部来自既有 session-debug 管线(bootstrap 生产端本就采集 inputTokens 与 timeToFirstContentMs),本 PR 只补 prefill 吞吐两个字段的计算与 UI 暴露
  • TTFT=0(全缓存直出)或未知时 null 不伪造速度;inputTokens 含缓存读取,缓存命中时口径为「有效 prefill 吞吐」
  • 动作行门控移除后样式沿用现有 muted 尺寸图标与 text-ui-sm,不引入新视觉规则
  • 旧消息的动作行同样常驻;速度按「row 创建后首个完成轮」关联,长对话旧行为自然收敛

验证

  • 根 typecheck 0 error;两文件 oxlint 0 warning 0 error
  • 悬浮门控残留全仓 grep 清零(group-hover/user-row、group-hover/assistant-row、group-hover/assistant-turn)
  • 本人在私有衍生仓(同源代码)实机验证:常驻动作行与用户时间戳渲染正常

自查

  • 无遥测 / 无外网调用新增
  • 无依赖变更
  • text-ui 字号约束遵守(DESIGN.md Highest-priority 段)

@SudoUserReal

Copy link
Copy Markdown
Contributor

审过了,实现主体没问题(时间戳复用 formatMessageTimeLabel、速度字段有 0/null 防护、动作行常驻的门控残留已 grep 清零),有一个需要修的性能问题:

每行一个 1s 轮询
useSessionDebug 是实例独立、REFRESH_INTERVAL_MS = 1000 的轮询。本 PR 让每个助手动作行都调用它 → 一个 20 轮会话 = 20 个并发轮询器、每秒 20 次 readSessionDebug;远控 / SSH 场景下每次还是跨 host 往返(此前只有调试面板一处调用)。建议把 session-debug 拉取提升到会话级共享(一份轮询 + 多行订阅 / 缓存快照),或至少大幅降频并只在轮尾行订阅。

一个兼容性小点
sessionDebugRoundSchema 的新字段目前是必填 nullable(非 optional):旧版远端 server(未升级)返回的 payload 会 strict 校验失败——错误虽被 hook 捕获(表现为速度不显示),但建议改 .nullable().optional(),让新旧版本混布时可降级。

其余(createdAt prop 链路、prefill 计算与 producedRound 关联、格式与样式)都没问题。修掉轮询这点就可以合。

@yachen4ever

Copy link
Copy Markdown
Collaborator Author

发现 review 检查在本 PR 和 #37 上都是 FAILURE,看了下日志:assistant-review 的 bot 在给 PR 留评论/表情时收到 403(Resource not accessible by integration,POST issues/40/comments 与 create-reaction 都被拒)。

原因:协作者从 fork 提 PR 时,pull_request 事件的 GITHUB_TOKEN 仍然是只读的(GitHub 对 fork PR 的硬性限制),所以 workflow 里 author_association = COLLABORATOR 的放行分支和「fork PR token 只读」两条规则撞在一起了——纯外部贡献者的 PR 会按注释预期被 if 跳过,但协作者的 fork PR 会进到 job 里然后 403。

供参考(任选其一):把 if 收紧为 ["OWNER","MEMBER"] 让 fork PR 一律跳过,红叉即消失;若希望协作者的 PR 也跑 bot,则需要 token 可写的触发形态。PR 内容本身不受影响,linked-issue 检查已通过,两个 PR 都在等你的 review。

yachen4ever added a commit to yachen4ever/ZCodium that referenced this pull request Oct 7, 2026
上游 review(ZCodium-project#40)指出两个问题:

1. 每个动作行实例独立轮询 useSessionDebug(1s 节拍),20 轮会话 =
   20 个并发轮询器,远控/SSH 场景每秒 N 次跨 host readSessionDebug
   往返。改为每个 (workspace, session) 一条共享循环 +
   useSyncExternalStore 多订阅者:最后一个订阅者退订即停循环,
   订阅清零前按完成节拍续期不重叠请求。hook 签名与返回形状不变,
   调试面板与动作行两个调用点零改动。

2. sessionDebugRoundSchema 新增的 prefillDurationMs /
   prefillTokensPerSecond 为必填 nullable,旧版 server 的快照缺字段
   时 strict 校验整轮失败。改 .nullable().optional() 让新旧混布时
   降级为不显示速度;消费端本就 null/undefined 双判,无需改动。

测试边界:packages/ui 无 hook 测试基建(全包 2 个测试文件),
本次为内部轮询拓扑重构、外部接口不变,验证走 typecheck + lint。
@yachen4ever

Copy link
Copy Markdown
Collaborator Author

两点都已修复(ba38202):

1. 每行一个轮询 → 会话级共享。useSessionDebug 内部改为每个 (workspaceIdentity||workspacePath, sessionId) 一条共享轮询循环 + useSyncExternalStore 多订阅者:同一会话的调试面板与所有动作行复用同一条循环,无论多少行恒定 1 次/秒 readSessionDebug;最后一个订阅者退订即停循环,按完成节拍续期、不重叠请求。hook 签名与返回形状不变,两个调用点零改动。

2. schema 兼容。prefillDurationMs / prefillTokensPerSecond 改为 .nullable().optional(),旧版 server 快照缺字段时降级为不显示速度;消费端原本就是 null/undefined 双判,无需改动。

同样的修复也落在了我们自己的产品线上。

@SudoUserReal

Copy link
Copy Markdown
Contributor

跟进检查:在 #43(v3.15.1 再基线)合并后的最新 main 上做了本地合并验证与逐项复核,结论如下——当前 head 不建议合并。

阻塞:速度展示没有渲染出口(功能不可见)

  • ConversationAssistantTextActions 中 decodeLabel / prefillLabel 只计算、从未渲染(head ba382021 全文件无任何 JSX 使用这两个变量);
  • 两个调用点均未传 workspacePath / workspaceIdentity(ConversationTurnGroup.tsx 轮尾动作行、ConversationRowView.tsx 内 AssistantTextRowView 的调用),而 useSessionDebug 的 enabled: Boolean(sessionId) && Boolean(workspacePath) 恒为 false,轮询根本不会启动;
  • 数据生产端(bootstrap session-debug 的 prefill 字段、shared schema)与最新 main 无冲突、可保留,但需要补渲染与传参后才能称为"速度展示"。

与最新 main 的合并状态(本地实测)

  • 与 v3.15.1 再基线后的 main 在 ConversationRowView.tsx(4 处)/ ConversationTurnGroup.tsx(1 处)冲突,均为 props/样式的并集问题,可解决;
  • 部分改动已被再基线覆盖:助手消息时间戳(main 已有等价实现)、远控常显分支(main 已按 compactForRemoteControl 落地);用户消息时间戳与 useSessionDebug 共享轮询仍是净增量,值得保留;
  • 「动作行完全常驻(移除 hover 门控)」与 main 现设计(远控常显 + 桌面 hover/focus 降噪)是方向性差异,建议先明确产品取舍(触屏/大屏发现性 vs 桌面降噪)再 rebase。

建议

  1. 速度展示:补上 prefillLabel / decodeLabel 的渲染节点,并在两个调用点传入 workspacePath / workspaceIdentity(或先删除未用逻辑,缩小 PR 范围);
  2. rebase 到最新 main,把「用户消息时间戳」「共享轮询」拆成独立小改动,减少与再基线的耦合;
  3. 「动作行常驻」与 main 现设计对齐后单独评审(并补一条 UI 测试覆盖远控与桌面两种语义)。

在以上问题解决前暂不合并。

用户气泡与助手回复的复制/编辑/反馈/fork 动作行原先 hover 才显现,
远控、触屏与大屏场景都出现过入口不可发现的问题(远控分支此前已
单独修过一次)。统一改为常驻:

- 用户气泡:MessageActions 去掉 group-hover/user-row 门控,并补上
  消息时间(formatMessageTimeLabel(row.createdAt),与 assistant
  动作栏共用相对日判定与 text-ui-sm subtle 样式)
- assistant 轮尾与 TurnGroup 轮尾动作行、hook 动作行:同样去掉
  group-hover/assistant-* 门控

DESIGN.md 的 text-ui 约束不受影响(时间标签沿用 text-ui-sm)。
session-debug 轮次本来就有 inputTokens 与 timeToFirstContentMs(TTFT≈
prefill 段时长),但只算了 decode TPS。补齐 prefill 两个维度并接到
assistant 动作栏:

- shared:round schema 增加 prefillDurationMs / prefillTokensPerSecond
  (inputTokens / TTFT 秒;TTFT=0 或未知时 null,不伪造速度;inputTokens
  含缓存读取,缓存命中时口径为「有效 prefill 吞吐」)
- bootstrap:round 生产端输出两字段
- UI:ConversationAssistantTextActions 轮询 session-debug(1s 节拍,
  DeveloperToolsPane 同款钩子),按「row 创建后首个完成的模型轮」关联
  产出轮,动作栏时间旁显示 ↑prefill ↓decode tok/s(text-ui-sm subtle)

配合动作行常驻(上一提交):速度与时间对当前回复始终可见。
上游 review(ZCodium-project#40)指出两个问题:

1. 每个动作行实例独立轮询 useSessionDebug(1s 节拍),20 轮会话 =
   20 个并发轮询器,远控/SSH 场景每秒 N 次跨 host readSessionDebug
   往返。改为每个 (workspace, session) 一条共享循环 +
   useSyncExternalStore 多订阅者:最后一个订阅者退订即停循环,
   订阅清零前按完成节拍续期不重叠请求。hook 签名与返回形状不变,
   调试面板与动作行两个调用点零改动。

2. sessionDebugRoundSchema 新增的 prefillDurationMs /
   prefillTokensPerSecond 为必填 nullable,旧版 server 的快照缺字段
   时 strict 校验整轮失败。改 .nullable().optional() 让新旧混布时
   降级为不显示速度;消费端本就 null/undefined 双判,无需改动。

测试边界:packages/ui 无 hook 测试基建(全包 2 个测试文件),
本次为内部轮询拓扑重构、外部接口不变,验证走 typecheck + lint。
- useSessionDebug 改用 useOptionalServices:服务缺席(宿主未就绪/无 Provider 测试环境)时速度展示降级为不轮询,而非渲染崩溃
- useSyncExternalStore 补第三参 server snapshot,对齐上游调用惯例
- TurnGroup 两个断言旧 hover 门控行为的用例更新为「动作行常驻」语义
@yachen4ever
yachen4ever force-pushed the feat/conversation-action-ux branch from ba38202 to e7b3881 Compare October 16, 2026 10:06
review 指出的两个同源缺陷(v1.0.7 首创时即存在)导致速度从未显示:
① decodeLabel/prefillLabel 计算后无任何 JSX 引用——在时间标签旁补 ↑/↓ tok/s 渲染节点;
② 两个调用点(轮内/轮尾动作栏)均未传 workspacePath/workspaceIdentity,
   useSessionDebug 启动守卫恒 false、轮询不启动——补传 props。

label 计算与启动守卫抽为纯函数 formatSpeedLabels/shouldStartSessionDebugPolling
(packages/ui/src/v4/speedLabels.ts,参数取结构化子集便于逻辑测试构造字面量),
配 6 例 node 语义测试(null 语义 ×3 + 启动守卫 ×3,vitest 口径)。
移植自 yazcode main 22a15d1(docs/handoff-pr40-port.md);TTFT=0 只显示 ↓、
历史消息不显示速度均为预期行为。
@yachen4ever

Copy link
Copy Markdown
Collaborator Author

建议 1 的速度展示双缺陷已修(2aaeddb1),移植自 yazcode 侧的同源修复(v1.0.7 首创时即存在,与 review 指出的一致):

  • 渲染出口:decodeLabel / prefillLabel 此前确实只计算未渲染——在时间标签旁补 ↑prefill tok/s / ↓decode tok/s 节点;
  • 轮询启动:两个调用点补传 workspacePath / workspaceIdentity,useSessionDebug 不再恒不启动;
  • label 计算与启动守卫抽为纯函数 formatSpeedLabels / shouldStartSessionDebugPolling(packages/ui/src/v4/speedLabels.ts),配 6 例逻辑测试(null 语义 ×3 + 启动守卫 ×3);typecheck / lint 全绿,v4ConversationTurnGroup 111 例无回归。

预期行为边界:TTFT=0(全缓存直出)只显示 ↓;历史/旧会话消息不显示速度(关联语义是「row 创建之后首个完成的模型轮」)。

建议 2/3(按「时间戳 + 共享轮询」拆分、动作行常驻与 main 现设计的取舍)想先听你的意见再动,当前分支保持五项完整(当前对 main 无冲突)。

@SudoUserReal
SudoUserReal merged commit 5328990 into ZCodium-project:main Oct 18, 2026
1 of 2 checks passed
yachen4ever added a commit to yachen4ever/ZCodium that referenced this pull request Oct 18, 2026
yachen4ever added a commit to yachen4ever/ZCodium that referenced this pull request Oct 18, 2026
yachen4ever added a commit to yachen4ever/ZCodium that referenced this pull request Oct 18, 2026
yachen4ever added a commit to yachen4ever/ZCodium that referenced this pull request Oct 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

对话动作行 UX:常驻动作行、用户消息时间戳、回复速度展示

2 participants