Skip to content

feat(agent): 显示 Agent 思考、计划与斜杠命令补全 - #1016

Open
Mucheen wants to merge 4 commits into
1lck:previewfrom
Mucheen:feat/agent-acp-session-updates
Open

Mucheen wants to merge 4 commits into
1lck:previewfrom
Mucheen:feat/agent-acp-session-updates

Conversation

@Mucheen

@Mucheen Mucheen commented Oct 1, 2026 •

Copy link
Copy Markdown
Collaborator

概述

参考 jetbrains-cc-gui 的对话体验,补齐 macOS Agent 面板对四类标准 ACP 会话更新的展示:思考过程、执行计划、斜杠命令补全、模式同步。

共享 Host(lithe-agent-host)一直把 ACP SessionUpdate 原样转发给 Swift,但 AgentConnectionModel.apply 之前只处理消息、工具、标题、配置和用量,下面这四类更新都落进 default: break 被丢弃了。本 PR 不改 Rust Host、C ABI 或 fixture 结构,只在 macOS 功能模型和视图层补上解析与展示。

改动内容

1. 思考块(agent_thought_chunk)

  • 新增消息角色 .thought,思考内容单独成一条消息,不再并入 Agent 回复。
  • 流式缓冲从“每会话一段文本”改为“每会话一段 + 角色”:角色切换时先刷新上一段,所以“思考 → 回复 → 工具 → 思考”交替到达时顺序正确、文本不会混在一起。
  • 新视图 AgentThoughtRow:正在流式输出的最后一段思考默认展开(显示“思考中…”),回复或工具到达后自动收起为“思考过程”;用户手动展开/收起后保持;搜索命中时临时展开,即使此前手动收起也能看到命中文字,搜索期间保持可见,清空搜索后恢复原来的手动选择。
  • 导出 Markdown 时思考以 > 引用块输出,和回复区分;历史列表的消息数只统计用户和 Agent 回复,不计思考。
  • 思考消息会把相邻工具调用分成两组时间线,保持原始顺序。

2. 执行计划(plan)

  • 新类型 AgentPlan(AgentSessionGuidance.swift)。ACP 规定每次发送完整计划,所以整体替换;空列表清除计划;格式错误的更新忽略;最多保留 100 条;未知状态的条目丢弃而不是猜测。
  • 新视图 AgentPlanView 固定在活动统计栏上方:折叠时显示“计划 已完成/总数 · 当前步骤”,展开后逐条显示待办 / 进行中 / 已完成。
  • session/load 回放历史时计划自然恢复。

3. 斜杠命令补全(available_commands_update)

  • 新类型 AgentCommand,按会话保存 Agent 上报的命令列表(最多 200 条)。

  • 输入框以 / 开头、且命令名中还没有空白时弹出 AgentCommandSuggestionList,显示名称、说明和参数提示;前缀匹配排在包含匹配之前。

  • 选择后只把 /name 填入草稿,命令仍作为普通 prompt 原样发送,由 Agent 自己解释。Lithe 不内置命令表,也不扫描 SKILL.md,列表与 Agent 真实能力保持一致。

  • Codex Skill 兼容:实测 codex-acp 1.13.1 把 Skill 以 $pdf 形式放进同一个命令列表,但它的命令解析会跳过 /$pdf。因此 $ 开头的命令补全为 $name (不加 /);输入 $ 只列 Skill;Agent 没有上报 Skill 时 $ 仍是普通字符,不会被拦截。

  • 键盘:Return 在命令名未输完时补全、输完时发送;macOS 14+ 支持 ↑↓ 和 Tab 导航(onKeyPress 需要 macOS 14,macOS 13 保留鼠标选择和 Return);Esc 先关闭补全,回复中再按 Esc 才停止。

  • 补全布局修复:AgentComposerDraftArea 优先保留 36pt 的可编辑输入行,空结果、短列表和长列表按实际内容与剩余高度分配空间。最小输入区放不下一整行命令时,使用对话布局内的锚点浮层,让列表既可见也能鼠标点击;浮层不改变输入焦点,不向会话模型发布几何尺寸,也不新增全局监听。

