oh-my-opencode-cohub 1.18.8 → 1.19.1
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 +26 -14
- package/dist/cli/config-io.d.ts.map +1 -1
- package/dist/cli/index.js +12 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +330 -44
- package/dist/prompts/fixer.d.ts +1 -1
- package/dist/prompts/fixer.d.ts.map +1 -1
- package/dist/prompts/orchestrator-gpt.d.ts +2 -0
- package/dist/prompts/orchestrator-gpt.d.ts.map +1 -0
- package/dist/shared/fs-atomic.d.ts +4 -0
- package/dist/shared/fs-atomic.d.ts.map +1 -1
- package/dist/task-manager/build-lock.d.ts +57 -0
- package/dist/task-manager/build-lock.d.ts.map +1 -0
- package/dist/task-manager/build-lock.test.d.ts +2 -0
- package/dist/task-manager/build-lock.test.d.ts.map +1 -0
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,16 +7,17 @@ OpenCode 中文智能体编排插件 CoHub——纯调度模式、全中文提
|
|
|
7
7
|
## 特性
|
|
8
8
|
|
|
9
9
|
- 🚀 **独立运行**:纯 OpenCode Plugin,依赖 `@opencode-ai/plugin` SDK,零外部插件依赖
|
|
10
|
-
- 🤖 **12
|
|
11
|
-
- 🪝 **自动注入**:通过 `experimental.chat.system.transform` 钩子在每次 LLM 调用时统一注入中文语言要求与并行工具调用总则(覆盖全部
|
|
10
|
+
- 🤖 **12 个专职代理 + 1 个 GPT 专用变体(co-orchestrator-gpt)**:8 个通用代理(orchestrator/oracle/librarian/explorer/designer/fixer/observer/council)+ 4 个规范/方案代理(rule-user/rule-project/rule-app/planner)+ 1 个 GPT 专用 orchestrator 纯调度变体
|
|
11
|
+
- 🪝 **自动注入**:通过 `experimental.chat.system.transform` 钩子在每次 LLM 调用时统一注入中文语言要求与并行工具调用总则(覆盖全部 13 个 agent)
|
|
12
12
|
- 🧠 **纯调度 Orchestrator**:不碰任何文件工具,只负责规划、委派、验证
|
|
13
|
-
- 🇨🇳 **全中文提示词**:
|
|
13
|
+
- 🇨🇳 **全中文提示词**:13 个 agent 全部使用中文提示词
|
|
14
14
|
- 📋 **规范分析代理**:rule-user(用户级 AGENTS.md)、rule-project(从项目根逐级发现 AGENTS.md / CLAUDE.md / AGENTS.local.md / CLAUDE.local.md 及 `.rules/*.md`)、rule-app(定向分析 `.opencode/rules/*.md`)
|
|
15
15
|
- 🎯 **方案制定代理**:planner 综合所有输入输出结构化任务分解
|
|
16
16
|
- 🔗 **编排引擎(Orchestration Engine)**:六状态 DAG 状态机(pending→ready→running→completed/failed→cancelled),诚实镜像原生 task 生命周期(观测/内部状态同步,不激活自动调度/自动重试);级联取消仅同步引擎内部状态,不会自动 abort 其他运行会话
|
|
17
17
|
- ⚡ **Wave 波次并行工作流**:理解→收集→规范分析→制定方案(按依赖分 Wave)→按波次并行调度(区分修改/验证 Wave)→验证,并行与失败处理由主代理显式推进。Wave 仅展示依赖层次,不构成整体等待屏障:任务实际前置依赖完成且无共享可变状态冲突即可派发,同次所有已就绪任务同一消息同时启动,不等无关任务
|
|
18
18
|
- 📜 **AGENTS.md 专用分析代理**:co-rule-user / co-rule-project / co-rule-app 三个专用代理分别分析用户级/项目级 AGENTS.md 与 .opencode/rules,orchestrator 在方案制定前自动委派,分析结果注入执行上下文
|
|
19
19
|
- 📖 **架构借鉴**:插件架构和代理编排理念借鉴了 oh-my-opencode-slim,但完全独立实现、无运行时依赖
|
|
20
|
+
- 🔒 **同工作树构建互斥**:同一 projectDir 下多个 OpenCode 会话并行时,构建类命令(npm/bun/pnpm/yarn build、bun build、tsc、generate-prompts)自动串行加锁;不同 worktree 并行不受影响;建议独立特性使用 `git worktree` 隔离
|
|
20
21
|
|
|
21
22
|
## 安装
|
|
22
23
|
|
|
@@ -90,6 +91,7 @@ npm install oh-my-opencode-cohub
|
|
|
90
91
|
"$schema": "https://unpkg.com/oh-my-opencode-cohub@latest/oh-my-opencode-cohub.schema.json",
|
|
91
92
|
"agents": {
|
|
92
93
|
"co-orchestrator": { "model": "provider/model", "variant": "max" },
|
|
94
|
+
"co-orchestrator-gpt": { "model": "provider/model", "variant": "max" },
|
|
93
95
|
...
|
|
94
96
|
},
|
|
95
97
|
"council": {
|
|
@@ -108,11 +110,12 @@ npm install oh-my-opencode-cohub
|
|
|
108
110
|
}
|
|
109
111
|
```
|
|
110
112
|
|
|
111
|
-
## 12
|
|
113
|
+
## 13 个 agent 配置规则(12 专职 + 1 GPT 变体)
|
|
112
114
|
|
|
113
115
|
| 代理 | 角色 | 推理强度 | variant 建议 | 模型偏好 |
|
|
114
116
|
|------|------|---------|-------------|---------|
|
|
115
117
|
| co-orchestrator | 纯调度者,编排任务、委派执行 | **重型** | max / xhigh | pro、max、sonnet、opus 等强推理模型 |
|
|
118
|
+
| co-orchestrator-gpt | GPT 专用纯调度变体(DS 用户仍用 co-orchestrator) | **重型** | max / xhigh | gpt-5 等 GPT 系强推理模型 |
|
|
116
119
|
| co-oracle | 战略顾问,架构审查、复杂调试 | **轻型** | low / medium | flash、mini、haiku 等轻量快速模型 |
|
|
117
120
|
| co-planner | 方案制定,综合信息输出任务分解 | **轻型** | low / medium | 同上 |
|
|
118
121
|
| co-council | 多模型共识,跨多个 LLM 综合 | **轻型** | low / medium | 同上 |
|
|
@@ -165,14 +168,15 @@ council 是内置的多模型共识机制,会将同一个问题发给 3 个 co
|
|
|
165
168
|
|
|
166
169
|
- 从 opencode.json 读取已配置的 provider,按上表规则为每个代理分配 model 和 variant
|
|
167
170
|
- 只有 1 个 provider:所有代理都用它,variant 按表格建议选不同档位
|
|
168
|
-
- 有多个 provider:co-orchestrator 优先选最强推理 provider,其余代理选最快 provider
|
|
171
|
+
- 有多个 provider:co-orchestrator / co-orchestrator-gpt 优先选最强推理 provider,其余代理选最快 provider
|
|
172
|
+
- 主控代理选择:GPT 系用户选 `co-orchestrator-gpt`,DS 系用户选 `co-orchestrator`;两者权限一致(均可调用 `close_job`)
|
|
169
173
|
- council 的 alpha/beta/gamma 优先选 3 个不同 provider;不够 3 个时用同一 provider 的不同 model
|
|
170
174
|
- opencode.json 无任何 provider 时,生成占位配置并在 `_comment` 字段提示用户先配置
|
|
171
175
|
|
|
172
176
|
## 注意
|
|
173
177
|
|
|
174
178
|
- 只写入 `oh-my-opencode-cohub.json`,不要修改 `opencode.json`
|
|
175
|
-
- agent 名必须用 `co-` 前缀(共
|
|
179
|
+
- agent 名必须用 `co-` 前缀(共 13 个),不要遗漏
|
|
176
180
|
````
|
|
177
181
|
|
|
178
182
|
### 卸载
|
|
@@ -190,7 +194,7 @@ CLI 会精确清理所有 `co-*` 代理和相关配置,不影响其他插件
|
|
|
190
194
|
安装并重启 OpenCode 后,确认以下效果:
|
|
191
195
|
|
|
192
196
|
- 对话中自动出现 **中文语言要求**(如 "你必须始终使用中文进行思考、推理和回复")
|
|
193
|
-
- 可用代理列表中出现
|
|
197
|
+
- 可用代理列表中出现 13 个 `co-*` 前缀 agent(12 专职 + 1 GPT 变体:`co-orchestrator`、`co-orchestrator-gpt`、`co-oracle`、`co-librarian`、`co-explorer`、`co-designer`、`co-fixer`、`co-observer`、`co-council`、`co-rule-user`、`co-rule-project`、`co-rule-app`、`co-planner`)
|
|
194
198
|
- Orchestrator 自动进入纯调度模式(只做规划、委派、验证,不直接操作文件)
|
|
195
199
|
|
|
196
200
|
### 故障排查:代理模型未生效?
|
|
@@ -208,8 +212,8 @@ CLI 会精确清理所有 `co-*` 代理和相关配置,不影响其他插件
|
|
|
208
212
|
|
|
209
213
|
### 第一步:检查 opencode.json 的 agent 条目
|
|
210
214
|
|
|
211
|
-
读取 `~/.config/opencode/opencode.json`,检查 `agent` 字段中是否存在以下
|
|
212
|
-
- co-orchestrator (mode: primary) + 其余 11 个 (mode: subagent)
|
|
215
|
+
读取 `~/.config/opencode/opencode.json`,检查 `agent` 字段中是否存在以下 13 个条目:
|
|
216
|
+
- co-orchestrator、co-orchestrator-gpt (mode: primary) + 其余 11 个 (mode: subagent)
|
|
213
217
|
|
|
214
218
|
如果缺少某些条目,说明插件未正确安装,运行以下命令重新安装:
|
|
215
219
|
```bash
|
|
@@ -232,7 +236,7 @@ bun pm cache rm && bunx oh-my-opencode-cohub@latest install
|
|
|
232
236
|
|
|
233
237
|
### 第三步:验证 config hook(仅诊断)
|
|
234
238
|
|
|
235
|
-
检查 `~/.local/share/opencode/storage/oh-my-opencode-cohub/config-hook-ran.json` 是否存在且 `count` 为
|
|
239
|
+
检查 `~/.local/share/opencode/storage/oh-my-opencode-cohub/config-hook-ran.json` 是否存在且 `count` 为 13。如果不存在或 count < 13,说明插件未正常加载,检查:
|
|
236
240
|
- opencode.json 的 `plugin` 数组是否包含 `"oh-my-opencode-cohub"`
|
|
237
241
|
- OpenCode 版本是否 >= 1.17
|
|
238
242
|
|
|
@@ -252,6 +256,10 @@ bunx oh-my-opencode-cohub uninstall && bun pm cache rm && bunx oh-my-opencode-co
|
|
|
252
256
|
- 随便 @ 某个子代理(如 `@co-explorer 搜索src目录`),确认它能正常工作
|
|
253
257
|
````
|
|
254
258
|
|
|
259
|
+
### 构建互斥与锁目录
|
|
260
|
+
|
|
261
|
+
同一 projectDir 下多个 OpenCode 会话并行构建时,插件自动加互斥锁。锁文件位于 `~/.local/share/opencode/storage/oh-my-opencode-cohub/build-locks/`,由插件自动管理(30 分钟 TTL + 进程陈旧检测),**不要手动删除锁文件**;不同 worktree 的构建互不影响。
|
|
262
|
+
|
|
255
263
|
### 从源码安装(本地开发)
|
|
256
264
|
|
|
257
265
|
如果需要修改源码或使用开发版本:
|
|
@@ -282,11 +290,12 @@ bunx oh-my-opencode-cohub install
|
|
|
282
290
|
|
|
283
291
|
## 代理一览
|
|
284
292
|
|
|
285
|
-
### 代理(
|
|
293
|
+
### 代理(13 个,全中文提示词)
|
|
286
294
|
|
|
287
295
|
| 代理 | 默认模型 | 职责 | 读取源 |
|
|
288
296
|
|------|----------|------|--------|
|
|
289
297
|
| co-orchestrator | `deepseek/deepseek-v4-pro` | 纯调度:规划→委派→验证 | — |
|
|
298
|
+
| co-orchestrator-gpt | `deepseek/deepseek-v4-pro` | GPT 专用纯调度变体:规划→委派→验证(DS 用户仍用 co-orchestrator) | — |
|
|
290
299
|
| co-oracle | `deepseek/deepseek-v4-flash` | 架构审查/代码审查 | — |
|
|
291
300
|
| co-librarian | `deepseek/deepseek-v4-flash` | 外部文档/API 研究 | — |
|
|
292
301
|
| co-explorer | `deepseek/deepseek-v4-flash` | 代码库搜索定位 | — |
|
|
@@ -301,7 +310,7 @@ bunx oh-my-opencode-cohub install
|
|
|
301
310
|
|
|
302
311
|
> **注意**:上表模型为内置兜底值。安装时 CLI 会根据 `opencode.json` 中已配置的 provider 智能匹配并写入 `oh-my-opencode-cohub.json`;若 `opencode.json` 无 provider 则生成占位配置。最终生效模型以 `oh-my-opencode-cohub.json` 为准,也可通过下文「配置文件」或「自定义模型」章节手动覆盖。
|
|
303
312
|
>
|
|
304
|
-
> **工具权限**:`close_job` 仅 co-orchestrator 可调用;`council_session` 仅 co-council 可调用;其余代理配置层 deny,纵深防御。
|
|
313
|
+
> **工具权限**:`close_job` 仅 co-orchestrator 与 co-orchestrator-gpt 可调用;`council_session` 仅 co-council 可调用;其余代理配置层 deny,纵深防御。
|
|
305
314
|
|
|
306
315
|
## 编排引擎
|
|
307
316
|
|
|
@@ -322,7 +331,7 @@ CoHub 内置轻量编排引擎(`src/orchestration/`,6 模块),**诚实
|
|
|
322
331
|
|
|
323
332
|
| 工具 | 可用代理 | 功能 |
|
|
324
333
|
|------|---------|------|
|
|
325
|
-
| `close_job` | 仅 co-orchestrator | 按 Session ID 或任务别名定位后台任务:**已绑定子会话**时执行真实 `session.abort()`(是否真实中止以返回的 `session_aborted` 为准),仅作用于指定目标会话;**未绑定子会话**仅本地取消(状态落 cancelled、`session_aborted=false`,不中止任何会话);未知/歧义目标幂等拒绝,不假成功 |
|
|
334
|
+
| `close_job` | 仅 co-orchestrator / co-orchestrator-gpt | 按 Session ID 或任务别名定位后台任务:**已绑定子会话**时执行真实 `session.abort()`(是否真实中止以返回的 `session_aborted` 为准),仅作用于指定目标会话;**未绑定子会话**仅本地取消(状态落 cancelled、`session_aborted=false`,不中止任何会话);未知/歧义目标幂等拒绝,不假成功 |
|
|
326
335
|
| `council_session` | 仅 co-council | 多模型并行/串行共识:共识检测、空响应重试、质量门禁、退避降级 |
|
|
327
336
|
|
|
328
337
|
### 上下文共享
|
|
@@ -402,6 +411,7 @@ CLI 安装后自动创建 `~/.config/opencode/oh-my-opencode-cohub.json`,这
|
|
|
402
411
|
"$schema": "https://unpkg.com/oh-my-opencode-cohub@latest/oh-my-opencode-cohub.schema.json",
|
|
403
412
|
"agents": {
|
|
404
413
|
"co-orchestrator": { "model": "deepseek/deepseek-v4-pro", "variant": "max" },
|
|
414
|
+
"co-orchestrator-gpt": { "model": "deepseek/deepseek-v4-pro", "variant": "max" },
|
|
405
415
|
"co-oracle": { "model": "deepseek/deepseek-v4-flash", "variant": "low" },
|
|
406
416
|
"co-librarian": { "model": "deepseek/deepseek-v4-flash", "variant": "low" },
|
|
407
417
|
"co-explorer": { "model": "deepseek/deepseek-v4-flash", "variant": "low" },
|
|
@@ -548,7 +558,7 @@ CoHub 采用 Wave 波次分组并行模式。并行与推进由**主代理显式
|
|
|
548
558
|
}
|
|
549
559
|
```
|
|
550
560
|
|
|
551
|
-
支持覆盖的代理名称:`orchestrator`、`oracle`、`librarian`、`explorer`、`designer`、`fixer`、`observer`、`council`、`rule-user`、`rule-project`、`rule-app`、`planner`
|
|
561
|
+
支持覆盖的代理名称:`orchestrator`、`orchestrator-gpt`、`oracle`、`librarian`、`explorer`、`designer`、`fixer`、`observer`、`council`、`rule-user`、`rule-project`、`rule-app`、`planner`
|
|
552
562
|
|
|
553
563
|
### 方式二:文件覆盖(类 oh-my-opencode-slim 机制)
|
|
554
564
|
|
|
@@ -558,6 +568,7 @@ CoHub 采用 Wave 波次分组并行模式。并行与推进由**主代理显式
|
|
|
558
568
|
oh-my-opencode-cohub/
|
|
559
569
|
├── oracle.md ← 完全替换 oracle 提示词
|
|
560
570
|
├── fixer_append.md ← 追加到 fixer 提示词末尾
|
|
571
|
+
├── co-orchestrator-gpt_append.md ← 追加到 co-orchestrator-gpt 提示词末尾
|
|
561
572
|
└── planner.md ← 完全替换 planner 提示词
|
|
562
573
|
```
|
|
563
574
|
|
|
@@ -584,6 +595,7 @@ npm run build
|
|
|
584
595
|
|
|
585
596
|
| 版本 | 日期 | 主要变更 |
|
|
586
597
|
|------|------|---------|
|
|
598
|
+
| 1.19.0 | 2026-10-19 | 新增 `co-orchestrator-gpt`(GPT 专用 orchestrator 纯调度变体,独立 agent,mode: primary);DS 的 `co-orchestrator` 提示词与行为保持不变。GPT 变体采用「先最小修复 → 先定向验证 → 再查漏补缺」节奏;`close_job` 权限扩展至 co-orchestrator-gpt(运行时权限分支 + job-control 纵深防御);CLI 安装模板同步 13 个代理,TUI 兜底列表加入 GPT 变体;文档同步(包 README / 包 AGENTS / .rules/05 / 根 README / 根 AGENTS) |
|
|
587
599
|
| 1.18.4 | 2026-10-16 | README 文档跟进:版本历史补齐 1.18.3 与当前编排语义(诚实镜像原生 task 生命周期,**不激活自动调度/自动重试**);上下文 `summaryReadMode`(`bounded`/`full`)与 opt-in 诊断日志说明;`close_job` 取消边界(已绑定子会话真实 abort / 未绑定仅本地取消)与后台超时清理例外(30 秒检查、30 分钟超时标记 errored)。无运行时代码变更 |
|
|
588
600
|
| 1.18.3 | 2026-10-16 | 编排提示词并发语义修正:移除默认 2-3 / 固定数量 / 强制分批限制,无依赖、无共享可变状态冲突的任务同一条消息同时派发,不以任务/文件数量或猜测容量预限;Wave 仅展示依赖层次不构成等待屏障,已就绪任务同时启动不等无关慢任务;同文件独立只读可并行,仅真实写冲突或要求特定文件版本/读取结果的读写任务按实际冲突与依赖串行;保留 429/TPM 限流反馈(尊重 retry.next / Retry-After)、有限重试、后台已启动任务不重复派发、定向规则分析与已核实事实复用。仅提示词文案调整,无运行时 API / TUI / MCP 变更 |
|
|
589
601
|
| 1.18.2 | 2026-10-16 | 任务生命周期按 `(parentSessionID, callID)` 精确关联与真实收尾;后台任务终态不再仅凭 `session.idle` 判定(有界读取验证明确终态,读失败/无终态信号保持 running 不假成功);`close_job` 真实取消与质量回写;内部状态机诚实镜像原生 task 生命周期(**不激活自动调度/自动重试**);`context.summaryReadMode` 支持 `bounded`(默认)/`full`;限流分类器 + opt-in 任务生命周期诊断 |
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-io.d.ts","sourceRoot":"","sources":["../../src/cli/config-io.ts"],"names":[],"mappings":"AAiJA,gEAAgE;AAChE,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CA0BhG;AAED,2DAA2D;AAC3D,wBAAgB,oBAAoB,IAAI;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAe5E;AAOD;;wDAEwD;AACxD,wBAAgB,mBAAmB,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":"AAiJA,gEAAgE;AAChE,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CA0BhG;AAED,2DAA2D;AAC3D,wBAAgB,oBAAoB,IAAI;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAe5E;AAOD;;wDAEwD;AACxD,wBAAgB,mBAAmB,IAAI;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAyF3E;AA+ED,4DAA4D;AAC5D,wBAAgB,kBAAkB,IAAI;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAwG1E;AAED,8BAA8B;AAC9B,wBAAgB,cAAc,IAAI;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CA2IzE;AAED,qFAAqF;AACrF,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CA6BxF"}
|
package/dist/cli/index.js
CHANGED
|
@@ -11,7 +11,7 @@ import * as path2 from "node:path";
|
|
|
11
11
|
import * as fs from "node:fs";
|
|
12
12
|
import * as path from "node:path";
|
|
13
13
|
function writeFileAtomic(filePath, data) {
|
|
14
|
-
const tmpPath = filePath + ".tmp";
|
|
14
|
+
const tmpPath = filePath + "." + process.pid + "." + Math.random().toString(36).slice(2, 8) + ".tmp";
|
|
15
15
|
const dir = path.dirname(filePath);
|
|
16
16
|
fs.mkdirSync(dir, { recursive: true });
|
|
17
17
|
try {
|
|
@@ -77,7 +77,7 @@ function computeStats(records, window = DEFAULT_STATS_WINDOW) {
|
|
|
77
77
|
return result;
|
|
78
78
|
}
|
|
79
79
|
// package.json
|
|
80
|
-
var version = "1.
|
|
80
|
+
var version = "1.19.1";
|
|
81
81
|
|
|
82
82
|
// src/cli/config-io.ts
|
|
83
83
|
import * as fs2 from "node:fs";
|
|
@@ -308,7 +308,8 @@ function registerCoHubAgents() {
|
|
|
308
308
|
{ name: "co-observer", mode: "subagent", description: "观察者——图片/PDF/截图视觉分析" },
|
|
309
309
|
{ name: "co-rule-user", mode: "subagent", description: "用户规范分析——用户级AGENTS.md" },
|
|
310
310
|
{ name: "co-rule-project", mode: "subagent", description: "项目规范分析——项目AGENTS.md" },
|
|
311
|
-
{ name: "co-rule-app", mode: "subagent", description: "应用规则分析——.opencode/rules/*.md" }
|
|
311
|
+
{ name: "co-rule-app", mode: "subagent", description: "应用规则分析——.opencode/rules/*.md" },
|
|
312
|
+
{ name: "co-orchestrator-gpt", mode: "primary", description: "纯调度者(GPT 变体)——编排任务、委派执行" }
|
|
312
313
|
];
|
|
313
314
|
config.agent = config.agent ?? {};
|
|
314
315
|
const agentTarget = config.agent;
|
|
@@ -423,7 +424,8 @@ function writeDefaultConfig() {
|
|
|
423
424
|
{ name: "co-rule-user", keywords: LIGHT_KEYWORDS, agentType: "rule-user" },
|
|
424
425
|
{ name: "co-rule-project", keywords: LIGHT_KEYWORDS, agentType: "rule-project" },
|
|
425
426
|
{ name: "co-rule-app", keywords: LIGHT_KEYWORDS, agentType: "rule-app" },
|
|
426
|
-
{ name: "co-planner", keywords: LIGHT_KEYWORDS, agentType: "planner" }
|
|
427
|
+
{ name: "co-planner", keywords: LIGHT_KEYWORDS, agentType: "planner" },
|
|
428
|
+
{ name: "co-orchestrator-gpt", keywords: HEAVY_KEYWORDS, agentType: "orchestrator" }
|
|
427
429
|
];
|
|
428
430
|
const agents = {};
|
|
429
431
|
let matched = 0;
|
|
@@ -481,7 +483,7 @@ function writeDefaultConfig() {
|
|
|
481
483
|
};
|
|
482
484
|
try {
|
|
483
485
|
writeJsonFileAtomic(COHUB_CONFIG_PATH, defaultConfig);
|
|
484
|
-
return { success: true, message: `✓ 已智能匹配 ${matched}/
|
|
486
|
+
return { success: true, message: `✓ 已智能匹配 ${matched}/13 个代理的模型,生成 oh-my-opencode-cohub.json` };
|
|
485
487
|
} catch {
|
|
486
488
|
return { success: false, message: "⚠ 无法创建配置文件" };
|
|
487
489
|
}
|
|
@@ -656,8 +658,8 @@ async function main() {
|
|
|
656
658
|
console.log(r4.message);
|
|
657
659
|
console.log(`
|
|
658
660
|
✅ CoHub 安装完成!`);
|
|
659
|
-
console.log(' 重启 OpenCode 后,TAB 选择 "co-orchestrator"
|
|
660
|
-
console.log("
|
|
661
|
+
console.log(' 重启 OpenCode 后,TAB 选择 "co-orchestrator" 主控代理(GPT 用户可选 "co-orchestrator-gpt")。');
|
|
662
|
+
console.log(" 13 个 co-* 代理(12 个专职 + 1 个 GPT 变体)可在对话中通过 @名称 或 task() 派发调用。");
|
|
661
663
|
console.log(" 模型和 variant 配置通过 config hook 从 oh-my-opencode-cohub.json 注入。");
|
|
662
664
|
console.log(`
|
|
663
665
|
${"=".repeat(60)}`);
|
|
@@ -710,11 +712,12 @@ ${"=".repeat(60)}`);
|
|
|
710
712
|
}
|
|
711
713
|
\`\`\`
|
|
712
714
|
|
|
713
|
-
##
|
|
715
|
+
## 13 个代理配置规则
|
|
714
716
|
|
|
715
717
|
| 代理 | 角色 | 推理强度 | variant 建议 | 模型偏好 |
|
|
716
718
|
|------|------|---------|-------------|---------|
|
|
717
719
|
| co-orchestrator | 纯调度者,编排任务、委派执行 | **重型** | max / xhigh | pro、max、sonnet、opus 等强推理模型 |
|
|
720
|
+
| co-orchestrator-gpt | 纯调度者(GPT 变体),与 co-orchestrator 同属主控、GPT 模型专用 | **重型** | max / xhigh | 同上 |
|
|
718
721
|
| co-oracle | 战略顾问,架构审查、复杂调试 | **重型** | max / xhigh | 同上 |
|
|
719
722
|
| co-planner | 方案制定,综合信息输出任务分解 | **重型** | max / xhigh | 同上 |
|
|
720
723
|
| co-council | 多模型共识,跨多个 LLM 综合 | **重型** | high / xhigh | 同上 |
|
|
@@ -774,7 +777,7 @@ council 是内置的多模型共识机制,会将同一个问题发给 3 个 co
|
|
|
774
777
|
## 注意
|
|
775
778
|
|
|
776
779
|
- 只写入 \`oh-my-opencode-cohub.json\`,不要修改 \`opencode.json\`
|
|
777
|
-
- agent 名必须用 \`co-\` 前缀(共
|
|
780
|
+
- agent 名必须用 \`co-\` 前缀(共 13 个),不要遗漏
|
|
778
781
|
`;
|
|
779
782
|
const lines = aiPrompt.trim().split(`
|
|
780
783
|
`);
|
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;AAyIlD,QAAA,MAAM,WAAW,EAAE,MAksClB,CAAC;AAEF,eAAO,MAAM,MAAM,QAAc,CAAC;AAClC,eAAe,WAAW,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -181,6 +181,124 @@ planner 的方案已按 Wave 分组(或你自己审核时重新分组),执
|
|
|
181
181
|
</自检清单>
|
|
182
182
|
`;
|
|
183
183
|
|
|
184
|
+
// src/prompts/orchestrator-gpt.ts
|
|
185
|
+
var ORCHESTRATOR_GPT_PROMPT = `<角色>
|
|
186
|
+
你是纯调度者(GPT 专用变体 Orchestrator)。唯一职责:委派 @co-planner 分诊 → 审核方案 → 按 Wave 调度执行 → 委派验证。**绝不亲自使用任何文件/代码操作工具**(read、grep、glob、bash、edit、write 等),可使用的工具只有调度工具(task、todowrite)。
|
|
187
|
+
</角色>
|
|
188
|
+
|
|
189
|
+
<子代理>
|
|
190
|
+
|
|
191
|
+
@co-explorer - 只读。Grep/Glob/AST 搜索定位。委派:发现代码库内容时。
|
|
192
|
+
@co-librarian - 只读+Web。官方文档/API/GitHub 研究。委派:不熟悉的库/边缘情况。
|
|
193
|
+
@co-oracle - 只读。架构决策/代码审查/YAGNI 简化/复杂调试。委派:高风险决策/反复 bug/安全审查。
|
|
194
|
+
@co-designer - 读写。UI/UX 设计/视觉润色/响应式布局。委派:需要润色的界面/UX 组件。
|
|
195
|
+
@co-fixer - 读写+Bash。代码修改执行(无论多小)。委派:所有文件编辑/写入/删除。
|
|
196
|
+
@co-observer - 只读。图片/PDF/截图视觉分析。委派:多媒体文件分析时(含完整路径)。
|
|
197
|
+
@co-council - 只读。多模型并行共识。委派:多专家视角/不可逆决策(数据迁移/API 变更)。错了还能改→@co-oracle,错了就完了→@co-council。
|
|
198
|
+
@co-rule-user - 只读。分析用户级 AGENTS.md(~/.config/opencode/AGENTS.md)约束。委派:方案需对照用户规则时。
|
|
199
|
+
@co-rule-project - 只读。分析项目 AGENTS.md / .rules/*.md 等仓库级规范。委派:方案需对照项目规则时。
|
|
200
|
+
@co-rule-app - 只读。分析 .opencode/rules/*.md 应用规则。**定向分析**:仅当方案确需对照应用规则时,先判断适用范围;同一任务/同一范围已核实过的规则不重复展开,只在发现新规则文件、规则变更或方案涉足新领域时定向分析相关文件(每个实例在 prompt 中明确指定负责的文件列表,可并行实例同条消息同时派发)。**注意**:\`.opencode/rules/\` 是应用级规则,勿与仓库级 \`.rules/*.md\`(归 @co-rule-project)混淆。委派:方案需对照安全/测试/数据库等应用规则时。
|
|
201
|
+
@co-planner - 只读。综合需求+信息+规范,输出结构化任务分解方案,并给出任务级别、阶段划分与验证级别判定。委派:收到需求后先分诊。
|
|
202
|
+
|
|
203
|
+
</子代理>
|
|
204
|
+
|
|
205
|
+
### @council vs @oracle 选择指南
|
|
206
|
+
|
|
207
|
+
**一句话判断**:\`@co-oracle\` = 深度推理(快、便宜、可逆判断),\`@co-council\` = 多模型背书共识(慢、贵、不可逆决策)。
|
|
208
|
+
|
|
209
|
+
orchestrator 委派时可参考上述原则。不确定时,co-oracle 自身会在审查时判断是否需要升级到 council。
|
|
210
|
+
|
|
211
|
+
<工作流>
|
|
212
|
+
|
|
213
|
+
## 1. 分诊交给 @co-planner
|
|
214
|
+
|
|
215
|
+
收到需求后先委派 @co-planner 做快速分诊。纯知识问答可直接回答;纯只读需求(查询/探索/审查类)可按需单次委派并综合,不强迫走完整变更管线;涉及代码/文件修改的需求,planner 的方案中须明确输出:
|
|
216
|
+
|
|
217
|
+
- **任务级别**:\`[trivial]\` / \`[standard]\` / \`[complex]\`(判定标准由 planner 给出)
|
|
218
|
+
- **阶段划分**:长任务拆成可独立验收的阶段,每阶段有验收标准
|
|
219
|
+
- **验证级别**:定向 / 扩大 / 全面,及每级范围
|
|
220
|
+
- **Wave 分组**
|
|
221
|
+
|
|
222
|
+
orchestrator 只审核方案的完整性与可执行性,**不自行判定或修改任务级别、阶段、验证级别**;方案缺项时委派 planner 补充,而不是自己决定。
|
|
223
|
+
|
|
224
|
+
## 2. 批准语义
|
|
225
|
+
|
|
226
|
+
- \`[trivial]\`:planner 标记后直接派发,不等待批准。
|
|
227
|
+
- \`[standard]\` / \`[complex]\`:方案末尾提供一次选项(立即执行 / 修改方案 / 取消),获批后所有 Wave 自动推进,**不再逐波等待批准**。
|
|
228
|
+
- 只有不可逆动作(git push、发布、外部写入、数据迁移)才需要再次向用户确认;本地可逆修改不设额外审批。
|
|
229
|
+
|
|
230
|
+
## 3. 阶段性修复:两阶段节奏
|
|
231
|
+
|
|
232
|
+
按 planner 给定的阶段划分推进(任务级别、阶段、验证级别均由 co-planner 输出,orchestrator 不自评),默认节奏为两个阶段,每个阶段按该阶段验收标准验收:
|
|
233
|
+
|
|
234
|
+
### 阶段 1:先处理、先验证
|
|
235
|
+
|
|
236
|
+
- planner 只给最小可验证修复方案——复现路径、改动点、定向验证命令,不附带完整架构分析。
|
|
237
|
+
- orchestrator 直接派发 @co-fixer 完成最小修复;fixer 完成后立即跑复现用例/受影响测试,拿到真实结果再上报。
|
|
238
|
+
- 本阶段不展开全量回归、不安排完整 oracle/designer 审查,也不反复向用户确认。
|
|
239
|
+
- 需要回滚保障时,由 fixer 先做本地 checkpoint 提交(可回滚);orchestrator 保持纯调度,不自己执行 git。
|
|
240
|
+
|
|
241
|
+
### 阶段 2:查漏补缺
|
|
242
|
+
|
|
243
|
+
- 定向验证通过后,再按影响面扩大验证、补边界/回归测试、做 oracle 审查。
|
|
244
|
+
- 发现问题定向修正,只重验相关范围,不整单重跑。
|
|
245
|
+
- 查漏补缺完成后才进入发布/不可逆动作;push、发布等仍需用户确认。
|
|
246
|
+
|
|
247
|
+
阶段间向用户简报进度,但简报不等于等待批准;失败先看真实退出码/错误消息归因,定向修正最小范围后只重验该阶段。
|
|
248
|
+
|
|
249
|
+
## 4. 验证分级
|
|
250
|
+
|
|
251
|
+
按 planner 指定的级别执行:
|
|
252
|
+
|
|
253
|
+
- **定向**:仅受影响测试集/文件(默认)
|
|
254
|
+
- **扩大**:跨模块/合并前
|
|
255
|
+
- **全面**:complex/发版/用户要求
|
|
256
|
+
|
|
257
|
+
不默认"编译 → oracle + designer 双审查"全链;仅 UI 改动才加 designer。
|
|
258
|
+
|
|
259
|
+
## 5. 调度执行(按 Wave 并行)
|
|
260
|
+
|
|
261
|
+
planner 方案已按 Wave 分组,执行时:
|
|
262
|
+
|
|
263
|
+
1. 从 Wave 1 开始——同一 Wave 内无依赖、无共享可变状态冲突的任务**在同一条消息中同时派发**(不按数量/容量预先分批)
|
|
264
|
+
2. 按实际前置结果推进——一个任务的全部实际前置依赖已完成且无共享可变状态冲突,即可派发,不必等本 Wave/其他 Wave 的无关任务
|
|
265
|
+
3. Wave 只展示依赖层次,不构成整体等待屏障——Wave 1 中已完成的任务所依赖的 Wave 2 任务可立即派发
|
|
266
|
+
|
|
267
|
+
**两层并行**:
|
|
268
|
+
- 单元内工具并行:同一子代理单元内,原生工具支持时同一条消息并行多个 read/grep/glob/查询
|
|
269
|
+
- 单元间代理并行:可独立执行与验收、无实际依赖/写冲突的工作单元同一条消息派发(共享总目标/基础上下文不自动要求合并,不按文件数/操作数拆代理)
|
|
270
|
+
|
|
271
|
+
**修改 Wave 与验证 Wave 分离**:修改 Wave 委派 fixer 时注明"本轮只修改不验证,编译/测试统一在后续 Wave 执行";验证 Wave 正常委派编译/测试。多文件修改全部完成后一次性编译验证,不每改一个文件跑一次。
|
|
272
|
+
|
|
273
|
+
**背压处理**:收到 429/TPM 限流等背压信号时暂停新增同类委派,尊重宿主提供的重试时间(retry.next / Retry-After);不无限重派/轮询,不取消他人任务。
|
|
274
|
+
|
|
275
|
+
**失败重派与根因分析**:失败先分析根因与重试预算,确认先前副作用(已写入文件/已启动后台任务)后再决定重派、降级或换代理;后台已启动的任务不能重复启动。未知状态不能当作成功,以 task 返回结果与宿主通知为准。
|
|
276
|
+
|
|
277
|
+
## 6. 同工作树构建互斥
|
|
278
|
+
|
|
279
|
+
同一工作树(projectDir)多个会话并行时,插件会在 bash hook 中自动识别构建类命令(npm/bun/pnpm/yarn build、bun build、tsc、generate-prompts)并加互斥锁:
|
|
280
|
+
|
|
281
|
+
- fixer 回报构建锁占用(build lock held by ...)时:等待 30-60 秒后重试一次;若仍被占用,说明持有者仍在构建,报告 orchestrator 建议使用独立 git worktree 或继续等待,不要删除锁文件
|
|
282
|
+
- **不要删除** \`~/.local/share/opencode/storage/oh-my-opencode-cohub/build-locks/\` 下的锁文件,也不要并发硬跑
|
|
283
|
+
- 不要把构建拆成小步骤绕过检测
|
|
284
|
+
- 频繁冲突时建议使用独立 \`git worktree\` 隔离
|
|
285
|
+
- orchestrator 纯调度不变:只按 fixer 回报决定重试/等待,不自行处理锁文件
|
|
286
|
+
|
|
287
|
+
## 7. 上下文预算
|
|
288
|
+
|
|
289
|
+
- task_id 复用仅当同一任务紧接续作且原子会话上下文仍必要;跨任务/阶段无须旧历史时新建子会话,prompt 只传目标、相关文件/关键结论、未解决问题
|
|
290
|
+
- 输入 token 软预算默认 200000,仅当最近输入量严格超过阈值时标注"不建议继续复用",优先新会话+交接简报;不强制换 session、不清空历史
|
|
291
|
+
- 委派时要求先定位再定向读大文件;完整日志/证据保留可访问位置(路径/行号),回传结论与必要片段
|
|
292
|
+
|
|
293
|
+
## 8. 反过度防御
|
|
294
|
+
|
|
295
|
+
- 不为假设风险追加额外确认、拆分或警告;完成标准以方案验收条件为准
|
|
296
|
+
- 不反复汇报中间步骤,不因"可能有问题"而停下;发现问题按阶段归因处理
|
|
297
|
+
- 不自行扩大范围,不修与当前阶段无关的问题
|
|
298
|
+
|
|
299
|
+
</工作流>
|
|
300
|
+
`;
|
|
301
|
+
|
|
184
302
|
// src/prompts/oracle.ts
|
|
185
303
|
var ORACLE_PROMPT = `你是 Oracle——战略技术顾问和代码审查者。
|
|
186
304
|
|
|
@@ -499,6 +617,7 @@ var FIXER_PROMPT = `你是 Fixer——快速、聚焦的实现专家。
|
|
|
499
617
|
- **单文件独立任务或被明确要求时**:运行相关验证(编译/测试/lint),否则注明跳过及原因
|
|
500
618
|
- **执行指定验证范围,不自行扩大全量**:验证范围以 orchestrator 委派指令为准(如定向测试集/全量测试),只执行指定范围,不擅自扩大到未指定的测试套件;确需扩大时,在报告中说明目的与扩大范围,交由 orchestrator 决策
|
|
501
619
|
- **报告失败与复验理由**:验证失败时不截断错误、保留可访问位置(保存路径/行号),回传失败归因与建议的复验范围;代码/测试/配置/环境状态与验证目标未变、无新理由时不重复验证——报告/复用已知结果
|
|
620
|
+
- **构建锁占用**:执行构建命令时若收到锁占用错误(build lock held by ...),不要删除锁文件或并发硬跑;等待 30-60 秒后重试一次;若仍被占用,说明持有者仍在构建,报告 orchestrator 建议使用独立 \`git worktree\` 或继续等待,不要删除锁文件
|
|
502
621
|
- 日志与证据:测试/构建失败与错误信息**不截断**;长日志保留可访问位置(保存路径/行号),回传结论与关键片段,不整段复制大日志入上下文
|
|
503
622
|
- 完成后报告变更摘要
|
|
504
623
|
|
|
@@ -813,7 +932,7 @@ import * as path2 from "node:path";
|
|
|
813
932
|
import * as fs from "node:fs";
|
|
814
933
|
import * as path from "node:path";
|
|
815
934
|
function writeFileAtomic(filePath, data) {
|
|
816
|
-
const tmpPath = filePath + ".tmp";
|
|
935
|
+
const tmpPath = filePath + "." + process.pid + "." + Math.random().toString(36).slice(2, 8) + ".tmp";
|
|
817
936
|
const dir = path.dirname(filePath);
|
|
818
937
|
fs.mkdirSync(dir, { recursive: true });
|
|
819
938
|
try {
|
|
@@ -1418,6 +1537,148 @@ class TaskTracker {
|
|
|
1418
1537
|
}
|
|
1419
1538
|
}
|
|
1420
1539
|
|
|
1540
|
+
// src/task-manager/build-lock.ts
|
|
1541
|
+
import * as crypto2 from "node:crypto";
|
|
1542
|
+
import * as fs2 from "node:fs";
|
|
1543
|
+
import * as path3 from "node:path";
|
|
1544
|
+
|
|
1545
|
+
class BuildLockError extends Error {
|
|
1546
|
+
}
|
|
1547
|
+
var DEFAULT_TTL_MS = 30 * 60 * 1000;
|
|
1548
|
+
function resolveLockPath(stateDir, projectDir) {
|
|
1549
|
+
const key = crypto2.createHash("sha256").update(path3.resolve(projectDir)).digest("hex").slice(0, 16);
|
|
1550
|
+
return path3.join(stateDir, "build-locks", `${key}.lock`);
|
|
1551
|
+
}
|
|
1552
|
+
function isPidAlive(pid) {
|
|
1553
|
+
try {
|
|
1554
|
+
process.kill(pid, 0);
|
|
1555
|
+
return true;
|
|
1556
|
+
} catch (err) {
|
|
1557
|
+
return err.code === "EPERM";
|
|
1558
|
+
}
|
|
1559
|
+
}
|
|
1560
|
+
function readLock(lockPath) {
|
|
1561
|
+
try {
|
|
1562
|
+
const raw = fs2.readFileSync(lockPath, "utf-8");
|
|
1563
|
+
const rec = JSON.parse(raw);
|
|
1564
|
+
if (typeof rec.pid !== "number" || typeof rec.acquiredAt !== "number")
|
|
1565
|
+
return;
|
|
1566
|
+
return { ...rec, token: typeof rec.token === "string" ? rec.token : null };
|
|
1567
|
+
} catch {
|
|
1568
|
+
return;
|
|
1569
|
+
}
|
|
1570
|
+
}
|
|
1571
|
+
function isStaleLock(rec, now, ttlMs) {
|
|
1572
|
+
if (!rec)
|
|
1573
|
+
return true;
|
|
1574
|
+
if (!isPidAlive(rec.pid))
|
|
1575
|
+
return true;
|
|
1576
|
+
return now - rec.acquiredAt > ttlMs;
|
|
1577
|
+
}
|
|
1578
|
+
function reclaimStaleLock(lockPath, expectedToken) {
|
|
1579
|
+
const stalePath = `${lockPath}.stale.${process.pid}.${crypto2.randomUUID()}`;
|
|
1580
|
+
let moved = false;
|
|
1581
|
+
try {
|
|
1582
|
+
try {
|
|
1583
|
+
fs2.renameSync(lockPath, stalePath);
|
|
1584
|
+
moved = true;
|
|
1585
|
+
} catch (err) {
|
|
1586
|
+
if (err.code === "ENOENT")
|
|
1587
|
+
return "retryable";
|
|
1588
|
+
throw err;
|
|
1589
|
+
}
|
|
1590
|
+
const movedToken = readLock(stalePath)?.token ?? null;
|
|
1591
|
+
if (movedToken !== expectedToken) {
|
|
1592
|
+
try {
|
|
1593
|
+
fs2.renameSync(stalePath, lockPath);
|
|
1594
|
+
} catch {}
|
|
1595
|
+
return "not-retryable";
|
|
1596
|
+
}
|
|
1597
|
+
fs2.unlinkSync(stalePath);
|
|
1598
|
+
return "retryable";
|
|
1599
|
+
} catch (err) {
|
|
1600
|
+
if (moved) {
|
|
1601
|
+
try {
|
|
1602
|
+
fs2.renameSync(stalePath, lockPath);
|
|
1603
|
+
} catch {}
|
|
1604
|
+
}
|
|
1605
|
+
throw err;
|
|
1606
|
+
}
|
|
1607
|
+
}
|
|
1608
|
+
function acquireBuildLock(opts) {
|
|
1609
|
+
const now = opts.now ?? Date.now();
|
|
1610
|
+
const ttlMs = opts.ttlMs ?? DEFAULT_TTL_MS;
|
|
1611
|
+
const lockPath = resolveLockPath(opts.stateDir, opts.projectDir);
|
|
1612
|
+
fs2.mkdirSync(path3.dirname(lockPath), { recursive: true });
|
|
1613
|
+
for (let attempt = 0;attempt < 2; attempt++) {
|
|
1614
|
+
try {
|
|
1615
|
+
const fd = fs2.openSync(lockPath, "wx");
|
|
1616
|
+
try {
|
|
1617
|
+
const record = {
|
|
1618
|
+
pid: process.pid,
|
|
1619
|
+
sessionID: opts.sessionID,
|
|
1620
|
+
callID: opts.callID,
|
|
1621
|
+
command: opts.command,
|
|
1622
|
+
acquiredAt: now,
|
|
1623
|
+
token: crypto2.randomUUID()
|
|
1624
|
+
};
|
|
1625
|
+
fs2.writeSync(fd, JSON.stringify(record));
|
|
1626
|
+
} finally {
|
|
1627
|
+
fs2.closeSync(fd);
|
|
1628
|
+
}
|
|
1629
|
+
return lockPath;
|
|
1630
|
+
} catch (err) {
|
|
1631
|
+
if (err.code !== "EEXIST")
|
|
1632
|
+
throw err;
|
|
1633
|
+
const rec = readLock(lockPath);
|
|
1634
|
+
if (isStaleLock(rec, now, ttlMs)) {
|
|
1635
|
+
if (reclaimStaleLock(lockPath, rec?.token ?? null) === "retryable")
|
|
1636
|
+
continue;
|
|
1637
|
+
}
|
|
1638
|
+
const holder = readLock(lockPath);
|
|
1639
|
+
throw new BuildLockError(`构建互斥:worktree ${path3.resolve(opts.projectDir)} 上已有进行中的构建(` + `sessionID=${holder?.sessionID ?? "未知"}, callID=${holder?.callID ?? "未知"}, command="${holder?.command ?? "未知"}", ` + `acquiredAt=${holder ? new Date(holder.acquiredAt).toISOString() : "未知"})。` + `请等待其完成(TTL ${Math.round(ttlMs / 60000)} 分钟,持有进程退出后自动失效)或改用独立 worktree 执行构建。`);
|
|
1640
|
+
}
|
|
1641
|
+
}
|
|
1642
|
+
throw new BuildLockError(`构建互斥:无法获取锁 ${lockPath}`);
|
|
1643
|
+
}
|
|
1644
|
+
function releaseBuildLock(opts) {
|
|
1645
|
+
const lockPath = resolveLockPath(opts.stateDir, opts.projectDir);
|
|
1646
|
+
const rec = readLock(lockPath);
|
|
1647
|
+
if (!rec)
|
|
1648
|
+
return false;
|
|
1649
|
+
if (rec.sessionID !== opts.sessionID || rec.callID !== opts.callID)
|
|
1650
|
+
return false;
|
|
1651
|
+
try {
|
|
1652
|
+
fs2.unlinkSync(lockPath);
|
|
1653
|
+
return true;
|
|
1654
|
+
} catch {
|
|
1655
|
+
return false;
|
|
1656
|
+
}
|
|
1657
|
+
}
|
|
1658
|
+
var BUILD_COMMAND_PATTERNS = [
|
|
1659
|
+
/^(?:npm|pnpm|yarn)(?:\s+run)?\s+build(?::[\w-]*)?(?:\s|$)/,
|
|
1660
|
+
/^bun(?:\s+run)?\s+build(?::[\w-]*)?(?:\s|$)/,
|
|
1661
|
+
/^bun(?:\s+run)?\s+\S*generate-prompts\S*(?:\s|$)/,
|
|
1662
|
+
/^(?:npx\s+)?tsc(?:\s|$)/,
|
|
1663
|
+
/^generate-prompts(?:\s|$)/,
|
|
1664
|
+
/^npm\s+run\s+prepublishOnly(?:\s|$)/
|
|
1665
|
+
];
|
|
1666
|
+
function isBuildCommand(command) {
|
|
1667
|
+
if (typeof command !== "string" || command.trim() === "")
|
|
1668
|
+
return false;
|
|
1669
|
+
const segments = command.split(/\s*&&\s*|\s*\|\|\s*|\s*;\s*|\r?\n/);
|
|
1670
|
+
for (const seg of segments) {
|
|
1671
|
+
const trimmed = seg.trim();
|
|
1672
|
+
if (trimmed === "")
|
|
1673
|
+
continue;
|
|
1674
|
+
for (const re of BUILD_COMMAND_PATTERNS) {
|
|
1675
|
+
if (re.test(trimmed))
|
|
1676
|
+
return true;
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1679
|
+
return false;
|
|
1680
|
+
}
|
|
1681
|
+
|
|
1421
1682
|
// src/task-manager/quality.ts
|
|
1422
1683
|
var DEFAULT_QUALITY_CONFIG = {
|
|
1423
1684
|
enabled: true
|
|
@@ -1569,7 +1830,7 @@ function isQualityEnabled(config) {
|
|
|
1569
1830
|
}
|
|
1570
1831
|
|
|
1571
1832
|
// src/context/engine.ts
|
|
1572
|
-
import * as
|
|
1833
|
+
import * as fs3 from "node:fs";
|
|
1573
1834
|
|
|
1574
1835
|
// src/shared/token-estimator.ts
|
|
1575
1836
|
function estimateTokens(text) {
|
|
@@ -1971,7 +2232,7 @@ class ContextEngine {
|
|
|
1971
2232
|
for (const file of files) {
|
|
1972
2233
|
try {
|
|
1973
2234
|
if (this.config.summaryReadMode === "full") {
|
|
1974
|
-
const content =
|
|
2235
|
+
const content = fs3.readFileSync(file.path, "utf-8");
|
|
1975
2236
|
file.body = truncateByTokens(content, budgetPerFile);
|
|
1976
2237
|
} else {
|
|
1977
2238
|
const { text, truncatedByReadLimit } = this.readBoundedUtf8(file.path, tokenBudgetToByteLimit(budgetPerFile));
|
|
@@ -1984,14 +2245,14 @@ class ContextEngine {
|
|
|
1984
2245
|
}
|
|
1985
2246
|
}
|
|
1986
2247
|
readBoundedUtf8(filePath, byteLimit) {
|
|
1987
|
-
const fd =
|
|
2248
|
+
const fd = fs3.openSync(filePath, "r");
|
|
1988
2249
|
try {
|
|
1989
|
-
const { size } =
|
|
2250
|
+
const { size } = fs3.fstatSync(fd);
|
|
1990
2251
|
const toRead = Math.min(size, byteLimit + SUMMARY_READ_LOOKAHEAD_BYTES);
|
|
1991
2252
|
const buf = Buffer.allocUnsafe(Math.max(0, toRead));
|
|
1992
2253
|
let filled = 0;
|
|
1993
2254
|
while (filled < toRead) {
|
|
1994
|
-
const n =
|
|
2255
|
+
const n = fs3.readSync(fd, buf, filled, toRead - filled, filled);
|
|
1995
2256
|
if (n <= 0)
|
|
1996
2257
|
break;
|
|
1997
2258
|
filled += n;
|
|
@@ -2000,7 +2261,7 @@ class ContextEngine {
|
|
|
2000
2261
|
const raw = buf.subarray(0, Math.min(filled, byteLimit));
|
|
2001
2262
|
return { text: utf8TrimIncomplete(raw).toString("utf-8"), truncatedByReadLimit };
|
|
2002
2263
|
} finally {
|
|
2003
|
-
|
|
2264
|
+
fs3.closeSync(fd);
|
|
2004
2265
|
}
|
|
2005
2266
|
}
|
|
2006
2267
|
consumeMarkedContext(messageText) {
|
|
@@ -2258,15 +2519,15 @@ class ContextEngine {
|
|
|
2258
2519
|
}
|
|
2259
2520
|
|
|
2260
2521
|
// src/config/loader.ts
|
|
2261
|
-
import * as
|
|
2262
|
-
import * as
|
|
2522
|
+
import * as fs4 from "node:fs";
|
|
2523
|
+
import * as path4 from "node:path";
|
|
2263
2524
|
import * as os2 from "node:os";
|
|
2264
|
-
var USER_CONFIG_PATH =
|
|
2525
|
+
var USER_CONFIG_PATH = path4.join(os2.homedir(), ".config", "opencode", "oh-my-opencode-cohub.json");
|
|
2265
2526
|
function loadCoHubConfig(projectDir) {
|
|
2266
2527
|
const base = readJSON(USER_CONFIG_PATH);
|
|
2267
2528
|
if (!projectDir)
|
|
2268
2529
|
return base;
|
|
2269
|
-
const projectPath =
|
|
2530
|
+
const projectPath = path4.join(projectDir, ".opencode", "oh-my-opencode-cohub.json");
|
|
2270
2531
|
const project = readJSON(projectPath);
|
|
2271
2532
|
if (!project || Object.keys(project).length === 0)
|
|
2272
2533
|
return base;
|
|
@@ -2299,9 +2560,9 @@ function resolveReuseBudget(config) {
|
|
|
2299
2560
|
}
|
|
2300
2561
|
function readJSON(filePath) {
|
|
2301
2562
|
try {
|
|
2302
|
-
if (!
|
|
2563
|
+
if (!fs4.existsSync(filePath))
|
|
2303
2564
|
return {};
|
|
2304
|
-
const raw =
|
|
2565
|
+
const raw = fs4.readFileSync(filePath, "utf-8");
|
|
2305
2566
|
return JSON.parse(raw);
|
|
2306
2567
|
} catch {
|
|
2307
2568
|
return {};
|
|
@@ -2311,7 +2572,7 @@ function readJSON(filePath) {
|
|
|
2311
2572
|
// src/context/diag-log.ts
|
|
2312
2573
|
import * as fsp from "node:fs/promises";
|
|
2313
2574
|
import * as os3 from "node:os";
|
|
2314
|
-
import * as
|
|
2575
|
+
import * as path5 from "node:path";
|
|
2315
2576
|
var MAX_BYTES = 256 * 1024;
|
|
2316
2577
|
var KEEP_LINES = 30;
|
|
2317
2578
|
var TAIL_WINDOW = 64 * 1024;
|
|
@@ -2333,7 +2594,7 @@ function resolveCtxDiagPath(config) {
|
|
|
2333
2594
|
const custom = config?.path;
|
|
2334
2595
|
if (typeof custom === "string" && custom.trim() !== "")
|
|
2335
2596
|
return custom;
|
|
2336
|
-
return
|
|
2597
|
+
return path5.join(os3.tmpdir(), "opencode", "ctx-diag.log");
|
|
2337
2598
|
}
|
|
2338
2599
|
function resolveCtxDiagSettings(config, env) {
|
|
2339
2600
|
return {
|
|
@@ -2384,7 +2645,7 @@ function appendCtxDiag(record, filePath) {
|
|
|
2384
2645
|
bytesSinceCompact = 0;
|
|
2385
2646
|
queue = queue.then(async () => {
|
|
2386
2647
|
try {
|
|
2387
|
-
await fsp.mkdir(
|
|
2648
|
+
await fsp.mkdir(path5.dirname(filePath), { recursive: true });
|
|
2388
2649
|
if (shouldCompact)
|
|
2389
2650
|
await compactTail(filePath, KEEP_LINES);
|
|
2390
2651
|
await fsp.appendFile(filePath, line, { encoding: "utf-8", mode: 384 });
|
|
@@ -2438,12 +2699,12 @@ import { tool } from "@opencode-ai/plugin";
|
|
|
2438
2699
|
|
|
2439
2700
|
// src/utils/log.ts
|
|
2440
2701
|
import * as os4 from "os";
|
|
2441
|
-
import * as
|
|
2702
|
+
import * as path7 from "path";
|
|
2442
2703
|
|
|
2443
2704
|
// src/shared/log.ts
|
|
2444
|
-
import * as
|
|
2705
|
+
import * as fs5 from "node:fs";
|
|
2445
2706
|
import * as fsp2 from "node:fs/promises";
|
|
2446
|
-
import * as
|
|
2707
|
+
import * as path6 from "node:path";
|
|
2447
2708
|
function createLogger(cfg) {
|
|
2448
2709
|
const logDir = cfg.logDir;
|
|
2449
2710
|
const prefix = cfg.prefix;
|
|
@@ -2456,12 +2717,12 @@ function createLogger(cfg) {
|
|
|
2456
2717
|
let cleanedToday = false;
|
|
2457
2718
|
function getLogPath() {
|
|
2458
2719
|
if (!dailyRotate) {
|
|
2459
|
-
return
|
|
2720
|
+
return path6.join(logDir, `${prefix}.log`);
|
|
2460
2721
|
}
|
|
2461
2722
|
const d = new Date().toISOString().slice(0, 10).replace(/-/g, "");
|
|
2462
2723
|
if (d !== today) {
|
|
2463
2724
|
today = d;
|
|
2464
|
-
logPath =
|
|
2725
|
+
logPath = path6.join(logDir, `${prefix}.${d}.log`);
|
|
2465
2726
|
cleanedToday = false;
|
|
2466
2727
|
}
|
|
2467
2728
|
return logPath;
|
|
@@ -2477,7 +2738,7 @@ function createLogger(cfg) {
|
|
|
2477
2738
|
const cutoff = new Date;
|
|
2478
2739
|
cutoff.setUTCDate(cutoff.getUTCDate() - keepDays);
|
|
2479
2740
|
const cutoffStr = cutoff.toISOString().slice(0, 10).replace(/-/g, "");
|
|
2480
|
-
const files =
|
|
2741
|
+
const files = fs5.readdirSync(logDir);
|
|
2481
2742
|
const escaped = prefix.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2482
2743
|
const re = new RegExp(`^${escaped}\\.(\\d{8})\\.log$`);
|
|
2483
2744
|
for (const file of files) {
|
|
@@ -2486,7 +2747,7 @@ function createLogger(cfg) {
|
|
|
2486
2747
|
continue;
|
|
2487
2748
|
if (match[1] < cutoffStr) {
|
|
2488
2749
|
try {
|
|
2489
|
-
|
|
2750
|
+
fs5.unlinkSync(path6.join(logDir, file));
|
|
2490
2751
|
} catch {}
|
|
2491
2752
|
}
|
|
2492
2753
|
}
|
|
@@ -2522,9 +2783,9 @@ function createLogger(cfg) {
|
|
|
2522
2783
|
function appendLogSync(tag, message, err) {
|
|
2523
2784
|
try {
|
|
2524
2785
|
const lp = getLogPath();
|
|
2525
|
-
|
|
2786
|
+
fs5.mkdirSync(logDir, { recursive: true });
|
|
2526
2787
|
const line = formatLine(tag, message, err);
|
|
2527
|
-
|
|
2788
|
+
fs5.appendFileSync(lp, line, "utf-8");
|
|
2528
2789
|
if (dailyRotate)
|
|
2529
2790
|
cleanOldLogsOnce();
|
|
2530
2791
|
} catch {}
|
|
@@ -2646,7 +2907,7 @@ function classifyRateLimit(error, now) {
|
|
|
2646
2907
|
}
|
|
2647
2908
|
|
|
2648
2909
|
// src/utils/log.ts
|
|
2649
|
-
var LOG_DIR =
|
|
2910
|
+
var LOG_DIR = path7.join(os4.homedir(), ".local", "share", "opencode", "log");
|
|
2650
2911
|
var appendLog = createLogger({
|
|
2651
2912
|
logDir: LOG_DIR,
|
|
2652
2913
|
prefix: "oh-my-opencode-cohub",
|
|
@@ -3494,8 +3755,8 @@ function createCloseJobTool(ctx, tracker, onClosed, onCancelled) {
|
|
|
3494
3755
|
task_id: z2.string().describe("The child session ID (ses_xxx) or task alias (e.g. coe-1) of the task to close.")
|
|
3495
3756
|
},
|
|
3496
3757
|
async execute(args, toolContext) {
|
|
3497
|
-
if (
|
|
3498
|
-
throw new Error(`[oh-my-opencode-cohub] close_job can only be invoked by co-orchestrator. Current agent: ${toolContext.agent}`);
|
|
3758
|
+
if (!["co-orchestrator", "co-orchestrator-gpt"].includes(toolContext.agent)) {
|
|
3759
|
+
throw new Error(`[oh-my-opencode-cohub] close_job can only be invoked by co-orchestrator/co-orchestrator-gpt. Current agent: ${toolContext.agent}`);
|
|
3499
3760
|
}
|
|
3500
3761
|
const target = tracker.resolveCancelTarget(args.task_id);
|
|
3501
3762
|
if (!target.ok) {
|
|
@@ -3566,8 +3827,8 @@ function createCloseJobTool(ctx, tracker, onClosed, onCancelled) {
|
|
|
3566
3827
|
}
|
|
3567
3828
|
|
|
3568
3829
|
// src/index.ts
|
|
3569
|
-
import * as
|
|
3570
|
-
import * as
|
|
3830
|
+
import * as fs6 from "node:fs";
|
|
3831
|
+
import * as path8 from "node:path";
|
|
3571
3832
|
import * as os5 from "node:os";
|
|
3572
3833
|
|
|
3573
3834
|
// src/orchestration/types.ts
|
|
@@ -3960,6 +4221,7 @@ function loadFileOverrides(projectDir) {
|
|
|
3960
4221
|
const overrides = {};
|
|
3961
4222
|
const agentNames = [
|
|
3962
4223
|
"co-orchestrator",
|
|
4224
|
+
"co-orchestrator-gpt",
|
|
3963
4225
|
"co-oracle",
|
|
3964
4226
|
"co-librarian",
|
|
3965
4227
|
"co-explorer",
|
|
@@ -3974,23 +4236,23 @@ function loadFileOverrides(projectDir) {
|
|
|
3974
4236
|
];
|
|
3975
4237
|
const searchDirs = [];
|
|
3976
4238
|
if (projectDir) {
|
|
3977
|
-
searchDirs.push(
|
|
4239
|
+
searchDirs.push(path8.join(projectDir, ".opencode", "oh-my-opencode-cohub"));
|
|
3978
4240
|
}
|
|
3979
|
-
searchDirs.push(
|
|
4241
|
+
searchDirs.push(path8.join(os5.homedir(), ".config", "opencode", "oh-my-opencode-cohub"));
|
|
3980
4242
|
for (const agent of agentNames) {
|
|
3981
4243
|
for (const dir of searchDirs) {
|
|
3982
|
-
const replacePath =
|
|
3983
|
-
if (!overrides[agent]?.replace &&
|
|
4244
|
+
const replacePath = path8.join(dir, `${agent}.md`);
|
|
4245
|
+
if (!overrides[agent]?.replace && fs6.existsSync(replacePath)) {
|
|
3984
4246
|
try {
|
|
3985
|
-
overrides[agent] = { ...overrides[agent], replace:
|
|
4247
|
+
overrides[agent] = { ...overrides[agent], replace: fs6.readFileSync(replacePath, "utf-8") };
|
|
3986
4248
|
} catch (err) {
|
|
3987
4249
|
appendLog("loadFileOverrides", "读取replace文件失败", err);
|
|
3988
4250
|
}
|
|
3989
4251
|
}
|
|
3990
|
-
const appendPath =
|
|
3991
|
-
if (!overrides[agent]?.append &&
|
|
4252
|
+
const appendPath = path8.join(dir, `${agent}_append.md`);
|
|
4253
|
+
if (!overrides[agent]?.append && fs6.existsSync(appendPath)) {
|
|
3992
4254
|
try {
|
|
3993
|
-
overrides[agent] = { ...overrides[agent], append:
|
|
4255
|
+
overrides[agent] = { ...overrides[agent], append: fs6.readFileSync(appendPath, "utf-8") };
|
|
3994
4256
|
} catch (err) {
|
|
3995
4257
|
appendLog("loadFileOverrides", "读取append文件失败", err);
|
|
3996
4258
|
}
|
|
@@ -4023,8 +4285,8 @@ var CoHubPlugin = async (input, options) => {
|
|
|
4023
4285
|
const promptOverrides = { ...configOverrides, ...fileOverrides };
|
|
4024
4286
|
const tracker = new TaskTracker;
|
|
4025
4287
|
const orchestrationLayer = createOrchestrationLayer(tracker, {});
|
|
4026
|
-
const STATE_DIR =
|
|
4027
|
-
const STATE_FILE =
|
|
4288
|
+
const STATE_DIR = path8.join(os5.homedir(), ".local", "share", "opencode", "storage", "oh-my-opencode-cohub");
|
|
4289
|
+
const STATE_FILE = path8.join(STATE_DIR, "tracker-state.json");
|
|
4028
4290
|
function syncTrackerState(sessionId) {
|
|
4029
4291
|
try {
|
|
4030
4292
|
const state = {
|
|
@@ -4035,7 +4297,7 @@ var CoHubPlugin = async (input, options) => {
|
|
|
4035
4297
|
writeFileAtomic(STATE_FILE, JSON.stringify(state));
|
|
4036
4298
|
} catch {}
|
|
4037
4299
|
}
|
|
4038
|
-
const AGENT_CONFIG_FILE =
|
|
4300
|
+
const AGENT_CONFIG_FILE = path8.join(STATE_DIR, "cohub-state.json");
|
|
4039
4301
|
function syncAgentConfig() {
|
|
4040
4302
|
try {
|
|
4041
4303
|
const configs = agents.filter((a) => a.config.model).map((a) => {
|
|
@@ -4060,6 +4322,10 @@ var CoHubPlugin = async (input, options) => {
|
|
|
4060
4322
|
name: "co-orchestrator",
|
|
4061
4323
|
config: { mode: "primary", prompt: ORCHESTRATOR_PROMPT }
|
|
4062
4324
|
},
|
|
4325
|
+
{
|
|
4326
|
+
name: "co-orchestrator-gpt",
|
|
4327
|
+
config: { mode: "primary", prompt: ORCHESTRATOR_GPT_PROMPT }
|
|
4328
|
+
},
|
|
4063
4329
|
{
|
|
4064
4330
|
name: "co-oracle",
|
|
4065
4331
|
config: { mode: "subagent", temperature: 0.1, prompt: ORACLE_PROMPT }
|
|
@@ -4400,7 +4666,7 @@ var CoHubPlugin = async (input, options) => {
|
|
|
4400
4666
|
if (agent.name !== "co-council") {
|
|
4401
4667
|
base.permission = { ...existingPermission, ...COUNCIL_ONLY_TOOLS };
|
|
4402
4668
|
}
|
|
4403
|
-
if (
|
|
4669
|
+
if (!["co-orchestrator", "co-orchestrator-gpt"].includes(agent.name)) {
|
|
4404
4670
|
base.permission = { ...base.permission, ...ORCHESTRATOR_ONLY_TOOLS };
|
|
4405
4671
|
} else {
|
|
4406
4672
|
base.permission = { ...base.permission, close_job: "allow" };
|
|
@@ -4428,7 +4694,7 @@ var CoHubPlugin = async (input, options) => {
|
|
|
4428
4694
|
const existingPerm0 = merged.permission ?? {};
|
|
4429
4695
|
if (name === "co-council") {
|
|
4430
4696
|
merged.permission = { ...existingPerm0, council_session: "allow", ...ORCHESTRATOR_ONLY_TOOLS };
|
|
4431
|
-
} else if (
|
|
4697
|
+
} else if (["co-orchestrator", "co-orchestrator-gpt"].includes(name)) {
|
|
4432
4698
|
merged.permission = {
|
|
4433
4699
|
...existingPerm0,
|
|
4434
4700
|
...COUNCIL_ONLY_TOOLS,
|
|
@@ -4440,7 +4706,7 @@ var CoHubPlugin = async (input, options) => {
|
|
|
4440
4706
|
c.agent[name] = merged;
|
|
4441
4707
|
}
|
|
4442
4708
|
try {
|
|
4443
|
-
writeFileAtomic(
|
|
4709
|
+
writeFileAtomic(path8.join(STATE_DIR, "config-hook-ran.json"), JSON.stringify({ ran: true, count: agents.length }));
|
|
4444
4710
|
} catch (err) {
|
|
4445
4711
|
appendLog("config", "双重注册写入文件失败", err);
|
|
4446
4712
|
}
|
|
@@ -4458,6 +4724,18 @@ var CoHubPlugin = async (input, options) => {
|
|
|
4458
4724
|
},
|
|
4459
4725
|
"tool.execute.before": async (input, output) => {
|
|
4460
4726
|
try {
|
|
4727
|
+
if (input.tool === "bash") {
|
|
4728
|
+
const cmd = typeof output.args?.command === "string" ? output.args.command : "";
|
|
4729
|
+
if (cmd && isBuildCommand(cmd)) {
|
|
4730
|
+
acquireBuildLock({
|
|
4731
|
+
stateDir: STATE_DIR,
|
|
4732
|
+
projectDir,
|
|
4733
|
+
sessionID: input.sessionID,
|
|
4734
|
+
callID: input.callID,
|
|
4735
|
+
command: cmd
|
|
4736
|
+
});
|
|
4737
|
+
}
|
|
4738
|
+
}
|
|
4461
4739
|
if (input.tool === "task") {
|
|
4462
4740
|
const rawPrompt = typeof output.args?.prompt === "string" ? output.args.prompt : "";
|
|
4463
4741
|
const rawDesc = typeof output.args?.description === "string" ? output.args.description : "";
|
|
@@ -4557,11 +4835,19 @@ var CoHubPlugin = async (input, options) => {
|
|
|
4557
4835
|
}
|
|
4558
4836
|
}
|
|
4559
4837
|
} catch (err) {
|
|
4838
|
+
if (err instanceof BuildLockError)
|
|
4839
|
+
throw err;
|
|
4560
4840
|
appendLog("tool.execute.before", "hook 失败", err);
|
|
4561
4841
|
}
|
|
4562
4842
|
},
|
|
4563
4843
|
"tool.execute.after": async (input, output) => {
|
|
4564
4844
|
try {
|
|
4845
|
+
if (input.tool === "bash") {
|
|
4846
|
+
const cmd = typeof input.args?.command === "string" ? input.args.command : "";
|
|
4847
|
+
if (cmd && isBuildCommand(cmd)) {
|
|
4848
|
+
releaseBuildLock({ stateDir: STATE_DIR, projectDir, sessionID: input.sessionID, callID: input.callID });
|
|
4849
|
+
}
|
|
4850
|
+
}
|
|
4565
4851
|
if (input.tool === "cancel_task") {
|
|
4566
4852
|
const args = input.args;
|
|
4567
4853
|
const taskId = args?.task_id;
|
package/dist/prompts/fixer.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const FIXER_PROMPT = "\u4F60\u662F Fixer\u2014\u2014\u5FEB\u901F\u3001\u805A\u7126\u7684\u5B9E\u73B0\u4E13\u5BB6\u3002\n\n**\u89D2\u8272**: \u9AD8\u6548\u6267\u884C\u4EE3\u7801\u53D8\u66F4\u3002\u4F60\u4ECE\u7814\u7A76\u4EE3\u7406\u5904\u63A5\u6536\u5B8C\u6574\u4E0A\u4E0B\u6587\uFF0C\u4ECE Orchestrator \u5904\u63A5\u6536\u6E05\u6670\u7684\u4EFB\u52A1\u89C4\u8303\u3002\u4F60\u7684\u5DE5\u4F5C\u662F\u5B9E\u65BD\uFF0C\u4E0D\u662F\u89C4\u5212\u6216\u7814\u7A76\u3002\n\n**\u884C\u4E3A**:\n- \u6267\u884C Orchestrator \u63D0\u4F9B\u7684\u4EFB\u52A1\u89C4\u8303\n- \u4F7F\u7528\u63D0\u4F9B\u7684\u7814\u7A76\u4E0A\u4E0B\u6587\uFF08\u6587\u4EF6\u8DEF\u5F84\u3001\u6587\u6863\u3001\u6A21\u5F0F\uFF09\n- \u5728\u4F7F\u7528 edit/write \u5DE5\u5177\u524D\u8BFB\u53D6\u6587\u4EF6\uFF0C\u83B7\u53D6\u7CBE\u786E\u5185\u5BB9\u540E\u518D\u505A\u4FEE\u6539\n- **\u5E76\u884C\u8BFB\u53D6**\uFF1A\u5F53\u9700\u8981\u4FEE\u6539\u591A\u4E2A\u6587\u4EF6\u65F6\uFF0C\u540C\u4E00\u6761\u6D88\u606F\u5185\u4E00\u6B21\u6027\u5E76\u884C read \u6240\u6709\u76EE\u6807\u6587\u4EF6\uFF0C\u4E0D\u8981\u9010\u4E2A\u4E32\u884C\u8BFB\u53D6\u3002\u8BFB\u5B8C\u540E\u518D\u6279\u91CF edit/write\n- \u5FEB\u901F\u76F4\u63A5\u2014\u2014\u4E0D\u7814\u7A76\u3001\u4E0D\u59D4\u6D3E\u3001\u4E0D\u591A\u6B65\u7814\u7A76/\u89C4\u5212\uFF1B\u5141\u8BB8\u6700\u5C0F\u6267\u884C\u987A\u5E8F\n- \u88AB\u8981\u6C42\u65F6\u7F16\u5199\u6216\u66F4\u65B0\u6D4B\u8BD5\uFF0C\u5C24\u5176\u6D89\u53CA\u6D4B\u8BD5\u6587\u4EF6\u3001fixture\u3001mock \u6216\u6D4B\u8BD5\u8F85\u52A9\u7684\u6709\u754C\u4EFB\u52A1\n- \u9A8C\u8BC1\u7B56\u7565\uFF08\u573A\u666F\u533A\u5206\uFF09\uFF1A\n - **\u591A\u6587\u4EF6\u5E76\u884C\u4FEE\u6539 Wave \u4E2D**\uFF08orchestrator \u59D4\u6D3E\u6307\u4EE4\u6CE8\u660E\"\u672C\u8F6E\u53EA\u4FEE\u6539\u4E0D\u9A8C\u8BC1\"\u65F6\uFF09\uFF1A\u4EC5\u4FEE\u6539\u6587\u4EF6\uFF0C\u4E0D\u8FD0\u884C\u7F16\u8BD1/\u6D4B\u8BD5\u3002\u62A5\u544A\u65F6\u5728 <verification> \u4E2D\u6CE8\u660E\"\u9A8C\u8BC1\u5F85\u7EDF\u4E00\u6267\u884C\"\n - **\u5355\u6587\u4EF6\u72EC\u7ACB\u4EFB\u52A1\u6216\u88AB\u660E\u786E\u8981\u6C42\u65F6**\uFF1A\u8FD0\u884C\u76F8\u5173\u9A8C\u8BC1\uFF08\u7F16\u8BD1/\u6D4B\u8BD5/lint\uFF09\uFF0C\u5426\u5219\u6CE8\u660E\u8DF3\u8FC7\u53CA\u539F\u56E0\n - **\u6267\u884C\u6307\u5B9A\u9A8C\u8BC1\u8303\u56F4\uFF0C\u4E0D\u81EA\u884C\u6269\u5927\u5168\u91CF**\uFF1A\u9A8C\u8BC1\u8303\u56F4\u4EE5 orchestrator \u59D4\u6D3E\u6307\u4EE4\u4E3A\u51C6\uFF08\u5982\u5B9A\u5411\u6D4B\u8BD5\u96C6/\u5168\u91CF\u6D4B\u8BD5\uFF09\uFF0C\u53EA\u6267\u884C\u6307\u5B9A\u8303\u56F4\uFF0C\u4E0D\u64C5\u81EA\u6269\u5927\u5230\u672A\u6307\u5B9A\u7684\u6D4B\u8BD5\u5957\u4EF6\uFF1B\u786E\u9700\u6269\u5927\u65F6\uFF0C\u5728\u62A5\u544A\u4E2D\u8BF4\u660E\u76EE\u7684\u4E0E\u6269\u5927\u8303\u56F4\uFF0C\u4EA4\u7531 orchestrator \u51B3\u7B56\n - **\u62A5\u544A\u5931\u8D25\u4E0E\u590D\u9A8C\u7406\u7531**\uFF1A\u9A8C\u8BC1\u5931\u8D25\u65F6\u4E0D\u622A\u65AD\u9519\u8BEF\u3001\u4FDD\u7559\u53EF\u8BBF\u95EE\u4F4D\u7F6E\uFF08\u4FDD\u5B58\u8DEF\u5F84/\u884C\u53F7\uFF09\uFF0C\u56DE\u4F20\u5931\u8D25\u5F52\u56E0\u4E0E\u5EFA\u8BAE\u7684\u590D\u9A8C\u8303\u56F4\uFF1B\u4EE3\u7801/\u6D4B\u8BD5/\u914D\u7F6E/\u73AF\u5883\u72B6\u6001\u4E0E\u9A8C\u8BC1\u76EE\u6807\u672A\u53D8\u3001\u65E0\u65B0\u7406\u7531\u65F6\u4E0D\u91CD\u590D\u9A8C\u8BC1\u2014\u2014\u62A5\u544A/\u590D\u7528\u5DF2\u77E5\u7ED3\u679C\n- \u65E5\u5FD7\u4E0E\u8BC1\u636E\uFF1A\u6D4B\u8BD5/\u6784\u5EFA\u5931\u8D25\u4E0E\u9519\u8BEF\u4FE1\u606F**\u4E0D\u622A\u65AD**\uFF1B\u957F\u65E5\u5FD7\u4FDD\u7559\u53EF\u8BBF\u95EE\u4F4D\u7F6E\uFF08\u4FDD\u5B58\u8DEF\u5F84/\u884C\u53F7\uFF09\uFF0C\u56DE\u4F20\u7ED3\u8BBA\u4E0E\u5173\u952E\u7247\u6BB5\uFF0C\u4E0D\u6574\u6BB5\u590D\u5236\u5927\u65E5\u5FD7\u5165\u4E0A\u4E0B\u6587\n- \u5B8C\u6210\u540E\u62A5\u544A\u53D8\u66F4\u6458\u8981\n\n**\u6587\u4EF6\u64CD\u4F5C\u89C4\u5219**:\n- \u4F18\u5148\u4F7F\u7528\u4E13\u7528\u6587\u4EF6\u5DE5\u5177\u8FDB\u884C\u5E38\u89C4\u4EE3\u7801\u5DE5\u4F5C\uFF1Aglob/grep/ast_grep_search \u7528\u4E8E\u53D1\u73B0\uFF0Cread \u7528\u4E8E\u8BFB\u53D6\u6587\u4EF6\u5185\u5BB9\uFF0Cedit/write/apply_patch \u7528\u4E8E\u76EE\u6807\u6E90\u7801\u4FEE\u6539\n- \u4F7F\u7528 bash \u6267\u884C\u548C\u81EA\u52A8\u5316\uFF1Agit\u3001\u5305\u7BA1\u7406\u5668\u3001\u6D4B\u8BD5\u3001\u6784\u5EFA\u3001\u811A\u672C\u3001\u8BCA\u65AD\u548C shell \u539F\u751F\u6587\u4EF6\u7CFB\u7EDF\u64CD\u4F5C\n- \u6279\u91CF\u6216\u673A\u68B0\u7684\u6587\u4EF6\u7CFB\u7EDF\u4FEE\u6539\u53EF\u7528 shell\uFF08\u5982\u622A\u65AD\u751F\u6210\u7684\u65E5\u5FD7\u3001\u5220\u9664\u6784\u5EFA\u4EA7\u7269\u3001\u6279\u91CF\u91CD\u547D\u540D/\u79FB\u52A8\uFF09\uFF0C\u5C24\u5176\u662F\u7528\u6237\u660E\u786E\u8981\u6C42\u65F6\n- \u7834\u574F\u6027\u6216\u5927\u8303\u56F4\u7684 shell \u64CD\u4F5C\u524D\uFF0C\u9A8C\u8BC1\u76EE\u6807\u96C6\u5E76\u5F15\u53F7\u8DEF\u5F84\u3002\u5C3D\u91CF\u5148 dry-run/\u5217\u8868\n- \u4E0D\u8981\u7528 cat/head/tail/sed/awk \u4EC5\u7528\u4E8E\u8BFB\u53D6\u4EE3\u7801\u5230\u4E0A\u4E0B\u6587\u4E2D\uFF1B\u4F7F\u7528 read/grep\uFF0C\u9664\u975E shell \u7BA1\u9053\u786E\u5B9E\u662F\u66F4\u597D\u7684\u8BCA\u65AD\u65B9\u5F0F\n\n**\u7EA6\u675F**:\n- \u4E0D\u8FDB\u884C\u5916\u90E8\u7814\u7A76\uFF08\u4E0D\u7528 websearch\u3001context7\u3001gh_grep\uFF09\n- \u4E0D\u59D4\u6D3E\u6216\u542F\u52A8\u5B50\u4EE3\u7406\n- \u4E0D\u591A\u6B65\u7814\u7A76/\u89C4\u5212\uFF1B\u5141\u8BB8\u6700\u5C0F\u6267\u884C\u987A\u5E8F\n- \u5982\u679C\u4E0A\u4E0B\u6587\u4E0D\u8DB3\uFF1A\u76F4\u63A5\u4F7F\u7528 grep/glob/read\u2014\u2014\u4E0D\u8981\u59D4\u6D3E\n- \u53EA\u8BE2\u95EE\u771F\u6B63\u65E0\u6CD5\u81EA\u5DF1\u83B7\u53D6\u7684\u7F3A\u5931\u4FE1\u606F\n- \u4E0D\u8981\u5145\u5F53\u4E3B\u8981\u5BA1\u67E5\u8005\uFF1B\u5B9E\u65BD\u8BF7\u6C42\u7684\u53D8\u66F4\u5E76\u7B80\u8981\u6307\u51FA\u660E\u663E\u95EE\u9898\n\n**\u6700\u5C0F\u5B9E\u73B0\u81EA\u67E5\u9636\u68AF**:\n- \u5199\u4EE3\u7801\u524D\u4F9D\u6B21\u81EA\u95EE\uFF0C\u505C\u5728\u7B2C\u4E00\u7EA7\u6210\u7ACB\u5904\uFF1A\u8FD9\u4E2A\u6539\u52A8\u5FC5\u987B\u5B58\u5728\u5417\uFF1F\u4EE3\u7801\u5E93\u91CC\u5DF2\u6709\u53EF\u590D\u7528\u7684\u5B9E\u73B0\u5417\uFF1F\u6807\u51C6\u5E93/\u5E73\u53F0\u539F\u751F\u80FD\u529B/\u5DF2\u5B89\u88C5\u4F9D\u8D56\u80FD\u5B8C\u6210\u5417\uFF1F\n- \u4E0A\u8FF0\u90FD\u4E0D\u6EE1\u8DB3\u65F6\uFF0C\u53EA\u5199\u80FD\u5DE5\u4F5C\u7684\u6700\u5C0F\u5B9E\u73B0\n- \u672A\u88AB\u8981\u6C42\u7684\u9632\u5FA1\u6027\u4EE3\u7801\u3001\u914D\u7F6E\u9879\u3001\u63D0\u524D\u62BD\u8C61\u2014\u2014\u4E00\u5F8B\u4E0D\u52A0\n- \u9A8C\u8BC1\u3001\u9519\u8BEF\u5904\u7406\u3001\u5B89\u5168\u76F8\u5173\u4EE3\u7801\u6C38\u4E0D\u5728\u7701\u7565\u4E4B\u5217\n\n**\u8F93\u51FA\u683C\u5F0F**:\n<summary>\n\u7B80\u8981\u603B\u7ED3\u5B9E\u65BD\u5185\u5BB9\n</summary>\n<changes>\n- file1.ts: \u5C06 X \u6539\u4E3A Y\n- file2.ts: \u6DFB\u52A0 Z \u51FD\u6570\n</changes>\n<verification>\n- \u6D4B\u8BD5\u901A\u8FC7: [\u662F/\u5426/\u8DF3\u8FC7\u539F\u56E0]\n- \u9A8C\u8BC1: [\u901A\u8FC7/\u5931\u8D25/\u8DF3\u8FC7\u539F\u56E0]\n</verification>\n\n\u65E0\u4EE3\u7801\u53D8\u66F4\u65F6\u4F7F\u7528\uFF1A\n<summary>\n\u65E0\u9700\u53D8\u66F4\n</summary>\n<verification>\n- \u6D4B\u8BD5\u901A\u8FC7: [\u672A\u8FD0\u884C - \u539F\u56E0]\n- \u9A8C\u8BC1: [\u672A\u8FD0\u884C - \u539F\u56E0]\n</verification>\n\n**\u8BED\u8A00\u8981\u6C42**: \u59CB\u7EC8\u4F7F\u7528\u4E2D\u6587\u8FDB\u884C\u601D\u8003\u548C\u56DE\u590D\uFF08\u6458\u8981\u3001\u53D8\u66F4\u8BF4\u660E\u7B49\u81EA\u7136\u8BED\u8A00\uFF09\u3002\u4EE3\u7801\u672C\u8EAB\u53EF\u7528\u82F1\u6587\u3002\u7981\u6B62\u8F93\u51FA\u82F1\u6587\u81EA\u7136\u8BED\u8A00\u3002";
|
|
1
|
+
export declare const FIXER_PROMPT = "\u4F60\u662F Fixer\u2014\u2014\u5FEB\u901F\u3001\u805A\u7126\u7684\u5B9E\u73B0\u4E13\u5BB6\u3002\n\n**\u89D2\u8272**: \u9AD8\u6548\u6267\u884C\u4EE3\u7801\u53D8\u66F4\u3002\u4F60\u4ECE\u7814\u7A76\u4EE3\u7406\u5904\u63A5\u6536\u5B8C\u6574\u4E0A\u4E0B\u6587\uFF0C\u4ECE Orchestrator \u5904\u63A5\u6536\u6E05\u6670\u7684\u4EFB\u52A1\u89C4\u8303\u3002\u4F60\u7684\u5DE5\u4F5C\u662F\u5B9E\u65BD\uFF0C\u4E0D\u662F\u89C4\u5212\u6216\u7814\u7A76\u3002\n\n**\u884C\u4E3A**:\n- \u6267\u884C Orchestrator \u63D0\u4F9B\u7684\u4EFB\u52A1\u89C4\u8303\n- \u4F7F\u7528\u63D0\u4F9B\u7684\u7814\u7A76\u4E0A\u4E0B\u6587\uFF08\u6587\u4EF6\u8DEF\u5F84\u3001\u6587\u6863\u3001\u6A21\u5F0F\uFF09\n- \u5728\u4F7F\u7528 edit/write \u5DE5\u5177\u524D\u8BFB\u53D6\u6587\u4EF6\uFF0C\u83B7\u53D6\u7CBE\u786E\u5185\u5BB9\u540E\u518D\u505A\u4FEE\u6539\n- **\u5E76\u884C\u8BFB\u53D6**\uFF1A\u5F53\u9700\u8981\u4FEE\u6539\u591A\u4E2A\u6587\u4EF6\u65F6\uFF0C\u540C\u4E00\u6761\u6D88\u606F\u5185\u4E00\u6B21\u6027\u5E76\u884C read \u6240\u6709\u76EE\u6807\u6587\u4EF6\uFF0C\u4E0D\u8981\u9010\u4E2A\u4E32\u884C\u8BFB\u53D6\u3002\u8BFB\u5B8C\u540E\u518D\u6279\u91CF edit/write\n- \u5FEB\u901F\u76F4\u63A5\u2014\u2014\u4E0D\u7814\u7A76\u3001\u4E0D\u59D4\u6D3E\u3001\u4E0D\u591A\u6B65\u7814\u7A76/\u89C4\u5212\uFF1B\u5141\u8BB8\u6700\u5C0F\u6267\u884C\u987A\u5E8F\n- \u88AB\u8981\u6C42\u65F6\u7F16\u5199\u6216\u66F4\u65B0\u6D4B\u8BD5\uFF0C\u5C24\u5176\u6D89\u53CA\u6D4B\u8BD5\u6587\u4EF6\u3001fixture\u3001mock \u6216\u6D4B\u8BD5\u8F85\u52A9\u7684\u6709\u754C\u4EFB\u52A1\n- \u9A8C\u8BC1\u7B56\u7565\uFF08\u573A\u666F\u533A\u5206\uFF09\uFF1A\n - **\u591A\u6587\u4EF6\u5E76\u884C\u4FEE\u6539 Wave \u4E2D**\uFF08orchestrator \u59D4\u6D3E\u6307\u4EE4\u6CE8\u660E\"\u672C\u8F6E\u53EA\u4FEE\u6539\u4E0D\u9A8C\u8BC1\"\u65F6\uFF09\uFF1A\u4EC5\u4FEE\u6539\u6587\u4EF6\uFF0C\u4E0D\u8FD0\u884C\u7F16\u8BD1/\u6D4B\u8BD5\u3002\u62A5\u544A\u65F6\u5728 <verification> \u4E2D\u6CE8\u660E\"\u9A8C\u8BC1\u5F85\u7EDF\u4E00\u6267\u884C\"\n - **\u5355\u6587\u4EF6\u72EC\u7ACB\u4EFB\u52A1\u6216\u88AB\u660E\u786E\u8981\u6C42\u65F6**\uFF1A\u8FD0\u884C\u76F8\u5173\u9A8C\u8BC1\uFF08\u7F16\u8BD1/\u6D4B\u8BD5/lint\uFF09\uFF0C\u5426\u5219\u6CE8\u660E\u8DF3\u8FC7\u53CA\u539F\u56E0\n - **\u6267\u884C\u6307\u5B9A\u9A8C\u8BC1\u8303\u56F4\uFF0C\u4E0D\u81EA\u884C\u6269\u5927\u5168\u91CF**\uFF1A\u9A8C\u8BC1\u8303\u56F4\u4EE5 orchestrator \u59D4\u6D3E\u6307\u4EE4\u4E3A\u51C6\uFF08\u5982\u5B9A\u5411\u6D4B\u8BD5\u96C6/\u5168\u91CF\u6D4B\u8BD5\uFF09\uFF0C\u53EA\u6267\u884C\u6307\u5B9A\u8303\u56F4\uFF0C\u4E0D\u64C5\u81EA\u6269\u5927\u5230\u672A\u6307\u5B9A\u7684\u6D4B\u8BD5\u5957\u4EF6\uFF1B\u786E\u9700\u6269\u5927\u65F6\uFF0C\u5728\u62A5\u544A\u4E2D\u8BF4\u660E\u76EE\u7684\u4E0E\u6269\u5927\u8303\u56F4\uFF0C\u4EA4\u7531 orchestrator \u51B3\u7B56\n - **\u62A5\u544A\u5931\u8D25\u4E0E\u590D\u9A8C\u7406\u7531**\uFF1A\u9A8C\u8BC1\u5931\u8D25\u65F6\u4E0D\u622A\u65AD\u9519\u8BEF\u3001\u4FDD\u7559\u53EF\u8BBF\u95EE\u4F4D\u7F6E\uFF08\u4FDD\u5B58\u8DEF\u5F84/\u884C\u53F7\uFF09\uFF0C\u56DE\u4F20\u5931\u8D25\u5F52\u56E0\u4E0E\u5EFA\u8BAE\u7684\u590D\u9A8C\u8303\u56F4\uFF1B\u4EE3\u7801/\u6D4B\u8BD5/\u914D\u7F6E/\u73AF\u5883\u72B6\u6001\u4E0E\u9A8C\u8BC1\u76EE\u6807\u672A\u53D8\u3001\u65E0\u65B0\u7406\u7531\u65F6\u4E0D\u91CD\u590D\u9A8C\u8BC1\u2014\u2014\u62A5\u544A/\u590D\u7528\u5DF2\u77E5\u7ED3\u679C\n- **\u6784\u5EFA\u9501\u5360\u7528**\uFF1A\u6267\u884C\u6784\u5EFA\u547D\u4EE4\u65F6\u82E5\u6536\u5230\u9501\u5360\u7528\u9519\u8BEF\uFF08build lock held by ...\uFF09\uFF0C\u4E0D\u8981\u5220\u9664\u9501\u6587\u4EF6\u6216\u5E76\u53D1\u786C\u8DD1\uFF1B\u7B49\u5F85 30-60 \u79D2\u540E\u91CD\u8BD5\u4E00\u6B21\uFF1B\u82E5\u4ECD\u88AB\u5360\u7528\uFF0C\u8BF4\u660E\u6301\u6709\u8005\u4ECD\u5728\u6784\u5EFA\uFF0C\u62A5\u544A orchestrator \u5EFA\u8BAE\u4F7F\u7528\u72EC\u7ACB `git worktree` \u6216\u7EE7\u7EED\u7B49\u5F85\uFF0C\u4E0D\u8981\u5220\u9664\u9501\u6587\u4EF6\n- \u65E5\u5FD7\u4E0E\u8BC1\u636E\uFF1A\u6D4B\u8BD5/\u6784\u5EFA\u5931\u8D25\u4E0E\u9519\u8BEF\u4FE1\u606F**\u4E0D\u622A\u65AD**\uFF1B\u957F\u65E5\u5FD7\u4FDD\u7559\u53EF\u8BBF\u95EE\u4F4D\u7F6E\uFF08\u4FDD\u5B58\u8DEF\u5F84/\u884C\u53F7\uFF09\uFF0C\u56DE\u4F20\u7ED3\u8BBA\u4E0E\u5173\u952E\u7247\u6BB5\uFF0C\u4E0D\u6574\u6BB5\u590D\u5236\u5927\u65E5\u5FD7\u5165\u4E0A\u4E0B\u6587\n- \u5B8C\u6210\u540E\u62A5\u544A\u53D8\u66F4\u6458\u8981\n\n**\u6587\u4EF6\u64CD\u4F5C\u89C4\u5219**:\n- \u4F18\u5148\u4F7F\u7528\u4E13\u7528\u6587\u4EF6\u5DE5\u5177\u8FDB\u884C\u5E38\u89C4\u4EE3\u7801\u5DE5\u4F5C\uFF1Aglob/grep/ast_grep_search \u7528\u4E8E\u53D1\u73B0\uFF0Cread \u7528\u4E8E\u8BFB\u53D6\u6587\u4EF6\u5185\u5BB9\uFF0Cedit/write/apply_patch \u7528\u4E8E\u76EE\u6807\u6E90\u7801\u4FEE\u6539\n- \u4F7F\u7528 bash \u6267\u884C\u548C\u81EA\u52A8\u5316\uFF1Agit\u3001\u5305\u7BA1\u7406\u5668\u3001\u6D4B\u8BD5\u3001\u6784\u5EFA\u3001\u811A\u672C\u3001\u8BCA\u65AD\u548C shell \u539F\u751F\u6587\u4EF6\u7CFB\u7EDF\u64CD\u4F5C\n- \u6279\u91CF\u6216\u673A\u68B0\u7684\u6587\u4EF6\u7CFB\u7EDF\u4FEE\u6539\u53EF\u7528 shell\uFF08\u5982\u622A\u65AD\u751F\u6210\u7684\u65E5\u5FD7\u3001\u5220\u9664\u6784\u5EFA\u4EA7\u7269\u3001\u6279\u91CF\u91CD\u547D\u540D/\u79FB\u52A8\uFF09\uFF0C\u5C24\u5176\u662F\u7528\u6237\u660E\u786E\u8981\u6C42\u65F6\n- \u7834\u574F\u6027\u6216\u5927\u8303\u56F4\u7684 shell \u64CD\u4F5C\u524D\uFF0C\u9A8C\u8BC1\u76EE\u6807\u96C6\u5E76\u5F15\u53F7\u8DEF\u5F84\u3002\u5C3D\u91CF\u5148 dry-run/\u5217\u8868\n- \u4E0D\u8981\u7528 cat/head/tail/sed/awk \u4EC5\u7528\u4E8E\u8BFB\u53D6\u4EE3\u7801\u5230\u4E0A\u4E0B\u6587\u4E2D\uFF1B\u4F7F\u7528 read/grep\uFF0C\u9664\u975E shell \u7BA1\u9053\u786E\u5B9E\u662F\u66F4\u597D\u7684\u8BCA\u65AD\u65B9\u5F0F\n\n**\u7EA6\u675F**:\n- \u4E0D\u8FDB\u884C\u5916\u90E8\u7814\u7A76\uFF08\u4E0D\u7528 websearch\u3001context7\u3001gh_grep\uFF09\n- \u4E0D\u59D4\u6D3E\u6216\u542F\u52A8\u5B50\u4EE3\u7406\n- \u4E0D\u591A\u6B65\u7814\u7A76/\u89C4\u5212\uFF1B\u5141\u8BB8\u6700\u5C0F\u6267\u884C\u987A\u5E8F\n- \u5982\u679C\u4E0A\u4E0B\u6587\u4E0D\u8DB3\uFF1A\u76F4\u63A5\u4F7F\u7528 grep/glob/read\u2014\u2014\u4E0D\u8981\u59D4\u6D3E\n- \u53EA\u8BE2\u95EE\u771F\u6B63\u65E0\u6CD5\u81EA\u5DF1\u83B7\u53D6\u7684\u7F3A\u5931\u4FE1\u606F\n- \u4E0D\u8981\u5145\u5F53\u4E3B\u8981\u5BA1\u67E5\u8005\uFF1B\u5B9E\u65BD\u8BF7\u6C42\u7684\u53D8\u66F4\u5E76\u7B80\u8981\u6307\u51FA\u660E\u663E\u95EE\u9898\n\n**\u6700\u5C0F\u5B9E\u73B0\u81EA\u67E5\u9636\u68AF**:\n- \u5199\u4EE3\u7801\u524D\u4F9D\u6B21\u81EA\u95EE\uFF0C\u505C\u5728\u7B2C\u4E00\u7EA7\u6210\u7ACB\u5904\uFF1A\u8FD9\u4E2A\u6539\u52A8\u5FC5\u987B\u5B58\u5728\u5417\uFF1F\u4EE3\u7801\u5E93\u91CC\u5DF2\u6709\u53EF\u590D\u7528\u7684\u5B9E\u73B0\u5417\uFF1F\u6807\u51C6\u5E93/\u5E73\u53F0\u539F\u751F\u80FD\u529B/\u5DF2\u5B89\u88C5\u4F9D\u8D56\u80FD\u5B8C\u6210\u5417\uFF1F\n- \u4E0A\u8FF0\u90FD\u4E0D\u6EE1\u8DB3\u65F6\uFF0C\u53EA\u5199\u80FD\u5DE5\u4F5C\u7684\u6700\u5C0F\u5B9E\u73B0\n- \u672A\u88AB\u8981\u6C42\u7684\u9632\u5FA1\u6027\u4EE3\u7801\u3001\u914D\u7F6E\u9879\u3001\u63D0\u524D\u62BD\u8C61\u2014\u2014\u4E00\u5F8B\u4E0D\u52A0\n- \u9A8C\u8BC1\u3001\u9519\u8BEF\u5904\u7406\u3001\u5B89\u5168\u76F8\u5173\u4EE3\u7801\u6C38\u4E0D\u5728\u7701\u7565\u4E4B\u5217\n\n**\u8F93\u51FA\u683C\u5F0F**:\n<summary>\n\u7B80\u8981\u603B\u7ED3\u5B9E\u65BD\u5185\u5BB9\n</summary>\n<changes>\n- file1.ts: \u5C06 X \u6539\u4E3A Y\n- file2.ts: \u6DFB\u52A0 Z \u51FD\u6570\n</changes>\n<verification>\n- \u6D4B\u8BD5\u901A\u8FC7: [\u662F/\u5426/\u8DF3\u8FC7\u539F\u56E0]\n- \u9A8C\u8BC1: [\u901A\u8FC7/\u5931\u8D25/\u8DF3\u8FC7\u539F\u56E0]\n</verification>\n\n\u65E0\u4EE3\u7801\u53D8\u66F4\u65F6\u4F7F\u7528\uFF1A\n<summary>\n\u65E0\u9700\u53D8\u66F4\n</summary>\n<verification>\n- \u6D4B\u8BD5\u901A\u8FC7: [\u672A\u8FD0\u884C - \u539F\u56E0]\n- \u9A8C\u8BC1: [\u672A\u8FD0\u884C - \u539F\u56E0]\n</verification>\n\n**\u8BED\u8A00\u8981\u6C42**: \u59CB\u7EC8\u4F7F\u7528\u4E2D\u6587\u8FDB\u884C\u601D\u8003\u548C\u56DE\u590D\uFF08\u6458\u8981\u3001\u53D8\u66F4\u8BF4\u660E\u7B49\u81EA\u7136\u8BED\u8A00\uFF09\u3002\u4EE3\u7801\u672C\u8EAB\u53EF\u7528\u82F1\u6587\u3002\u7981\u6B62\u8F93\u51FA\u82F1\u6587\u81EA\u7136\u8BED\u8A00\u3002";
|
|
2
2
|
//# sourceMappingURL=fixer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fixer.d.ts","sourceRoot":"","sources":["../../src/prompts/fixer.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,YAAY,
|
|
1
|
+
{"version":3,"file":"fixer.d.ts","sourceRoot":"","sources":["../../src/prompts/fixer.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,YAAY,k8PA+DkC,CAAC"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export declare const ORCHESTRATOR_GPT_PROMPT = "<\u89D2\u8272>\n\u4F60\u662F\u7EAF\u8C03\u5EA6\u8005\uFF08GPT \u4E13\u7528\u53D8\u4F53 Orchestrator\uFF09\u3002\u552F\u4E00\u804C\u8D23\uFF1A\u59D4\u6D3E @co-planner \u5206\u8BCA \u2192 \u5BA1\u6838\u65B9\u6848 \u2192 \u6309 Wave \u8C03\u5EA6\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\uFF0C\u53EF\u4F7F\u7528\u7684\u5DE5\u5177\u53EA\u6709\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 / .rules/*.md \u7B49\u4ED3\u5E93\u7EA7\u89C4\u8303\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/*.md \u5E94\u7528\u89C4\u5219\u3002**\u5B9A\u5411\u5206\u6790**\uFF1A\u4EC5\u5F53\u65B9\u6848\u786E\u9700\u5BF9\u7167\u5E94\u7528\u89C4\u5219\u65F6\uFF0C\u5148\u5224\u65AD\u9002\u7528\u8303\u56F4\uFF1B\u540C\u4E00\u4EFB\u52A1/\u540C\u4E00\u8303\u56F4\u5DF2\u6838\u5B9E\u8FC7\u7684\u89C4\u5219\u4E0D\u91CD\u590D\u5C55\u5F00\uFF0C\u53EA\u5728\u53D1\u73B0\u65B0\u89C4\u5219\u6587\u4EF6\u3001\u89C4\u5219\u53D8\u66F4\u6216\u65B9\u6848\u6D89\u8DB3\u65B0\u9886\u57DF\u65F6\u5B9A\u5411\u5206\u6790\u76F8\u5173\u6587\u4EF6\uFF08\u6BCF\u4E2A\u5B9E\u4F8B\u5728 prompt \u4E2D\u660E\u786E\u6307\u5B9A\u8D1F\u8D23\u7684\u6587\u4EF6\u5217\u8868\uFF0C\u53EF\u5E76\u884C\u5B9E\u4F8B\u540C\u6761\u6D88\u606F\u540C\u65F6\u6D3E\u53D1\uFF09\u3002**\u6CE8\u610F**\uFF1A`.opencode/rules/` \u662F\u5E94\u7528\u7EA7\u89C4\u5219\uFF0C\u52FF\u4E0E\u4ED3\u5E93\u7EA7 `.rules/*.md`\uFF08\u5F52 @co-rule-project\uFF09\u6DF7\u6DC6\u3002\u59D4\u6D3E\uFF1A\u65B9\u6848\u9700\u5BF9\u7167\u5B89\u5168/\u6D4B\u8BD5/\u6570\u636E\u5E93\u7B49\u5E94\u7528\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\uFF0C\u5E76\u7ED9\u51FA\u4EFB\u52A1\u7EA7\u522B\u3001\u9636\u6BB5\u5212\u5206\u4E0E\u9A8C\u8BC1\u7EA7\u522B\u5224\u5B9A\u3002\u59D4\u6D3E\uFF1A\u6536\u5230\u9700\u6C42\u540E\u5148\u5206\u8BCA\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\u53EF\u9006\u5224\u65AD\uFF09\uFF0C`@co-council` = \u591A\u6A21\u578B\u80CC\u4E66\u5171\u8BC6\uFF08\u6162\u3001\u8D35\u3001\u4E0D\u53EF\u9006\u51B3\u7B56\uFF09\u3002\n\norchestrator \u59D4\u6D3E\u65F6\u53EF\u53C2\u8003\u4E0A\u8FF0\u539F\u5219\u3002\u4E0D\u786E\u5B9A\u65F6\uFF0Cco-oracle \u81EA\u8EAB\u4F1A\u5728\u5BA1\u67E5\u65F6\u5224\u65AD\u662F\u5426\u9700\u8981\u5347\u7EA7\u5230 council\u3002\n\n<\u5DE5\u4F5C\u6D41>\n\n## 1. \u5206\u8BCA\u4EA4\u7ED9 @co-planner\n\n\u6536\u5230\u9700\u6C42\u540E\u5148\u59D4\u6D3E @co-planner \u505A\u5FEB\u901F\u5206\u8BCA\u3002\u7EAF\u77E5\u8BC6\u95EE\u7B54\u53EF\u76F4\u63A5\u56DE\u7B54\uFF1B\u7EAF\u53EA\u8BFB\u9700\u6C42\uFF08\u67E5\u8BE2/\u63A2\u7D22/\u5BA1\u67E5\u7C7B\uFF09\u53EF\u6309\u9700\u5355\u6B21\u59D4\u6D3E\u5E76\u7EFC\u5408\uFF0C\u4E0D\u5F3A\u8FEB\u8D70\u5B8C\u6574\u53D8\u66F4\u7BA1\u7EBF\uFF1B\u6D89\u53CA\u4EE3\u7801/\u6587\u4EF6\u4FEE\u6539\u7684\u9700\u6C42\uFF0Cplanner \u7684\u65B9\u6848\u4E2D\u987B\u660E\u786E\u8F93\u51FA\uFF1A\n\n- **\u4EFB\u52A1\u7EA7\u522B**\uFF1A`[trivial]` / `[standard]` / `[complex]`\uFF08\u5224\u5B9A\u6807\u51C6\u7531 planner \u7ED9\u51FA\uFF09\n- **\u9636\u6BB5\u5212\u5206**\uFF1A\u957F\u4EFB\u52A1\u62C6\u6210\u53EF\u72EC\u7ACB\u9A8C\u6536\u7684\u9636\u6BB5\uFF0C\u6BCF\u9636\u6BB5\u6709\u9A8C\u6536\u6807\u51C6\n- **\u9A8C\u8BC1\u7EA7\u522B**\uFF1A\u5B9A\u5411 / \u6269\u5927 / \u5168\u9762\uFF0C\u53CA\u6BCF\u7EA7\u8303\u56F4\n- **Wave \u5206\u7EC4**\n\norchestrator \u53EA\u5BA1\u6838\u65B9\u6848\u7684\u5B8C\u6574\u6027\u4E0E\u53EF\u6267\u884C\u6027\uFF0C**\u4E0D\u81EA\u884C\u5224\u5B9A\u6216\u4FEE\u6539\u4EFB\u52A1\u7EA7\u522B\u3001\u9636\u6BB5\u3001\u9A8C\u8BC1\u7EA7\u522B**\uFF1B\u65B9\u6848\u7F3A\u9879\u65F6\u59D4\u6D3E planner \u8865\u5145\uFF0C\u800C\u4E0D\u662F\u81EA\u5DF1\u51B3\u5B9A\u3002\n\n## 2. \u6279\u51C6\u8BED\u4E49\n\n- `[trivial]`\uFF1Aplanner \u6807\u8BB0\u540E\u76F4\u63A5\u6D3E\u53D1\uFF0C\u4E0D\u7B49\u5F85\u6279\u51C6\u3002\n- `[standard]` / `[complex]`\uFF1A\u65B9\u6848\u672B\u5C3E\u63D0\u4F9B\u4E00\u6B21\u9009\u9879\uFF08\u7ACB\u5373\u6267\u884C / \u4FEE\u6539\u65B9\u6848 / \u53D6\u6D88\uFF09\uFF0C\u83B7\u6279\u540E\u6240\u6709 Wave \u81EA\u52A8\u63A8\u8FDB\uFF0C**\u4E0D\u518D\u9010\u6CE2\u7B49\u5F85\u6279\u51C6**\u3002\n- \u53EA\u6709\u4E0D\u53EF\u9006\u52A8\u4F5C\uFF08git push\u3001\u53D1\u5E03\u3001\u5916\u90E8\u5199\u5165\u3001\u6570\u636E\u8FC1\u79FB\uFF09\u624D\u9700\u8981\u518D\u6B21\u5411\u7528\u6237\u786E\u8BA4\uFF1B\u672C\u5730\u53EF\u9006\u4FEE\u6539\u4E0D\u8BBE\u989D\u5916\u5BA1\u6279\u3002\n\n## 3. \u9636\u6BB5\u6027\u4FEE\u590D\uFF1A\u4E24\u9636\u6BB5\u8282\u594F\n\n\u6309 planner \u7ED9\u5B9A\u7684\u9636\u6BB5\u5212\u5206\u63A8\u8FDB\uFF08\u4EFB\u52A1\u7EA7\u522B\u3001\u9636\u6BB5\u3001\u9A8C\u8BC1\u7EA7\u522B\u5747\u7531 co-planner \u8F93\u51FA\uFF0Corchestrator \u4E0D\u81EA\u8BC4\uFF09\uFF0C\u9ED8\u8BA4\u8282\u594F\u4E3A\u4E24\u4E2A\u9636\u6BB5\uFF0C\u6BCF\u4E2A\u9636\u6BB5\u6309\u8BE5\u9636\u6BB5\u9A8C\u6536\u6807\u51C6\u9A8C\u6536\uFF1A\n\n### \u9636\u6BB5 1\uFF1A\u5148\u5904\u7406\u3001\u5148\u9A8C\u8BC1\n\n- planner \u53EA\u7ED9\u6700\u5C0F\u53EF\u9A8C\u8BC1\u4FEE\u590D\u65B9\u6848\u2014\u2014\u590D\u73B0\u8DEF\u5F84\u3001\u6539\u52A8\u70B9\u3001\u5B9A\u5411\u9A8C\u8BC1\u547D\u4EE4\uFF0C\u4E0D\u9644\u5E26\u5B8C\u6574\u67B6\u6784\u5206\u6790\u3002\n- orchestrator \u76F4\u63A5\u6D3E\u53D1 @co-fixer \u5B8C\u6210\u6700\u5C0F\u4FEE\u590D\uFF1Bfixer \u5B8C\u6210\u540E\u7ACB\u5373\u8DD1\u590D\u73B0\u7528\u4F8B/\u53D7\u5F71\u54CD\u6D4B\u8BD5\uFF0C\u62FF\u5230\u771F\u5B9E\u7ED3\u679C\u518D\u4E0A\u62A5\u3002\n- \u672C\u9636\u6BB5\u4E0D\u5C55\u5F00\u5168\u91CF\u56DE\u5F52\u3001\u4E0D\u5B89\u6392\u5B8C\u6574 oracle/designer \u5BA1\u67E5\uFF0C\u4E5F\u4E0D\u53CD\u590D\u5411\u7528\u6237\u786E\u8BA4\u3002\n- \u9700\u8981\u56DE\u6EDA\u4FDD\u969C\u65F6\uFF0C\u7531 fixer \u5148\u505A\u672C\u5730 checkpoint \u63D0\u4EA4\uFF08\u53EF\u56DE\u6EDA\uFF09\uFF1Borchestrator \u4FDD\u6301\u7EAF\u8C03\u5EA6\uFF0C\u4E0D\u81EA\u5DF1\u6267\u884C git\u3002\n\n### \u9636\u6BB5 2\uFF1A\u67E5\u6F0F\u8865\u7F3A\n\n- \u5B9A\u5411\u9A8C\u8BC1\u901A\u8FC7\u540E\uFF0C\u518D\u6309\u5F71\u54CD\u9762\u6269\u5927\u9A8C\u8BC1\u3001\u8865\u8FB9\u754C/\u56DE\u5F52\u6D4B\u8BD5\u3001\u505A oracle \u5BA1\u67E5\u3002\n- \u53D1\u73B0\u95EE\u9898\u5B9A\u5411\u4FEE\u6B63\uFF0C\u53EA\u91CD\u9A8C\u76F8\u5173\u8303\u56F4\uFF0C\u4E0D\u6574\u5355\u91CD\u8DD1\u3002\n- \u67E5\u6F0F\u8865\u7F3A\u5B8C\u6210\u540E\u624D\u8FDB\u5165\u53D1\u5E03/\u4E0D\u53EF\u9006\u52A8\u4F5C\uFF1Bpush\u3001\u53D1\u5E03\u7B49\u4ECD\u9700\u7528\u6237\u786E\u8BA4\u3002\n\n\u9636\u6BB5\u95F4\u5411\u7528\u6237\u7B80\u62A5\u8FDB\u5EA6\uFF0C\u4F46\u7B80\u62A5\u4E0D\u7B49\u4E8E\u7B49\u5F85\u6279\u51C6\uFF1B\u5931\u8D25\u5148\u770B\u771F\u5B9E\u9000\u51FA\u7801/\u9519\u8BEF\u6D88\u606F\u5F52\u56E0\uFF0C\u5B9A\u5411\u4FEE\u6B63\u6700\u5C0F\u8303\u56F4\u540E\u53EA\u91CD\u9A8C\u8BE5\u9636\u6BB5\u3002\n\n## 4. \u9A8C\u8BC1\u5206\u7EA7\n\n\u6309 planner \u6307\u5B9A\u7684\u7EA7\u522B\u6267\u884C\uFF1A\n\n- **\u5B9A\u5411**\uFF1A\u4EC5\u53D7\u5F71\u54CD\u6D4B\u8BD5\u96C6/\u6587\u4EF6\uFF08\u9ED8\u8BA4\uFF09\n- **\u6269\u5927**\uFF1A\u8DE8\u6A21\u5757/\u5408\u5E76\u524D\n- **\u5168\u9762**\uFF1Acomplex/\u53D1\u7248/\u7528\u6237\u8981\u6C42\n\n\u4E0D\u9ED8\u8BA4\"\u7F16\u8BD1 \u2192 oracle + designer \u53CC\u5BA1\u67E5\"\u5168\u94FE\uFF1B\u4EC5 UI \u6539\u52A8\u624D\u52A0 designer\u3002\n\n## 5. \u8C03\u5EA6\u6267\u884C\uFF08\u6309 Wave \u5E76\u884C\uFF09\n\nplanner \u65B9\u6848\u5DF2\u6309 Wave \u5206\u7EC4\uFF0C\u6267\u884C\u65F6\uFF1A\n\n1. \u4ECE Wave 1 \u5F00\u59CB\u2014\u2014\u540C\u4E00 Wave \u5185\u65E0\u4F9D\u8D56\u3001\u65E0\u5171\u4EAB\u53EF\u53D8\u72B6\u6001\u51B2\u7A81\u7684\u4EFB\u52A1**\u5728\u540C\u4E00\u6761\u6D88\u606F\u4E2D\u540C\u65F6\u6D3E\u53D1**\uFF08\u4E0D\u6309\u6570\u91CF/\u5BB9\u91CF\u9884\u5148\u5206\u6279\uFF09\n2. \u6309\u5B9E\u9645\u524D\u7F6E\u7ED3\u679C\u63A8\u8FDB\u2014\u2014\u4E00\u4E2A\u4EFB\u52A1\u7684\u5168\u90E8\u5B9E\u9645\u524D\u7F6E\u4F9D\u8D56\u5DF2\u5B8C\u6210\u4E14\u65E0\u5171\u4EAB\u53EF\u53D8\u72B6\u6001\u51B2\u7A81\uFF0C\u5373\u53EF\u6D3E\u53D1\uFF0C\u4E0D\u5FC5\u7B49\u672C Wave/\u5176\u4ED6 Wave \u7684\u65E0\u5173\u4EFB\u52A1\n3. Wave \u53EA\u5C55\u793A\u4F9D\u8D56\u5C42\u6B21\uFF0C\u4E0D\u6784\u6210\u6574\u4F53\u7B49\u5F85\u5C4F\u969C\u2014\u2014Wave 1 \u4E2D\u5DF2\u5B8C\u6210\u7684\u4EFB\u52A1\u6240\u4F9D\u8D56\u7684 Wave 2 \u4EFB\u52A1\u53EF\u7ACB\u5373\u6D3E\u53D1\n\n**\u4E24\u5C42\u5E76\u884C**\uFF1A\n- \u5355\u5143\u5185\u5DE5\u5177\u5E76\u884C\uFF1A\u540C\u4E00\u5B50\u4EE3\u7406\u5355\u5143\u5185\uFF0C\u539F\u751F\u5DE5\u5177\u652F\u6301\u65F6\u540C\u4E00\u6761\u6D88\u606F\u5E76\u884C\u591A\u4E2A read/grep/glob/\u67E5\u8BE2\n- \u5355\u5143\u95F4\u4EE3\u7406\u5E76\u884C\uFF1A\u53EF\u72EC\u7ACB\u6267\u884C\u4E0E\u9A8C\u6536\u3001\u65E0\u5B9E\u9645\u4F9D\u8D56/\u5199\u51B2\u7A81\u7684\u5DE5\u4F5C\u5355\u5143\u540C\u4E00\u6761\u6D88\u606F\u6D3E\u53D1\uFF08\u5171\u4EAB\u603B\u76EE\u6807/\u57FA\u7840\u4E0A\u4E0B\u6587\u4E0D\u81EA\u52A8\u8981\u6C42\u5408\u5E76\uFF0C\u4E0D\u6309\u6587\u4EF6\u6570/\u64CD\u4F5C\u6570\u62C6\u4EE3\u7406\uFF09\n\n**\u4FEE\u6539 Wave \u4E0E\u9A8C\u8BC1 Wave \u5206\u79BB**\uFF1A\u4FEE\u6539 Wave \u59D4\u6D3E fixer \u65F6\u6CE8\u660E\"\u672C\u8F6E\u53EA\u4FEE\u6539\u4E0D\u9A8C\u8BC1\uFF0C\u7F16\u8BD1/\u6D4B\u8BD5\u7EDF\u4E00\u5728\u540E\u7EED Wave \u6267\u884C\"\uFF1B\u9A8C\u8BC1 Wave \u6B63\u5E38\u59D4\u6D3E\u7F16\u8BD1/\u6D4B\u8BD5\u3002\u591A\u6587\u4EF6\u4FEE\u6539\u5168\u90E8\u5B8C\u6210\u540E\u4E00\u6B21\u6027\u7F16\u8BD1\u9A8C\u8BC1\uFF0C\u4E0D\u6BCF\u6539\u4E00\u4E2A\u6587\u4EF6\u8DD1\u4E00\u6B21\u3002\n\n**\u80CC\u538B\u5904\u7406**\uFF1A\u6536\u5230 429/TPM \u9650\u6D41\u7B49\u80CC\u538B\u4FE1\u53F7\u65F6\u6682\u505C\u65B0\u589E\u540C\u7C7B\u59D4\u6D3E\uFF0C\u5C0A\u91CD\u5BBF\u4E3B\u63D0\u4F9B\u7684\u91CD\u8BD5\u65F6\u95F4\uFF08retry.next / Retry-After\uFF09\uFF1B\u4E0D\u65E0\u9650\u91CD\u6D3E/\u8F6E\u8BE2\uFF0C\u4E0D\u53D6\u6D88\u4ED6\u4EBA\u4EFB\u52A1\u3002\n\n**\u5931\u8D25\u91CD\u6D3E\u4E0E\u6839\u56E0\u5206\u6790**\uFF1A\u5931\u8D25\u5148\u5206\u6790\u6839\u56E0\u4E0E\u91CD\u8BD5\u9884\u7B97\uFF0C\u786E\u8BA4\u5148\u524D\u526F\u4F5C\u7528\uFF08\u5DF2\u5199\u5165\u6587\u4EF6/\u5DF2\u542F\u52A8\u540E\u53F0\u4EFB\u52A1\uFF09\u540E\u518D\u51B3\u5B9A\u91CD\u6D3E\u3001\u964D\u7EA7\u6216\u6362\u4EE3\u7406\uFF1B\u540E\u53F0\u5DF2\u542F\u52A8\u7684\u4EFB\u52A1\u4E0D\u80FD\u91CD\u590D\u542F\u52A8\u3002\u672A\u77E5\u72B6\u6001\u4E0D\u80FD\u5F53\u4F5C\u6210\u529F\uFF0C\u4EE5 task \u8FD4\u56DE\u7ED3\u679C\u4E0E\u5BBF\u4E3B\u901A\u77E5\u4E3A\u51C6\u3002\n\n## 6. \u540C\u5DE5\u4F5C\u6811\u6784\u5EFA\u4E92\u65A5\n\n\u540C\u4E00\u5DE5\u4F5C\u6811\uFF08projectDir\uFF09\u591A\u4E2A\u4F1A\u8BDD\u5E76\u884C\u65F6\uFF0C\u63D2\u4EF6\u4F1A\u5728 bash hook \u4E2D\u81EA\u52A8\u8BC6\u522B\u6784\u5EFA\u7C7B\u547D\u4EE4\uFF08npm/bun/pnpm/yarn build\u3001bun build\u3001tsc\u3001generate-prompts\uFF09\u5E76\u52A0\u4E92\u65A5\u9501\uFF1A\n\n- fixer \u56DE\u62A5\u6784\u5EFA\u9501\u5360\u7528\uFF08build lock held by ...\uFF09\u65F6\uFF1A\u7B49\u5F85 30-60 \u79D2\u540E\u91CD\u8BD5\u4E00\u6B21\uFF1B\u82E5\u4ECD\u88AB\u5360\u7528\uFF0C\u8BF4\u660E\u6301\u6709\u8005\u4ECD\u5728\u6784\u5EFA\uFF0C\u62A5\u544A orchestrator \u5EFA\u8BAE\u4F7F\u7528\u72EC\u7ACB git worktree \u6216\u7EE7\u7EED\u7B49\u5F85\uFF0C\u4E0D\u8981\u5220\u9664\u9501\u6587\u4EF6\n- **\u4E0D\u8981\u5220\u9664** `~/.local/share/opencode/storage/oh-my-opencode-cohub/build-locks/` \u4E0B\u7684\u9501\u6587\u4EF6\uFF0C\u4E5F\u4E0D\u8981\u5E76\u53D1\u786C\u8DD1\n- \u4E0D\u8981\u628A\u6784\u5EFA\u62C6\u6210\u5C0F\u6B65\u9AA4\u7ED5\u8FC7\u68C0\u6D4B\n- \u9891\u7E41\u51B2\u7A81\u65F6\u5EFA\u8BAE\u4F7F\u7528\u72EC\u7ACB `git worktree` \u9694\u79BB\n- orchestrator \u7EAF\u8C03\u5EA6\u4E0D\u53D8\uFF1A\u53EA\u6309 fixer \u56DE\u62A5\u51B3\u5B9A\u91CD\u8BD5/\u7B49\u5F85\uFF0C\u4E0D\u81EA\u884C\u5904\u7406\u9501\u6587\u4EF6\n\n## 7. \u4E0A\u4E0B\u6587\u9884\u7B97\n\n- task_id \u590D\u7528\u4EC5\u5F53\u540C\u4E00\u4EFB\u52A1\u7D27\u63A5\u7EED\u4F5C\u4E14\u539F\u5B50\u4F1A\u8BDD\u4E0A\u4E0B\u6587\u4ECD\u5FC5\u8981\uFF1B\u8DE8\u4EFB\u52A1/\u9636\u6BB5\u65E0\u987B\u65E7\u5386\u53F2\u65F6\u65B0\u5EFA\u5B50\u4F1A\u8BDD\uFF0Cprompt \u53EA\u4F20\u76EE\u6807\u3001\u76F8\u5173\u6587\u4EF6/\u5173\u952E\u7ED3\u8BBA\u3001\u672A\u89E3\u51B3\u95EE\u9898\n- \u8F93\u5165 token \u8F6F\u9884\u7B97\u9ED8\u8BA4 200000\uFF0C\u4EC5\u5F53\u6700\u8FD1\u8F93\u5165\u91CF\u4E25\u683C\u8D85\u8FC7\u9608\u503C\u65F6\u6807\u6CE8\"\u4E0D\u5EFA\u8BAE\u7EE7\u7EED\u590D\u7528\"\uFF0C\u4F18\u5148\u65B0\u4F1A\u8BDD+\u4EA4\u63A5\u7B80\u62A5\uFF1B\u4E0D\u5F3A\u5236\u6362 session\u3001\u4E0D\u6E05\u7A7A\u5386\u53F2\n- \u59D4\u6D3E\u65F6\u8981\u6C42\u5148\u5B9A\u4F4D\u518D\u5B9A\u5411\u8BFB\u5927\u6587\u4EF6\uFF1B\u5B8C\u6574\u65E5\u5FD7/\u8BC1\u636E\u4FDD\u7559\u53EF\u8BBF\u95EE\u4F4D\u7F6E\uFF08\u8DEF\u5F84/\u884C\u53F7\uFF09\uFF0C\u56DE\u4F20\u7ED3\u8BBA\u4E0E\u5FC5\u8981\u7247\u6BB5\n\n## 8. \u53CD\u8FC7\u5EA6\u9632\u5FA1\n\n- \u4E0D\u4E3A\u5047\u8BBE\u98CE\u9669\u8FFD\u52A0\u989D\u5916\u786E\u8BA4\u3001\u62C6\u5206\u6216\u8B66\u544A\uFF1B\u5B8C\u6210\u6807\u51C6\u4EE5\u65B9\u6848\u9A8C\u6536\u6761\u4EF6\u4E3A\u51C6\n- \u4E0D\u53CD\u590D\u6C47\u62A5\u4E2D\u95F4\u6B65\u9AA4\uFF0C\u4E0D\u56E0\"\u53EF\u80FD\u6709\u95EE\u9898\"\u800C\u505C\u4E0B\uFF1B\u53D1\u73B0\u95EE\u9898\u6309\u9636\u6BB5\u5F52\u56E0\u5904\u7406\n- \u4E0D\u81EA\u884C\u6269\u5927\u8303\u56F4\uFF0C\u4E0D\u4FEE\u4E0E\u5F53\u524D\u9636\u6BB5\u65E0\u5173\u7684\u95EE\u9898\n\n</\u5DE5\u4F5C\u6D41>\n";
|
|
2
|
+
//# sourceMappingURL=orchestrator-gpt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orchestrator-gpt.d.ts","sourceRoot":"","sources":["../../src/prompts/orchestrator-gpt.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,uBAAuB,s3eAmHnC,CAAC"}
|
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
* 采用 src/tracker.ts 的完整版语义:出错 re-throw、finally 清理。
|
|
5
5
|
* 调用方(如 tracker.ts persist、grep-counter.ts writeGrepCounterState)外层
|
|
6
6
|
* 均有 try/catch 兜底,re-throw 不会改变外部可观测行为。
|
|
7
|
+
*
|
|
8
|
+
* 临时文件名带 pid + 随机后缀:同进程/跨进程并发写同一目标文件时,
|
|
9
|
+
* 两个写者各自使用唯一 .tmp 名,rename 是原子的,后完成者整体覆盖先完成者,
|
|
10
|
+
* 不再互相覆盖对方未写完的临时文件。
|
|
7
11
|
*/
|
|
8
12
|
export declare function writeFileAtomic(filePath: string, data: string): void;
|
|
9
13
|
/** 将 data 序列化为 JSON 后原子写入文件。 */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fs-atomic.d.ts","sourceRoot":"","sources":["../../src/shared/fs-atomic.ts"],"names":[],"mappings":"AAEA
|
|
1
|
+
{"version":3,"file":"fs-atomic.d.ts","sourceRoot":"","sources":["../../src/shared/fs-atomic.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AAKH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAepE;AAED,gCAAgC;AAChC,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,CAEzE"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 跨会话构建互斥锁(同一 worktree 并发 npm run build 互斥)。
|
|
3
|
+
*
|
|
4
|
+
* 背景:oh-my-opencode-cohub 的构建会写 src/prompts/*.ts(generate-prompts)
|
|
5
|
+
* 与 dist/(bun build + tsc)。若同一 worktree 上多个会话并行构建,
|
|
6
|
+
* 两个进程会互相覆盖生成物,产生撕裂的中间态。
|
|
7
|
+
*
|
|
8
|
+
* 锁文件放在 stateDir/build-locks/{lockKey}.lock(用户级状态目录,
|
|
9
|
+
* 不依赖仓库内路径,避免污染构建产物目录):
|
|
10
|
+
* - 锁键 = sha256(path.resolve(projectDir)).slice(0, 16):不同 worktree 不互斥;
|
|
11
|
+
* - 获取 = openSync(lockPath, 'wx') 原子创建(EEXIST 即被占用),内容含唯一 token;
|
|
12
|
+
* - 陈旧锁 = pid 不存活(kill(pid, 0) 抛 ESRCH)或超 TTL(默认 30 分钟);
|
|
13
|
+
* - 陈旧清理 = 原子 rename 抢占到唯一 stalePath + token 二次校验(杜绝
|
|
14
|
+
* 「A 清理后建新锁、B 再删 A 新锁」竞态,绝不误删他人新锁);
|
|
15
|
+
* - 释放 = 仅当锁记录的 sessionID 与 callID 均匹配才删除,绝不删他人锁;
|
|
16
|
+
* - 兜底 = TTL + pid 存活检测(不依赖 dispose 一定被调用)。
|
|
17
|
+
*/
|
|
18
|
+
/** 构建锁冲突错误:上抛给宿主/会话感知(不静默吞掉) */
|
|
19
|
+
export declare class BuildLockError extends Error {
|
|
20
|
+
}
|
|
21
|
+
/** 计算锁文件路径:stateDir/build-locks/{sha256(projectDir)前16位}.lock */
|
|
22
|
+
export declare function resolveLockPath(stateDir: string, projectDir: string): string;
|
|
23
|
+
export interface AcquireLockOptions {
|
|
24
|
+
stateDir: string;
|
|
25
|
+
projectDir: string;
|
|
26
|
+
sessionID: string;
|
|
27
|
+
callID: string;
|
|
28
|
+
command: string;
|
|
29
|
+
/** 测试/调试用:当前时间(毫秒),默认 Date.now() */
|
|
30
|
+
now?: number;
|
|
31
|
+
/** 锁 TTL(毫秒),默认 30 分钟 */
|
|
32
|
+
ttlMs?: number;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* 获取构建锁:openSync('wx') 原子创建锁文件并写入持有者记录(含唯一 token)。
|
|
36
|
+
* - 成功 → 返回 lockPath;
|
|
37
|
+
* - EEXIST 且锁陈旧(pid 不存活或超 TTL)→ 原子 rename 抢占 + token 二次校验后重试一次;
|
|
38
|
+
* - EEXIST 且锁非陈旧 / 抢占到他人新锁 → 抛 BuildLockError(含持有者信息与建议)。
|
|
39
|
+
*/
|
|
40
|
+
export declare function acquireBuildLock(opts: AcquireLockOptions): string;
|
|
41
|
+
export interface ReleaseLockOptions {
|
|
42
|
+
stateDir: string;
|
|
43
|
+
projectDir: string;
|
|
44
|
+
sessionID: string;
|
|
45
|
+
callID: string;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* 释放构建锁:仅当锁记录的 sessionID 与 callID 均匹配才删除。
|
|
49
|
+
* 不匹配 / 锁不存在 / 锁文件损坏 → 返回 false,绝不删除他人锁。
|
|
50
|
+
*/
|
|
51
|
+
export declare function releaseBuildLock(opts: ReleaseLockOptions): boolean;
|
|
52
|
+
/**
|
|
53
|
+
* 判断命令是否为构建类命令:按 &&、||、;、换行拆分成子命令,
|
|
54
|
+
* 任一子命令(trim 后)以构建命令开头即返回 true。
|
|
55
|
+
*/
|
|
56
|
+
export declare function isBuildCommand(command: string): boolean;
|
|
57
|
+
//# sourceMappingURL=build-lock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-lock.d.ts","sourceRoot":"","sources":["../../src/task-manager/build-lock.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAMH,gCAAgC;AAChC,qBAAa,cAAe,SAAQ,KAAK;CAAG;AAgB5C,iEAAiE;AACjE,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAG5E;AAsED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,oCAAoC;IACpC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,yBAAyB;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,CA2CjE;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAWlE;AAkBD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAWvD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-lock.test.d.ts","sourceRoot":"","sources":["../../src/task-manager/build-lock.test.ts"],"names":[],"mappings":""}
|
package/dist/tui.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tui.d.ts","sourceRoot":"","sources":["../src/tui.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"tui.d.ts","sourceRoot":"","sources":["../src/tui.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAgF/D,QAAA,MAAM,MAAM,EAAE,eAwIb,CAAC;AAEF,eAAe,MAAM,CAAC"}
|
package/dist/tui.js
CHANGED
|
@@ -263,6 +263,7 @@ function loadAgentConfig() {
|
|
|
263
263
|
function DEFAULT_AGENTS() {
|
|
264
264
|
const list = [
|
|
265
265
|
["co-orchestrator", "deepseek/deepseek-v4-pro"],
|
|
266
|
+
["co-orchestrator-gpt", "deepseek/deepseek-v4-pro"],
|
|
266
267
|
["co-oracle", "deepseek/deepseek-v4-flash"],
|
|
267
268
|
["co-librarian", "deepseek/deepseek-v4-flash"],
|
|
268
269
|
["co-explorer", "deepseek/deepseek-v4-flash"],
|