Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 127 additions & 0 deletions docs/specs/acp-session-config-options/plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
# ACP Session Config Options 实施计划

## 1. 当前基线

1. ACP 状态栏当前只把 provider/model 锁定为外层 ACP agent。
2. ACP 内部 model/mode 能力部分来自旧 `models/modes`,没有统一配置状态。
3. 新版 SDK `0.16.1` 已支持 `configOptions`、`config_option_update`、`session_info_update`、`usage_update`。

## 2. 设计决策

### 2.1 统一配置状态

新增共享类型:

1. `AcpConfigOptionValue`
2. `AcpConfigOption`
3. `AcpConfigState`

主进程通过 `normalizeAcpConfigState()` 统一把两类来源归一为同一结构:

1. `configOptions` 直接映射,标记 `source=configOptions`
2. legacy `models/modes` 合成为伪 config option,标记 `source=legacy`

### 2.2 Warmup / Session 双缓存

1. `AcpProcessHandle` 缓存 process 级 warmup config state
2. `AcpSessionRecord` 缓存 session 级 config state
3. `prepareAcpSession` 在 draft 建立后立即发出 config-ready 事件,让 renderer 无缝从 process cache 切到 session cache

### 2.3 事件策略

新增事件:

1. `ACP_WORKSPACE_EVENTS.SESSION_CONFIG_OPTIONS_READY`

触发时机:

1. process warmup 完成
2. `prepareAcpSession` / `coreStream` 绑定 session 后
3. 收到 `config_option_update`
4. `setSessionConfigOption` / legacy mode/model 写入成功后

### 2.4 Renderer 展示策略

状态栏维持双轨:

1. 非 ACP:继续显示普通模型列表和 generation settings
2. ACP:显示 ACP options 面板,不再清空设置区

排序规则:

1. `model`
2. `thought_level`
3. 其余按 agent 原顺序

读写规则:

1. 有 `draftSessionId` 或活动 ACP session 时,走 session 级读写
2. 仅有 process warmup 数据时,面板只读

UI refinement:

1. ACP 状态栏隐藏 permission mode 入口,右侧只保留 `更多` 与最右侧 `MCP`
2. inline 只展示前 3 个 `select` 类型配置,触发器复用 MCP 风格的 ghost button + popover header
3. `boolean` 与剩余配置统一进入 `更多` 面板,不再 inline 展示

## 3. 分阶段实施

### Phase 1:SDK 与主进程兼容

1. 升级 SDK 到 `0.16.1`
2. 修正 schema import 路径
3. 兼容 `unstable_setSessionModel` / `KillTerminalRequest` 等 SDK 差异

### Phase 2:ACP 配置状态归一

1. 新增 `acpConfigState.ts`
2. `AcpProcessManager` warmup 归一 `configOptions/models/modes`
3. `AcpSessionManager` 建 session 时继承并缓存统一 state
4. `AcpContentMapper` 支持 `config_option_update`

### Phase 3:Presenter 与事件

1. `AcpProvider` 增加 process/session config 读写接口
2. `LLMProviderPresenter` 和 `NewAgentPresenter` 暴露代理方法
3. 发出 `SESSION_CONFIG_OPTIONS_READY`

### Phase 4:Renderer 状态栏

1. `NewThreadPage` 透传 ACP draft sessionId
2. `ChatStatusBar` 加入 ACP config 同步、只读控制和更新逻辑
3. trigger 显示 `ACP agent / internal model`

## 4. 测试策略

### 4.1 Main

1. `AcpContentMapper` 覆盖 `config_option_update`
2. `AcpProvider.prepareSession` 发出 config-ready 事件
3. `AcpProvider.setSessionConfigOption` 使用 agent 返回的全量 state 回写缓存
4. `NewAgentPresenter` 覆盖 ACP session config 读写代理

### 4.2 Renderer

1. ACP draft 首屏读取 process warmup config
2. draft sessionId 就绪后切换到 session config
3. 写入 ACP select/boolean option 时调用 session presenter
4. 非 ACP 原有状态栏行为无回归

## 5. 风险与缓解

1. 风险:不同 ACP agent 同时返回 `configOptions` 与 legacy 字段。
缓解:统一以 `configOptions` 为准,legacy 仅在缺失时启用。

2. 风险:renderer 在 draft 早期拿不到 sessionId,导致控件误可写。
缓解:基于 `activeAcpSessionId` 做只读门控。

3. 风险:新 SDK 增加的 session 通知被误判为未处理异常。
缓解:`session_info_update` 与 `usage_update` 静默兼容。