4. 模式同步(current_mode_update)

  • Agent 自己切换模式(例如 Claude 退出计划模式)时,更新 category == "mode" 且包含该值的配置选项,不向上游回发设置请求;选项中没有的模式 ID 忽略,不显示原始 ID。

5. 本地化补齐

  • 模型层原本硬编码英文的文案改为 String(localized:) 并补齐 zh-Hans:Tool call、Allow the Agent to continue?、The Agent request failed.、三条 stopReason 提示(token 上限 / 请求次数上限 / 拒绝继续)。
  • 工具证据标题 Output / Content / Diff / Terminal / Unsupported content 本地化。
  • 新增思考、计划、命令相关文案的中文翻译。

6. 契约、文档与矩阵

  • shared/fixtures/agent/acp-events-v1.json 新增 agentThoughtChunk、plan、availableCommands、currentModeUpdate 四个事件样例,并加入 Rust 往返测试 serialized_events_match_the_shared_fixture,证明它们是官方 ACP SDK 可原样往返的合法格式(Windows 后续接入可直接复用)。
  • Agent Note 2026-09-25-shared-acp-agent-conversation.md 新增“思考、计划、斜杠命令与模式通知”一节,记录处理规则、正反例和资源边界。
  • 功能矩阵新增 4 行:agent-reasoning-display、agent-plan-display、agent-slash-commands、agent-mode-sync(macOS implemented / pending,Windows missing),并重新生成 Markdown/CSV 视图。

7. 按审查意见修正

  • 为 current_mode_update 新增独立功能矩阵行 agent-mode-sync,补齐 AgentConnectionModel.swift、测试与 fixture 证据;从斜杠命令行移除模式同步验收语句并重新生成 Markdown/CSV。macOS 保持 implemented/pending,Windows 保持 missing/not-applicable。
  • 输入区最小高度按上下栏、外边距及 36pt 可编辑行计算(122pt);附带文件后增加附件行(156pt)。附件有无通过局部视图偏好更新分隔容器,命令列表与逐帧几何尺寸不进入会话模型。测试改为覆盖实际对话容器和生产输入布局。
  • 上游同名命令只保留首条定义,避免 ForEach/scrollTo 重复 ID;断连时清空全部会话旧命令,重连后等待新进程上报。
  • 活跃思考块仍显示“思考中…”,底部等待行改为“回复中…”并保留计时,补齐中英文;取消继续显示“正在停止…”。
  • Return、Esc、↑↓、Tab 共用视图局部补全状态并增加自动化测试;Esc 隐藏建议后,编辑草稿重新显示,即使再改回原前缀也不继续隐藏。
  • 合入最新 preview,解决功能矩阵生成文档冲突;未强推或改写原 PR 历史。

主要文件

文件 说明
macos/Sources/LitheAgentConversationModule/Application/AgentSessionGuidance.swift 新增:AgentPlan、AgentCommand 及解析、补全过滤
macos/Sources/LitheAgentConversationModule/Application/AgentConnectionModel.swift 处理四类新更新;流式缓冲按角色切分;文案本地化
macos/Sources/LitheAgentConversationModule/Application/AgentConversationState.swift .thought 角色;会话增加 plan、availableCommands
macos/Sources/Lithe/Views/Agent/AgentSessionGuidanceViews.swift 新增:思考块、计划栏、命令补全列表视图
macos/Sources/Lithe/Views/Agent/AgentComposerView.swift 命令补全交互与键盘导航
macos/Sources/Lithe/Views/Agent/AgentComposerDraftArea.swift 补全高度分配、可编辑输入行与可点击浮层
macos/Sources/Lithe/Views/Agent/AgentTranscriptView.swift 渲染思考块和计划栏

测试与验证

