@fkqfkq123/opencode-autopilot 0.1.5 → 0.1.8
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/GUIDE.zh-CN.md +49 -394
- package/README.md +50 -391
- package/dist/packages/core/src/state/workflow-runtime-state.d.ts +2 -0
- package/dist/packages/core/src/transitions/default-phase-transition.js +45 -0
- package/dist/packages/runtime/src/artifacts/file-system-artifact-evaluator.js +7 -3
- package/dist/packages/runtime/src/bootstrap/create-harness.d.ts +1 -0
- package/dist/packages/runtime/src/bootstrap/create-harness.js +2 -1
- package/dist/packages/runtime/src/bootstrap/initialize-workflow.js +1 -0
- package/dist/packages/runtime/src/diagnostics/workflow-doctor.d.ts +3 -1
- package/dist/packages/runtime/src/diagnostics/workflow-doctor.js +3 -2
- package/dist/packages/runtime/src/engine/default-workflow-engine.js +15 -0
- package/dist/packages/runtime/src/plugin/workflow-plugin-entry.js +1 -1
- package/package.json +1 -1
package/GUIDE.zh-CN.md
CHANGED
|
@@ -2,226 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
[English](./README.md) | 中文说明
|
|
4
4
|
|
|
5
|
-
Autopilot
|
|
5
|
+
Autopilot 是一个 OpenCode 插件,可以把自然语言需求推进成一套完整流程:需求精炼、计划、实现、评审和测试。
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## 安装
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
- 面向 OpenCode 的 workflow 命令:`workflow_open`、`workflow_attach`、`workflow_status`、`workflow_answer`、`workflow_approve`、`workflow_resume`、`workflow_back`
|
|
11
|
-
- OpenCode 风格宿主的插件加载能力与原生 primary workflow agent 注册能力
|
|
12
|
-
- `install` / `doctor` 初始化与自检流程
|
|
13
|
-
- review/test loop-back、人工断点、事件存储、attach / re-attach 支持
|
|
14
|
-
|
|
15
|
-
## 2. 适合谁使用
|
|
16
|
-
|
|
17
|
-
如果你希望:
|
|
18
|
-
|
|
19
|
-
- 在 OpenCode 风格宿主中接入 workflow 主代理
|
|
20
|
-
- 把工程流程拆成显式 phase
|
|
21
|
-
- 通过插件形式验证 workflow runtime 与 command surface
|
|
22
|
-
|
|
23
|
-
那么这个项目适合你。
|
|
24
|
-
|
|
25
|
-
## 3. 环境准备
|
|
26
|
-
|
|
27
|
-
建议环境:
|
|
28
|
-
|
|
29
|
-
- macOS / Linux / Windows
|
|
30
|
-
- [Bun](https://bun.sh/) `1.3.5` 或兼容版本
|
|
31
|
-
- 已安装 OpenCode(如果你需要实际加载并验证插件)
|
|
32
|
-
|
|
33
|
-
检查 Bun:
|
|
34
|
-
|
|
35
|
-
```bash
|
|
36
|
-
bun --version
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
如果还没有安装 Bun:
|
|
40
|
-
|
|
41
|
-
```bash
|
|
42
|
-
curl -fsSL https://bun.sh/install | bash
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
安装完成后重启终端,再执行:
|
|
46
|
-
|
|
47
|
-
```bash
|
|
48
|
-
bun --version
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
## 4. 安装
|
|
52
|
-
|
|
53
|
-
### 4.1 推荐方式:作为 npm 插件包安装
|
|
54
|
-
|
|
55
|
-
OpenCode 原生支持 npm 插件。等这个包发布后,最简单的配置方式是:
|
|
56
|
-
|
|
57
|
-
```json
|
|
58
|
-
{
|
|
59
|
-
"plugin": ["@fkqfkq123/opencode-autopilot"]
|
|
60
|
-
}
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
也可以固定版本:
|
|
64
|
-
|
|
65
|
-
```json
|
|
66
|
-
{
|
|
67
|
-
"plugin": ["@fkqfkq123/opencode-autopilot@0.1.2"]
|
|
68
|
-
}
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
在这种模式下,OpenCode 会自动安装并缓存 npm 包,不需要手动 `git clone`、不需要本地 `plugin.js`、也不需要额外安装脚本。
|
|
72
|
-
|
|
73
|
-
### 4.2 备用方式:通过 GitHub Releases 安装
|
|
74
|
-
|
|
75
|
-
如果你更希望走本地文件安装路径,或者需要 fallback 分发方式,可以使用 GitHub Releases 一键安装脚本:
|
|
76
|
-
|
|
77
|
-
```bash
|
|
78
|
-
curl -fsSL https://raw.githubusercontent.com/juhuaxia/Autopilot/main/install.sh | bash
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
安装指定版本:
|
|
82
|
-
|
|
83
|
-
```bash
|
|
84
|
-
curl -fsSL https://raw.githubusercontent.com/juhuaxia/Autopilot/main/install.sh | bash -s -- --version v0.1.2
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
这个备用安装脚本会:
|
|
88
|
-
|
|
89
|
-
- 从 GitHub Releases 下载预构建发布包
|
|
90
|
-
- 安装到 `~/.config/opencode/plugins/autopilot/`
|
|
91
|
-
- 更新 `~/.config/opencode/opencode.json`
|
|
92
|
-
|
|
93
|
-
发布要求:
|
|
94
|
-
|
|
95
|
-
- 每个 GitHub Release 需要包含 `autopilot-release.tar.gz`
|
|
96
|
-
- 仓库内置 `.github/workflows/release.yml`,在推送 `v*` tag 时会自动构建并上传该文件
|
|
97
|
-
|
|
98
|
-
如果你想修改源码或从源码开发,继续看下面的源码安装流程。
|
|
99
|
-
|
|
100
|
-
### 4.3 克隆仓库
|
|
101
|
-
|
|
102
|
-
```bash
|
|
103
|
-
git clone https://github.com/juhuaxia/Autopilot.git
|
|
104
|
-
cd Autopilot
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
### 4.4 安装依赖
|
|
108
|
-
|
|
109
|
-
```bash
|
|
110
|
-
bun install
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
项目使用 `bun.lock`,依赖版本应保持可复现。
|
|
114
|
-
|
|
115
|
-
## 5. 推荐首次执行的命令
|
|
116
|
-
|
|
117
|
-
在项目根目录执行:
|
|
118
|
-
|
|
119
|
-
```bash
|
|
120
|
-
bun run src/cli.ts install
|
|
121
|
-
bun run src/cli.ts doctor
|
|
122
|
-
bun run build
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
它们分别会:
|
|
126
|
-
|
|
127
|
-
1. `install`
|
|
128
|
-
- 创建项目级 `.workflow-harness/autopilot.json`
|
|
129
|
-
- 在缺失时创建全局 `~/.config/opencode/autopilot.json`
|
|
130
|
-
- 尝试安全写入 `~/.config/opencode/opencode.json`
|
|
131
|
-
- 如有 `opencode.jsonc`,在安全情况下归一化写回 `opencode.json`
|
|
132
|
-
2. `doctor`
|
|
133
|
-
- 检查 `autopilot.json`
|
|
134
|
-
- 检查 `skillRoots`
|
|
135
|
-
- 检查各 phase 的 `requiredSkills`
|
|
136
|
-
- 输出告警与缺失项
|
|
137
|
-
3. `build`
|
|
138
|
-
- 编译 TypeScript
|
|
139
|
-
- 生成 `dist/plugin.js`
|
|
140
|
-
|
|
141
|
-
之后建议确认:
|
|
142
|
-
|
|
143
|
-
- `.workflow-harness/autopilot.json` 已生成
|
|
144
|
-
- `doctor` 没有阻断性配置问题
|
|
145
|
-
- `dist/plugin.js` 已生成
|
|
146
|
-
|
|
147
|
-
## 6. 常用开发命令
|
|
148
|
-
|
|
149
|
-
### 6.1 构建
|
|
150
|
-
|
|
151
|
-
```bash
|
|
152
|
-
bun run build
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
### 6.2 类型检查
|
|
156
|
-
|
|
157
|
-
```bash
|
|
158
|
-
bun run typecheck
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
### 6.3 运行测试
|
|
162
|
-
|
|
163
|
-
```bash
|
|
164
|
-
bun test
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
### 6.4 运行插件 smoke test
|
|
168
|
-
|
|
169
|
-
```bash
|
|
170
|
-
bun run smoke:plugin
|
|
171
|
-
```
|
|
172
|
-
|
|
173
|
-
### 6.5 直接运行 CLI
|
|
174
|
-
|
|
175
|
-
```bash
|
|
176
|
-
bun run src/cli.ts doctor
|
|
177
|
-
bun run src/cli.ts install
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
也可以通过脚本别名运行:
|
|
181
|
-
|
|
182
|
-
```bash
|
|
183
|
-
bun run cli --help
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
> CLI 主要用于 workflow 初始化、attach/status 流程以及 install/doctor 动作。
|
|
187
|
-
|
|
188
|
-
## 7. CLI 快速使用
|
|
189
|
-
|
|
190
|
-
### 7.1 初始化配置
|
|
191
|
-
|
|
192
|
-
```bash
|
|
193
|
-
bun run src/cli.ts install
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
### 7.2 做一次自检
|
|
197
|
-
|
|
198
|
-
```bash
|
|
199
|
-
bun run src/cli.ts doctor
|
|
200
|
-
```
|
|
201
|
-
|
|
202
|
-
### 7.3 创建一个 workflow
|
|
203
|
-
|
|
204
|
-
```bash
|
|
205
|
-
bun run src/cli.ts workflow-open wf-1
|
|
206
|
-
```
|
|
207
|
-
|
|
208
|
-
### 7.4 查看 workflow 状态
|
|
209
|
-
|
|
210
|
-
```bash
|
|
211
|
-
bun run src/cli.ts workflow-status wf-1
|
|
212
|
-
```
|
|
213
|
-
|
|
214
|
-
### 7.5 重新 attach 到 workflow channel
|
|
215
|
-
|
|
216
|
-
```bash
|
|
217
|
-
bun run src/cli.ts workflow-attach wf-1
|
|
218
|
-
```
|
|
219
|
-
|
|
220
|
-
## 8. 如何把插件加载到 OpenCode
|
|
221
|
-
|
|
222
|
-
### 8.0 推荐的 npm 插件方式
|
|
223
|
-
|
|
224
|
-
推荐的 OpenCode 配置:
|
|
9
|
+
在 OpenCode 配置里加入插件:
|
|
225
10
|
|
|
226
11
|
```json
|
|
227
12
|
{
|
|
@@ -229,237 +14,107 @@ bun run src/cli.ts workflow-attach wf-1
|
|
|
229
14
|
}
|
|
230
15
|
```
|
|
231
16
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
如果你希望使用本地安装后的 fallback 插件,执行:
|
|
235
|
-
|
|
236
|
-
```bash
|
|
237
|
-
curl -fsSL https://raw.githubusercontent.com/juhuaxia/Autopilot/main/install.sh | bash
|
|
238
|
-
```
|
|
239
|
-
|
|
240
|
-
默认安装位置:
|
|
241
|
-
|
|
242
|
-
```txt
|
|
243
|
-
~/.config/opencode/plugins/autopilot/
|
|
244
|
-
```
|
|
17
|
+
然后重启 `opencode`。
|
|
245
18
|
|
|
246
|
-
|
|
19
|
+
如果加载成功,你应该看到类似日志:
|
|
247
20
|
|
|
248
21
|
```txt
|
|
249
|
-
|
|
250
|
-
```
|
|
251
|
-
|
|
252
|
-
### 8.2 源码开发方式
|
|
253
|
-
|
|
254
|
-
执行:
|
|
255
|
-
|
|
256
|
-
```bash
|
|
257
|
-
bun run src/cli.ts install
|
|
258
|
-
bun run src/cli.ts doctor
|
|
259
|
-
```
|
|
260
|
-
|
|
261
|
-
如果 installer 能安全改写 OpenCode 配置,通常不需要手工编辑。
|
|
262
|
-
|
|
263
|
-
> `install.sh` 面向 GitHub Releases 安装;项目内 installer 面向源码开发场景。
|
|
264
|
-
|
|
265
|
-
### 8.3 手工注册插件
|
|
266
|
-
|
|
267
|
-
OpenCode 配置通常在:
|
|
268
|
-
|
|
269
|
-
- `~/.config/opencode/opencode.json`
|
|
270
|
-
- 或 `~/.config/opencode/opencode.jsonc`
|
|
271
|
-
|
|
272
|
-
#### 方案 A:加载构建产物
|
|
273
|
-
|
|
274
|
-
先构建:
|
|
275
|
-
|
|
276
|
-
```bash
|
|
277
|
-
bun run build
|
|
278
|
-
```
|
|
279
|
-
|
|
280
|
-
然后在 OpenCode 配置中加入:
|
|
281
|
-
|
|
282
|
-
```json
|
|
283
|
-
{
|
|
284
|
-
"plugin": [
|
|
285
|
-
"file:///ABSOLUTE_PATH_TO_PROJECT/dist/plugin.js"
|
|
286
|
-
]
|
|
287
|
-
}
|
|
288
|
-
```
|
|
289
|
-
|
|
290
|
-
#### 方案 B:开发阶段直接加载源码
|
|
291
|
-
|
|
292
|
-
```json
|
|
293
|
-
{
|
|
294
|
-
"plugin": [
|
|
295
|
-
"file:///ABSOLUTE_PATH_TO_PROJECT/plugin.ts"
|
|
296
|
-
]
|
|
297
|
-
}
|
|
22
|
+
[autopilot] Autopilot plugin loaded (... commands)
|
|
298
23
|
```
|
|
299
24
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
交互模式:
|
|
303
|
-
|
|
304
|
-
```bash
|
|
305
|
-
opencode
|
|
306
|
-
```
|
|
25
|
+
## 使用
|
|
307
26
|
|
|
308
|
-
|
|
27
|
+
直接输入自然语言需求,例如:
|
|
309
28
|
|
|
310
|
-
```
|
|
311
|
-
|
|
29
|
+
```txt
|
|
30
|
+
给商品列表页增加排序能力,并注意回归风险。
|
|
312
31
|
```
|
|
313
32
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
插件会暴露这些工具/命令:
|
|
33
|
+
Autopilot 会通过这些工具推进流程:
|
|
317
34
|
|
|
318
|
-
- `workflow_channel`
|
|
319
35
|
- `workflow_open`
|
|
320
36
|
- `workflow_attach`
|
|
321
37
|
- `workflow_status`
|
|
322
38
|
- `workflow_answer`
|
|
323
39
|
- `workflow_approve`
|
|
324
40
|
- `workflow_resume`
|
|
325
|
-
- `workflow_back`
|
|
326
|
-
- `workflow_doctor`
|
|
327
41
|
|
|
328
|
-
|
|
42
|
+
通常你只需要按照 workflow 输出里提示的下一步工具继续即可。
|
|
329
43
|
|
|
330
|
-
|
|
331
|
-
- `workflow_attach`
|
|
332
|
-
- `workflow_status`
|
|
333
|
-
- `workflow_answer`
|
|
334
|
-
- `workflow_approve`
|
|
335
|
-
- `workflow_resume`
|
|
336
|
-
- `workflow_back`
|
|
44
|
+
## 配置
|
|
337
45
|
|
|
338
|
-
|
|
46
|
+
Autopilot 会在需要时自动创建:
|
|
339
47
|
|
|
340
48
|
```txt
|
|
341
|
-
|
|
49
|
+
.workflow-harness/autopilot.json
|
|
50
|
+
~/.config/opencode/autopilot.json
|
|
342
51
|
```
|
|
343
52
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
### 10.1 配置层级
|
|
347
|
-
|
|
348
|
-
- 用户默认:`~/.config/opencode/autopilot.json`
|
|
349
|
-
- 项目级覆盖:`<repo>/.workflow-harness/autopilot.json`
|
|
350
|
-
- 运行时状态:`<repo>/.workflow-harness/workflows/<workflowId>/`
|
|
351
|
-
|
|
352
|
-
### 10.2 各目录作用
|
|
53
|
+
如果配置保持空值,就使用默认行为。
|
|
353
54
|
|
|
354
|
-
|
|
355
|
-
- `packages/runtime/` — workflow runtime 实现
|
|
356
|
-
- `tests/` — 测试
|
|
357
|
-
- `scripts/` — 辅助脚本
|
|
358
|
-
- `.workflow-harness/` — 运行时配置、状态与产物
|
|
359
|
-
- `dist/` — 构建输出
|
|
55
|
+
### `autopilot.json`
|
|
360
56
|
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
先从完全中性的配置开始:
|
|
57
|
+
最小示例:
|
|
364
58
|
|
|
365
59
|
```json
|
|
366
60
|
{
|
|
367
61
|
"skillRoots": ["~/.claude/skills", "~/.config/opencode/skills"],
|
|
368
62
|
"phases": {
|
|
63
|
+
"spec_refinement": { "requiredSkills": [] },
|
|
64
|
+
"plan": { "requiredSkills": [] },
|
|
369
65
|
"develop": { "requiredSkills": [] },
|
|
66
|
+
"review": { "requiredSkills": [] },
|
|
370
67
|
"test": { "requiredSkills": [] }
|
|
371
68
|
}
|
|
372
69
|
}
|
|
373
70
|
```
|
|
374
71
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
```json
|
|
378
|
-
{
|
|
379
|
-
"skillRoots": ["~/.claude/skills", "~/.config/opencode/skills"],
|
|
380
|
-
"phases": {
|
|
381
|
-
"develop": { "requiredSkills": ["frontend-design"] },
|
|
382
|
-
"test": { "requiredSkills": ["playwright"] }
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
```
|
|
386
|
-
|
|
387
|
-
这个前端示例只是示例,workflow runtime 默认并不绑定前端。
|
|
72
|
+
字段说明:
|
|
388
73
|
|
|
389
|
-
|
|
74
|
+
- `skillRoots`:要扫描的 skill 目录
|
|
75
|
+
- `phases.<phase>.requiredSkills`:该阶段需要注入的 skill
|
|
390
76
|
|
|
391
|
-
|
|
392
|
-
- 不要把 skill 配置写到 `workflows/<workflowId>/`
|
|
393
|
-
- 新配置上线前先跑 `workflow_doctor` 或 CLI `doctor`
|
|
77
|
+
支持的 phase:
|
|
394
78
|
|
|
395
|
-
|
|
79
|
+
- `spec_refinement`
|
|
80
|
+
- `plan`
|
|
81
|
+
- `develop`
|
|
82
|
+
- `review`
|
|
83
|
+
- `test`
|
|
396
84
|
|
|
397
|
-
|
|
85
|
+
如果旧的 `workflow.json` 存在而新的 `autopilot.json` 不存在,Autopilot 会复用旧文件,并提示你后续迁移。
|
|
398
86
|
|
|
399
|
-
|
|
87
|
+
## 备用安装方式
|
|
400
88
|
|
|
401
|
-
|
|
402
|
-
{
|
|
403
|
-
"plugin": [
|
|
404
|
-
"file:///Users/<your-user>/.config/opencode/plugins/autopilot/plugin.js"
|
|
405
|
-
]
|
|
406
|
-
}
|
|
407
|
-
```
|
|
408
|
-
|
|
409
|
-
如果你是源码开发场景,也可以指向本地的 `dist/plugin.js`。
|
|
410
|
-
|
|
411
|
-
如果你使用 npm 插件模式,则只需要这样配置:
|
|
89
|
+
如果你更想走本地文件安装:
|
|
412
90
|
|
|
413
|
-
```
|
|
414
|
-
|
|
415
|
-
"plugin": ["@fkqfkq123/opencode-autopilot"]
|
|
416
|
-
}
|
|
91
|
+
```bash
|
|
92
|
+
curl -fsSL https://raw.githubusercontent.com/juhuaxia/Autopilot/main/install.sh | bash
|
|
417
93
|
```
|
|
418
94
|
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
通常是宿主集成层还没有把导出的 `workflowCommands` 真正注册到宿主命令面板 / tool surface。
|
|
422
|
-
|
|
423
|
-
### Q3:我应该先验证什么?
|
|
424
|
-
|
|
425
|
-
建议先按这个顺序验证:
|
|
426
|
-
|
|
427
|
-
1. 宿主能导入插件文件
|
|
428
|
-
2. 宿主能调用默认导出
|
|
429
|
-
3. 宿主能收到一个 plugin-like 对象
|
|
95
|
+
## 常见问题
|
|
430
96
|
|
|
431
|
-
|
|
97
|
+
### OpenCode 启动失败
|
|
432
98
|
|
|
433
|
-
|
|
99
|
+
先临时从 `opencode.json` 中移除这个插件,确认 OpenCode 能正常启动,再检查配置后重新启用。
|
|
434
100
|
|
|
435
|
-
|
|
101
|
+
### 插件加载了,但看不到 workflow 命令
|
|
436
102
|
|
|
437
|
-
|
|
103
|
+
通常是宿主没有正确注册导出的 workflow tools。
|
|
438
104
|
|
|
439
|
-
|
|
440
|
-
|---|---|
|
|
441
|
-
| `README.md` | 安装、发布、使用总入口 |
|
|
442
|
-
| `WORKFLOW_SKILL_PROFILE_ARCHITECTURE_CN.md` | skill / profile 配置设计 |
|
|
443
|
-
| `OPENCODE_WORKFLOW_AGENT_GUIDE.md` | agent / tool 调用顺序 |
|
|
444
|
-
| `REQUIREMENT_TEMPLATE.md` | 需求输入模板 |
|
|
105
|
+
### 某个 workflow 状态坏掉了
|
|
445
106
|
|
|
446
|
-
|
|
107
|
+
删除当前项目的运行时目录后重新开始:
|
|
447
108
|
|
|
448
|
-
|
|
109
|
+
```bash
|
|
110
|
+
rm -rf .workflow-harness
|
|
111
|
+
```
|
|
449
112
|
|
|
450
|
-
|
|
113
|
+
## 如果你要开发这个插件
|
|
451
114
|
|
|
452
115
|
```bash
|
|
453
116
|
bun install
|
|
454
|
-
bun run
|
|
455
|
-
bun
|
|
117
|
+
bun run typecheck
|
|
118
|
+
bun test
|
|
456
119
|
bun run build
|
|
457
|
-
opencode
|
|
458
120
|
```
|
|
459
|
-
|
|
460
|
-
然后:
|
|
461
|
-
|
|
462
|
-
1. 确认 `.workflow-harness/autopilot.json` 已生成
|
|
463
|
-
2. 确认 `dist/plugin.js` 已生成
|
|
464
|
-
3. 如果 OpenCode 没有自动加载插件,手工把 `file:///ABSOLUTE_PATH_TO_PROJECT/dist/plugin.js` 加到配置里
|
|
465
|
-
4. 在宿主中验证 `workflow_open`、`workflow_attach`、`workflow_status` 是否可见
|
package/README.md
CHANGED
|
@@ -2,224 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
English | [中文说明](./GUIDE.zh-CN.md)
|
|
4
4
|
|
|
5
|
-
Autopilot is an OpenCode
|
|
5
|
+
Autopilot is an OpenCode plugin that turns a natural-language request into a structured workflow: refinement, plan, implementation, review, and testing.
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Install
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
- OpenCode-facing workflow commands such as `workflow_open`, `workflow_attach`, `workflow_status`, `workflow_answer`, `workflow_approve`, `workflow_resume`, and `workflow_back`
|
|
11
|
-
- Plugin loading and native primary workflow agent registration for OpenCode-style hosts
|
|
12
|
-
- `install` and `doctor` flows for bootstrapping configuration and validating setup
|
|
13
|
-
- Review/test loop-back semantics, human breakpoints, event storage, attach/re-attach support
|
|
14
|
-
|
|
15
|
-
## 2. Who this is for
|
|
16
|
-
|
|
17
|
-
Autopilot is a good fit if you want to:
|
|
18
|
-
|
|
19
|
-
- add a workflow primary agent to an OpenCode-style host,
|
|
20
|
-
- structure engineering work into explicit workflow phases,
|
|
21
|
-
- validate a workflow runtime and command surface through a plugin.
|
|
22
|
-
|
|
23
|
-
## 3. Prerequisites
|
|
24
|
-
|
|
25
|
-
Recommended environment:
|
|
26
|
-
|
|
27
|
-
- macOS / Linux / Windows
|
|
28
|
-
- [Bun](https://bun.sh/) `1.3.5` or a compatible version
|
|
29
|
-
- OpenCode installed if you want to actually load and verify the plugin
|
|
30
|
-
|
|
31
|
-
Check Bun:
|
|
32
|
-
|
|
33
|
-
```bash
|
|
34
|
-
bun --version
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
If Bun is not installed yet:
|
|
38
|
-
|
|
39
|
-
```bash
|
|
40
|
-
curl -fsSL https://bun.sh/install | bash
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
Then restart your terminal and verify again:
|
|
44
|
-
|
|
45
|
-
```bash
|
|
46
|
-
bun --version
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
## 4. Installation
|
|
50
|
-
|
|
51
|
-
### 4.1 Recommended: install as an npm plugin package
|
|
52
|
-
|
|
53
|
-
OpenCode supports npm-based plugins directly. Once this package is published, the simplest configuration is:
|
|
54
|
-
|
|
55
|
-
```json
|
|
56
|
-
{
|
|
57
|
-
"plugin": ["@fkqfkq123/opencode-autopilot"]
|
|
58
|
-
}
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
You can also pin a version:
|
|
62
|
-
|
|
63
|
-
```json
|
|
64
|
-
{
|
|
65
|
-
"plugin": ["@fkqfkq123/opencode-autopilot@0.1.2"]
|
|
66
|
-
}
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
In this mode, OpenCode installs and caches the npm package automatically. No manual `git clone`, local `plugin.js`, or extra install script is required.
|
|
70
|
-
|
|
71
|
-
### 4.2 Fallback: install from GitHub Releases
|
|
72
|
-
|
|
73
|
-
If you prefer a local-file installation path or need a fallback distribution mode, use the one-line installer from GitHub Releases:
|
|
74
|
-
|
|
75
|
-
```bash
|
|
76
|
-
curl -fsSL https://raw.githubusercontent.com/juhuaxia/Autopilot/main/install.sh | bash
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
Install a specific version:
|
|
80
|
-
|
|
81
|
-
```bash
|
|
82
|
-
curl -fsSL https://raw.githubusercontent.com/juhuaxia/Autopilot/main/install.sh | bash -s -- --version v0.1.2
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
The fallback installer will:
|
|
86
|
-
|
|
87
|
-
- download the prebuilt release package from GitHub Releases,
|
|
88
|
-
- install it into `~/.config/opencode/plugins/autopilot/`,
|
|
89
|
-
- update `~/.config/opencode/opencode.json`.
|
|
90
|
-
|
|
91
|
-
Release requirement:
|
|
92
|
-
|
|
93
|
-
- Each GitHub Release must include `autopilot-release.tar.gz`
|
|
94
|
-
- The repository includes `.github/workflows/release.yml`, which builds and uploads that file automatically on `v*` tags
|
|
95
|
-
|
|
96
|
-
If you want to modify the codebase or work from source, continue with the source setup below.
|
|
97
|
-
|
|
98
|
-
### 4.3 Clone the repository
|
|
99
|
-
|
|
100
|
-
```bash
|
|
101
|
-
git clone https://github.com/juhuaxia/Autopilot.git
|
|
102
|
-
cd Autopilot
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
### 4.4 Install dependencies
|
|
106
|
-
|
|
107
|
-
```bash
|
|
108
|
-
bun install
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
The project uses `bun.lock`, so dependencies are expected to stay reproducible.
|
|
112
|
-
|
|
113
|
-
## 5. Recommended first-run commands
|
|
114
|
-
|
|
115
|
-
Run these from the project root:
|
|
116
|
-
|
|
117
|
-
```bash
|
|
118
|
-
bun run src/cli.ts install
|
|
119
|
-
bun run src/cli.ts doctor
|
|
120
|
-
bun run build
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
What they do:
|
|
124
|
-
|
|
125
|
-
1. `install`
|
|
126
|
-
- creates project-level `.workflow-harness/autopilot.json`
|
|
127
|
-
- creates global `~/.config/opencode/autopilot.json` when missing
|
|
128
|
-
- tries to safely update `~/.config/opencode/opencode.json`
|
|
129
|
-
- normalizes `opencode.jsonc` into `opencode.json` when safe
|
|
130
|
-
2. `doctor`
|
|
131
|
-
- checks `autopilot.json`
|
|
132
|
-
- checks `skillRoots`
|
|
133
|
-
- checks phase-level `requiredSkills`
|
|
134
|
-
- reports warnings and missing pieces
|
|
135
|
-
3. `build`
|
|
136
|
-
- compiles TypeScript
|
|
137
|
-
- produces `dist/plugin.js`
|
|
138
|
-
|
|
139
|
-
After that, confirm:
|
|
140
|
-
|
|
141
|
-
- `.workflow-harness/autopilot.json` exists
|
|
142
|
-
- `doctor` shows no blocking configuration issue
|
|
143
|
-
- `dist/plugin.js` exists
|
|
144
|
-
|
|
145
|
-
## 6. Common development commands
|
|
146
|
-
|
|
147
|
-
### 6.1 Build
|
|
148
|
-
|
|
149
|
-
```bash
|
|
150
|
-
bun run build
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
### 6.2 Typecheck
|
|
154
|
-
|
|
155
|
-
```bash
|
|
156
|
-
bun run typecheck
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
### 6.3 Run tests
|
|
160
|
-
|
|
161
|
-
```bash
|
|
162
|
-
bun test
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
### 6.4 Run plugin smoke tests
|
|
166
|
-
|
|
167
|
-
```bash
|
|
168
|
-
bun run smoke:plugin
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
### 6.5 Run CLI commands directly
|
|
172
|
-
|
|
173
|
-
```bash
|
|
174
|
-
bun run src/cli.ts doctor
|
|
175
|
-
bun run src/cli.ts install
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
Or through the script alias:
|
|
179
|
-
|
|
180
|
-
```bash
|
|
181
|
-
bun run cli --help
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
> The CLI mainly provides workflow initialization, attach/status flows, and install/doctor actions.
|
|
185
|
-
|
|
186
|
-
## 7. CLI quick usage
|
|
187
|
-
|
|
188
|
-
### 7.1 Initialize config
|
|
189
|
-
|
|
190
|
-
```bash
|
|
191
|
-
bun run src/cli.ts install
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
### 7.2 Run a self-check
|
|
195
|
-
|
|
196
|
-
```bash
|
|
197
|
-
bun run src/cli.ts doctor
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
### 7.3 Create a workflow
|
|
201
|
-
|
|
202
|
-
```bash
|
|
203
|
-
bun run src/cli.ts workflow-open wf-1
|
|
204
|
-
```
|
|
205
|
-
|
|
206
|
-
### 7.4 Check workflow status
|
|
207
|
-
|
|
208
|
-
```bash
|
|
209
|
-
bun run src/cli.ts workflow-status wf-1
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
### 7.5 Re-attach to the workflow channel
|
|
213
|
-
|
|
214
|
-
```bash
|
|
215
|
-
bun run src/cli.ts workflow-attach wf-1
|
|
216
|
-
```
|
|
217
|
-
|
|
218
|
-
## 8. Loading the plugin into OpenCode
|
|
219
|
-
|
|
220
|
-
### 8.0 Recommended npm plugin path
|
|
221
|
-
|
|
222
|
-
Recommended OpenCode config:
|
|
9
|
+
Add the plugin to your OpenCode config:
|
|
223
10
|
|
|
224
11
|
```json
|
|
225
12
|
{
|
|
@@ -227,237 +14,109 @@ Recommended OpenCode config:
|
|
|
227
14
|
}
|
|
228
15
|
```
|
|
229
16
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
If you prefer a local installed fallback plugin, use:
|
|
233
|
-
|
|
234
|
-
```bash
|
|
235
|
-
curl -fsSL https://raw.githubusercontent.com/juhuaxia/Autopilot/main/install.sh | bash
|
|
236
|
-
```
|
|
237
|
-
|
|
238
|
-
Default install location:
|
|
239
|
-
|
|
240
|
-
```txt
|
|
241
|
-
~/.config/opencode/plugins/autopilot/
|
|
242
|
-
```
|
|
17
|
+
Restart `opencode`.
|
|
243
18
|
|
|
244
|
-
|
|
19
|
+
If the plugin loads correctly, you should see a log like:
|
|
245
20
|
|
|
246
21
|
```txt
|
|
247
|
-
|
|
248
|
-
```
|
|
249
|
-
|
|
250
|
-
### 8.2 Source-development path
|
|
251
|
-
|
|
252
|
-
Run:
|
|
253
|
-
|
|
254
|
-
```bash
|
|
255
|
-
bun run src/cli.ts install
|
|
256
|
-
bun run src/cli.ts doctor
|
|
257
|
-
```
|
|
258
|
-
|
|
259
|
-
If the installer can safely update the OpenCode config, you usually do not need to edit anything manually.
|
|
260
|
-
|
|
261
|
-
> `install.sh` targets GitHub Releases installs. The project-local installer targets source-development setups.
|
|
262
|
-
|
|
263
|
-
### 8.3 Manual plugin registration
|
|
264
|
-
|
|
265
|
-
OpenCode config is usually located at:
|
|
266
|
-
|
|
267
|
-
- `~/.config/opencode/opencode.json`
|
|
268
|
-
- or `~/.config/opencode/opencode.jsonc`
|
|
269
|
-
|
|
270
|
-
#### Option A: load the built plugin
|
|
271
|
-
|
|
272
|
-
Build first:
|
|
273
|
-
|
|
274
|
-
```bash
|
|
275
|
-
bun run build
|
|
276
|
-
```
|
|
277
|
-
|
|
278
|
-
Then add this to OpenCode config:
|
|
279
|
-
|
|
280
|
-
```json
|
|
281
|
-
{
|
|
282
|
-
"plugin": [
|
|
283
|
-
"file:///ABSOLUTE_PATH_TO_PROJECT/dist/plugin.js"
|
|
284
|
-
]
|
|
285
|
-
}
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
#### Option B: load source directly during development
|
|
289
|
-
|
|
290
|
-
```json
|
|
291
|
-
{
|
|
292
|
-
"plugin": [
|
|
293
|
-
"file:///ABSOLUTE_PATH_TO_PROJECT/plugin.ts"
|
|
294
|
-
]
|
|
295
|
-
}
|
|
22
|
+
[autopilot] Autopilot plugin loaded (... commands)
|
|
296
23
|
```
|
|
297
24
|
|
|
298
|
-
|
|
25
|
+
## Use
|
|
299
26
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
```bash
|
|
303
|
-
opencode
|
|
304
|
-
```
|
|
27
|
+
Start with a natural-language request, for example:
|
|
305
28
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
```bash
|
|
309
|
-
opencode serve
|
|
29
|
+
```txt
|
|
30
|
+
Add sorting to the product list page and make sure regression risks are reviewed.
|
|
310
31
|
```
|
|
311
32
|
|
|
312
|
-
|
|
33
|
+
Autopilot will guide the workflow through the available tools:
|
|
313
34
|
|
|
314
|
-
The plugin exposes these tools/commands:
|
|
315
|
-
|
|
316
|
-
- `workflow_channel`
|
|
317
35
|
- `workflow_open`
|
|
318
36
|
- `workflow_attach`
|
|
319
37
|
- `workflow_status`
|
|
320
38
|
- `workflow_answer`
|
|
321
39
|
- `workflow_approve`
|
|
322
40
|
- `workflow_resume`
|
|
323
|
-
- `workflow_back`
|
|
324
|
-
- `workflow_doctor`
|
|
325
41
|
|
|
326
|
-
|
|
42
|
+
You usually only need to follow the next recommended tool shown by the workflow output.
|
|
327
43
|
|
|
328
|
-
|
|
329
|
-
- `workflow_attach`
|
|
330
|
-
- `workflow_status`
|
|
331
|
-
- `workflow_answer`
|
|
332
|
-
- `workflow_approve`
|
|
333
|
-
- `workflow_resume`
|
|
334
|
-
- `workflow_back`
|
|
44
|
+
## Configuration
|
|
335
45
|
|
|
336
|
-
|
|
46
|
+
Autopilot automatically creates these files when needed:
|
|
337
47
|
|
|
338
48
|
```txt
|
|
339
|
-
|
|
49
|
+
.workflow-harness/autopilot.json
|
|
50
|
+
~/.config/opencode/autopilot.json
|
|
340
51
|
```
|
|
341
52
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
### 10.1 Configuration layers
|
|
345
|
-
|
|
346
|
-
- user default: `~/.config/opencode/autopilot.json`
|
|
347
|
-
- project override: `<repo>/.workflow-harness/autopilot.json`
|
|
348
|
-
- runtime state: `<repo>/.workflow-harness/workflows/<workflowId>/`
|
|
53
|
+
If they are left empty, Autopilot uses default behavior.
|
|
349
54
|
|
|
350
|
-
###
|
|
55
|
+
### `autopilot.json`
|
|
351
56
|
|
|
352
|
-
|
|
353
|
-
- `packages/runtime/` — workflow runtime implementation
|
|
354
|
-
- `tests/` — tests
|
|
355
|
-
- `scripts/` — auxiliary scripts
|
|
356
|
-
- `.workflow-harness/` — runtime config, state, and artifacts
|
|
357
|
-
- `dist/` — build output
|
|
358
|
-
|
|
359
|
-
## 11. Minimal `autopilot.json` example
|
|
360
|
-
|
|
361
|
-
Start with a fully neutral config:
|
|
57
|
+
Minimal example:
|
|
362
58
|
|
|
363
59
|
```json
|
|
364
60
|
{
|
|
365
61
|
"skillRoots": ["~/.claude/skills", "~/.config/opencode/skills"],
|
|
366
62
|
"phases": {
|
|
63
|
+
"spec_refinement": { "requiredSkills": [] },
|
|
64
|
+
"plan": { "requiredSkills": [] },
|
|
367
65
|
"develop": { "requiredSkills": [] },
|
|
66
|
+
"review": { "requiredSkills": [] },
|
|
368
67
|
"test": { "requiredSkills": [] }
|
|
369
68
|
}
|
|
370
69
|
}
|
|
371
70
|
```
|
|
372
71
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
```json
|
|
376
|
-
{
|
|
377
|
-
"skillRoots": ["~/.claude/skills", "~/.config/opencode/skills"],
|
|
378
|
-
"phases": {
|
|
379
|
-
"develop": { "requiredSkills": ["frontend-design"] },
|
|
380
|
-
"test": { "requiredSkills": ["playwright"] }
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
```
|
|
384
|
-
|
|
385
|
-
That frontend example is only an example. The workflow runtime is not frontend-bound by default.
|
|
72
|
+
Field meanings:
|
|
386
73
|
|
|
387
|
-
|
|
74
|
+
- `skillRoots`: directories to scan for skill files
|
|
75
|
+
- `phases.<phase>.requiredSkills`: skills to inject into that phase
|
|
388
76
|
|
|
389
|
-
|
|
390
|
-
- do not put skill config under `workflows/<workflowId>/`
|
|
391
|
-
- run `workflow_doctor` or CLI `doctor` before using a new config
|
|
77
|
+
Supported phases:
|
|
392
78
|
|
|
393
|
-
|
|
79
|
+
- `spec_refinement`
|
|
80
|
+
- `plan`
|
|
81
|
+
- `develop`
|
|
82
|
+
- `review`
|
|
83
|
+
- `test`
|
|
394
84
|
|
|
395
|
-
|
|
85
|
+
If an old `workflow.json` exists and `autopilot.json` does not, Autopilot can reuse the legacy file and warn you to migrate.
|
|
396
86
|
|
|
397
|
-
|
|
87
|
+
## Fallback Install
|
|
398
88
|
|
|
399
|
-
|
|
400
|
-
{
|
|
401
|
-
"plugin": [
|
|
402
|
-
"file:///Users/<your-user>/.config/opencode/plugins/autopilot/plugin.js"
|
|
403
|
-
]
|
|
404
|
-
}
|
|
405
|
-
```
|
|
406
|
-
|
|
407
|
-
For source development, you can also point to your local `dist/plugin.js`.
|
|
89
|
+
If you prefer a local file install instead of the npm package:
|
|
408
90
|
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
```json
|
|
412
|
-
{
|
|
413
|
-
"plugin": ["@fkqfkq123/opencode-autopilot"]
|
|
414
|
-
}
|
|
91
|
+
```bash
|
|
92
|
+
curl -fsSL https://raw.githubusercontent.com/juhuaxia/Autopilot/main/install.sh | bash
|
|
415
93
|
```
|
|
416
94
|
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
That usually means the host integration layer has not actually registered the exported `workflowCommands` onto the host command/tool surface.
|
|
420
|
-
|
|
421
|
-
### Q3: What should I validate first?
|
|
422
|
-
|
|
423
|
-
Validate this order first:
|
|
95
|
+
## Troubleshooting
|
|
424
96
|
|
|
425
|
-
|
|
426
|
-
2. the host can call the default export
|
|
427
|
-
3. the host receives a plugin-like object
|
|
97
|
+
### OpenCode fails to start
|
|
428
98
|
|
|
429
|
-
|
|
99
|
+
Temporarily remove the plugin from `opencode.json`, restart OpenCode, then re-enable it after checking the config.
|
|
430
100
|
|
|
431
|
-
###
|
|
101
|
+
### The plugin loads but workflow commands do not appear
|
|
432
102
|
|
|
433
|
-
|
|
103
|
+
This usually means the host did not register the exported workflow tools correctly.
|
|
434
104
|
|
|
435
|
-
|
|
105
|
+
### A workflow seems broken
|
|
436
106
|
|
|
437
|
-
|
|
438
|
-
|---|---|
|
|
439
|
-
| `README.md` | Main entry for installation, release, and usage |
|
|
440
|
-
| `WORKFLOW_SKILL_PROFILE_ARCHITECTURE_CN.md` | Skill/profile configuration design |
|
|
441
|
-
| `OPENCODE_WORKFLOW_AGENT_GUIDE.md` | Agent/tool calling loop |
|
|
442
|
-
| `REQUIREMENT_TEMPLATE.md` | Requirement input template |
|
|
107
|
+
Delete the project runtime folder and start again:
|
|
443
108
|
|
|
444
|
-
|
|
109
|
+
```bash
|
|
110
|
+
rm -rf .workflow-harness
|
|
111
|
+
```
|
|
445
112
|
|
|
446
|
-
##
|
|
113
|
+
## For source development
|
|
447
114
|
|
|
448
|
-
If you
|
|
115
|
+
If you want to work on the plugin itself:
|
|
449
116
|
|
|
450
117
|
```bash
|
|
451
118
|
bun install
|
|
452
|
-
bun run
|
|
453
|
-
bun
|
|
119
|
+
bun run typecheck
|
|
120
|
+
bun test
|
|
454
121
|
bun run build
|
|
455
|
-
opencode
|
|
456
122
|
```
|
|
457
|
-
|
|
458
|
-
Then:
|
|
459
|
-
|
|
460
|
-
1. confirm `.workflow-harness/autopilot.json` exists
|
|
461
|
-
2. confirm `dist/plugin.js` exists
|
|
462
|
-
3. if OpenCode does not auto-load the plugin, add `file:///ABSOLUTE_PATH_TO_PROJECT/dist/plugin.js` manually to config
|
|
463
|
-
4. verify `workflow_open`, `workflow_attach`, and `workflow_status` are visible in the host
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export type RecoveryState = "idle" | "recovering";
|
|
2
|
+
export type PhaseDispatchAttempts = Partial<Record<"spec_refinement" | "plan" | "develop" | "review" | "test", number>>;
|
|
2
3
|
export interface WorkflowRuntimeState {
|
|
3
4
|
workflowId: string;
|
|
4
5
|
preferredForegroundSessionId?: string | null;
|
|
@@ -11,4 +12,5 @@ export interface WorkflowRuntimeState {
|
|
|
11
12
|
refinementLastDispatchSummary?: string | null;
|
|
12
13
|
refinementEscalationReason?: string | null;
|
|
13
14
|
lastContinuationAt?: string;
|
|
15
|
+
phaseDispatchAttempts?: PhaseDispatchAttempts;
|
|
14
16
|
}
|
|
@@ -1,4 +1,24 @@
|
|
|
1
1
|
const MAX_SPEC_REFINEMENT_SELF_REPAIR_ATTEMPTS = 1;
|
|
2
|
+
const MAX_CONSECUTIVE_FAILURES = 3;
|
|
3
|
+
const MAX_REVIEW_OR_TEST_UNKNOWN_DISPATCH_ATTEMPTS = 3;
|
|
4
|
+
function getPhaseDispatchAttempts(runtime, phase) {
|
|
5
|
+
return runtime.phaseDispatchAttempts?.[phase] ?? 0;
|
|
6
|
+
}
|
|
7
|
+
function shouldEscalateUnknownConclusion(input, phase) {
|
|
8
|
+
if (getPhaseDispatchAttempts(input.runtime, phase) < MAX_REVIEW_OR_TEST_UNKNOWN_DISPATCH_ATTEMPTS) {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
const action = {
|
|
12
|
+
type: "blocked",
|
|
13
|
+
workflowId: input.workflow.workflowId,
|
|
14
|
+
phase,
|
|
15
|
+
reason: `${phase} exceeded dispatch retry budget and needs human decision`,
|
|
16
|
+
required: true,
|
|
17
|
+
createdAt: new Date().toISOString(),
|
|
18
|
+
...(input.artifact.summary ? { summary: input.artifact.summary } : {}),
|
|
19
|
+
};
|
|
20
|
+
return { type: "wait_human", action };
|
|
21
|
+
}
|
|
2
22
|
function nextPhaseFor(current) {
|
|
3
23
|
if (current === "spec_refinement")
|
|
4
24
|
return "plan";
|
|
@@ -68,6 +88,9 @@ export class DefaultPhaseTransition {
|
|
|
68
88
|
return { type: "stop", reason: "Background work still in progress" };
|
|
69
89
|
}
|
|
70
90
|
if (session.status === "failed") {
|
|
91
|
+
if (runtime.consecutiveFailures >= MAX_CONSECUTIVE_FAILURES) {
|
|
92
|
+
return { type: "recover", reason: "Exceeded consecutive failure retry budget" };
|
|
93
|
+
}
|
|
71
94
|
return { type: "recover", reason: "Relevant session failed" };
|
|
72
95
|
}
|
|
73
96
|
if (workflow.phase === "spec_refinement"
|
|
@@ -141,6 +164,17 @@ export class DefaultPhaseTransition {
|
|
|
141
164
|
reason: `Continue phase ${workflow.phase}`,
|
|
142
165
|
};
|
|
143
166
|
}
|
|
167
|
+
if (artifact.reportStatus === "unknown" && workflow.status === "in_progress" && (session.status === "idle" || session.status === "stale")) {
|
|
168
|
+
const escalation = shouldEscalateUnknownConclusion(input, "review");
|
|
169
|
+
if (escalation) {
|
|
170
|
+
return escalation;
|
|
171
|
+
}
|
|
172
|
+
return {
|
|
173
|
+
type: "dispatch",
|
|
174
|
+
phase: workflow.phase,
|
|
175
|
+
reason: "Review conclusion is still ambiguous; set an explicit PASS or FAIL conclusion",
|
|
176
|
+
};
|
|
177
|
+
}
|
|
144
178
|
}
|
|
145
179
|
if (workflow.phase === "test") {
|
|
146
180
|
if (artifact.valid && artifact.missing.length === 0 && artifact.reportStatus === "pass") {
|
|
@@ -171,6 +205,17 @@ export class DefaultPhaseTransition {
|
|
|
171
205
|
reason: `Continue phase ${workflow.phase}`,
|
|
172
206
|
};
|
|
173
207
|
}
|
|
208
|
+
if (artifact.reportStatus === "unknown" && workflow.status === "in_progress" && (session.status === "idle" || session.status === "stale")) {
|
|
209
|
+
const escalation = shouldEscalateUnknownConclusion(input, "test");
|
|
210
|
+
if (escalation) {
|
|
211
|
+
return escalation;
|
|
212
|
+
}
|
|
213
|
+
return {
|
|
214
|
+
type: "dispatch",
|
|
215
|
+
phase: workflow.phase,
|
|
216
|
+
reason: "Test conclusion is still ambiguous; set an explicit PASS or FAIL conclusion",
|
|
217
|
+
};
|
|
218
|
+
}
|
|
174
219
|
}
|
|
175
220
|
if (artifact.readyForNextPhase) {
|
|
176
221
|
const nextPhase = nextPhaseFor(workflow.phase);
|
|
@@ -145,6 +145,7 @@ const extractSectionBody = (content, heading, allHeadings) => {
|
|
|
145
145
|
return stripComments(content.slice(afterHeading, end));
|
|
146
146
|
};
|
|
147
147
|
const sectionHasContent = (content, heading, allHeadings) => extractSectionBody(content, heading, allHeadings).length > 0;
|
|
148
|
+
const isOptionalSection = (heading) => heading.includes("(如适用)") || heading.includes("(非阻塞,可选)");
|
|
148
149
|
const sanitizeSummaryBody = (body) => body
|
|
149
150
|
.split("\n")
|
|
150
151
|
.map((line) => line.trim())
|
|
@@ -1090,6 +1091,9 @@ export class FileSystemArtifactEvaluator {
|
|
|
1090
1091
|
missing.push(sectionRule.title);
|
|
1091
1092
|
}
|
|
1092
1093
|
for (const section of sectionRule.sections) {
|
|
1094
|
+
if (isOptionalSection(section)) {
|
|
1095
|
+
continue;
|
|
1096
|
+
}
|
|
1093
1097
|
if (!content.includes(section) || !sectionHasContent(content, section, sectionRule.sections)) {
|
|
1094
1098
|
missing.push(section);
|
|
1095
1099
|
}
|
|
@@ -1140,8 +1144,8 @@ export class FileSystemArtifactEvaluator {
|
|
|
1140
1144
|
readyForNextPhase: false,
|
|
1141
1145
|
missing,
|
|
1142
1146
|
summary: "审查报告结构不完整,暂不能决定 pass/fail",
|
|
1143
|
-
reportStatus:
|
|
1144
|
-
hasBlockingSeverity:
|
|
1147
|
+
reportStatus: getReportStatus(content),
|
|
1148
|
+
hasBlockingSeverity: hasBlockingSeverity(content),
|
|
1145
1149
|
};
|
|
1146
1150
|
}
|
|
1147
1151
|
if (phase === "test") {
|
|
@@ -1150,7 +1154,7 @@ export class FileSystemArtifactEvaluator {
|
|
|
1150
1154
|
readyForNextPhase: false,
|
|
1151
1155
|
missing,
|
|
1152
1156
|
summary: "测试报告证据不足,暂不能决定 pass/fail",
|
|
1153
|
-
reportStatus:
|
|
1157
|
+
reportStatus: getReportStatus(content),
|
|
1154
1158
|
hasBlockingSeverity: false,
|
|
1155
1159
|
};
|
|
1156
1160
|
}
|
|
@@ -14,6 +14,7 @@ export interface CreateHarnessOptions {
|
|
|
14
14
|
sessionClient?: OpencodeSessionClient;
|
|
15
15
|
opencodeBaseUrl?: string;
|
|
16
16
|
opencodePassword?: string;
|
|
17
|
+
homeDir?: string;
|
|
17
18
|
}
|
|
18
19
|
export declare function createHarness(baseDir: string, options?: CreateHarnessOptions): Promise<{
|
|
19
20
|
stateStore: FileSystemWorkflowStateStore;
|
|
@@ -22,9 +22,10 @@ export async function createHarness(baseDir, options = {}) {
|
|
|
22
22
|
await mkdir(join(baseDir, "workflows"), { recursive: true });
|
|
23
23
|
const workspace = new DefaultWorkflowWorkspace(baseDir);
|
|
24
24
|
await ensureAutopilotConfigFile(workspace.workflowConfigFile());
|
|
25
|
-
await ensureAutopilotConfigFile(join(homedir(), ".config", "opencode", AUTOPILOT_CONFIG_FILENAME));
|
|
25
|
+
await ensureAutopilotConfigFile(join(options.homeDir ?? homedir(), ".config", "opencode", AUTOPILOT_CONFIG_FILENAME));
|
|
26
26
|
const resolvedConfig = await resolveWorkflowConfig({
|
|
27
27
|
projectConfigFile: workspace.workflowConfigFile(),
|
|
28
|
+
...(options.homeDir ? { homeDir: options.homeDir } : {}),
|
|
28
29
|
});
|
|
29
30
|
const skillRegistryResult = await buildSkillRegistryWithWarnings(resolvedConfig.skillRoots);
|
|
30
31
|
const skillRegistry = skillRegistryResult.registry;
|
|
@@ -26,6 +26,7 @@ export async function initializeWorkflow(args) {
|
|
|
26
26
|
refinementAttempts: 0,
|
|
27
27
|
refinementLastDispatchSummary: null,
|
|
28
28
|
refinementEscalationReason: null,
|
|
29
|
+
phaseDispatchAttempts: {},
|
|
29
30
|
};
|
|
30
31
|
await stateStore.saveWorkflow(workflow);
|
|
31
32
|
await stateStore.saveRuntime(runtime);
|
|
@@ -20,4 +20,6 @@ export type WorkflowDoctorResult = {
|
|
|
20
20
|
nextSteps: string[];
|
|
21
21
|
warnings: string[];
|
|
22
22
|
};
|
|
23
|
-
export declare function runWorkflowDoctor(workspace: WorkflowWorkspace
|
|
23
|
+
export declare function runWorkflowDoctor(workspace: WorkflowWorkspace, options?: {
|
|
24
|
+
homeDir?: string;
|
|
25
|
+
}): Promise<WorkflowDoctorResult>;
|
|
@@ -27,11 +27,12 @@ function gitignoreHasWorkflowHarness(content) {
|
|
|
27
27
|
return normalized.includes(".workflow-harness/");
|
|
28
28
|
});
|
|
29
29
|
}
|
|
30
|
-
export async function runWorkflowDoctor(workspace) {
|
|
30
|
+
export async function runWorkflowDoctor(workspace, options = {}) {
|
|
31
31
|
const projectConfigFile = workspace.workflowConfigFile();
|
|
32
|
-
const globalConfigFile = join(homedir(), ".config", "opencode", AUTOPILOT_CONFIG_FILENAME);
|
|
32
|
+
const globalConfigFile = join(options.homeDir ?? homedir(), ".config", "opencode", AUTOPILOT_CONFIG_FILENAME);
|
|
33
33
|
const resolvedConfig = await resolveWorkflowConfig({
|
|
34
34
|
projectConfigFile,
|
|
35
|
+
...(options.homeDir ? { homeDir: options.homeDir } : {}),
|
|
35
36
|
});
|
|
36
37
|
const registryResult = await buildSkillRegistryWithWarnings(resolvedConfig.skillRoots);
|
|
37
38
|
const checks = [];
|
|
@@ -195,6 +195,12 @@ export class DefaultWorkflowEngine {
|
|
|
195
195
|
});
|
|
196
196
|
const waitRuntimePatch = {
|
|
197
197
|
waitingHumanActionId: record.id,
|
|
198
|
+
phaseDispatchAttempts: {
|
|
199
|
+
...(runtime.phaseDispatchAttempts ?? {}),
|
|
200
|
+
...(workflow.phase === "spec_refinement" || workflow.phase === "plan" || workflow.phase === "develop" || workflow.phase === "review" || workflow.phase === "test"
|
|
201
|
+
? { [workflow.phase]: 0 }
|
|
202
|
+
: {}),
|
|
203
|
+
},
|
|
198
204
|
...(workflow.phase === "spec_refinement" && (runtime.refinementAttempts ?? 0) > 0
|
|
199
205
|
? { refinementEscalationReason: "Autonomous refinement retry budget exhausted" }
|
|
200
206
|
: {}),
|
|
@@ -229,6 +235,8 @@ export class DefaultWorkflowEngine {
|
|
|
229
235
|
await this.deps.humanActionStore.markConsumed(currentHumanAction.id);
|
|
230
236
|
await this.deps.stateStore.updateRuntime(workflowId, {
|
|
231
237
|
waitingHumanActionId: null,
|
|
238
|
+
consecutiveFailures: 0,
|
|
239
|
+
phaseDispatchAttempts: {},
|
|
232
240
|
...(workflow.phase === "spec_refinement"
|
|
233
241
|
? {
|
|
234
242
|
refinementAttempts: 0,
|
|
@@ -275,6 +283,13 @@ export class DefaultWorkflowEngine {
|
|
|
275
283
|
: 0;
|
|
276
284
|
const runtimePatch = {
|
|
277
285
|
lastContinuationAt: new Date().toISOString(),
|
|
286
|
+
consecutiveFailures: 0,
|
|
287
|
+
phaseDispatchAttempts: {
|
|
288
|
+
...(runtime.phaseDispatchAttempts ?? {}),
|
|
289
|
+
...(action.phase === "spec_refinement" || action.phase === "plan" || action.phase === "develop" || action.phase === "review" || action.phase === "test"
|
|
290
|
+
? { [action.phase]: (runtime.phaseDispatchAttempts?.[action.phase] ?? 0) + 1 }
|
|
291
|
+
: {}),
|
|
292
|
+
},
|
|
278
293
|
...(action.phase === "spec_refinement"
|
|
279
294
|
? {
|
|
280
295
|
refinementAttempts: nextAttempt,
|
|
@@ -30,7 +30,7 @@ Hard rules:
|
|
|
30
30
|
- If the user provides natural language only, keep it as-is and let the workflow runtime + downstream AI refinement handle understanding and document selection.
|
|
31
31
|
`;
|
|
32
32
|
const WORKFLOW_PRIMARY_AGENT_DESCRIPTION = "Primary workflow agent that drives refine->plan->develop->review->test via workflow tools";
|
|
33
|
-
const WORKFLOW_PRIMARY_AGENT_MODEL = "
|
|
33
|
+
const WORKFLOW_PRIMARY_AGENT_MODEL = "openai/gpt-5.5";
|
|
34
34
|
function buildPrimaryAgentMetadata(baseDir) {
|
|
35
35
|
return {
|
|
36
36
|
name: "workflow",
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fkqfkq123/opencode-autopilot",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.8",
|
|
5
5
|
"description": "An OpenCode plugin for attached-session workflow execution with refinement, planning, development, review, and test phases.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"packageManager": "bun@1.3.5",
|