feat(acp): surface dropped SessionUpdate variants + UI (slash commands, plan, config options)#979
Open
harryfan1985 wants to merge 6 commits into
Open
feat(acp): surface dropped SessionUpdate variants + UI (slash commands, plan, config options)#979harryfan1985 wants to merge 6 commits into
harryfan1985 wants to merge 6 commits into
Conversation
Common ACP-host mechanism (not agent-specific): capture the slash commands an
ACP agent advertises via `session/update` → `AvailableCommandsUpdate`, store
them per session, and expose them to the frontend so it can build a `/` command
menu. Benefits every ACP agent (opencode / claude-code / codex / omp).
Background: BitFun's ACP client previously ignored every SessionUpdate variant
except message/thought/tool/usage. Slash commands are not a dedicated RPC in
ACP — discovery is `AvailableCommandsUpdate`; invocation is a plain
`session/prompt` whose text starts with `/<name>`. This wires the discovery half.
- session_options.rs: `AcpAvailableCommand { name, description, inputHint }` DTO
+ `From<schema::AvailableCommand>` (maps the Unstructured input hint).
- stream.rs: new `AcpClientStreamEvent::AvailableCommandsUpdated`; parse the
`SessionUpdate::AvailableCommandsUpdate` notification; round-tracker passes it
through.
- manager.rs: store latest commands on the session (`available_commands`), update
it in the prompt loop, and add `get_session_commands(...)` (read-after-ensure,
mirrors get_session_options).
- desktop acp_client_api.rs: emit `agentic://acp-available-commands-updated`
live during a turn, and add the `get_acp_session_commands` query command
(registered in lib.rs).
- ACPClientAPI.ts: `AcpAvailableCommand` type + `getSessionCommands()` + the
live-event payload type.
Not included (follow-up): the actual `/` menu UI in ChatInput consuming this
data. This commit is the reusable host-side mechanism only.
Verified: cargo test -p bitfun-acp (46 passed, incl. new conversion +
dispatch tests); cargo check -p bitfun-desktop; tsc clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Builds the data/logic layer the chat input will use to offer a `/` command menu
for ACP sessions, consuming the host-side mechanism added in the previous commit.
- acpSession.ts: `AcpSessionRef` + `acpSessionRef(session)` (derive the
client/session/workspace identifiers from a flow-chat session, mirroring
ModelSelector's ACP resolution) + `acpSlashCommandText(name)` (the `/name `
prompt text that actually invokes a command — ACP has no command RPC).
- useAcpSlashCommands.ts:
- `filterSlashCommands(commands, query)` — pure, case-insensitive match over
name + description, tolerant of a leading slash.
- `useAcpSlashCommands(acpSession)` — fetches `get_acp_session_commands` on
session change and stays live via the
`agentic://acp-available-commands-updated` event; empty for non-ACP sessions.
Tested: vitest (10) over the pure helpers (filter, acpSessionRef, command text).
Not included (needs in-app verification): the contenteditable `/` popup wiring
in ChatInput/RichTextInput (the `@`-mention system is hardcoded to `@`, so the
trigger + insert path must be built and verified with the app running). This
commit is the testable logic that wiring will consume.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Second ACP-host SessionUpdate surfacing (after available-commands): capture the
agent's execution plan (ACP `Plan` / agent-plan) and forward it live to the
frontend so it can render a task checklist during a turn. Benefits every ACP
agent. The plan replaces the prior one in full on each update (per spec).
- session_options.rs: `AcpPlanEntry { content, priority, status }` DTO +
`From<schema::PlanEntry>` (priority -> high/medium/low,
status -> pending/in_progress/completed).
- stream.rs: `AcpClientStreamEvent::PlanUpdated(Vec<AcpPlanEntry>)`; parse
`SessionUpdate::Plan`; round-tracker passthrough.
- desktop acp_client_api.rs: emit `agentic://acp-plan-updated` live during a turn.
- ACPClientAPI.ts: `AcpPlanEntry` + `AcpPlanUpdatedEvent` types.
Plan is live turn-progress (not queried at input time like slash commands), so
there is no query command — the frontend consumes the live event only.
Verified: cargo test -p bitfun-acp (47 passed, incl. exposes_plan_updates
dispatch test); cargo check -p bitfun-desktop; tsc clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Third ACP-host SessionUpdate surfacing. The session already stored `config_options` (consumed by the model/options UI via get_acp_session_options), but the client ignored the agent's `ConfigOptionUpdate` notification — so the stored options went stale when the agent changed them mid-session. This wires that notification through so the stored set stays accurate. - stream.rs: `AcpClientStreamEvent::ConfigOptionsUpdated(Vec<SessionConfigOption>)`; parse `SessionUpdate::ConfigOptionUpdate`; round-tracker passthrough. - manager.rs: `update_session_config_options` replaces the stored full set in the prompt loop (the agent always sends the complete set). - desktop acp_client_api.rs: emit `agentic://acp-session-options-changed` so the frontend can refetch the combined session options live. - ACPClientAPI.ts: `AcpSessionOptionsChangedEvent` type. Verified: cargo test -p bitfun-acp (48 passed, incl. exposes_config_option_updates); cargo check -p bitfun-desktop; tsc clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Completes the P1 view layer that consumes the host-side mechanism and the consumer-side logic added earlier. Slash commands — integrated into the EXISTING ChatInput slash picker (the same one that already lists native actions and MCP prompts), so no new contenteditable trigger was needed: - new SlashAcpCommandItem item kind + `getFilteredAcpCommands()`, fed by `useAcpSlashCommands(acpSessionRef(session))`. - agent commands are prepended in `getSlashPickerItems()` (primary for ACP sessions) and selectable by click / keyboard (Enter, Tab) like the other kinds. - `selectSlashAcpCommand` inserts `/<name> ` via the existing SET_VALUE dispatch (ACP has no command RPC — a command is sent as normal prompt text). Plan — live execution-plan checklist: - `useAcpPlan(sessionId)` subscribes to `agentic://acp-plan-updated`. - `AcpPlanPanel` renders the entries (status icons, done/total, strike-through for completed); mounted above the chat input box; renders nothing when empty. Verified: tsc clean; vitest 151 passed (incl. acpSession + slash-command logic), ChatInput layout test passes. Note: behavior was built by faithfully mirroring the existing slash picker (MCP prompts) and event-subscription patterns; final visual/interaction behavior should still be confirmed in the running app. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
10 tasks
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.
概要
让 BitFun 的 ACP host 把此前收到即丢弃的几个
session/update通知接进来,并补上前端视图层,benefits 所有 ACP agent(opencode / claude-code / codex / omp)。实现 #967 的 P1 两项(完整三层) + P2 一项。之前 BitFun 的 ACP client 只处理
AgentMessageChunk/AgentThoughtChunk/ToolCall/ToolCallUpdate/UsageUpdate,其余 SessionUpdate 变体全部丢弃。相关:#967(ACP host 完整度跟踪)。
改动
1. Slash 命令(
AvailableCommandsUpdate)— 后端 + 逻辑 + UI 全套ACP 里 slash 命令没有专门 RPC:发现靠 agent 的
AvailableCommandsUpdate,调用靠普通session/prompt发/<name> <args>文本。AcpAvailableCommandDTO、stream.rs解析、manager.rs按 session 存储 +get_session_commands查询、desktopget_acp_session_commands命令 +agentic://acp-available-commands-updated实时事件。ACPClientAPI.getSessionCommands()+ 类型;useAcpSlashCommandshook +filterSlashCommands/acpSessionRef/acpSlashCommandText纯函数(已测)。SlashAcpCommandItem,agent 命令置顶、可点击/键盘选中,选中后插入/<name>文本。2. 执行计划(
Plan)— 后端 + UIAcpPlanEntryDTO +From(priority→high/medium/low,status→pending/in_progress/completed);stream.rs解析;desktopagentic://acp-plan-updated实时事件;前端类型。useAcpPlan(sessionId)订阅事件;AcpPlanPanel渲染实时任务清单(状态图标、done/total、完成项删除线),挂在输入框上方,空时不渲染。3. 配置项保鲜(
ConfigOptionUpdate)config_options并被 model/options UI 消费,但ConfigOptionUpdate通知被忽略 → 中途更新会变陈旧。本 PR 接通,manager.rs替换整套;desktop emitagentic://acp-session-options-changed让前端 refetch。测试
cargo test -p bitfun-acp—— 48 passed(新增 commands / plan / config-option 三个 dispatch 测试 + command 转换测试)。vitest—— 151 passed(slash 命令消费逻辑、acpSession 工具等);ChatInput 布局测试通过。cargo check -p bitfun-desktop、tsc --noEmit—— clean。说明 / 后续
CurrentModeUpdate(需配 available_modes + set_mode)、SessionInfoUpdate(标题)、以及 P0 的 fs/terminal 宿主能力 —— 更重或需产品决策,留作后续单独 PR。🤖 Generated with Claude Code