自动化测试(已合入最新 preview afb7a766;审查修复提交 ccc5dbbd)

  • macOS:test-stability-macos.sh -- --filter Agent,10 个套件 102 项通过,1 项原有集成测试默认跳过;新增 14 个测试(原功能 6 个、首次修复 3 个、本次审查修复 5 个):
    • interleavedReasoningAndReplyBecomeSeparateMessagesInArrivalOrder:思考/回复交替时的切分、顺序与导出格式
    • planUpdatesReplaceTheWholePlanAndAnEmptyPlanClearsIt:整体替换、未知状态丢弃、空计划清除、格式错误忽略
    • advertisedCommandsArePerSessionAndFilterOnlyWhileTypingAName:按会话隔离、前缀优先过滤、$ Skill 补全规则、命令原样发送
    • agentReportedModeChangeMovesOnlyTheMatchingModeSelector:只更新模式选择器、不回发请求、忽略未知模式
    • reasoningSplitsToolTimelinesAndIsSearchableButNotCountedAsAMessage:思考分隔工具组、可搜索、不计入消息数
    • planReasoningAndCommandListsFitNarrowAndWidePanelsInBothAppearances:窄(280pt)/宽(620pt)面板 × 深/浅主题布局(已人工查看截图,长文本正常截断)
    • thoughtSearchRevealsAManuallyCollapsedMatchAndRestoresItsPreference:手动收起后搜索仍展开,搜索期间保持可见,清空后恢复选择
    • thoughtStreamingCollapsesAutomaticallyButKeepsManualExpansion:流式结束自动收起、手动展开仍保持
    • commandSuggestionsKeepAWritingLineAtDefaultAndMinimumComposerHeights:在真实 AgentConversationLayout 中托管生产 AgentComposerContent 与原生 TextField,覆盖 400/700pt 对话高度、280/620pt 宽度、有无附件、0/1/40/200 条命令;验证默认输入区与最小输入区、输入滚动容器至少 36pt、TextField 可见且在 sized pane 内、完整命令行、浮层位置和对话范围
    • commandKeysCompleteWithoutSendingAndSubmitFullInvocations:方向键循环选择、Tab/Return 只补全、完整命令 Return 发送及 $Skill 格式
    • escapeDismissesSuggestionsBeforeCancellingAndEditingReopensThem:Esc 先隐藏建议、再次停止,编辑草稿重新显示,空匹配列表也遵守优先级
    • unavailableCommandKeysLeaveOrdinaryTypingAndChangedListsUsable:普通文字、无匹配、未上报 Skill 的 $ 和命令参数不拦截导航;列表缩短或断连清空时安全处理
    • activeThoughtKeepsOneThinkingLabelAndTheWaitingTimer:活跃思考时等待行显示“回复中…”,取消优先显示“正在停止…”
    • duplicateAdvertisedCommandsKeepTheFirstDefinitionAndUniqueRowIdentities:同名命令保留首条定义,ID 唯一,读取最多前 200 条
    • 已扩展 agentExitKeepsTranscriptAndRequiresReloadAfterReconnect:所有会话断连清空旧命令,重连加载后只显示新进程能力,显式 stop 同样清空
  • Rust:cargo test -p lithe-agent-host 71 个测试通过,cargo fmt --check 通过。
  • 检查脚本:verify-platform-feature-matrix、verify-platform-feature-matrix-change、verify-agent-notes、verify-shared-contracts、verify-runtime-bundle-immutability、测试稳定性静态检查均通过。

真实 Agent 协议验证

用临时探针按 ACP 直连本机安装的 adapter,各建会话发一条消息(工具权限一律拒绝,未修改任何文件):

Codex(codex-acp 1.13.1 / CLI 0.157.1) Claude(claude-agent-acp 0.81.2 / Claude Code 2.1.286)
available_commands_update ✅ 11 个内置命令 + 约 38 个 $xxx Skill ✅ 收到 2 次,大多带参数提示
agent_thought_chunk 本次未触发 ✅ 收到 39 段
plan / current_mode_update 本次未触发 本次未触发

上述协议探针没有覆盖所有更新。已核对两个 adapter 源码:Codex 的计划来自 turn plan 事件;Claude 的计划来自 TodoWrite/任务工具,退出计划模式时依次发送 current_mode_update 和 config_option_update。推送格式与 fixture 一致。探针还发现了上面的 /$name 问题,已在本 PR 修复。

