codex@macbookpro
·
2026-03-27
PROPOSAL-BAA-INSTRUCTION-V3.original.md
1# 方案:BAA 指令 v3 — 代码块驱动的通用 AI 指令协议
2
3日期:2026-03-27
4来源:George 需求 + Claude/ChatGPT 讨论
5
6---
7
8## 背景
9
10### 指令协议演进
11
12| 版本 | 格式 | 问题 |
13|---|---|---|
14| v1 | `:: @home.local shell ls` | `::` 容易被渲染引擎吃掉;长对话 AI 忘格式 |
15| v2 | `@system::shell::{"cmd":"ls"} /@` | AI 能用但格式重;只有 BAA 系统内部走得通 |
16| v3 | ` ```baa ` 代码块 | 任何 AI 输出代码块就能驱动;不需要原生 function calling |
17
18### 核心洞察
19
20所有 AI 都会输出代码块。代码块的语言标记已经是一种"这段内容的类型声明"。用 ` ```baa ` 作为"这是一条要执行的指令"的类型声明,天然不会被 Markdown 渲染器吃掉,AI 也很难忘记怎么写代码块。
21
22---
23
24## 核心规则
25
26### 一个代码块 = 一条指令
27
28这是最重要的设计决策。一个 baa 代码块只包含一条指令,多条指令用多个代码块表达。
29
30好处:
31- 多个代码块 → 多条指令 → **并行执行**
32- 语义清晰:一块一事
33- 和 conductor 的异步模式一致(并行提交 → sleep → 单次 poll)
34
35---
36
37## 指令格式
38
39### 三段式:谁 :: 干什么 :: 怎么干
40
41```
42@target::tool::params
43```
44
45### 单行指令(带参数)
46
47 ```baa
48 @conductor::exec::ls -la /Users/george/code
49 ```
50
51### 单行指令(JSON 参数)
52
53 ```baa
54 @conductor::files/read::{"path": "/Users/george/Desktop/HANDOFF.md"}
55 ```
56
57### 单行指令(无参数)
58
59 ```baa
60 @conductor::describe
61 ```
62
63### 多行参数
64
65第一行是 `@target::tool`(没有 `::params`),后续所有行拼接为这一条指令的参数:
66
67 ```baa
68 @conductor::exec
69 cd /Users/george/code/baa-conductor
70 git status
71 git log --oneline -3
72 ```
73
74这是**一条指令**,三行 shell 命令拼成一个多行参数。
75
76### 并行执行示例
77
78AI 回复中出现 3 个 baa 代码块 = 3 条独立指令 = 并行提交:
79
80 我来同时检查几个东西:
81
82 ```baa
83 @conductor::exec::ls /tmp
84 ```
85
86 ```baa
87 @conductor::files/read::{"path":"/etc/hostname"}
88 ```
89
90 ```baa
91 @conductor::describe
92 ```
93
94 上面三条同时执行,结果出来后我一起分析。
95
96代码块之间的普通文本(AI 的思考和解释)被忽略,只提取 baa 块。
97
98---
99
100## 目标地址(target)
101
102| target | 含义 | 路由到 |
103|---|---|---|
104| `conductor` | conductor 本机 | conductor local API |
105| `system` | `conductor` 的别名 | 同上 |
106| `codex` | codexd 代理 | `/v1/codex/*` |
107| `browser` | 浏览器代发 | `/v1/browser/request` |
108| `browser.claude` | Claude 平台 | `/v1/browser/request` platform=claude |
109| `browser.chatgpt` | ChatGPT 平台 | `/v1/browser/request` platform=chatgpt |
110| `browser.gemini` | Gemini 平台 | `/v1/browser/request` platform=gemini |
111
112### 扩展性
113
114target 格式是开放的。未来可以加:
115- `mac` → SSH 到 Mac 执行
116- `mini` → 直接在 mini 执行
117- `racknerd` → VPS 执行
118- `node.某个节点名` → BAA 网络中的任意节点
119
120---
121
122## 工具映射(tool → conductor API)
123
124| tool | conductor API | 说明 |
125|---|---|---|
126| `exec` | `POST /v1/exec` | 执行 shell 命令 |
127| `files/read` | `POST /v1/files/read` | 读文件 |
128| `files/write` | `POST /v1/files/write` | 写文件 |
129| `describe` | `GET /describe` | 系统自描述 |
130| `describe/business` | `GET /describe/business` | 业务面 |
131| `describe/control` | `GET /describe/control` | 控制面 |
132| `status` | `GET /v1/status` | 状态视图 |
133| `browser/status` | `GET /v1/browser` | 浏览器状态 |
134| `browser/request` | `POST /v1/browser/request` | 通用代发 |
135| `browser/actions` | `POST /v1/browser/actions` | 插件管理 |
136| `codex/sessions` | `POST /v1/codex/sessions` | 创建 codex session |
137| `codex/turn` | `POST /v1/codex/turn` | 发 codex turn |
138| `tasks` | `GET /v1/tasks` | 查看任务 |
139
140---
141
142## 参数解析规则
143
1441. `@target::tool`(tool 后面没有 `::` 且后面没有更多行)→ 无参数
1452. `@target::tool::params`(单行)→ params 以 `{` 开头则 JSON 解析,否则作为字符串
1463. `@target::tool` 后面有更多行 → 后续行拼接为多行字符串参数
147
148---
149
150## 解析器
151
152### 提取 baa 代码块
153
154```javascript
155function extractBaaBlocks(text) {
156 const blocks = [];
157 const re = /```baa\s*\n([\s\S]*?)```/g;
158 let m;
159 while ((m = re.exec(text)) !== null) {
160 const body = m[1].trim();
161 if (body) blocks.push(body);
162 }
163 return blocks;
164}
165```
166
167### 解析单条指令(单个代码块)
168
169```javascript
170function parseBaaBlock(blockText) {
171 const lines = blockText.split('\n');
172 const firstLine = lines[0].trim();
173
174 // 第一行必须是 @target::tool 格式
175 const m = firstLine.match(/^@([^:\s]+)::([^:\s]+)(?:::([\s\S]*))?$/);
176 if (!m) return null;
177
178 const target = m[1];
179 const tool = m[2];
180 const inlineParams = m[3] ? m[3].trim() : null;
181
182 // 有内联参数 → 单行指令
183 if (inlineParams !== null) {
184 return { target, tool, params: parseParamValue(inlineParams) };
185 }
186
187 // 无内联参数 → 后续行是多行参数
188 const restLines = lines.slice(1);
189 if (restLines.length === 0 || restLines.every(l => l.trim() === '')) {
190 return { target, tool, params: {} };
191 }
192
193 return { target, tool, params: { command: restLines.join('\n') } };
194}
195
196function parseParamValue(raw) {
197 if (!raw) return {};
198 if (raw.startsWith('{')) {
199 try { return JSON.parse(raw); } catch { /* fall through */ }
200 }
201 return { command: raw };
202}
203```
204
205### 完整流程
206
207```javascript
208function extractInstructions(aiReplyText) {
209 return extractBaaBlocks(aiReplyText)
210 .map(parseBaaBlock)
211 .filter(inst => inst !== null);
212}
213```
214
215---
216
217## 执行链路
218
219### 插件侧解析执行(首版)
220
221```
222AI 回复完成
223→ 插件提取所有 ```baa 块
224→ 解析为指令数组
225→ 并行发给 conductor API(Promise.allSettled)
226→ 等全部返回
227→ 拼接结果,一次性注入 AI 对话输入框
228→ 自动发送
229→ AI 看到结果继续工作
230```
231
232conductor 侧零改动。
233
234### 并行执行
235
236```javascript
237async function executeInstructions(instructions) {
238 const results = await Promise.allSettled(
239 instructions.map(inst => routeAndExecute(inst))
240 );
241
242 return results.map((result, i) => {
243 const inst = instructions[i];
244 const label = formatInstructionLabel(inst);
245 if (result.status === 'fulfilled') {
246 return `--- ${label} ---\n成功:\n${formatOutput(result.value)}`;
247 } else {
248 return `--- ${label} ---\n失败: ${result.reason.message}`;
249 }
250 }).join('\n\n');
251}
252```
253
254---
255
256## 防死循环
257
258AI 回复含 baa 指令 → 执行 → 注入结果 → AI 再回复可能又含 baa 指令 → …
259
260### 保护机制
261
2621. **最大轮次**:单次对话最多自动执行 N 轮(默认 10)
2632. **冷却时间**:每轮执行后等 2 秒再注入结果
2643. **结果标记**:注入文本带 `[BAA 执行结果]` 前缀
2654. **用户中断**:用户在输入框打字 → 立刻停止自动循环
2665. **错误熔断**:连续 3 次执行失败 → 自动停止,注入错误摘要
267
268---
269
270## 结果注入格式
271
272并行执行完成后,一次性注入所有结果:
273
274```
275[BAA 执行结果]
276
277--- @conductor::exec::ls /tmp ---
278成功:
279file1.txt
280file2.txt
281
282--- @conductor::files/read::{"path":"/etc/hostname"} ---
283成功:
284mini.local
285
286--- @conductor::describe ---
287成功:
288{"deployment_mode": "single-node mini", ...}
289```
290
291---
292
293## AI 侧提示词
294
295只需要在 system prompt 或记忆里写:
296
297```
298你可以通过 baa 代码块执行操作。每个代码块是一条独立指令,多个代码块并行执行:
299
300 ```baa
301 @conductor::exec::shell 命令
302 ```
303
304 ```baa
305 @conductor::files/read::{"path": "文件路径"}
306 ```
307
308多行 shell 命令:
309
310 ```baa
311 @conductor::exec
312 cd /some/path
313 git status
314 ```
315
316执行后结果会自动回传给你。
317```
318
319所有 AI 平台通用(Claude、ChatGPT、Gemini),不需要原生 function calling。
320
321---
322
323## 实现优先级
324
325| 步骤 | 内容 | 改动位置 |
326|---|---|---|
327| 1 | 解析器:extractBaaBlocks + parseBaaBlock | controller.js 新增 |
328| 2 | 执行路由:instruction → conductor API 调用 | controller.js 新增 |
329| 3 | 并行执行 + 结果拼接 | controller.js 新增 |
330| 4 | 结果注入 + 自动发送 | controller.js 复用已有 injectText |
331| 5 | 防死循环保护 | controller.js 新增 |
332
333首版全在插件侧(controller.js),conductor 零改动。