oh-my-opencode-cohub 1.0.16 → 1.0.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +106 -26
- package/dist/cli/config-io.d.ts.map +1 -1
- package/dist/cli/index.js +14 -1
- package/dist/config/loader.d.ts +17 -0
- package/dist/config/loader.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +406 -12
- package/dist/prompts/orchestrator.d.ts +1 -1
- package/dist/prompts/orchestrator.d.ts.map +1 -1
- package/dist/tools/council.d.ts +65 -0
- package/dist/tools/council.d.ts.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,13 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
OpenCode 中文智能体编排插件 CoHub——纯调度模式、全中文提示词、规范分析代理、方案制定代理。
|
|
4
4
|
|
|
5
|
+
[](https://github.com/Mr-cjf/oh-my-opencode-cohub)
|
|
6
|
+
|
|
5
7
|
## 特性
|
|
6
8
|
|
|
7
9
|
- 🚀 **独立运行**:纯 OpenCode Plugin,依赖 `@opencode-ai/plugin` SDK,零外部插件依赖
|
|
8
10
|
- 🤖 **12 个内置代理**:8 个通用代理(orchestrator/oracle/librarian/explorer/designer/fixer/observer/council)+ 4 个规范/方案代理(rule-user/rule-project/rule-app/planner)
|
|
9
11
|
- 🪝 **自动注入**:通过 `system.transform` 钩子在每次 LLM 调用时注入中文语言要求
|
|
10
12
|
- 🧠 **纯调度 Orchestrator**:不碰任何文件工具,只负责规划、委派、验证
|
|
11
|
-
- 🇨🇳 **全中文提示词**:
|
|
13
|
+
- 🇨🇳 **全中文提示词**:12 个代理全部使用中文提示词
|
|
12
14
|
- 📋 **规范分析代理**:rule-user(用户AGENTS.md)、rule-project(项目AGENTS.md)、rule-app(.opencode/rules/)
|
|
13
15
|
- 🎯 **方案制定代理**:planner 综合所有输入输出结构化任务分解
|
|
14
16
|
- 🔗 **OpenSpec + Superpowers 死板路由**:收到需求即触发,不判断"大小"
|
|
@@ -78,7 +80,7 @@ CLI 会精确清理所有 `co-*` 代理和相关配置,不影响其他插件
|
|
|
78
80
|
|
|
79
81
|
```bash
|
|
80
82
|
# 1. 克隆项目
|
|
81
|
-
git clone
|
|
83
|
+
git clone https://github.com/Mr-cjf/oh-my-opencode-cohub.git && cd oh-my-opencode-cohub
|
|
82
84
|
|
|
83
85
|
# 2. 安装依赖
|
|
84
86
|
npm install
|
|
@@ -104,43 +106,119 @@ bunx oh-my-opencode-cohub install
|
|
|
104
106
|
|
|
105
107
|
### 代理(12 个,全中文提示词)
|
|
106
108
|
|
|
107
|
-
| 代理 |
|
|
108
|
-
|
|
109
|
-
| orchestrator |
|
|
110
|
-
| oracle |
|
|
111
|
-
| librarian |
|
|
112
|
-
| explorer |
|
|
113
|
-
| designer |
|
|
114
|
-
| fixer |
|
|
115
|
-
| observer |
|
|
116
|
-
| council |
|
|
117
|
-
| rule-user |
|
|
118
|
-
| rule-project |
|
|
119
|
-
| rule-app |
|
|
120
|
-
| planner |
|
|
121
|
-
|
|
122
|
-
>
|
|
109
|
+
| 代理 | 默认模型 | 职责 | 读取源 |
|
|
110
|
+
|------|----------|------|--------|
|
|
111
|
+
| co-orchestrator | `deepseek/deepseek-v4-pro` | 纯调度:规划→委派→验证 | — |
|
|
112
|
+
| co-oracle | `deepseek/deepseek-v4-pro` | 架构审查/代码审查(含 Superpowers skills) | — |
|
|
113
|
+
| co-librarian | `deepseek/deepseek-v4-flash` | 外部文档/API 研究 | — |
|
|
114
|
+
| co-explorer | `deepseek/deepseek-v4-flash` | 代码库搜索定位 | — |
|
|
115
|
+
| co-designer | `minimax/MiniMax-M3` | UI/UX 设计与实现 | — |
|
|
116
|
+
| co-fixer | `deepseek/deepseek-v4-flash` | 代码修改执行(含 TDD skill) | — |
|
|
117
|
+
| co-observer | `codermxtest/gpt-5.5` | 图片/PDF 分析 | — |
|
|
118
|
+
| co-council | `deepseek/deepseek-v4-pro` | 多模型共识 | — |
|
|
119
|
+
| co-rule-user | `deepseek/deepseek-v4-flash` | 用户级规范分析 | `~/.config/opencode/AGENTS.md` |
|
|
120
|
+
| co-rule-project | `deepseek/deepseek-v4-flash` | 项目级规范分析 | 项目 `AGENTS.md` |
|
|
121
|
+
| co-rule-app | `deepseek/deepseek-v4-flash` | 应用规则分析 | `.opencode/rules/*.md` |
|
|
122
|
+
| co-planner | `deepseek/deepseek-v4-pro` | 方案制定 | 综合需求+信息+规则 |
|
|
123
|
+
|
|
124
|
+
> 模型可通过下文「配置文件」或「自定义模型」章节覆盖。
|
|
125
|
+
|
|
126
|
+
## 配置文件
|
|
127
|
+
|
|
128
|
+
CLI 安装后自动创建 `~/.config/opencode/oh-my-opencode-cohub.json`,这是 CoHub 的专用配置文件,结构如下:
|
|
129
|
+
|
|
130
|
+
```json
|
|
131
|
+
{
|
|
132
|
+
"$schema": "https://unpkg.com/oh-my-opencode-cohub@latest/oh-my-opencode-cohub.schema.json",
|
|
133
|
+
"agents": {
|
|
134
|
+
"co-orchestrator": { "model": "deepseek/deepseek-v4-pro", "variant": "max" },
|
|
135
|
+
"co-oracle": { "model": "deepseek/deepseek-v4-pro", "variant": "max" },
|
|
136
|
+
"co-librarian": { "model": "deepseek/deepseek-v4-flash", "variant": "low" },
|
|
137
|
+
"co-explorer": { "model": "deepseek/deepseek-v4-flash", "variant": "low" },
|
|
138
|
+
"co-designer": { "model": "minimax/MiniMax-M3", "variant": "medium" },
|
|
139
|
+
"co-fixer": { "model": "deepseek/deepseek-v4-flash", "variant": "high" },
|
|
140
|
+
"co-observer": { "model": "codermxtest/gpt-5.5", "variant": "low" },
|
|
141
|
+
"co-council": { "model": "deepseek/deepseek-v4-pro", "variant": "high" },
|
|
142
|
+
"co-rule-user": { "model": "deepseek/deepseek-v4-flash", "variant": "medium" },
|
|
143
|
+
"co-rule-project":{ "model": "deepseek/deepseek-v4-flash", "variant": "medium" },
|
|
144
|
+
"co-rule-app": { "model": "deepseek/deepseek-v4-flash", "variant": "medium" },
|
|
145
|
+
"co-planner": { "model": "deepseek/deepseek-v4-pro", "variant": "high" }
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
直接编辑此文件即可修改任意代理的模型和变体。`$schema` 提供 IDE 自动补全支持。
|
|
151
|
+
|
|
152
|
+
> **注意**:同一目录 `~/.config/opencode/oh-my-opencode-cohub/` 下也可放置 `{agent}.md` 提示词覆盖文件(见「自定义提示词」章节),与 JSON 配置文件共存。
|
|
153
|
+
|
|
154
|
+
### Council 多模型共识配置
|
|
155
|
+
|
|
156
|
+
`co-council` 代理通过 `council_session` 工具并行调用多个模型(councillors),综合各方观点形成共识。councillors 的数量、模型、推理强度完全可配置:
|
|
157
|
+
|
|
158
|
+
```json
|
|
159
|
+
{
|
|
160
|
+
"council": {
|
|
161
|
+
"default_preset": "default",
|
|
162
|
+
"timeout": 180000,
|
|
163
|
+
"councillor_execution_mode": "parallel",
|
|
164
|
+
"councillor_retries": 3,
|
|
165
|
+
"presets": {
|
|
166
|
+
"default": {
|
|
167
|
+
"alpha": { "model": "deepseek/deepseek-v4-pro", "variant": "max" },
|
|
168
|
+
"beta": { "model": "deepseek/deepseek-v4-flash", "variant": "high" },
|
|
169
|
+
"gamma": { "model": "minimax/MiniMax-M3", "variant": "medium" }
|
|
170
|
+
},
|
|
171
|
+
"quick": {
|
|
172
|
+
"alpha": { "model": "deepseek/deepseek-v4-flash", "variant": "high" },
|
|
173
|
+
"beta": { "model": "deepseek/deepseek-v4-flash", "variant": "low" }
|
|
174
|
+
},
|
|
175
|
+
"deep": {
|
|
176
|
+
"alpha": { "model": "deepseek/deepseek-v4-pro", "variant": "max" },
|
|
177
|
+
"beta": { "model": "deepseek/deepseek-v4-pro", "variant": "max" },
|
|
178
|
+
"gamma": { "model": "minimax/MiniMax-M3", "variant": "medium" },
|
|
179
|
+
"delta": { "model": "codermxtest/gpt-5.5", "variant": "high" }
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
| 字段 | 类型 | 默认值 | 说明 |
|
|
187
|
+
|------|------|--------|------|
|
|
188
|
+
| `presets` | object | (必填) | 预设字典,每个预设是一组 councillor |
|
|
189
|
+
| `default_preset` | string | `"default"` | 调用时不指定 preset 时使用的预设 |
|
|
190
|
+
| `timeout` | number | `180000` | 单个 councillor 超时(毫秒),默认 3 分钟 |
|
|
191
|
+
| `councillor_execution_mode` | `"parallel"` \| `"serial"` | `"parallel"` | 并行/串行执⾏ |
|
|
192
|
+
| `councillor_retries` | number | `3` | 空响应重试次数 |
|
|
193
|
+
|
|
194
|
+
- 每个 councillor 的 key(如 `alpha`、`beta`)可任意命名,会出现在输出中
|
|
195
|
+
- `model` 格式为 `"provider/model"`,`variant` 可选 `"max"` / `"high"` / `"medium"` / `"low"`
|
|
196
|
+
- councillor 数量无上限,但建议 2-5 个以平衡成本和质量
|
|
197
|
+
- 调用时可通过 `council_session` 工具的 `preset` 参数切换预设,如 `"quick"` 或 `"deep"`
|
|
123
198
|
|
|
124
199
|
## 工作流
|
|
125
200
|
|
|
126
201
|
```
|
|
127
202
|
1. 理解需求
|
|
128
|
-
2. 信息收集(@explorer / @librarian / @observer)
|
|
129
|
-
3. 规范分析(并行 @rule-user / @rule-project / @rule-app)
|
|
130
|
-
4. 制定方案 → @planner
|
|
131
|
-
5. 调度执行(@fixer / @designer 等)
|
|
132
|
-
6. 验证(@oracle / @designer)
|
|
203
|
+
2. 信息收集(@co-explorer / @co-librarian / @co-observer)
|
|
204
|
+
3. 规范分析(并行 @co-rule-user / @co-rule-project / @co-rule-app)
|
|
205
|
+
4. 制定方案 → @co-planner
|
|
206
|
+
5. 调度执行(@co-fixer / @co-designer 等)
|
|
207
|
+
6. 验证(@co-oracle / @co-designer)
|
|
133
208
|
```
|
|
134
209
|
|
|
135
210
|
## 依赖
|
|
136
211
|
|
|
137
|
-
- OpenCode
|
|
138
|
-
- `@opencode-ai/plugin
|
|
212
|
+
- [OpenCode](https://opencode.ai) ≥ 1.17
|
|
213
|
+
- `@opencode-ai/plugin@^1.17`(运行时依赖)
|
|
214
|
+
- `@opencode-ai/sdk@^1.3`(运行时依赖)
|
|
139
215
|
- 无其他外部插件依赖
|
|
140
216
|
|
|
141
217
|
## 自定义模型
|
|
142
218
|
|
|
143
|
-
|
|
219
|
+
**推荐**:直接编辑 `~/.config/opencode/oh-my-opencode-cohub.json`(见「配置文件」章节),修改对应代理的 `model` 和 `variant` 即可。
|
|
220
|
+
|
|
221
|
+
**备选**:通过 `opencode.json` 的 plugin config 覆盖:
|
|
144
222
|
|
|
145
223
|
```json
|
|
146
224
|
{
|
|
@@ -158,6 +236,8 @@ bunx oh-my-opencode-cohub install
|
|
|
158
236
|
}
|
|
159
237
|
```
|
|
160
238
|
|
|
239
|
+
> 注意:plugin config 中的 key 使用无 `co-` 前缀的短名(如 `orchestrator`);JSON 配置文件使用完整的 `co-` 前缀名(如 `co-orchestrator`)。
|
|
240
|
+
|
|
161
241
|
## 自定义提示词
|
|
162
242
|
|
|
163
243
|
### 方式一:通过 plugin config 覆盖(推荐)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-io.d.ts","sourceRoot":"","sources":["../../src/cli/config-io.ts"],"names":[],"mappings":"AA4BA,2CAA2C;AAC3C,wBAAgB,yBAAyB,IAAI;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAajF;AAED,sCAAsC;AACtC,wBAAgB,oBAAoB,IAAI;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAa5E;AAOD,mDAAmD;AACnD,wBAAgB,mBAAmB,IAAI;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAmC3E;AAID,uBAAuB;AACvB,wBAAgB,kBAAkB,IAAI;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"config-io.d.ts","sourceRoot":"","sources":["../../src/cli/config-io.ts"],"names":[],"mappings":"AA4BA,2CAA2C;AAC3C,wBAAgB,yBAAyB,IAAI;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAajF;AAED,sCAAsC;AACtC,wBAAgB,oBAAoB,IAAI;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAa5E;AAOD,mDAAmD;AACnD,wBAAgB,mBAAmB,IAAI;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAmC3E;AAID,uBAAuB;AACvB,wBAAgB,kBAAkB,IAAI;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CA0C1E;AAED,8BAA8B;AAC9B,wBAAgB,cAAc,IAAI;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CA6GzE"}
|
package/dist/cli/index.js
CHANGED
|
@@ -426,7 +426,7 @@ function registerCoHubAgents() {
|
|
|
426
426
|
## Council 总结
|
|
427
427
|
总结 councillor 在哪些方面共识、哪些方面分歧,为什么选择最终答案,以及剩余的不确定性。包含共识信心评级:一致、多数或分歧。
|
|
428
428
|
|
|
429
|
-
**语言要求**: 始终使用中文进行思考、综合和回复。Council 响应、总结等自然语言部分必须用中文。Code examples 可用英文。`, model: "deepseek/deepseek-v4-pro", variant: "high" },
|
|
429
|
+
**语言要求**: 始终使用中文进行思考、综合和回复。Council 响应、总结等自然语言部分必须用中文。Code examples 可用英文。`, model: "deepseek/deepseek-v4-pro", variant: "high", permission: { council_session: "allow" } },
|
|
430
430
|
"co-rule-user": { description: "用户规范分析", mode: "subagent", prompt: `你是规则分析代理——负责用户级规范。
|
|
431
431
|
|
|
432
432
|
**职责**:读取 \`~/.config/opencode/AGENTS.md\`(用户级全局规则),结合 Orchestrator 提供的当前方案,分析是否有遗漏或冲突。返回具体的调整建议(不要笼统)。
|
|
@@ -486,6 +486,19 @@ function writeDefaultConfig() {
|
|
|
486
486
|
"co-rule-project": { model: "deepseek/deepseek-v4-flash", variant: "medium" },
|
|
487
487
|
"co-rule-app": { model: "deepseek/deepseek-v4-flash", variant: "medium" },
|
|
488
488
|
"co-planner": { model: "deepseek/deepseek-v4-pro", variant: "high" }
|
|
489
|
+
},
|
|
490
|
+
council: {
|
|
491
|
+
default_preset: "default",
|
|
492
|
+
timeout: 180000,
|
|
493
|
+
councillor_execution_mode: "parallel",
|
|
494
|
+
councillor_retries: 3,
|
|
495
|
+
presets: {
|
|
496
|
+
default: {
|
|
497
|
+
alpha: { model: "deepseek/deepseek-v4-pro", variant: "max" },
|
|
498
|
+
beta: { model: "deepseek/deepseek-v4-flash", variant: "high" },
|
|
499
|
+
gamma: { model: "minimax/MiniMax-M3", variant: "medium" }
|
|
500
|
+
}
|
|
501
|
+
}
|
|
489
502
|
}
|
|
490
503
|
};
|
|
491
504
|
try {
|
package/dist/config/loader.d.ts
CHANGED
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
/** 单个 councillor 配置 */
|
|
2
|
+
export interface CouncillorConfig {
|
|
3
|
+
model: string;
|
|
4
|
+
variant?: string;
|
|
5
|
+
prompt?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface CouncilPreset {
|
|
8
|
+
[councillorName: string]: CouncillorConfig;
|
|
9
|
+
}
|
|
10
|
+
export interface CouncilConfig {
|
|
11
|
+
presets: Record<string, CouncilPreset>;
|
|
12
|
+
timeout?: number;
|
|
13
|
+
default_preset?: string;
|
|
14
|
+
councillor_execution_mode?: 'parallel' | 'serial';
|
|
15
|
+
councillor_retries?: number;
|
|
16
|
+
}
|
|
1
17
|
/** 用户配置中单个代理的覆盖项 */
|
|
2
18
|
export interface AgentOverride {
|
|
3
19
|
model?: string;
|
|
@@ -6,6 +22,7 @@ export interface AgentOverride {
|
|
|
6
22
|
}
|
|
7
23
|
export interface CoHubConfig {
|
|
8
24
|
agents?: Record<string, AgentOverride>;
|
|
25
|
+
council?: CouncilConfig;
|
|
9
26
|
}
|
|
10
27
|
/** 加载用户配置 */
|
|
11
28
|
export declare function loadCoHubConfig(): CoHubConfig;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAIA,oBAAoB;AACpB,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAIA,uBAAuB;AACvB,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,CAAC,cAAc,EAAE,MAAM,GAAG,gBAAgB,CAAC;CAC5C;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IACvC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,yBAAyB,CAAC,EAAE,UAAU,GAAG,QAAQ,CAAC;IAClD,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,oBAAoB;AACpB,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IACvC,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AAKD,aAAa;AACb,wBAAgB,eAAe,IAAI,WAAW,CAQ7C;AAED,aAAa;AACb,eAAO,MAAM,cAAc,EAAE,WAe5B,CAAC"}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAsClD,wBAAwB;AACxB,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAalD,CAAC;AAwEF;;GAEG;AACH,eAAO,MAAM,mBAAmB,wrBAA+B,CAAC;AAEhE,QAAA,MAAM,WAAW,EAAE,MA6SlB,CAAC;AAEF,eAAe,WAAW,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -19,6 +19,47 @@ var ORCHESTRATOR_PROMPT = `<角色>
|
|
|
19
19
|
|
|
20
20
|
</子代理>
|
|
21
21
|
|
|
22
|
+
### @council vs @oracle 选择指南
|
|
23
|
+
|
|
24
|
+
**一句话判断**:\`@co-oracle\` = 深度推理(快、便宜、单视角),\`@co-council\` = 多模型背书的共识(慢、贵、多视角)。
|
|
25
|
+
|
|
26
|
+
| 维度 | @co-oracle | @co-council |
|
|
27
|
+
|------|-----------|-------------|
|
|
28
|
+
| 模式 | 单模型深度推理 | 多模型并行共识 |
|
|
29
|
+
| 适用场景 | 错了还能改的决策 | 错了就完了的决策 |
|
|
30
|
+
| 典型用例 | 代码审查、架构建议、bug 根因、YAGNI 简化、文案审查、重构方向 | 数据迁移方案、API 破坏性变更、安全合规审计、选型代价极大、多方案择优 |
|
|
31
|
+
| 输出形式 | 直接建议 + 推理 | 多专家观点 → 综合共识 → 信心评级(一致/多数/分歧) |
|
|
32
|
+
| 误用代价 | 低:建议错了可以讨论纠正 | 高:浪费 N 次调用成本,拖延决策 |
|
|
33
|
+
| 成本 | 1 次 LLM 调用 | 3–5 次并行 LLM 调用 |
|
|
34
|
+
|
|
35
|
+
**决策规则**:
|
|
36
|
+
1. **可逆性优先判断**:操作错了能无代价回滚?→ \`@co-oracle\`(如代码修改、lint 修复)。操作错了数据丢失/API 不兼容?→ \`@co-council\`(如 DROP TABLE、公共 API 签名变更)。
|
|
37
|
+
2. **异议价值判断**:需要单一深度分析?→ \`@co-oracle\`。需要多个独立判断互相验证?→ \`@co-council\`。
|
|
38
|
+
3. **默认倾向**:不确定时优先 \`@co-oracle\`(更快更便宜)。只有满足以下**至少 2 条**时才用 \`@co-council\`:
|
|
39
|
+
- 决策不可逆或回滚代价极高
|
|
40
|
+
- 影响范围跨多个模块/团队/服务
|
|
41
|
+
- 单一判断出错会造成安全事故/线上故障/数据损坏
|
|
42
|
+
- 存在多种合理方案且选错代价大
|
|
43
|
+
|
|
44
|
+
**典型场景对照**:
|
|
45
|
+
|
|
46
|
+
| 场景 | 用谁 | 理由 |
|
|
47
|
+
|------|------|------|
|
|
48
|
+
| PR 代码审查 | @co-oracle | 错了还能改,审查意见可讨论 |
|
|
49
|
+
| 重构建议 | @co-oracle | 方案可迭代调整 |
|
|
50
|
+
| 单文件 bug 修复思路 | @co-oracle | 低风险,快速反馈 |
|
|
51
|
+
| 数据库 Schema 迁移(含删列/改类型) | @co-council | 数据不可逆,需要多模型背书 |
|
|
52
|
+
| 公共 API 签名废弃/变更 | @co-council | 下游影响不可控 |
|
|
53
|
+
| 安全漏洞修复方案 | @co-council | 错了可能被利用 |
|
|
54
|
+
| 第三方库选型(如 ORM/状态管理) | @co-council | 迁移成本极高 |
|
|
55
|
+
| 文案/提示词修改 | @co-oracle | 错了能改,低风险 |
|
|
56
|
+
| 多方案架构决策(各有利弊) | @co-council | 需要多方面权衡 |
|
|
57
|
+
|
|
58
|
+
**反面教材——不要这样用**:
|
|
59
|
+
- ❌ 用 \`@co-council\` 审查一个简单的 lint 修复(杀鸡用牛刀)
|
|
60
|
+
- ❌ 用 \`@co-oracle\` 决定是否删除生产数据库的某个表(赌单模型判断)
|
|
61
|
+
- ❌ 用 \`@co-council\` 做日常代码格式化建议(纯浪费)
|
|
62
|
+
|
|
22
63
|
<核心规则>
|
|
23
64
|
|
|
24
65
|
## 硬性规则——不可违反
|
|
@@ -575,6 +616,347 @@ function loadCoHubConfig() {
|
|
|
575
616
|
}
|
|
576
617
|
}
|
|
577
618
|
|
|
619
|
+
// src/tools/council.ts
|
|
620
|
+
import { tool } from "@opencode-ai/plugin";
|
|
621
|
+
var z = tool.schema;
|
|
622
|
+
|
|
623
|
+
class OperationTimeoutError extends Error {
|
|
624
|
+
constructor(message) {
|
|
625
|
+
super(message);
|
|
626
|
+
this.name = "OperationTimeoutError";
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
function isTextPart(part) {
|
|
630
|
+
return (part.type === "text" || part.type === "reasoning") && typeof part.text === "string";
|
|
631
|
+
}
|
|
632
|
+
function shortModelLabel(model) {
|
|
633
|
+
return model.split("/").pop() ?? model;
|
|
634
|
+
}
|
|
635
|
+
function parseModelReference(model) {
|
|
636
|
+
const slashIndex = model.indexOf("/");
|
|
637
|
+
if (slashIndex <= 0 || slashIndex >= model.length - 1)
|
|
638
|
+
return null;
|
|
639
|
+
return {
|
|
640
|
+
providerID: model.slice(0, slashIndex),
|
|
641
|
+
modelID: model.slice(slashIndex + 1)
|
|
642
|
+
};
|
|
643
|
+
}
|
|
644
|
+
async function abortSession(client, sessionId) {
|
|
645
|
+
try {
|
|
646
|
+
await client.session.abort({ path: { id: sessionId } });
|
|
647
|
+
} catch {}
|
|
648
|
+
}
|
|
649
|
+
async function promptWithTimeout(client, path2, body, timeoutMs, directory) {
|
|
650
|
+
const sessionId = path2.id;
|
|
651
|
+
let timer;
|
|
652
|
+
try {
|
|
653
|
+
const promptPromise = client.session.prompt({
|
|
654
|
+
path: path2,
|
|
655
|
+
body,
|
|
656
|
+
query: directory ? { directory } : undefined
|
|
657
|
+
});
|
|
658
|
+
promptPromise.catch(() => {});
|
|
659
|
+
const racers = [promptPromise];
|
|
660
|
+
if (timeoutMs > 0) {
|
|
661
|
+
racers.push(new Promise((_, reject) => {
|
|
662
|
+
timer = setTimeout(() => {
|
|
663
|
+
reject(new OperationTimeoutError(`Prompt timed out after ${timeoutMs}ms`));
|
|
664
|
+
}, timeoutMs);
|
|
665
|
+
}));
|
|
666
|
+
}
|
|
667
|
+
await Promise.race(racers);
|
|
668
|
+
} catch (error) {
|
|
669
|
+
if (error instanceof OperationTimeoutError) {
|
|
670
|
+
await abortSession(client, sessionId);
|
|
671
|
+
}
|
|
672
|
+
throw error;
|
|
673
|
+
} finally {
|
|
674
|
+
if (timer !== undefined)
|
|
675
|
+
clearTimeout(timer);
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
async function extractSessionResult(client, sessionId, options) {
|
|
679
|
+
const includeReasoning = options?.includeReasoning ?? true;
|
|
680
|
+
const messagesResult = await client.session.messages({
|
|
681
|
+
path: { id: sessionId }
|
|
682
|
+
});
|
|
683
|
+
const messages = messagesResult.data ?? [];
|
|
684
|
+
const assistantMessages = messages.filter((m) => m.info?.role === "assistant");
|
|
685
|
+
const extractedContent = [];
|
|
686
|
+
for (const message of assistantMessages) {
|
|
687
|
+
for (const part of message.parts ?? []) {
|
|
688
|
+
if (!isTextPart(part))
|
|
689
|
+
continue;
|
|
690
|
+
const allowed = includeReasoning || part.type === "text";
|
|
691
|
+
if (allowed && part.text) {
|
|
692
|
+
extractedContent.push(part.text);
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
const text = extractedContent.filter((t) => t.length > 0).join(`
|
|
697
|
+
|
|
698
|
+
`);
|
|
699
|
+
return { text, empty: text.length === 0 };
|
|
700
|
+
}
|
|
701
|
+
function formatCouncillorPrompt(userPrompt, councillorPrompt) {
|
|
702
|
+
if (!councillorPrompt)
|
|
703
|
+
return userPrompt;
|
|
704
|
+
return `${councillorPrompt}
|
|
705
|
+
|
|
706
|
+
---
|
|
707
|
+
|
|
708
|
+
${userPrompt}`;
|
|
709
|
+
}
|
|
710
|
+
function formatCouncillorResults(originalPrompt, councillorResults) {
|
|
711
|
+
const completedWithResults = councillorResults.filter((cr) => cr.status === "completed" && cr.result);
|
|
712
|
+
const councillorSection = completedWithResults.map((cr) => {
|
|
713
|
+
const shortModel = shortModelLabel(cr.model);
|
|
714
|
+
return `**${cr.name}** (${shortModel}):
|
|
715
|
+
${cr.result}`;
|
|
716
|
+
}).join(`
|
|
717
|
+
|
|
718
|
+
`);
|
|
719
|
+
const failedEntries = councillorResults.filter((cr) => cr.status !== "completed");
|
|
720
|
+
const failedSection = failedEntries.map((cr) => `**${cr.name}**: ${cr.status} — ${cr.error ?? "Unknown"}`).join(`
|
|
721
|
+
`);
|
|
722
|
+
if (completedWithResults.length === 0) {
|
|
723
|
+
const errorDetails = councillorResults.map((cr) => `**${cr.name}** (${shortModelLabel(cr.model)}): ${cr.status} — ${cr.error ?? "Unknown"}`).join(`
|
|
724
|
+
`);
|
|
725
|
+
return [
|
|
726
|
+
"---",
|
|
727
|
+
"",
|
|
728
|
+
"**Original Prompt**:",
|
|
729
|
+
originalPrompt,
|
|
730
|
+
"",
|
|
731
|
+
"---",
|
|
732
|
+
"",
|
|
733
|
+
"**Councillor Responses**:",
|
|
734
|
+
"All councillors failed to produce output:",
|
|
735
|
+
errorDetails,
|
|
736
|
+
"",
|
|
737
|
+
"Please generate a response based on the original prompt alone."
|
|
738
|
+
].join(`
|
|
739
|
+
`);
|
|
740
|
+
}
|
|
741
|
+
const parts = [
|
|
742
|
+
"---",
|
|
743
|
+
"",
|
|
744
|
+
"**Original Prompt**:",
|
|
745
|
+
originalPrompt,
|
|
746
|
+
"",
|
|
747
|
+
"---",
|
|
748
|
+
"",
|
|
749
|
+
"**Councillor Responses**:",
|
|
750
|
+
councillorSection
|
|
751
|
+
];
|
|
752
|
+
if (failedSection) {
|
|
753
|
+
parts.push("", "---", "", "**Failed/Timed-out Councillors**:", failedSection);
|
|
754
|
+
}
|
|
755
|
+
parts.push("", "---", "", "You MUST follow the Synthesis Process steps before producing output: " + "review each councillor response individually, then produce the required output " + "with a synthesized Council Response, per-councillor details using their exact names, " + "and a Council Summary with consensus confidence rating (unanimous, majority, or split).");
|
|
756
|
+
return parts.join(`
|
|
757
|
+
`);
|
|
758
|
+
}
|
|
759
|
+
function formatModelComposition(councillorResults) {
|
|
760
|
+
return councillorResults.map((cr) => `${cr.name}: ${shortModelLabel(cr.model)}`).join(", ");
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
class CouncilManager {
|
|
764
|
+
client;
|
|
765
|
+
directory;
|
|
766
|
+
config;
|
|
767
|
+
constructor(client, directory, config) {
|
|
768
|
+
this.client = client;
|
|
769
|
+
this.directory = directory;
|
|
770
|
+
this.config = config;
|
|
771
|
+
}
|
|
772
|
+
async runCouncil(prompt, presetName, parentSessionId) {
|
|
773
|
+
const resolvedPreset = presetName ?? this.config.default_preset ?? "default";
|
|
774
|
+
const preset = this.config.presets[resolvedPreset];
|
|
775
|
+
if (!preset) {
|
|
776
|
+
const available = Object.keys(this.config.presets).join(", ");
|
|
777
|
+
return {
|
|
778
|
+
success: false,
|
|
779
|
+
error: `Preset "${resolvedPreset}" does not exist. Available presets: ${available}`,
|
|
780
|
+
councillorResults: []
|
|
781
|
+
};
|
|
782
|
+
}
|
|
783
|
+
if (Object.keys(preset).length === 0) {
|
|
784
|
+
return {
|
|
785
|
+
success: false,
|
|
786
|
+
error: `Preset "${resolvedPreset}" has no councillors configured.`,
|
|
787
|
+
councillorResults: []
|
|
788
|
+
};
|
|
789
|
+
}
|
|
790
|
+
const timeout = this.config.timeout ?? 180000;
|
|
791
|
+
const executionMode = this.config.councillor_execution_mode ?? "parallel";
|
|
792
|
+
const maxRetries = this.config.councillor_retries ?? 3;
|
|
793
|
+
const councillorResults = await this.runCouncillors(prompt, preset, parentSessionId, timeout, executionMode, maxRetries);
|
|
794
|
+
const completedCount = councillorResults.filter((r) => r.status === "completed").length;
|
|
795
|
+
if (completedCount === 0) {
|
|
796
|
+
return {
|
|
797
|
+
success: false,
|
|
798
|
+
error: "All councillors failed or timed out",
|
|
799
|
+
councillorResults
|
|
800
|
+
};
|
|
801
|
+
}
|
|
802
|
+
const formatted = formatCouncillorResults(prompt, councillorResults);
|
|
803
|
+
return {
|
|
804
|
+
success: true,
|
|
805
|
+
result: formatted,
|
|
806
|
+
councillorResults
|
|
807
|
+
};
|
|
808
|
+
}
|
|
809
|
+
async runCouncillors(prompt, councillors, parentSessionId, timeout, executionMode, maxRetries) {
|
|
810
|
+
const entries = Object.entries(councillors);
|
|
811
|
+
const results = [];
|
|
812
|
+
if (executionMode === "serial") {
|
|
813
|
+
for (const [name, config] of entries) {
|
|
814
|
+
const r = await this.runCouncillorWithRetry(name, config, prompt, parentSessionId, timeout, maxRetries);
|
|
815
|
+
results.push(r);
|
|
816
|
+
}
|
|
817
|
+
} else {
|
|
818
|
+
const promises = entries.map(([name, config]) => this.runCouncillorWithRetry(name, config, prompt, parentSessionId, timeout, maxRetries));
|
|
819
|
+
const settled = await Promise.allSettled(promises);
|
|
820
|
+
for (let i = 0;i < settled.length; i++) {
|
|
821
|
+
const s = settled[i];
|
|
822
|
+
const [name, cfg] = entries[i];
|
|
823
|
+
if (s.status === "fulfilled") {
|
|
824
|
+
results.push(s.value);
|
|
825
|
+
} else {
|
|
826
|
+
results.push({
|
|
827
|
+
name,
|
|
828
|
+
model: cfg.model,
|
|
829
|
+
status: "failed",
|
|
830
|
+
error: s.reason instanceof Error ? s.reason.message : String(s.reason)
|
|
831
|
+
});
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
return results;
|
|
836
|
+
}
|
|
837
|
+
async runCouncillorWithRetry(name, config, prompt, parentSessionId, timeout, maxRetries) {
|
|
838
|
+
const totalAttempts = 1 + maxRetries;
|
|
839
|
+
for (let attempt = 1;attempt <= totalAttempts; attempt++) {
|
|
840
|
+
try {
|
|
841
|
+
const result = await this.runAgentSession({
|
|
842
|
+
parentSessionId,
|
|
843
|
+
title: `Council ${name} (${shortModelLabel(config.model)})`,
|
|
844
|
+
model: config.model,
|
|
845
|
+
promptText: formatCouncillorPrompt(prompt, config.prompt),
|
|
846
|
+
variant: config.variant,
|
|
847
|
+
timeout
|
|
848
|
+
});
|
|
849
|
+
return { name, model: config.model, status: "completed", result };
|
|
850
|
+
} catch (error) {
|
|
851
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
852
|
+
const isEmptyResponse = msg.includes("Empty response from provider");
|
|
853
|
+
const canRetry = attempt < totalAttempts && isEmptyResponse;
|
|
854
|
+
if (!canRetry) {
|
|
855
|
+
return {
|
|
856
|
+
name,
|
|
857
|
+
model: config.model,
|
|
858
|
+
status: msg.includes("timed out") ? "timed_out" : "failed",
|
|
859
|
+
error: `Councillor "${name}": ${msg}`
|
|
860
|
+
};
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
return {
|
|
865
|
+
name,
|
|
866
|
+
model: config.model,
|
|
867
|
+
status: "failed",
|
|
868
|
+
error: `Councillor "${name}": max retries exhausted`
|
|
869
|
+
};
|
|
870
|
+
}
|
|
871
|
+
async runAgentSession(options) {
|
|
872
|
+
const modelRef = parseModelReference(options.model);
|
|
873
|
+
if (!modelRef) {
|
|
874
|
+
throw new Error(`Invalid model format: ${options.model}`);
|
|
875
|
+
}
|
|
876
|
+
let sessionId;
|
|
877
|
+
try {
|
|
878
|
+
const session = await this.client.session.create({
|
|
879
|
+
body: {
|
|
880
|
+
parentID: options.parentSessionId,
|
|
881
|
+
title: options.title
|
|
882
|
+
},
|
|
883
|
+
query: { directory: this.directory }
|
|
884
|
+
});
|
|
885
|
+
if (!session.data?.id) {
|
|
886
|
+
throw new Error("Failed to create session");
|
|
887
|
+
}
|
|
888
|
+
sessionId = session.data.id;
|
|
889
|
+
const promptBody = {
|
|
890
|
+
model: modelRef,
|
|
891
|
+
tools: {
|
|
892
|
+
task: false,
|
|
893
|
+
question: false,
|
|
894
|
+
edit: false,
|
|
895
|
+
write: false,
|
|
896
|
+
apply_patch: false,
|
|
897
|
+
ast_grep_replace: false,
|
|
898
|
+
bash: false
|
|
899
|
+
},
|
|
900
|
+
parts: [{ type: "text", text: options.promptText }]
|
|
901
|
+
};
|
|
902
|
+
if (options.variant) {
|
|
903
|
+
promptBody.variant = options.variant;
|
|
904
|
+
}
|
|
905
|
+
await promptWithTimeout(this.client, { id: sessionId }, promptBody, options.timeout, this.directory);
|
|
906
|
+
const extraction = await extractSessionResult(this.client, sessionId);
|
|
907
|
+
if (extraction.empty) {
|
|
908
|
+
throw new Error("Empty response from provider");
|
|
909
|
+
}
|
|
910
|
+
return extraction.text;
|
|
911
|
+
} finally {
|
|
912
|
+
if (sessionId) {
|
|
913
|
+
abortSession(this.client, sessionId).catch(() => {});
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
function createCouncilTool(ctx, councilManager) {
|
|
919
|
+
const council_session = tool({
|
|
920
|
+
description: [
|
|
921
|
+
"Launch a multi-LLM council session for consensus-based analysis.",
|
|
922
|
+
"",
|
|
923
|
+
"Sends the prompt to multiple models (councillors) in parallel and returns",
|
|
924
|
+
"their formatted responses for you to synthesize.",
|
|
925
|
+
"",
|
|
926
|
+
"Returns the councillor responses with a summary footer."
|
|
927
|
+
].join(`
|
|
928
|
+
`),
|
|
929
|
+
args: {
|
|
930
|
+
prompt: z.string().describe("The prompt to send to all councillors"),
|
|
931
|
+
preset: z.string().optional().describe('Council preset to use (default: "default"). Must match a preset in the council config.')
|
|
932
|
+
},
|
|
933
|
+
async execute(args, toolContext) {
|
|
934
|
+
const allowedAgents = ["co-council"];
|
|
935
|
+
const callingAgent = toolContext.agent;
|
|
936
|
+
if (callingAgent && !allowedAgents.includes(callingAgent)) {
|
|
937
|
+
throw new Error(`Council sessions can only be invoked by the co-council agent. Current agent: ${callingAgent}`);
|
|
938
|
+
}
|
|
939
|
+
const prompt = String(args.prompt);
|
|
940
|
+
const preset = typeof args.preset === "string" ? args.preset : undefined;
|
|
941
|
+
const parentSessionId = toolContext.sessionID;
|
|
942
|
+
const result = await councilManager.runCouncil(prompt, preset, parentSessionId);
|
|
943
|
+
if (!result.success) {
|
|
944
|
+
return `Council session failed: ${result.error}`;
|
|
945
|
+
}
|
|
946
|
+
let output = result.result ?? "(No output)";
|
|
947
|
+
const completed = result.councillorResults.filter((cr) => cr.status === "completed").length;
|
|
948
|
+
const total = result.councillorResults.length;
|
|
949
|
+
const composition = formatModelComposition(result.councillorResults);
|
|
950
|
+
output += `
|
|
951
|
+
|
|
952
|
+
---
|
|
953
|
+
*Council: ${completed}/${total} councillors responded (${composition})*`;
|
|
954
|
+
return output;
|
|
955
|
+
}
|
|
956
|
+
});
|
|
957
|
+
return { council_session };
|
|
958
|
+
}
|
|
959
|
+
|
|
578
960
|
// src/index.ts
|
|
579
961
|
import * as fs2 from "node:fs";
|
|
580
962
|
import * as path2 from "node:path";
|
|
@@ -716,7 +1098,13 @@ var CoHubPlugin = async (input, options) => {
|
|
|
716
1098
|
{
|
|
717
1099
|
name: "co-council",
|
|
718
1100
|
description: "多模型共识——并行 LLM 综合",
|
|
719
|
-
config: {
|
|
1101
|
+
config: {
|
|
1102
|
+
mode: "subagent",
|
|
1103
|
+
model: "deepseek/deepseek-v4-pro",
|
|
1104
|
+
variant: "high",
|
|
1105
|
+
prompt: COUNCIL_PROMPT,
|
|
1106
|
+
permission: { council_session: "allow" }
|
|
1107
|
+
}
|
|
720
1108
|
},
|
|
721
1109
|
{
|
|
722
1110
|
name: "co-rule-user",
|
|
@@ -753,6 +1141,22 @@ var CoHubPlugin = async (input, options) => {
|
|
|
753
1141
|
}
|
|
754
1142
|
}
|
|
755
1143
|
}
|
|
1144
|
+
const DEFAULT_COUNCIL_CONFIG = {
|
|
1145
|
+
default_preset: "default",
|
|
1146
|
+
timeout: 180000,
|
|
1147
|
+
councillor_execution_mode: "parallel",
|
|
1148
|
+
councillor_retries: 3,
|
|
1149
|
+
presets: {
|
|
1150
|
+
default: {
|
|
1151
|
+
alpha: { model: "deepseek/deepseek-v4-pro", variant: "max" },
|
|
1152
|
+
beta: { model: "deepseek/deepseek-v4-flash", variant: "high" },
|
|
1153
|
+
gamma: { model: "minimax/MiniMax-M3", variant: "medium" }
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
};
|
|
1157
|
+
const councilConfig = userConfig.council ?? DEFAULT_COUNCIL_CONFIG;
|
|
1158
|
+
const councilManager = new CouncilManager(input.client, input.directory, councilConfig);
|
|
1159
|
+
const councilTools = createCouncilTool(input, councilManager);
|
|
756
1160
|
syncAgentConfig();
|
|
757
1161
|
function extractChildSessionId(output) {
|
|
758
1162
|
if (!output || typeof output !== "object")
|
|
@@ -805,6 +1209,7 @@ var CoHubPlugin = async (input, options) => {
|
|
|
805
1209
|
return {
|
|
806
1210
|
name: "oh-my-opencode-cohub",
|
|
807
1211
|
agent: agentConfigs,
|
|
1212
|
+
tool: councilTools,
|
|
808
1213
|
config: async (cfg) => {
|
|
809
1214
|
const c = cfg;
|
|
810
1215
|
c.agent ??= {};
|
|
@@ -832,17 +1237,6 @@ var CoHubPlugin = async (input, options) => {
|
|
|
832
1237
|
"tool.execute.after": async (input2, output) => {
|
|
833
1238
|
try {
|
|
834
1239
|
if (input2.tool === "task") {
|
|
835
|
-
try {
|
|
836
|
-
const debugDir = path2.join(os2.homedir(), ".local", "share", "opencode", "storage", "oh-my-opencode-cohub");
|
|
837
|
-
if (!fs2.existsSync(debugDir))
|
|
838
|
-
fs2.mkdirSync(debugDir, { recursive: true });
|
|
839
|
-
fs2.writeFileSync(path2.join(debugDir, "task-output-debug.json"), JSON.stringify({
|
|
840
|
-
time: new Date().toISOString(),
|
|
841
|
-
callID: input2.callID,
|
|
842
|
-
output_keys: Object.keys(output || {}),
|
|
843
|
-
output: JSON.parse(JSON.stringify(output))
|
|
844
|
-
}, null, 2), "utf-8");
|
|
845
|
-
} catch {}
|
|
846
1240
|
const childSessionId = extractChildSessionId(output);
|
|
847
1241
|
tracker.updateAfterTask(input2.sessionID, "completed", childSessionId);
|
|
848
1242
|
syncTrackerState(input2.sessionID ?? "");
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const ORCHESTRATOR_PROMPT = "<\u89D2\u8272>\n\u4F60\u662F\u7EAF\u8C03\u5EA6\u8005\uFF08Orchestrator\uFF09\u3002\u552F\u4E00\u804C\u8D23\uFF1A\u7406\u89E3\u9700\u6C42 \u2192 \u59D4\u6D3E\u4FE1\u606F\u6536\u96C6 \u2192 \u5236\u5B9A\u65B9\u6848 \u2192 \u8C03\u5EA6\u5B50\u4EE3\u7406\u6267\u884C \u2192 \u59D4\u6D3E\u9A8C\u8BC1\u3002**\u7EDD\u4E0D\u4EB2\u81EA\u4F7F\u7528\u4EFB\u4F55\u6587\u4EF6/\u4EE3\u7801\u64CD\u4F5C\u5DE5\u5177**\uFF08read\u3001grep\u3001glob\u3001bash\u3001edit\u3001write \u7B49\uFF09\u3002\u552F\u4E00\u53EF\u4F7F\u7528\u7684\u5DE5\u5177\u662F\u8C03\u5EA6\u5DE5\u5177\uFF08task\u3001todowrite\uFF09\u3002\n</\u89D2\u8272>\n\n<\u5B50\u4EE3\u7406>\n\n@co-explorer - \u53EA\u8BFB\u3002Grep/Glob/AST \u641C\u7D22\u5B9A\u4F4D\u3002\u59D4\u6D3E\uFF1A\u53D1\u73B0\u4EE3\u7801\u5E93\u5185\u5BB9\u65F6\u3002\n@co-librarian - \u53EA\u8BFB+Web\u3002\u5B98\u65B9\u6587\u6863/API/GitHub \u7814\u7A76\u3002\u59D4\u6D3E\uFF1A\u4E0D\u719F\u6089\u7684\u5E93/\u8FB9\u7F18\u60C5\u51B5\u3002\n@co-oracle - \u53EA\u8BFB\u3002\u67B6\u6784\u51B3\u7B56/\u4EE3\u7801\u5BA1\u67E5/YAGNI \u7B80\u5316/\u590D\u6742\u8C03\u8BD5\u3002\u59D4\u6D3E\uFF1A\u9AD8\u98CE\u9669\u51B3\u7B56/\u53CD\u590D bug/\u5B89\u5168\u5BA1\u67E5\u3002\n@co-designer - \u8BFB\u5199\u3002UI/UX \u8BBE\u8BA1/\u89C6\u89C9\u6DA6\u8272/\u54CD\u5E94\u5F0F\u5E03\u5C40\u3002\u59D4\u6D3E\uFF1A\u9700\u8981\u6DA6\u8272\u7684\u754C\u9762/UX \u7EC4\u4EF6\u3002\n@co-fixer - \u8BFB\u5199+Bash\u3002\u4EE3\u7801\u4FEE\u6539\u6267\u884C(\u65E0\u8BBA\u591A\u5C0F)\u3002\u59D4\u6D3E\uFF1A\u6240\u6709\u6587\u4EF6\u7F16\u8F91/\u5199\u5165/\u5220\u9664\u3002\n@co-observer - \u53EA\u8BFB\u3002\u56FE\u7247/PDF/\u622A\u56FE\u89C6\u89C9\u5206\u6790\u3002\u59D4\u6D3E\uFF1A\u591A\u5A92\u4F53\u6587\u4EF6\u5206\u6790\u65F6(\u542B\u5B8C\u6574\u8DEF\u5F84)\u3002\n@co-council - \u53EA\u8BFB\u3002\u591A\u6A21\u578B\u5E76\u884C\u5171\u8BC6\u3002\u59D4\u6D3E\uFF1A\u591A\u4E13\u5BB6\u89C6\u89D2/\u4E0D\u53EF\u9006\u51B3\u7B56\uFF08\u6570\u636E\u8FC1\u79FB/API \u53D8\u66F4\uFF09\u3002\u9519\u4E86\u8FD8\u80FD\u6539\u2192@co-oracle\uFF0C\u9519\u4E86\u5C31\u5B8C\u4E86\u2192@co-council\u3002\n@co-rule-user - \u53EA\u8BFB\u3002\u5206\u6790\u7528\u6237\u7EA7 AGENTS.md(~/.config/opencode/AGENTS.md)\u7EA6\u675F\u3002\u59D4\u6D3E\uFF1A\u65B9\u6848\u9700\u5BF9\u7167\u7528\u6237\u89C4\u5219\u65F6\u3002\n@co-rule-project - \u53EA\u8BFB\u3002\u5206\u6790\u9879\u76EE AGENTS.md \u7EA6\u675F\u3002\u59D4\u6D3E\uFF1A\u65B9\u6848\u9700\u5BF9\u7167\u9879\u76EE\u89C4\u5219\u65F6\u3002\n@co-rule-app - \u53EA\u8BFB\u3002\u5206\u6790 .opencode/rules/* \u7EA6\u675F\u3002\u59D4\u6D3E\uFF1A\u65B9\u6848\u9700\u5BF9\u7167\u5B89\u5168/\u6D4B\u8BD5/\u6570\u636E\u5E93\u7B49\u89C4\u5219\u65F6\u3002\n@co-planner - \u53EA\u8BFB\u3002\u7EFC\u5408\u9700\u6C42+\u4FE1\u606F+\u89C4\u8303\uFF0C\u8F93\u51FA\u7ED3\u6784\u5316\u4EFB\u52A1\u5206\u89E3\u65B9\u6848\u3002\u59D4\u6D3E\uFF1A\u4FE1\u606F\u6536\u96C6\u548C\u89C4\u8303\u5206\u6790\u5B8C\u6210\u540E\u3002\n\n</\u5B50\u4EE3\u7406>\n\n<\u6838\u5FC3\u89C4\u5219>\n\n## \u786C\u6027\u89C4\u5219\u2014\u2014\u4E0D\u53EF\u8FDD\u53CD\n\n### \u89C4\u5219 1\uFF1A\u7406\u89E3\u9700\u6C42\u540E\u5FC5\u987B\u5148\u8F93\u51FA\u65B9\u6848\n\u6536\u5230\u9700\u6C42\u540E\uFF08\u6D89\u53CA\u4EE3\u7801\u6216\u6587\u4EF6\u4FEE\u6539\u65F6\uFF09\uFF0C**\u7981\u6B62\u7ACB\u5373\u6267\u884C**\u3002\u5FC5\u987B\u5148\u5206\u6790\u9700\u6C42\uFF0C\u8F93\u51FA\u53EF\u9A8C\u8BC1\u7684\u4EFB\u52A1\u5206\u89E3\u65B9\u6848\uFF0C\u5305\u542B\uFF1A\n\uFF08\u7EAF\u4FE1\u606F\u6027\u95EE\u9898\u53EF\u76F4\u63A5\u56DE\u7B54\uFF0C\u65E0\u9700\u65B9\u6848\u3002\uFF09\n- \u5B50\u4EFB\u52A1\u5217\u8868\u53CA\u5176\u4F9D\u8D56\u5173\u7CFB\n- \u6BCF\u4E2A\u5B50\u4EFB\u52A1\u7684\u59D4\u6D3E\u5BF9\u8C61\uFF08@co-explorer / @co-librarian / @co-fixer / @co-designer / @co-oracle / @co-observer\uFF09\n- \u5E76\u884C\u5316\u7B56\u7565\uFF08\u54EA\u4E9B\u4EFB\u52A1\u53EF\u540C\u65F6\u6267\u884C\uFF09\n- \u9A8C\u8BC1\u6B65\u9AA4\n\n\u65B9\u6848\u8981\u5177\u4F53\u5230\u6587\u4EF6\u548C\u64CD\u4F5C\u7C92\u5EA6\u3002\u7528 `todowrite` \u521B\u5EFA\u4EFB\u52A1\u5217\u8868\u3002\n\n### \u89C4\u5219 2\uFF1A\u6240\u6709\u5DE5\u5177\u64CD\u4F5C\u5FC5\u987B\u59D4\u6D3E\u2014\u2014\u65E0\u4F8B\u5916\n**Orchestrator \u7981\u6B62\u4F7F\u7528\u4EFB\u4F55\u6587\u4EF6/\u4EE3\u7801\u64CD\u4F5C\u5DE5\u5177**\uFF08read\u3001grep\u3001glob\u3001ast_grep_search\u3001bash\u3001edit\u3001write \u7B49\uFF09\uFF0C**\u4EC5\u5141\u8BB8\u4F7F\u7528\u8C03\u5EA6\u5DE5\u5177**\uFF08task\u3001todowrite\uFF09\u3002\n- \u8BFB\u53D6\u6587\u4EF6\u3001\u641C\u7D22\u4EE3\u7801\u3001\u67E5\u770B git diff \u2192 \u59D4\u6D3E @co-explorer\n- \u4EE3\u7801\u7F16\u8F91\u3001\u5199\u5165\u3001\u5220\u9664\uFF08\u65E0\u8BBA\u591A\u5C0F\uFF09 \u2192 \u59D4\u6D3E @co-fixer\n- UI/UX \u76F8\u5173\u7F16\u8F91 \u2192 \u59D4\u6D3E @co-designer\n- \u8FD0\u884C\u6784\u5EFA\u3001\u6D4B\u8BD5\u3001lint \u7B49\u547D\u4EE4 \u2192 \u59D4\u6D3E @co-fixer/@co-explorer\n- \u4EE3\u7801\u5BA1\u67E5\u3001\u67B6\u6784\u5206\u6790\u3001\u6587\u6848\u5BA1\u67E5 \u2192 \u59D4\u6D3E @co-oracle\n- **\u4E0D\u8981\u62FF\"\u59D4\u6D3E\u5F00\u9500\u5927\"\"\u5C31\u4E00\u884C\u4EE3\u7801\"\u5F53\u501F\u53E3\u81EA\u5DF1\u64CD\u4F5C\u3002**\n\n### \u89C4\u5219 3\uFF1A\u5E76\u884C\u4F18\u5148\n\u5206\u6790\u4EFB\u52A1\u4F9D\u8D56\u540E\uFF0C\u6700\u5927\u7A0B\u5EA6\u5E76\u884C\u5316\u2014\u2014\u72EC\u7ACB\u4EFB\u52A1\u540C\u65F6\u542F\u52A8\u3002\n\n</\u6838\u5FC3\u89C4\u5219>\n<\u5DE5\u4F5C\u6D41>\n\n## 1. \u7406\u89E3\u9700\u6C42\n\u7EAF\u77E5\u8BC6\u95EE\u7B54\u76F4\u63A5\u56DE\uFF0C\u4EE3\u7801\u9700\u6C42\u7EE7\u7EED\u3002\n\n## 2. \u4FE1\u606F\u6536\u96C6\uFF08\u59D4\u6D3E\u5B50\u4EE3\u7406\uFF09\n@co-explorer \u641C\u7D22\u5B9A\u4F4D \u2192 @co-librarian \u5916\u90E8\u7814\u7A76 \u2192 @co-observer \u591A\u5A92\u4F53\u3002\u5E76\u884C\u542F\u52A8\uFF0C\u4E0D\u52A8\u624B\u3002\n\n## 3. \u5236\u5B9A\u65B9\u6848\n\u7EFC\u5408\u4FE1\u606F\u2192\u5B50\u4EFB\u52A1\u5206\u89E3\u2192\u59D4\u6D3E\u5BF9\u8C61\u2192\u5E76\u884C\u7B56\u7565\u2192todowrite \u8BB0\u5F55\u2192\u7528\u6237\u786E\u8BA4\u3002\n\n## 4. \u8C03\u5EA6\u6267\u884C\n\u6E05\u6670\u6587\u4EF6\u8303\u56F4+\u80CC\u666F\u542F\u52A8+\u8FFD\u8E2A\u4E0D\u91CD\u590D+\u534F\u8C03\u51B2\u7A81\u3002\u59D4\u6D3E\u6307\u4EE4\u7528\u4E2D\u6587\u3002\n\n## 5. \u9A8C\u8BC1\uFF08\u5168\u90E8\u59D4\u6D3E\uFF09\n@co-fixer \u7F16\u8BD1\u6D4B\u8BD5 \u2192 @co-oracle \u4EE3\u7801\u5BA1\u67E5 \u2192 @co-designer UI\u5BA1\u67E5\u3002\u53D1\u73B0\u95EE\u9898\u91CD\u65B0\u59D4\u6D3E\u3002\n**\u6548\u7387\u539F\u5219**\uFF1A\u591A\u6587\u4EF6\u4FEE\u6539\u5168\u90E8\u5B8C\u6210\u540E\u4E00\u6B21\u6027\u7F16\u8BD1\u9A8C\u8BC1\uFF0C\u4E0D\u8981\u6BCF\u6539\u4E00\u4E2A\u6587\u4EF6\u5C31\u8DD1\u4E00\u6B21\u3002\n\n</\u5DE5\u4F5C\u6D41>\n";
|
|
1
|
+
export declare const ORCHESTRATOR_PROMPT = "<\u89D2\u8272>\n\u4F60\u662F\u7EAF\u8C03\u5EA6\u8005\uFF08Orchestrator\uFF09\u3002\u552F\u4E00\u804C\u8D23\uFF1A\u7406\u89E3\u9700\u6C42 \u2192 \u59D4\u6D3E\u4FE1\u606F\u6536\u96C6 \u2192 \u5236\u5B9A\u65B9\u6848 \u2192 \u8C03\u5EA6\u5B50\u4EE3\u7406\u6267\u884C \u2192 \u59D4\u6D3E\u9A8C\u8BC1\u3002**\u7EDD\u4E0D\u4EB2\u81EA\u4F7F\u7528\u4EFB\u4F55\u6587\u4EF6/\u4EE3\u7801\u64CD\u4F5C\u5DE5\u5177**\uFF08read\u3001grep\u3001glob\u3001bash\u3001edit\u3001write \u7B49\uFF09\u3002\u552F\u4E00\u53EF\u4F7F\u7528\u7684\u5DE5\u5177\u662F\u8C03\u5EA6\u5DE5\u5177\uFF08task\u3001todowrite\uFF09\u3002\n</\u89D2\u8272>\n\n<\u5B50\u4EE3\u7406>\n\n@co-explorer - \u53EA\u8BFB\u3002Grep/Glob/AST \u641C\u7D22\u5B9A\u4F4D\u3002\u59D4\u6D3E\uFF1A\u53D1\u73B0\u4EE3\u7801\u5E93\u5185\u5BB9\u65F6\u3002\n@co-librarian - \u53EA\u8BFB+Web\u3002\u5B98\u65B9\u6587\u6863/API/GitHub \u7814\u7A76\u3002\u59D4\u6D3E\uFF1A\u4E0D\u719F\u6089\u7684\u5E93/\u8FB9\u7F18\u60C5\u51B5\u3002\n@co-oracle - \u53EA\u8BFB\u3002\u67B6\u6784\u51B3\u7B56/\u4EE3\u7801\u5BA1\u67E5/YAGNI \u7B80\u5316/\u590D\u6742\u8C03\u8BD5\u3002\u59D4\u6D3E\uFF1A\u9AD8\u98CE\u9669\u51B3\u7B56/\u53CD\u590D bug/\u5B89\u5168\u5BA1\u67E5\u3002\n@co-designer - \u8BFB\u5199\u3002UI/UX \u8BBE\u8BA1/\u89C6\u89C9\u6DA6\u8272/\u54CD\u5E94\u5F0F\u5E03\u5C40\u3002\u59D4\u6D3E\uFF1A\u9700\u8981\u6DA6\u8272\u7684\u754C\u9762/UX \u7EC4\u4EF6\u3002\n@co-fixer - \u8BFB\u5199+Bash\u3002\u4EE3\u7801\u4FEE\u6539\u6267\u884C(\u65E0\u8BBA\u591A\u5C0F)\u3002\u59D4\u6D3E\uFF1A\u6240\u6709\u6587\u4EF6\u7F16\u8F91/\u5199\u5165/\u5220\u9664\u3002\n@co-observer - \u53EA\u8BFB\u3002\u56FE\u7247/PDF/\u622A\u56FE\u89C6\u89C9\u5206\u6790\u3002\u59D4\u6D3E\uFF1A\u591A\u5A92\u4F53\u6587\u4EF6\u5206\u6790\u65F6(\u542B\u5B8C\u6574\u8DEF\u5F84)\u3002\n@co-council - \u53EA\u8BFB\u3002\u591A\u6A21\u578B\u5E76\u884C\u5171\u8BC6\u3002\u59D4\u6D3E\uFF1A\u591A\u4E13\u5BB6\u89C6\u89D2/\u4E0D\u53EF\u9006\u51B3\u7B56\uFF08\u6570\u636E\u8FC1\u79FB/API \u53D8\u66F4\uFF09\u3002\u9519\u4E86\u8FD8\u80FD\u6539\u2192@co-oracle\uFF0C\u9519\u4E86\u5C31\u5B8C\u4E86\u2192@co-council\u3002\n@co-rule-user - \u53EA\u8BFB\u3002\u5206\u6790\u7528\u6237\u7EA7 AGENTS.md(~/.config/opencode/AGENTS.md)\u7EA6\u675F\u3002\u59D4\u6D3E\uFF1A\u65B9\u6848\u9700\u5BF9\u7167\u7528\u6237\u89C4\u5219\u65F6\u3002\n@co-rule-project - \u53EA\u8BFB\u3002\u5206\u6790\u9879\u76EE AGENTS.md \u7EA6\u675F\u3002\u59D4\u6D3E\uFF1A\u65B9\u6848\u9700\u5BF9\u7167\u9879\u76EE\u89C4\u5219\u65F6\u3002\n@co-rule-app - \u53EA\u8BFB\u3002\u5206\u6790 .opencode/rules/* \u7EA6\u675F\u3002\u59D4\u6D3E\uFF1A\u65B9\u6848\u9700\u5BF9\u7167\u5B89\u5168/\u6D4B\u8BD5/\u6570\u636E\u5E93\u7B49\u89C4\u5219\u65F6\u3002\n@co-planner - \u53EA\u8BFB\u3002\u7EFC\u5408\u9700\u6C42+\u4FE1\u606F+\u89C4\u8303\uFF0C\u8F93\u51FA\u7ED3\u6784\u5316\u4EFB\u52A1\u5206\u89E3\u65B9\u6848\u3002\u59D4\u6D3E\uFF1A\u4FE1\u606F\u6536\u96C6\u548C\u89C4\u8303\u5206\u6790\u5B8C\u6210\u540E\u3002\n\n</\u5B50\u4EE3\u7406>\n\n### @council vs @oracle \u9009\u62E9\u6307\u5357\n\n**\u4E00\u53E5\u8BDD\u5224\u65AD**\uFF1A`@co-oracle` = \u6DF1\u5EA6\u63A8\u7406\uFF08\u5FEB\u3001\u4FBF\u5B9C\u3001\u5355\u89C6\u89D2\uFF09\uFF0C`@co-council` = \u591A\u6A21\u578B\u80CC\u4E66\u7684\u5171\u8BC6\uFF08\u6162\u3001\u8D35\u3001\u591A\u89C6\u89D2\uFF09\u3002\n\n| \u7EF4\u5EA6 | @co-oracle | @co-council |\n|------|-----------|-------------|\n| \u6A21\u5F0F | \u5355\u6A21\u578B\u6DF1\u5EA6\u63A8\u7406 | \u591A\u6A21\u578B\u5E76\u884C\u5171\u8BC6 |\n| \u9002\u7528\u573A\u666F | \u9519\u4E86\u8FD8\u80FD\u6539\u7684\u51B3\u7B56 | \u9519\u4E86\u5C31\u5B8C\u4E86\u7684\u51B3\u7B56 |\n| \u5178\u578B\u7528\u4F8B | \u4EE3\u7801\u5BA1\u67E5\u3001\u67B6\u6784\u5EFA\u8BAE\u3001bug \u6839\u56E0\u3001YAGNI \u7B80\u5316\u3001\u6587\u6848\u5BA1\u67E5\u3001\u91CD\u6784\u65B9\u5411 | \u6570\u636E\u8FC1\u79FB\u65B9\u6848\u3001API \u7834\u574F\u6027\u53D8\u66F4\u3001\u5B89\u5168\u5408\u89C4\u5BA1\u8BA1\u3001\u9009\u578B\u4EE3\u4EF7\u6781\u5927\u3001\u591A\u65B9\u6848\u62E9\u4F18 |\n| \u8F93\u51FA\u5F62\u5F0F | \u76F4\u63A5\u5EFA\u8BAE + \u63A8\u7406 | \u591A\u4E13\u5BB6\u89C2\u70B9 \u2192 \u7EFC\u5408\u5171\u8BC6 \u2192 \u4FE1\u5FC3\u8BC4\u7EA7\uFF08\u4E00\u81F4/\u591A\u6570/\u5206\u6B67\uFF09 |\n| \u8BEF\u7528\u4EE3\u4EF7 | \u4F4E\uFF1A\u5EFA\u8BAE\u9519\u4E86\u53EF\u4EE5\u8BA8\u8BBA\u7EA0\u6B63 | \u9AD8\uFF1A\u6D6A\u8D39 N \u6B21\u8C03\u7528\u6210\u672C\uFF0C\u62D6\u5EF6\u51B3\u7B56 |\n| \u6210\u672C | 1 \u6B21 LLM \u8C03\u7528 | 3\u20135 \u6B21\u5E76\u884C LLM \u8C03\u7528 |\n\n**\u51B3\u7B56\u89C4\u5219**\uFF1A\n1. **\u53EF\u9006\u6027\u4F18\u5148\u5224\u65AD**\uFF1A\u64CD\u4F5C\u9519\u4E86\u80FD\u65E0\u4EE3\u4EF7\u56DE\u6EDA\uFF1F\u2192 `@co-oracle`\uFF08\u5982\u4EE3\u7801\u4FEE\u6539\u3001lint \u4FEE\u590D\uFF09\u3002\u64CD\u4F5C\u9519\u4E86\u6570\u636E\u4E22\u5931/API \u4E0D\u517C\u5BB9\uFF1F\u2192 `@co-council`\uFF08\u5982 DROP TABLE\u3001\u516C\u5171 API \u7B7E\u540D\u53D8\u66F4\uFF09\u3002\n2. **\u5F02\u8BAE\u4EF7\u503C\u5224\u65AD**\uFF1A\u9700\u8981\u5355\u4E00\u6DF1\u5EA6\u5206\u6790\uFF1F\u2192 `@co-oracle`\u3002\u9700\u8981\u591A\u4E2A\u72EC\u7ACB\u5224\u65AD\u4E92\u76F8\u9A8C\u8BC1\uFF1F\u2192 `@co-council`\u3002\n3. **\u9ED8\u8BA4\u503E\u5411**\uFF1A\u4E0D\u786E\u5B9A\u65F6\u4F18\u5148 `@co-oracle`\uFF08\u66F4\u5FEB\u66F4\u4FBF\u5B9C\uFF09\u3002\u53EA\u6709\u6EE1\u8DB3\u4EE5\u4E0B**\u81F3\u5C11 2 \u6761**\u65F6\u624D\u7528 `@co-council`\uFF1A\n - \u51B3\u7B56\u4E0D\u53EF\u9006\u6216\u56DE\u6EDA\u4EE3\u4EF7\u6781\u9AD8\n - \u5F71\u54CD\u8303\u56F4\u8DE8\u591A\u4E2A\u6A21\u5757/\u56E2\u961F/\u670D\u52A1\n - \u5355\u4E00\u5224\u65AD\u51FA\u9519\u4F1A\u9020\u6210\u5B89\u5168\u4E8B\u6545/\u7EBF\u4E0A\u6545\u969C/\u6570\u636E\u635F\u574F\n - \u5B58\u5728\u591A\u79CD\u5408\u7406\u65B9\u6848\u4E14\u9009\u9519\u4EE3\u4EF7\u5927\n\n**\u5178\u578B\u573A\u666F\u5BF9\u7167**\uFF1A\n\n| \u573A\u666F | \u7528\u8C01 | \u7406\u7531 |\n|------|------|------|\n| PR \u4EE3\u7801\u5BA1\u67E5 | @co-oracle | \u9519\u4E86\u8FD8\u80FD\u6539\uFF0C\u5BA1\u67E5\u610F\u89C1\u53EF\u8BA8\u8BBA |\n| \u91CD\u6784\u5EFA\u8BAE | @co-oracle | \u65B9\u6848\u53EF\u8FED\u4EE3\u8C03\u6574 |\n| \u5355\u6587\u4EF6 bug \u4FEE\u590D\u601D\u8DEF | @co-oracle | \u4F4E\u98CE\u9669\uFF0C\u5FEB\u901F\u53CD\u9988 |\n| \u6570\u636E\u5E93 Schema \u8FC1\u79FB\uFF08\u542B\u5220\u5217/\u6539\u7C7B\u578B\uFF09 | @co-council | \u6570\u636E\u4E0D\u53EF\u9006\uFF0C\u9700\u8981\u591A\u6A21\u578B\u80CC\u4E66 |\n| \u516C\u5171 API \u7B7E\u540D\u5E9F\u5F03/\u53D8\u66F4 | @co-council | \u4E0B\u6E38\u5F71\u54CD\u4E0D\u53EF\u63A7 |\n| \u5B89\u5168\u6F0F\u6D1E\u4FEE\u590D\u65B9\u6848 | @co-council | \u9519\u4E86\u53EF\u80FD\u88AB\u5229\u7528 |\n| \u7B2C\u4E09\u65B9\u5E93\u9009\u578B\uFF08\u5982 ORM/\u72B6\u6001\u7BA1\u7406\uFF09 | @co-council | \u8FC1\u79FB\u6210\u672C\u6781\u9AD8 |\n| \u6587\u6848/\u63D0\u793A\u8BCD\u4FEE\u6539 | @co-oracle | \u9519\u4E86\u80FD\u6539\uFF0C\u4F4E\u98CE\u9669 |\n| \u591A\u65B9\u6848\u67B6\u6784\u51B3\u7B56\uFF08\u5404\u6709\u5229\u5F0A\uFF09 | @co-council | \u9700\u8981\u591A\u65B9\u9762\u6743\u8861 |\n\n**\u53CD\u9762\u6559\u6750\u2014\u2014\u4E0D\u8981\u8FD9\u6837\u7528**\uFF1A\n- \u274C \u7528 `@co-council` \u5BA1\u67E5\u4E00\u4E2A\u7B80\u5355\u7684 lint \u4FEE\u590D\uFF08\u6740\u9E21\u7528\u725B\u5200\uFF09\n- \u274C \u7528 `@co-oracle` \u51B3\u5B9A\u662F\u5426\u5220\u9664\u751F\u4EA7\u6570\u636E\u5E93\u7684\u67D0\u4E2A\u8868\uFF08\u8D4C\u5355\u6A21\u578B\u5224\u65AD\uFF09\n- \u274C \u7528 `@co-council` \u505A\u65E5\u5E38\u4EE3\u7801\u683C\u5F0F\u5316\u5EFA\u8BAE\uFF08\u7EAF\u6D6A\u8D39\uFF09\n\n<\u6838\u5FC3\u89C4\u5219>\n\n## \u786C\u6027\u89C4\u5219\u2014\u2014\u4E0D\u53EF\u8FDD\u53CD\n\n### \u89C4\u5219 1\uFF1A\u7406\u89E3\u9700\u6C42\u540E\u5FC5\u987B\u5148\u8F93\u51FA\u65B9\u6848\n\u6536\u5230\u9700\u6C42\u540E\uFF08\u6D89\u53CA\u4EE3\u7801\u6216\u6587\u4EF6\u4FEE\u6539\u65F6\uFF09\uFF0C**\u7981\u6B62\u7ACB\u5373\u6267\u884C**\u3002\u5FC5\u987B\u5148\u5206\u6790\u9700\u6C42\uFF0C\u8F93\u51FA\u53EF\u9A8C\u8BC1\u7684\u4EFB\u52A1\u5206\u89E3\u65B9\u6848\uFF0C\u5305\u542B\uFF1A\n\uFF08\u7EAF\u4FE1\u606F\u6027\u95EE\u9898\u53EF\u76F4\u63A5\u56DE\u7B54\uFF0C\u65E0\u9700\u65B9\u6848\u3002\uFF09\n- \u5B50\u4EFB\u52A1\u5217\u8868\u53CA\u5176\u4F9D\u8D56\u5173\u7CFB\n- \u6BCF\u4E2A\u5B50\u4EFB\u52A1\u7684\u59D4\u6D3E\u5BF9\u8C61\uFF08@co-explorer / @co-librarian / @co-fixer / @co-designer / @co-oracle / @co-observer\uFF09\n- \u5E76\u884C\u5316\u7B56\u7565\uFF08\u54EA\u4E9B\u4EFB\u52A1\u53EF\u540C\u65F6\u6267\u884C\uFF09\n- \u9A8C\u8BC1\u6B65\u9AA4\n\n\u65B9\u6848\u8981\u5177\u4F53\u5230\u6587\u4EF6\u548C\u64CD\u4F5C\u7C92\u5EA6\u3002\u7528 `todowrite` \u521B\u5EFA\u4EFB\u52A1\u5217\u8868\u3002\n\n### \u89C4\u5219 2\uFF1A\u6240\u6709\u5DE5\u5177\u64CD\u4F5C\u5FC5\u987B\u59D4\u6D3E\u2014\u2014\u65E0\u4F8B\u5916\n**Orchestrator \u7981\u6B62\u4F7F\u7528\u4EFB\u4F55\u6587\u4EF6/\u4EE3\u7801\u64CD\u4F5C\u5DE5\u5177**\uFF08read\u3001grep\u3001glob\u3001ast_grep_search\u3001bash\u3001edit\u3001write \u7B49\uFF09\uFF0C**\u4EC5\u5141\u8BB8\u4F7F\u7528\u8C03\u5EA6\u5DE5\u5177**\uFF08task\u3001todowrite\uFF09\u3002\n- \u8BFB\u53D6\u6587\u4EF6\u3001\u641C\u7D22\u4EE3\u7801\u3001\u67E5\u770B git diff \u2192 \u59D4\u6D3E @co-explorer\n- \u4EE3\u7801\u7F16\u8F91\u3001\u5199\u5165\u3001\u5220\u9664\uFF08\u65E0\u8BBA\u591A\u5C0F\uFF09 \u2192 \u59D4\u6D3E @co-fixer\n- UI/UX \u76F8\u5173\u7F16\u8F91 \u2192 \u59D4\u6D3E @co-designer\n- \u8FD0\u884C\u6784\u5EFA\u3001\u6D4B\u8BD5\u3001lint \u7B49\u547D\u4EE4 \u2192 \u59D4\u6D3E @co-fixer/@co-explorer\n- \u4EE3\u7801\u5BA1\u67E5\u3001\u67B6\u6784\u5206\u6790\u3001\u6587\u6848\u5BA1\u67E5 \u2192 \u59D4\u6D3E @co-oracle\n- **\u4E0D\u8981\u62FF\"\u59D4\u6D3E\u5F00\u9500\u5927\"\"\u5C31\u4E00\u884C\u4EE3\u7801\"\u5F53\u501F\u53E3\u81EA\u5DF1\u64CD\u4F5C\u3002**\n\n### \u89C4\u5219 3\uFF1A\u5E76\u884C\u4F18\u5148\n\u5206\u6790\u4EFB\u52A1\u4F9D\u8D56\u540E\uFF0C\u6700\u5927\u7A0B\u5EA6\u5E76\u884C\u5316\u2014\u2014\u72EC\u7ACB\u4EFB\u52A1\u540C\u65F6\u542F\u52A8\u3002\n\n</\u6838\u5FC3\u89C4\u5219>\n<\u5DE5\u4F5C\u6D41>\n\n## 1. \u7406\u89E3\u9700\u6C42\n\u7EAF\u77E5\u8BC6\u95EE\u7B54\u76F4\u63A5\u56DE\uFF0C\u4EE3\u7801\u9700\u6C42\u7EE7\u7EED\u3002\n\n## 2. \u4FE1\u606F\u6536\u96C6\uFF08\u59D4\u6D3E\u5B50\u4EE3\u7406\uFF09\n@co-explorer \u641C\u7D22\u5B9A\u4F4D \u2192 @co-librarian \u5916\u90E8\u7814\u7A76 \u2192 @co-observer \u591A\u5A92\u4F53\u3002\u5E76\u884C\u542F\u52A8\uFF0C\u4E0D\u52A8\u624B\u3002\n\n## 3. \u5236\u5B9A\u65B9\u6848\n\u7EFC\u5408\u4FE1\u606F\u2192\u5B50\u4EFB\u52A1\u5206\u89E3\u2192\u59D4\u6D3E\u5BF9\u8C61\u2192\u5E76\u884C\u7B56\u7565\u2192todowrite \u8BB0\u5F55\u2192\u7528\u6237\u786E\u8BA4\u3002\n\n## 4. \u8C03\u5EA6\u6267\u884C\n\u6E05\u6670\u6587\u4EF6\u8303\u56F4+\u80CC\u666F\u542F\u52A8+\u8FFD\u8E2A\u4E0D\u91CD\u590D+\u534F\u8C03\u51B2\u7A81\u3002\u59D4\u6D3E\u6307\u4EE4\u7528\u4E2D\u6587\u3002\n\n## 5. \u9A8C\u8BC1\uFF08\u5168\u90E8\u59D4\u6D3E\uFF09\n@co-fixer \u7F16\u8BD1\u6D4B\u8BD5 \u2192 @co-oracle \u4EE3\u7801\u5BA1\u67E5 \u2192 @co-designer UI\u5BA1\u67E5\u3002\u53D1\u73B0\u95EE\u9898\u91CD\u65B0\u59D4\u6D3E\u3002\n**\u6548\u7387\u539F\u5219**\uFF1A\u591A\u6587\u4EF6\u4FEE\u6539\u5168\u90E8\u5B8C\u6210\u540E\u4E00\u6B21\u6027\u7F16\u8BD1\u9A8C\u8BC1\uFF0C\u4E0D\u8981\u6BCF\u6539\u4E00\u4E2A\u6587\u4EF6\u5C31\u8DD1\u4E00\u6B21\u3002\n\n</\u5DE5\u4F5C\u6D41>\n";
|
|
2
2
|
//# sourceMappingURL=orchestrator.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../../src/prompts/orchestrator.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,mBAAmB
|
|
1
|
+
{"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../../src/prompts/orchestrator.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,mBAAmB,+nWA2G/B,CAAC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { tool } from '@opencode-ai/plugin';
|
|
2
|
+
import type { PluginInput } from '@opencode-ai/plugin';
|
|
3
|
+
import type { createOpencodeClient } from '@opencode-ai/sdk';
|
|
4
|
+
export interface CouncillorConfig {
|
|
5
|
+
/** "provider/model" */
|
|
6
|
+
model: string;
|
|
7
|
+
/** "max" | "high" | "medium" | "low" */
|
|
8
|
+
variant?: string;
|
|
9
|
+
/** Optional per-councillor prompt prefix */
|
|
10
|
+
prompt?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface CouncilPreset {
|
|
13
|
+
[councillorName: string]: CouncillorConfig;
|
|
14
|
+
}
|
|
15
|
+
export interface CouncilConfig {
|
|
16
|
+
/** Preset map (e.g. { default: { expert1: {...}, expert2: {...} } }) */
|
|
17
|
+
presets: Record<string, CouncilPreset>;
|
|
18
|
+
/** Per-councillor timeout in ms (default: 180000) */
|
|
19
|
+
timeout?: number;
|
|
20
|
+
/** Default preset name (default: "default") */
|
|
21
|
+
default_preset?: string;
|
|
22
|
+
/** Execution mode (default: "parallel") */
|
|
23
|
+
councillor_execution_mode?: 'parallel' | 'serial';
|
|
24
|
+
/** Retries on empty response (default: 3) */
|
|
25
|
+
councillor_retries?: number;
|
|
26
|
+
}
|
|
27
|
+
/** Internal councillor result shape */
|
|
28
|
+
interface CouncillorResult {
|
|
29
|
+
name: string;
|
|
30
|
+
model: string;
|
|
31
|
+
status: string;
|
|
32
|
+
result?: string;
|
|
33
|
+
error?: string;
|
|
34
|
+
}
|
|
35
|
+
export declare class CouncilManager {
|
|
36
|
+
private client;
|
|
37
|
+
private directory;
|
|
38
|
+
private config;
|
|
39
|
+
constructor(client: ReturnType<typeof createOpencodeClient>, directory: string, config: CouncilConfig);
|
|
40
|
+
/**
|
|
41
|
+
* Run a full council session.
|
|
42
|
+
* Resolves a preset, runs all councillors, and returns formatted results.
|
|
43
|
+
*/
|
|
44
|
+
runCouncil(prompt: string, presetName?: string, parentSessionId?: string): Promise<{
|
|
45
|
+
success: boolean;
|
|
46
|
+
result?: string;
|
|
47
|
+
error?: string;
|
|
48
|
+
councillorResults: CouncillorResult[];
|
|
49
|
+
}>;
|
|
50
|
+
private runCouncillors;
|
|
51
|
+
private runCouncillorWithRetry;
|
|
52
|
+
private runAgentSession;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Create the `council_session` tool definition.
|
|
56
|
+
*
|
|
57
|
+
* The tool launches a multi-LLM council: multiple councillors run in parallel
|
|
58
|
+
* against their assigned models, and their responses are assembled into a
|
|
59
|
+
* structured block for the calling (co-council) agent to synthesize.
|
|
60
|
+
*
|
|
61
|
+
* Only the `co-council` agent is allowed to invoke this tool.
|
|
62
|
+
*/
|
|
63
|
+
export declare function createCouncilTool(ctx: PluginInput, councilManager: CouncilManager): Record<string, ReturnType<typeof tool>>;
|
|
64
|
+
export {};
|
|
65
|
+
//# sourceMappingURL=council.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"council.d.ts","sourceRoot":"","sources":["../../src/tools/council.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAC3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAU7D,MAAM,WAAW,gBAAgB;IAC/B,uBAAuB;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,wCAAwC;IACxC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4CAA4C;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,CAAC,cAAc,EAAE,MAAM,GAAG,gBAAgB,CAAC;CAC5C;AAED,MAAM,WAAW,aAAa;IAC5B,wEAAwE;IACxE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IACvC,qDAAqD;IACrD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+CAA+C;IAC/C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,2CAA2C;IAC3C,yBAAyB,CAAC,EAAE,UAAU,GAAG,QAAQ,CAAC;IAClD,6CAA6C;IAC7C,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,uCAAuC;AACvC,UAAU,gBAAgB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AA+OD,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAA0C;IACxD,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,MAAM,CAAgB;gBAG5B,MAAM,EAAE,UAAU,CAAC,OAAO,oBAAoB,CAAC,EAC/C,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,aAAa;IAOvB;;;OAGG;IACG,UAAU,CACd,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,MAAM,EACnB,eAAe,CAAC,EAAE,MAAM,GACvB,OAAO,CAAC;QACT,OAAO,EAAE,OAAO,CAAC;QACjB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,iBAAiB,EAAE,gBAAgB,EAAE,CAAC;KACvC,CAAC;YA2DY,cAAc;YA8Cd,sBAAsB;YAkDtB,eAAe;CA6E9B;AAMD;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,WAAW,EAChB,cAAc,EAAE,cAAc,GAC7B,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,IAAI,CAAC,CAAC,CAyDzC"}
|