真实界面验证(本次修复):生产预览连接本机 Claude 配置,显示 Opus 4.6,取得会话实际上报的命令列表。默认和拖到最小输入区时输入区域均保留 36pt;方向键选中最后一条后列表滚动跟随,Tab 填入命令;真实鼠标点击浮出的 /design 后填入 /design ;Esc 关闭建议并保留草稿。验证只补全,没有执行这些命令或发送模型请求。思考块另用编译当前生产视图及状态代码的原生探针验证“手动收起 → 搜索展开 → 清空后恢复收起”,只替换样式依赖。

真实思考、计划与模式同步的完整端到端验证仍未完成,功能矩阵继续标为 pending。应用、探针及关联子进程均已退出,临时探针注销并归档。

已知问题(与本 PR 无关)

  • 当前服务商配置下,真实 ACP prompt 曾在 150 秒内未返回回复、思考或计划;直接 API 和 Claude CLI 的简单请求能返回。原因尚未定位,本次界面修复没有修改 Host 或服务商链路,不将补全验证当作完整对话链路验证。
  • verify-service-boundaries.sh 因 AppModel+RunConfiguration.swift 为 616 行(上限 600)而失败,preview 基线上同样失败,本 PR 未触及该文件。
  • 并行运行完整 test-macos.sh 时约 20 个 Git / 文档 / 回滚相关的并发测试失败,preview 基线上同样失败;串行(--no-parallel)重跑全部通过。

不在本 PR 范围

Windows 端尚未接入 Agent 对话 UI(矩阵中标为 missing)。后续计划另开 PR:流式渲染性能、块级 Markdown 与代码高亮、输入框排队与 @ 文件补全、ACP fs / terminal 客户端能力。

Windows CI 安装失败修复(cd7315bf)

原失败发生在 tree-sitter-cli 下载超时:Bun 返回失败后,并行生命周期脚本仍占用 tree-sitter-kotlin 目录,导致冷重试的清理阶段再次失败。原失败任务重跑已通过,另外补上进程清理保证:

  • 每次安装由独立 PowerShell worker 执行,启动 Bun 前加入 Windows Job Object;worker 正常退出、失败、超时或被取消时,系统清理其安装子进程。每次尝试默认 300 秒本地期限,超时返回 124。
  • 释放进程树后清理部分依赖、缓存和临时文件;文件锁释放重试有 10 秒期限,只冷重试一次,永久错误仍明确失败。清缓存时撤销旧 verified 标记,成功后重新生成完整性清单。
  • 新增四个无外网 Windows 回归场景,用真实子进程占用目录并通过 IPC 确认顺序:失败后成功恢复、两次失败、成功后残留子进程、安装卡住超时。接入 Windows frontend CI 和逐项计时报告。
  • CI 分类覆盖新 worker 和测试;资源复用清单明确排除 node_modules、两个 workspace 的依赖目录与 .artifacts/bun-tmp,复用脚本测试、CI 文档与工程决策笔记同步更新。

本地缓存校验、资源复用测试(7 项)、测试稳定性、Windows 边界、bundle 只读、Agent Notes 和矩阵检查通过。新安装回归用例在 macOS 明确跳过,已由 本次 Windows frontend CI 在 Windows 执行并全部通过(4 项,最慢 9.484 秒)。真实安装一次成功(1,595 个包、175.4 秒),类型检查和前端测试全部通过。下载的前端计时报告共 1,018 条通过记录,含重复验证;最新提交的 6 个工作流、20 项 CI 检查全部成功(包含 macOS Swift、Rust/Swift 桥接、双架构打包、数据库、插件、Agent Notes 和矩阵)。

共享 Host 原本就透传 ACP SessionUpdate,但 macOS 只处理消息、工具、
标题、配置和用量,其余更新被丢弃。本次补齐四类标准更新:

- agent_thought_chunk:独立的可折叠思考块,流式输出时展开、回复或
  工具到达后收起;缓冲按角色切分,思考与回复不再混在一起;导出
  Markdown 以引用块保留,历史消息数不计思考
- plan:计划栏固定在活动统计栏上方,显示进度与当前步骤;每次整体
  替换,空计划清除
- available_commands_update:输入 / 弹出 Agent 上报的命令补全,前缀
  优先;Codex 的 $Skill 补全为 $name(codex-acp 不解析 /$name),
  输入 $ 只列 Skill;macOS 14+ 支持方向键与 Tab
