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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
| 特性 | 说明 | 文档 |
|------|------|------|
| **Claude 群控技术** | Pipe IPC 多实例协作:同机 main/sub 自动编排 + LAN 跨机器零配置发现与通讯,`/pipes` 选择面板 + `Shift+↓` 交互 + 消息广播路由 | [Pipe IPC](https://ccb.agent-aura.top/docs/features/pipes-and-lan) / [LAN](https://ccb.agent-aura.top/docs/features/lan-pipes) |
| ACP 协议一等一支持 | 支持接入 Zed、Cursor 等 IDE,支持会话恢复、Skills、权限桥接 | [文档](https://ccb.agent-aura.top/docs/features/acp-zed) |
| Remote Control 私有部署 | Docker 自托管 RCS + Web UI | [文档](https://ccb.agent-aura.top/docs/features/remote-control-self-hosting) |
| /dream 记忆整理 | 自动整理和优化记忆文件 | [文档](https://ccb.agent-aura.top/docs/features/auto-dream) |
| Web Search | 内置网页搜索工具 | [文档](https://ccb.agent-aura.top/docs/features/web-browser-tool) |
Expand Down
2 changes: 2 additions & 0 deletions build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ const DEFAULT_BUILD_FEATURES = [
'ULTRAPLAN',
// P2: daemon + remote control server
'DAEMON',
// ACP (Agent Client Protocol) agent mode
'ACP',
// PR-package restored features
'WORKFLOW_SCRIPTS',
'HISTORY_SNIP',
Expand Down
3 changes: 3 additions & 0 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

189 changes: 189 additions & 0 deletions docs/features/acp-zed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
# ACP (Agent Client Protocol) — Zed / IDE 集成

> Feature Flag: `FEATURE_ACP=1`(build 和 dev 模式默认启用)
> 实现状态:可用(支持 Zed、Cursor 等 ACP 客户端)
> 源码目录:`src/services/acp/`

## 一、功能概述

ACP (Agent Client Protocol) 是一种标准化的 stdio 协议,允许 IDE 和编辑器通过 stdin/stdout 的 NDJSON 流驱动 AI Agent。CCB 实现了完整的 ACP agent 端,可以被 Zed、Cursor 等支持 ACP 的客户端直接调用。

### 核心特性

- **会话管理**:新建 / 恢复 / 加载 / 分叉 / 关闭会话
- **历史回放**:恢复会话时自动加载并回放对话历史
- **权限桥接**:ACP 客户端的权限决策映射到 CCB 的工具权限系统
- **斜杠命令 & Skills**:加载真实命令列表,支持 `/commit`、`/review` 等 prompt 型 skill
- **Context Window 跟踪**:精确的 usage_update,含 model prefix matching
- **Prompt 排队**:支持连续发送多条 prompt,自动排队处理
- **模式切换**:auto / default / acceptEdits / plan / dontAsk / bypassPermissions
- **模型切换**:运行时切换 AI 模型

## 二、架构

```
┌──────────────┐ NDJSON/stdio ┌──────────────────┐
│ Zed / IDE │ ◄────────────────► │ CCB ACP Agent │
│ (Client) │ stdin / stdout │ (Agent) │
└──────────────┘ │ │
│ entry.ts │ ← stdio → NDJSON stream
│ agent.ts │ ← ACP protocol handler
│ bridge.ts │ ← SDKMessage → ACP SessionUpdate
│ permissions.ts │ ← 权限桥接
│ utils.ts │ ← 通用工具
│ │
│ QueryEngine │ ← 内部查询引擎
└──────────────────┘
```
Comment on lines +24 to +37
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add language identifiers to fenced code blocks (MD040).

Two fenced blocks are missing a language tag, which will keep markdownlint warnings active.

Proposed fix
-```
+```text
 ┌──────────────┐    NDJSON/stdio    ┌──────────────────┐
 │  Zed / IDE   │ ◄────────────────► │  CCB ACP Agent   │
 │  (Client)    │   stdin / stdout   │  (Agent)         │
 └──────────────┘                    │                  │
                                     │  entry.ts        │ ← stdio → NDJSON stream
                                     │  agent.ts        │ ← ACP protocol handler
                                     │  bridge.ts       │ ← SDKMessage → ACP SessionUpdate
                                     │  permissions.ts  │ ← 权限桥接
                                     │  utils.ts        │ ← 通用工具
                                     │                  │
                                     │  QueryEngine     │ ← 内部查询引擎
                                     └──────────────────┘

- +text
命令: ccb --acp
参数: ["--acp"]
通信: stdin/stdout NDJSON
协议版本: ACP v1

Also applies to: 111-116

🧰 Tools
🪛 markdownlint-cli2 (0.22.0)

[warning] 24-24: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/features/acp-zed.md` around lines 24 - 37, Two fenced code blocks in
docs/features/acp-zed.md (the ASCII diagram block beginning "┌──────────────┐   
NDJSON/stdio    ┌──────────────────┐" and the command/params block starting "命令:
ccb --acp") lack language identifiers; add a language tag (e.g., ```text) to
both fenced blocks so markdownlint MD040 is satisfied, updating the opening
triple-backtick lines for those two blocks accordingly.


### 文件职责

| 文件 | 职责 |
|------|------|
| `entry.ts` | 入口,创建 stdio → NDJSON stream,启动 `AgentSideConnection` |
| `agent.ts` | 实现 ACP `Agent` 接口:会话 CRUD、prompt、cancel、模式/模型切换 |
| `bridge.ts` | `SDKMessage` → ACP `SessionUpdate` 转换:文本/思考/工具/用量/编辑 diff |
| `permissions.ts` | ACP `requestPermission()` → CCB `CanUseToolFn` 桥接 |
| `utils.ts` | Pushable、流转换、权限模式解析、session fingerprint、路径显示 |

## 三、配置 Zed 编辑器

### 3.1 Zed settings.json 配置

打开 Zed 的 `settings.json`(`Cmd+,` → Open Settings),添加 `agent_servers` 配置:

```json
{
"agent_servers": {
"ccb": {
"type": "custom",
"command": "ccb",
"args": ["--acp"]
}
}
}
```

### 3.3 API 认证配置

CCB 的 ACP agent 在启动时会自动加载 `settings.json` 中的环境变量(`ANTHROPIC_BASE_URL`、`ANTHROPIC_AUTH_TOKEN` 等)。确保已通过 `/login` 配置好 API 供应商。

也可通过环境变量传入:

```json
{
"agent_servers": {
"claude-code": {
"command": "ccb",
"args": ["--acp"],
"env": {
"ANTHROPIC_BASE_URL": "https://api.example.com/v1",
"ANTHROPIC_AUTH_TOKEN": "sk-xxx"
}
}
}
}
```

### 3.4 在 Zed 中使用

1. 配置完成后重启 Zed
2. 打开任意项目目录
3. 按 `Cmd+'`(macOS)或 `Ctrl+'`(Linux)打开 Agent Panel
4. 在 Agent Panel 顶部的下拉菜单中选择 **claude-code**
5. 开始对话

### 3.5 功能说明

| 功能 | 操作 |
|------|------|
| 对话 | 在 Agent Panel 中直接输入消息 |
| 斜杠命令 | 输入 `/` 查看可用 skills 列表(如 `/commit`、`/review`) |
| 工具权限 | 弹出权限请求时选择 Allow / Reject / Always Allow |
| 模式切换 | 通过 Agent Panel 的设置菜单切换 auto/default/plan 等模式 |
| 模型切换 | 通过 Agent Panel 的设置菜单切换 AI 模型 |
| 会话恢复 | 关闭重开 Zed 后,之前的会话可自动恢复(含历史消息) |

## 四、配置其他 ACP 客户端

ACP 是开放协议,任何支持 ACP 的客户端都可以连接 CCB。通用配置模式:

```
命令: ccb --acp
参数: ["--acp"]
通信: stdin/stdout NDJSON
协议版本: ACP v1
```

### 4.1 Cursor

在 Cursor 的设置中配置 MCP / Agent Server,使用同样的 `ccb --acp` 命令。

### 4.2 自定义客户端

使用 `@agentclientprotocol/sdk` 可以快速构建 ACP 客户端:

```typescript
import { ClientSideConnection, ndJsonStream } from '@agentclientprotocol/sdk'

// 创建连接(将 ccb --acp 作为子进程启动)
const child = spawn('ccb', ['--acp'])
const stream = ndJsonStream(
Writable.toWeb(child.stdin),
Readable.toWeb(child.stdout),
)

const client = new ClientSideConnection(stream)

// 初始化
await client.initialize({ clientCapabilities: {} })

// 创建会话
const { sessionId } = await client.newSession({
cwd: '/path/to/project',
})

// 发送 prompt
const response = await client.prompt({
sessionId,
prompt: [{ type: 'text', text: 'Hello, explain this project' }],
})

// 监听 session 更新
client.on('sessionUpdate', (update) => {
console.log('Update:', update)
})
```

## 五、ACP 协议支持矩阵

| 方法 | 状态 | 说明 |
|------|------|------|
| `initialize` | ✅ | 返回 agent 信息和能力 |
| `authenticate` | ✅ | 无需认证(自托管) |
| `newSession` | ✅ | 创建新会话 |
| `resumeSession` | ✅ | 恢复已有会话(含历史回放) |
| `loadSession` | ✅ | 加载指定会话(含历史回放) |
| `listSessions` | ✅ | 列出可用会话 |
| `forkSession` | ✅ | 分叉会话 |
| `closeSession` | ✅ | 关闭会话 |
| `prompt` | ✅ | 发送消息,支持排队 |
| `cancel` | ✅ | 取消当前/排队的 prompt |
| `setSessionMode` | ✅ | 切换权限模式 |
| `setSessionModel` | ✅ | 切换 AI 模型 |
| `setSessionConfigOption` | ✅ | 动态修改配置 |

### SessionUpdate 类型

| 类型 | 状态 | 说明 |
|------|------|------|
| `agent_message_chunk` | ✅ | 助手文本消息 |
| `agent_thought_chunk` | ✅ | 思考/推理内容 |
| `user_message_chunk` | ✅ | 用户消息(历史回放) |
| `tool_call` | ✅ | 工具调用开始 |
| `tool_call_update` | ✅ | 工具调用结果/状态更新 |
| `usage_update` | ✅ | token 用量 + context window |
| `plan` | ✅ | TodoWrite → plan entries |
| `available_commands_update` | ✅ | 斜杠命令 & skills 列表 |
| `current_mode_update` | ✅ | 模式切换通知 |
| `config_option_update` | ✅ | 配置更新通知 |
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,9 @@
"rcs": "bun run scripts/rcs.ts"
},
"dependencies": {
"ws": "^8.20.0",
"@claude-code-best/mcp-chrome-bridge": "^2.0.7"
"@agentclientprotocol/sdk": "^0.19.0",
"@claude-code-best/mcp-chrome-bridge": "^2.0.7",
"ws": "^8.20.0"
},
"devDependencies": {
"@alcalzone/ansi-tokenize": "^0.3.0",
Expand Down
2 changes: 2 additions & 0 deletions scripts/dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ const DEFAULT_FEATURES = [
"KAIROS_BRIEF", "AWAY_SUMMARY", "ULTRAPLAN",
// P2: daemon + remote control server
"DAEMON",
// ACP (Agent Client Protocol) agent mode
"ACP",
// PR-package restored features
"WORKFLOW_SCRIPTS",
"HISTORY_SNIP",
Expand Down
11 changes: 11 additions & 0 deletions src/QueryEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1184,6 +1184,17 @@ export class QueryEngine {
this.abortController.abort()
}

/** Reset the abort controller so the next submitMessage() call can start
* with a fresh, non-aborted signal. Must be called after interrupt(). */
resetAbortController(): void {
this.abortController = createAbortController()
}

/** Expose the current abort signal for external consumers (e.g. ACP bridge). */
getAbortSignal(): AbortSignal {
return this.abortController.signal
}

getMessages(): readonly Message[] {
return this.mutableMessages
}
Expand Down
8 changes: 8 additions & 0 deletions src/entrypoints/cli.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,14 @@ async function main(): Promise<void> {
return
}

// Fast-path for `--acp` — ACP (Agent Client Protocol) agent mode over stdio.
if (feature('ACP') && process.argv[2] === '--acp') {
profileCheckpoint('cli_acp_path')
const { runAcpAgent } = await import('../services/acp/entry.js')
await runAcpAgent()
return
}

// Fast-path for `--daemon-worker=<kind>` (internal — supervisor spawns this).
// Must come before the daemon subcommand check: spawned per-worker, so
// perf-sensitive. No enableConfigs(), no analytics sinks at this layer —
Expand Down
Loading
Loading