## 6. 质量门槛

1. `pnpm run typecheck`
2. `pnpm run format`
3. `pnpm run i18n`
4. `pnpm run lint`
5. 关键 main/renderer 测试通过
93 changes: 93 additions & 0 deletions docs/specs/acp-session-config-options/spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# ACP Session Config Options 规格

## 概述

为 ACP 接入协议级 `session config options`,让 ACP agent 的内部 `model`、`thought_level`、`mode`、布尔开关等能力在 DeepChat 状态栏中直接展示和修改。

本次改动同时完成:

1. 升级 `@agentclientprotocol/sdk` 到 `0.16.1`
2. ACP 优先走新版 `configOptions`
3. 旧 `models/modes` 仅作为兼容兜底
4. 预热阶段拿到的配置立即可展示,不等待首条消息

## 背景与动机

1. 当前 ACP 外层模型选择器只表示“ACP agent”,内部 session model 被固定,用户无法直观看到真实内部模型。
2. 协议已提供 `session config options`,可以统一承载 `model`、`thought_level`、`mode` 以及其他 agent 自定义配置。
3. ACP warmup 阶段已经能拿到这些信息,继续延迟到首条消息后再展示会造成首屏空窗。

## 用户故事

### US-1:看到 ACP 内部真实模型

作为用户,我希望状态栏显示 `ACP agent / 内部 model`,这样我能确认当前 ACP session 真正在用哪个模型。

### US-2:在新线程阶段就能看配置

作为用户,我希望 ACP draft 刚建立时就能看到 agent 的可配置项,而不是要先发一条消息。

### US-3:统一修改 ACP session 配置

作为用户,我希望在同一个状态栏面板里修改 ACP 的 `model`、`thought_level`、`mode` 和布尔类开关。

## 功能需求

### A. 配置来源与兼容策略

- [ ] ACP 主路径使用协议 `configOptions`
- [ ] 当 agent 未返回 `configOptions` 时,回退到 legacy `models/modes`
- [ ] 若同时返回两套字段,只采用 `configOptions`

### B. 外层 agent 与内层 session model 分离

- [ ] 状态栏外层仍显示 ACP agent
- [ ] ACP 内部 `model` 不写回现有通用 `SessionGenerationSettings`
- [ ] ACP agent 不允许通过普通 `setSessionModel` 切走 provider/model

### C. Warmup 与缓存

- [ ] warmup 的 `newSession/loadSession` 结果要归一为统一 `AcpConfigState`
- [ ] 预热缓存应绑定到 process handle
- [ ] `prepareAcpSession` 建立 draft/session 后立即把缓存灌入 session,并发出 ready 事件

### D. Renderer 状态栏

- [ ] 非 ACP 路径保持现有模型选择和 generation settings 行为
- [ ] ACP 路径改为展示 ACP options 面板
- [ ] `category=model` 作为首要选项,并参与 trigger 文案展示
- [ ] `category=thought_level` 排在 `model` 后,保留 agent 返回的 label/value
- [ ] `category=mode` 与其他 generic 选项保持 agent 顺序
- [ ] draft 无 sessionId 时展示 warmup 数据但控件只读
- [ ] draft sessionId 就绪后切到 session 级读写

### E. 事件与接口

- [ ] 新增 `AcpConfigOption`、`AcpConfigOptionValue`、`AcpConfigState`
- [ ] `ILlmProviderPresenter` 增加 ACP process/session config 读写接口
- [ ] `INewAgentPresenter` 增加 ACP session config 读写接口
- [ ] 新增 renderer 事件 `ACP_WORKSPACE_EVENTS.SESSION_CONFIG_OPTIONS_READY`

## 验收标准

- [ ] ACP trigger 可显示 `agentId / internal model`
- [ ] 新线程 ACP draft 能先显示 warmup config
- [ ] draft sessionId 就绪后可切到 session config 并允许写入
- [ ] `config_option_update` 会整组替换当前 config state
- [ ] 旧 ACP agent 只有 `models/modes` 时仍可正常展示和切换

## 非目标

1. 不把 ACP `model/thought_level/mode` 混入通用 provider generation settings。
2. 不重做非 ACP 状态栏 UI。
3. 不在本次把 `systemPrompt/temperature/contextLength/maxTokens` 合并进 ACP options。

## 约束

1. 继续遵循现有 Presenter + EventBus 架构。
2. 所有兼容逻辑集中在 ACP 主进程归一层,不在 renderer 分散判断 legacy 字段。
3. UI 不新增独立 ACP 设置页,先复用状态栏入口。

## 开放问题

无。
52 changes: 52 additions & 0 deletions docs/specs/acp-session-config-options/tasks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# ACP Session Config Options 任务清单

## T0 规格文档

- [x] 新建 `spec.md`
- [x] 新建 `plan.md`
- [x] 新建 `tasks.md`

## T1 SDK 与共享类型

- [x] 升级 `@agentclientprotocol/sdk` 到 `0.16.1`
- [x] 修正 ACP schema import 路径
- [x] 新增 `AcpConfigOptionValue`
- [x] 新增 `AcpConfigOption`
- [x] 新增 `AcpConfigState`

## T2 ACP 主进程归一层

- [x] 新增 `acpConfigState.ts`
- [x] warmup 解析 `configOptions`
- [x] legacy `models/modes` 回退归一
- [x] `config_option_update` 整组替换 session config state
- [x] `session_info_update` / `usage_update` 静默兼容

## T3 Presenter / EventBus

- [x] `AcpProcessHandle` / `AcpSessionRecord` 缓存统一 config state
- [x] 新增 `SESSION_CONFIG_OPTIONS_READY` 事件
- [x] `ILlmProviderPresenter` 增加 ACP process/session config 读写接口
- [x] `INewAgentPresenter` 增加 ACP session config 读写接口

## T4 Renderer 状态栏

- [x] `NewThreadPage` 透传 `acpDraftSessionId`
- [x] `ChatStatusBar` 增加 ACP config 拉取与事件订阅
- [x] ACP trigger 显示 `agent / internal model`
- [x] draft 无 sessionId 时显示 warmup config 且只读
- [x] draft sessionId 就绪后切换到 session 级读写

## T5 测试

- [x] 更新 `acpContentMapper.test.ts`
- [x] 更新 `acpProvider.test.ts`
- [x] 更新 `newAgentPresenter.test.ts`
- [x] 更新 `ChatStatusBar.test.ts`

## T6 质量门禁

- [x] `pnpm run format`
- [x] `pnpm run i18n`
- [x] `pnpm run lint`
- [x] 运行关键测试并记录结果
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
"update-shadcn": "node scripts/update-shadcn.js"
},
"dependencies": {
"@agentclientprotocol/sdk": "^0.5.1",
"@agentclientprotocol/sdk": "^0.16.1",
"@anthropic-ai/sdk": "^0.53.0",
"@antv/infographic": "^0.2.7",
"@aws-sdk/client-bedrock": "^3.958.0",
Expand Down Expand Up @@ -116,8 +116,6 @@
"@lingual/i18n-check": "0.8.12",
"@mcp-ui/client": "^5.13.3",
"@pinia/colada": "^0.20.0",
"@unovis/ts": "1.6.4",
"@unovis/vue": "1.6.4",
"@tailwindcss/typography": "^0.5.19",
"@tailwindcss/vite": "^4.1.18",
"@tiptap/core": "^2.11.7",
Expand All @@ -137,6 +135,8 @@
"@types/node": "^22.19.3",
"@types/xlsx": "^0.0.35",
"@typescript/native-preview": "7.0.0-dev.20260115.1",
"@unovis/ts": "1.6.4",
"@unovis/vue": "1.6.4",
"@vee-validate/zod": "^4.15.1",
"@vitejs/plugin-vue": "^6.0.3",
"@vitest/ui": "^3.2.4",
Expand Down
3 changes: 2 additions & 1 deletion src/main/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,8 @@ export const WORKSPACE_EVENTS = {
// ACP-specific workspace events
export const ACP_WORKSPACE_EVENTS = {
SESSION_MODES_READY: 'acp-workspace:session-modes-ready', // Session modes available
SESSION_COMMANDS_READY: 'acp-workspace:session-commands-ready' // Session commands available
SESSION_COMMANDS_READY: 'acp-workspace:session-commands-ready', // Session commands available
SESSION_CONFIG_OPTIONS_READY: 'acp-workspace:session-config-options-ready' // Session config options available
}

export const ACP_DEBUG_EVENTS = {
Expand Down
2 changes: 1 addition & 1 deletion src/main/presenter/agentPresenter/acp/acpCapabilities.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type * as schema from '@agentclientprotocol/sdk/dist/schema.js'
import type * as schema from '@agentclientprotocol/sdk/dist/schema/index.js'

export interface AcpCapabilityOptions {
enableFs?: boolean
Expand Down
Loading
Loading