- current_mode_update:Agent 自行切换模式时同步权限模式选择器

另外把模型层的兜底文案、stopReason 提示和工具证据标题改为本地化,
补齐 zh-Hans 翻译。

fixture 新增四类事件样例并加入 Rust 往返测试;更新功能矩阵与
shared-acp Agent Note。真实 Agent 已在协议层确认 Codex/Claude 会上报
命令列表、Claude 会上报思考,界面层验证仍待完成。
@ghfind-review ghfind-review Bot added the review: medium ghfind author score; see https://ghfind.com label Oct 1, 2026
为输入区保留可编辑行,空间不足时在对话布局中显示可点击的命令浮层。搜索临时展开匹配思考块,清空后恢复手动选择。补充三项回归测试并同步功能矩阵与架构笔记。

@1lck 1lck left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review 结论

⚠️ 建议修改(无阻塞问题)

Findings

[P2] 命令补全列表会把输入框挤没

位置: macos/Sources/Lithe/Views/Agent/AgentComposerView.swift:48-54,AgentSessionGuidanceViews.swift:175-176

实际影响:

  • 补全列表放在输入区内部,.frame(maxHeight: 168)。输入区默认高度约 210pt,扣掉上下栏(contextBar 30、toolbar 38、padding)后,ScrollView 容纳 TextField 的空间会被压到 0。
  • 在 Codex 这类有大量命令的 Agent(11 个内置 + 约 38 个 $Skill)里输入 /,用户看不到自己在输入什么。剩余约 46pt 的溢出会盖住分隔条或把工具栏推出边界。
  • 附带文件时还要再占 34pt。

触发条件: 连接命令很多的 Agent,输入框保持默认高度或更矮,输入 / 或 $。

修复建议:

  • 把补全列表改成锚定在输入区上方的 overlay(alignment: .top) 或 popover,向上浮在 transcript 上,不占输入区高度。
  • 或者按输入区可用高度动态限制列表高度(例如最多 可用高度 − 输入框最小行高),并保证 TextField 至少保留一行。
  • 加一条布局测试:在默认和最小高度的 AgentConversationLayout 中渲染带 10 条以上命令的 composer,断言 TextField 高度大于 0,且内容不超出 sized pane。

[P3] 模式同步能力被并进斜杠命令矩阵行

位置: shared/platform-feature-matrix.json:344-366

实际影响:

  • current_mode_update 同步权限模式选择器是可独立验收的能力,但只出现在 agent-slash-commands 行验证文案的最后一句。
  • 该行 evidence 没有列出真正实现它的 AgentConnectionModel.swift。
  • 和 develop-lithe 里每行对应一个可独立验证的能力的规则不一致。

修复建议:

  • 为 current_mode_update 单独加一行矩阵(例如 agent-mode-sync),evidence 写 AgentConnectionModel.swift 和对应测试,然后重新生成 Markdown/CSV。
  • 或者把这句验证移到已有的 agent-acp-conversation 行(模型/权限配置所在行),并补上 evidence。

观察项(不阻塞)

  • 思考流式输出期间会同时出现两个思考中…:AgentThoughtRow 标题和底部等待行 AgentThinkingRow。文案一样,但语义不同。可以考虑在有活跃思考块时调整其中一个的措辞。
  • AgentCommand.id 直接用 name。如果上游列表里出现同名命令,ForEach 和 scrollTo 会遇到重复 ID。
  • 输入框的补全交互(Return 补全或发送、Esc 优先关闭、↑↓/Tab)没有自动化测试,只测了模型层的 suggestions(for:in:)。建议在真实界面走查时重点覆盖。
  • 断开连接后,未附着会话仍保留上一个进程上报的 availableCommands,输入 / 会显示旧列表。发送时会先触发 load,由新进程重新上报,实际影响有限。

Summary

模型层改动集中、正确,状态都落在 LitheAgentConversationModule/Application,视图不解析原始更新,符合 Note 规定的边界。fixture 加 Rust 往返测试把四类更新锁定为合法 ACP。主要缺口在输入区内补全列表的布局:大命令列表在默认高度下会挤掉输入框,现有截图测试没覆盖这种组合。

CI 全绿。思考块、计划栏和模式同步还没在真实界面上走查过,Windows 端也还没接入(矩阵标为 pending/missing)。

@Mucheen

Mucheen commented Oct 1, 2026 •

Copy link
Copy Markdown
Collaborator Author

已在 8c1cc49d、ccc5dbbd 处理本次 review,逐项结果如下:

  • P2:补全挤掉输入框:先保留 36pt 的可编辑行,再按剩余高度限制建议列表;放不下完整命令行时,在整个对话布局的锚点浮层中显示,保持鼠标可点击。最小输入区包含固定上下栏和外边距(122pt),附带文件后增加附件行(156pt),避免附件再次挤掉输入。commandSuggestionsKeepAWritingLineAtDefaultAndMinimumComposerHeights 现在直接托管 AgentConversationLayout、生产 AgentComposerContent 和原生 TextField,覆盖窄/宽、默认/最小输入区、有/无附件、0/1/40/200 条命令;断言输入可见且在 sized pane 内、编辑滚动区至少 36pt、命令行完整且不覆盖输入。
  • P3:模式同步矩阵归属:新增独立 agent-mode-sync 行,证据包含 AgentConnectionModel.swift、对应模式同步测试和 ACP fixture;从 agent-slash-commands 验收说明移除模式同步,并重新生成 Markdown/CSV。
  • 重复“思考中…”:活跃思考块保留“思考中…”,底部等待行改为“回复中…”并保留计时;取消优先显示“正在停止…”,补齐中英文和状态测试。
  • 重复命令 ID:解析上游列表时同名命令只保留首条定义,名称、说明和参数提示保持一致;新增 ID 唯一性和 200 条输入上限测试。
  • 键盘交互验证:Return、Esc、↑↓、Tab 共用视图局部的补全状态。新增自动化测试覆盖导航循环、Tab/Return 补全而不发送、完整命令 Return 发送、Esc 先关闭再取消、编辑后重新出现、无匹配/普通输入不拦截及列表缩短时安全处理。此前真实界面已走查方向键滚动、Tab、浮层鼠标选择和 Esc;自动化交互测试验证状态与动作,不将其称为完整 Agent 端到端测试。
  • 断连后旧列表:断连和显式 stop 清空所有会话 availableCommands;重连加载后等待新进程上报。已扩展断连/重连测试,验证旧记录保留而旧能力清空、新列表恢复。

本地 Swift 6.3.3 运行 Agent 测试:102 项通过、1 项原有集成测试默认跳过;矩阵、Agent Notes、共享契约和 bundle 只读检查通过。已合入最新 preview 并解决生成文档冲突。

真实 Agent 思考、计划、模式同步的完整端到端仍待验收,矩阵继续保持 pending;Windows Agent 对话 UI 仍为 missing。未把代码和合成测试结果标成实机验收完成。

CI 修复补充(cd7315bf)

原失败是 tree-sitter-cli 下载超时后,Bun 安装脚本子进程残留,占用目录,导致冷重试无法清理。已把每次安装放进独立 PowerShell worker,通过 Windows Job Object 在结束时清理所属子进程,再清理目录并冷重试;每次安装有 300 秒本地期限,文件锁释放重试有 10 秒期限,永久失败仍报错。缓存清理同时撤销旧 verified 标记。资源复用清单、排除测试、CI 分类与文档一并更新。

最新 Windows frontend job 已通过:真实安装一次完成(1,595 个包、175.4 秒),类型检查与前端测试成功。新增四项 Windows 回归测试全部通过,分别验证失败后恢复、永久失败、成功后残留子进程以及卡住超时;最慢 9.484 秒,均低于 30 秒预算。Windows 整个工作流已通过,包括 Rust 与真实 JDT;最新提交的 macOS Swift、Rust/Swift 桥接、arm64/x86_64 打包、数据库、插件、Agent Notes 和功能矩阵检查也全部成功。当前 PR 的全部 CI 检查 已通过。

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

review: medium ghfind author score; see https://ghfind.com

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants