@fkqfkq123/opencode-autopilot 0.1.0 → 0.1.3

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # Autopilot
2
2
 
3
- English | [中文说明](./README.zh-CN.md)
3
+ English | [中文说明](./GUIDE.zh-CN.md)
4
4
 
5
5
  Autopilot is an OpenCode-oriented **attached-session workflow harness**. It provides a workflow runtime skeleton covering refinement, planning, development, review, and testing, plus a locally loadable plugin, CLI entrypoints, and diagnostics.
6
6
 
@@ -62,7 +62,7 @@ You can also pin a version:
62
62
 
63
63
  ```json
64
64
  {
65
- "plugin": ["@fkqfkq123/opencode-autopilot@0.1.0"]
65
+ "plugin": ["@fkqfkq123/opencode-autopilot@0.1.2"]
66
66
  }
67
67
  ```
68
68
 
@@ -79,7 +79,7 @@ curl -fsSL https://raw.githubusercontent.com/juhuaxia/Autopilot/main/install.sh
79
79
  Install a specific version:
80
80
 
81
81
  ```bash
82
- curl -fsSL https://raw.githubusercontent.com/juhuaxia/Autopilot/main/install.sh | bash -s -- --version v0.1.0
82
+ curl -fsSL https://raw.githubusercontent.com/juhuaxia/Autopilot/main/install.sh | bash -s -- --version v0.1.2
83
83
  ```
84
84
 
85
85
  The fallback installer will:
@@ -3,6 +3,11 @@ import { renderHumanActionBlock } from "../presentation/human-action-renderer";
3
3
  import { buildWorkflowOpenRequest } from "./workflow-open-request";
4
4
  import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
5
5
  import { join } from "node:path";
6
+ function assertWorkflowId(workflowId) {
7
+ if (!workflowId.trim()) {
8
+ throw new Error("workflowId is required for workflow commands");
9
+ }
10
+ }
6
11
  function extractSection(content, heading) {
7
12
  const start = content.indexOf(heading);
8
13
  if (start === -1) {
@@ -197,6 +202,7 @@ ${rawPayload}`;
197
202
  export class DefaultWorkflowCommandRunner {
198
203
  async run(args) {
199
204
  const { harness, command, workflowId, payload, foregroundSessionId } = args;
205
+ assertWorkflowId(workflowId);
200
206
  if (command === "workflow-open") {
201
207
  const openRequest = await buildWorkflowOpenRequest(payload, process.cwd());
202
208
  if (openRequest.needsClarification) {
@@ -9,6 +9,7 @@ import { mkdir, readFile, writeFile } from "node:fs/promises";
9
9
  import { homedir } from "node:os";
10
10
  import { join } from "node:path";
11
11
  import { z } from "zod";
12
+ const workflowIdSchema = z.string().min(1).describe("Workflow identifier");
12
13
  const WORKFLOW_PRIMARY_AGENT_PROMPT = `You are the workflow execution agent.
13
14
 
14
15
  Responsibilities:
@@ -252,7 +253,7 @@ export async function workflowPlugin(input) {
252
253
  args: {
253
254
  command: z.enum(commandNames)
254
255
  .describe("Workflow channel command to execute"),
255
- workflowId: z.string().describe("Workflow identifier"),
256
+ workflowId: workflowIdSchema,
256
257
  payload: z.string().optional().describe("Optional JSON/string payload for answer-like commands"),
257
258
  },
258
259
  execute: async (args, context) => {
@@ -262,7 +263,7 @@ export async function workflowPlugin(input) {
262
263
  workflow_open: {
263
264
  description: "Open or initialize a workflow channel and attach to it.",
264
265
  args: {
265
- workflowId: z.string().describe("Workflow identifier"),
266
+ workflowId: workflowIdSchema,
266
267
  payload: z.string().optional().describe("Initial request. Supports plain text or JSON: { prompt, docPaths[], projectContext }"),
267
268
  },
268
269
  execute: async (args, context) => invokeCommand("workflow-open", args.workflowId, args.payload, context?.sessionID),
@@ -270,21 +271,21 @@ export async function workflowPlugin(input) {
270
271
  workflow_attach: {
271
272
  description: "Attach to an existing workflow channel.",
272
273
  args: {
273
- workflowId: z.string().describe("Workflow identifier"),
274
+ workflowId: workflowIdSchema,
274
275
  },
275
276
  execute: async (args, context) => invokeCommand("workflow-attach", args.workflowId, undefined, context?.sessionID),
276
277
  },
277
278
  workflow_status: {
278
279
  description: "Render the current workflow status block.",
279
280
  args: {
280
- workflowId: z.string().describe("Workflow identifier"),
281
+ workflowId: workflowIdSchema,
281
282
  },
282
283
  execute: async (args, context) => invokeCommand("workflow-status", args.workflowId, undefined, context?.sessionID),
283
284
  },
284
285
  workflow_answer: {
285
286
  description: "Answer workflow clarification questions.",
286
287
  args: {
287
- workflowId: z.string().describe("Workflow identifier"),
288
+ workflowId: workflowIdSchema,
288
289
  payload: z.string().describe("JSON string payload for question answers"),
289
290
  },
290
291
  execute: async (args, context) => invokeCommand("workflow-answer", args.workflowId, args.payload, context?.sessionID),
@@ -292,21 +293,21 @@ export async function workflowPlugin(input) {
292
293
  workflow_approve: {
293
294
  description: "Approve the current workflow plan or decision.",
294
295
  args: {
295
- workflowId: z.string().describe("Workflow identifier"),
296
+ workflowId: workflowIdSchema,
296
297
  },
297
298
  execute: async (args, context) => invokeCommand("workflow-approve", args.workflowId, undefined, context?.sessionID),
298
299
  },
299
300
  workflow_resume: {
300
301
  description: "Resume a blocked workflow.",
301
302
  args: {
302
- workflowId: z.string().describe("Workflow identifier"),
303
+ workflowId: workflowIdSchema,
303
304
  },
304
305
  execute: async (args, context) => invokeCommand("workflow-resume", args.workflowId, undefined, context?.sessionID),
305
306
  },
306
307
  workflow_back: {
307
308
  description: "Leave the workflow channel without stopping the workflow.",
308
309
  args: {
309
- workflowId: z.string().describe("Workflow identifier"),
310
+ workflowId: workflowIdSchema,
310
311
  },
311
312
  execute: async (args, context) => invokeCommand("workflow-back", args.workflowId, undefined, context?.sessionID),
312
313
  },
@@ -3,11 +3,17 @@ import { dirname } from "node:path";
3
3
  export async function readJsonFile(filePath) {
4
4
  try {
5
5
  const raw = await readFile(filePath, "utf8");
6
+ if (!raw.trim()) {
7
+ return null;
8
+ }
6
9
  return JSON.parse(raw);
7
10
  }
8
11
  catch (error) {
9
12
  const message = error instanceof Error ? error.message : String(error);
10
- if (message.includes("ENOENT")) {
13
+ if (message.includes("ENOENT") || message.includes("ENOTDIR") || message.includes("EINVAL")) {
14
+ return null;
15
+ }
16
+ if (error instanceof SyntaxError) {
11
17
  return null;
12
18
  }
13
19
  throw error;
@@ -50,7 +50,9 @@ export class FileSystemHumanActionStore {
50
50
  const workflowsDir = this.workspace.workflowsRoot();
51
51
  let workflowIds = [];
52
52
  try {
53
- workflowIds = await readdir(workflowsDir);
53
+ workflowIds = (await readdir(workflowsDir, { withFileTypes: true }))
54
+ .filter((entry) => entry.isDirectory())
55
+ .map((entry) => entry.name);
54
56
  }
55
57
  catch (error) {
56
58
  const message = error instanceof Error ? error.message : String(error);
@@ -7,7 +7,9 @@ export class FileSystemWorkflowStateStore {
7
7
  }
8
8
  async listWorkflows() {
9
9
  try {
10
- const workflowIds = await readdir(this.workspace.workflowsRoot());
10
+ const workflowIds = (await readdir(this.workspace.workflowsRoot(), { withFileTypes: true }))
11
+ .filter((entry) => entry.isDirectory())
12
+ .map((entry) => entry.name);
11
13
  const items = await Promise.all(workflowIds.map((workflowId) => this.getWorkflow(workflowId)));
12
14
  return items.filter((item) => item !== null);
13
15
  }
@@ -16,6 +16,7 @@ export interface WorkflowWorkspace {
16
16
  export declare class DefaultWorkflowWorkspace implements WorkflowWorkspace {
17
17
  private readonly root;
18
18
  constructor(root: string);
19
+ private normalizeWorkflowId;
19
20
  baseDir(): string;
20
21
  workflowsRoot(): string;
21
22
  workflowConfigFile(): string;
@@ -4,6 +4,13 @@ export class DefaultWorkflowWorkspace {
4
4
  constructor(root) {
5
5
  this.root = root;
6
6
  }
7
+ normalizeWorkflowId(workflowId) {
8
+ const normalized = workflowId.trim();
9
+ if (!normalized) {
10
+ throw new Error("workflowId must be a non-empty string");
11
+ }
12
+ return normalized;
13
+ }
7
14
  baseDir() {
8
15
  return this.root;
9
16
  }
@@ -14,7 +21,7 @@ export class DefaultWorkflowWorkspace {
14
21
  return join(this.root, "workflow.json");
15
22
  }
16
23
  workflowDir(workflowId) {
17
- return join(this.workflowsRoot(), workflowId);
24
+ return join(this.workflowsRoot(), this.normalizeWorkflowId(workflowId));
18
25
  }
19
26
  artifactStateFile(workflowId) {
20
27
  return join(this.workflowDir(workflowId), "artifact-state.json");
package/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "name": "@fkqfkq123/opencode-autopilot",
3
3
  "private": false,
4
- "version": "0.1.0",
4
+ "version": "0.1.3",
5
+ "description": "An OpenCode plugin for attached-session workflow execution with refinement, planning, development, review, and test phases.",
5
6
  "type": "module",
6
7
  "packageManager": "bun@1.3.5",
7
8
  "main": "./dist/plugin.js",
package/README.zh-CN.md DELETED
@@ -1,464 +0,0 @@
1
- # Autopilot
2
-
3
- [English](./README.md) | 中文说明
4
-
5
- Autopilot 是一个面向 OpenCode 风格运行时的 **attached-session workflow harness**。它提供从需求精炼、计划、开发、评审到测试的 workflow runtime 骨架,以及可本地加载的插件、CLI 入口和诊断能力。
6
-
7
- ## 1. 这个项目提供什么
8
-
9
- - 完整 workflow phase 主链:`spec_refinement -> plan -> develop -> review -> test -> done`
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.0"]
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.0
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/workflow.json`
129
- - 尝试安全写入 `~/.config/opencode/opencode.json`
130
- - 如有 `opencode.jsonc`,在安全情况下归一化写回 `opencode.json`
131
- 2. `doctor`
132
- - 检查 `workflow.json`
133
- - 检查 `skillRoots`
134
- - 检查各 phase 的 `requiredSkills`
135
- - 输出告警与缺失项
136
- 3. `build`
137
- - 编译 TypeScript
138
- - 生成 `dist/plugin.js`
139
-
140
- 之后建议确认:
141
-
142
- - `.workflow-harness/workflow.json` 已生成
143
- - `doctor` 没有阻断性配置问题
144
- - `dist/plugin.js` 已生成
145
-
146
- ## 6. 常用开发命令
147
-
148
- ### 6.1 构建
149
-
150
- ```bash
151
- bun run build
152
- ```
153
-
154
- ### 6.2 类型检查
155
-
156
- ```bash
157
- bun run typecheck
158
- ```
159
-
160
- ### 6.3 运行测试
161
-
162
- ```bash
163
- bun test
164
- ```
165
-
166
- ### 6.4 运行插件 smoke test
167
-
168
- ```bash
169
- bun run smoke:plugin
170
- ```
171
-
172
- ### 6.5 直接运行 CLI
173
-
174
- ```bash
175
- bun run src/cli.ts doctor
176
- bun run src/cli.ts install
177
- ```
178
-
179
- 也可以通过脚本别名运行:
180
-
181
- ```bash
182
- bun run cli --help
183
- ```
184
-
185
- > CLI 主要用于 workflow 初始化、attach/status 流程以及 install/doctor 动作。
186
-
187
- ## 7. CLI 快速使用
188
-
189
- ### 7.1 初始化配置
190
-
191
- ```bash
192
- bun run src/cli.ts install
193
- ```
194
-
195
- ### 7.2 做一次自检
196
-
197
- ```bash
198
- bun run src/cli.ts doctor
199
- ```
200
-
201
- ### 7.3 创建一个 workflow
202
-
203
- ```bash
204
- bun run src/cli.ts workflow-open wf-1
205
- ```
206
-
207
- ### 7.4 查看 workflow 状态
208
-
209
- ```bash
210
- bun run src/cli.ts workflow-status wf-1
211
- ```
212
-
213
- ### 7.5 重新 attach 到 workflow channel
214
-
215
- ```bash
216
- bun run src/cli.ts workflow-attach wf-1
217
- ```
218
-
219
- ## 8. 如何把插件加载到 OpenCode
220
-
221
- ### 8.0 推荐的 npm 插件方式
222
-
223
- 推荐的 OpenCode 配置:
224
-
225
- ```json
226
- {
227
- "plugin": ["@fkqfkq123/opencode-autopilot"]
228
- }
229
- ```
230
-
231
- ### 8.1 备用的 release 安装方式
232
-
233
- 如果你希望使用本地安装后的 fallback 插件,执行:
234
-
235
- ```bash
236
- curl -fsSL https://raw.githubusercontent.com/juhuaxia/Autopilot/main/install.sh | bash
237
- ```
238
-
239
- 默认安装位置:
240
-
241
- ```txt
242
- ~/.config/opencode/plugins/autopilot/
243
- ```
244
-
245
- 安装脚本会写入类似这样的插件入口:
246
-
247
- ```txt
248
- file:///Users/<your-user>/.config/opencode/plugins/autopilot/plugin.js
249
- ```
250
-
251
- ### 8.2 源码开发方式
252
-
253
- 执行:
254
-
255
- ```bash
256
- bun run src/cli.ts install
257
- bun run src/cli.ts doctor
258
- ```
259
-
260
- 如果 installer 能安全改写 OpenCode 配置,通常不需要手工编辑。
261
-
262
- > `install.sh` 面向 GitHub Releases 安装;项目内 installer 面向源码开发场景。
263
-
264
- ### 8.3 手工注册插件
265
-
266
- OpenCode 配置通常在:
267
-
268
- - `~/.config/opencode/opencode.json`
269
- - 或 `~/.config/opencode/opencode.jsonc`
270
-
271
- #### 方案 A:加载构建产物
272
-
273
- 先构建:
274
-
275
- ```bash
276
- bun run build
277
- ```
278
-
279
- 然后在 OpenCode 配置中加入:
280
-
281
- ```json
282
- {
283
- "plugin": [
284
- "file:///ABSOLUTE_PATH_TO_PROJECT/dist/plugin.js"
285
- ]
286
- }
287
- ```
288
-
289
- #### 方案 B:开发阶段直接加载源码
290
-
291
- ```json
292
- {
293
- "plugin": [
294
- "file:///ABSOLUTE_PATH_TO_PROJECT/plugin.ts"
295
- ]
296
- }
297
- ```
298
-
299
- ### 8.4 启动 OpenCode
300
-
301
- 交互模式:
302
-
303
- ```bash
304
- opencode
305
- ```
306
-
307
- Server 模式:
308
-
309
- ```bash
310
- opencode serve
311
- ```
312
-
313
- ## 9. 加载成功后你应该看到什么
314
-
315
- 插件会暴露这些工具/命令:
316
-
317
- - `workflow_channel`
318
- - `workflow_open`
319
- - `workflow_attach`
320
- - `workflow_status`
321
- - `workflow_answer`
322
- - `workflow_approve`
323
- - `workflow_resume`
324
- - `workflow_back`
325
- - `workflow_doctor`
326
-
327
- 推荐优先使用 split tools:
328
-
329
- - `workflow_open`
330
- - `workflow_attach`
331
- - `workflow_status`
332
- - `workflow_answer`
333
- - `workflow_approve`
334
- - `workflow_resume`
335
- - `workflow_back`
336
-
337
- 典型加载日志:
338
-
339
- ```txt
340
- [autopilot] Autopilot plugin loaded (... commands)
341
- ```
342
-
343
- ## 10. 目录结构
344
-
345
- ### 10.1 配置层级
346
-
347
- - 用户默认:`~/.config/opencode/workflow.json`
348
- - 项目级覆盖:`<repo>/.workflow-harness/workflow.json`
349
- - 运行时状态:`<repo>/.workflow-harness/workflows/<workflowId>/`
350
-
351
- ### 10.2 各目录作用
352
-
353
- - `src/` — CLI 入口与顶层源码
354
- - `packages/runtime/` — workflow runtime 实现
355
- - `tests/` — 测试
356
- - `scripts/` — 辅助脚本
357
- - `.workflow-harness/` — 运行时配置、状态与产物
358
- - `dist/` — 构建输出
359
-
360
- ## 11. 最小 `workflow.json` 示例
361
-
362
- 先从完全中性的配置开始:
363
-
364
- ```json
365
- {
366
- "skillRoots": ["~/.claude/skills", "~/.config/opencode/skills"],
367
- "phases": {
368
- "develop": { "requiredSkills": [] },
369
- "test": { "requiredSkills": [] }
370
- }
371
- }
372
- ```
373
-
374
- 然后按项目需要添加 skill。以前端项目为例:
375
-
376
- ```json
377
- {
378
- "skillRoots": ["~/.claude/skills", "~/.config/opencode/skills"],
379
- "phases": {
380
- "develop": { "requiredSkills": ["frontend-design"] },
381
- "test": { "requiredSkills": ["playwright"] }
382
- }
383
- }
384
- ```
385
-
386
- 这个前端示例只是示例,workflow runtime 默认并不绑定前端。
387
-
388
- 建议:
389
-
390
- - skill / profile 配置放在全局或项目级 `workflow.json`
391
- - 不要把 skill 配置写到 `workflows/<workflowId>/`
392
- - 新配置上线前先跑 `workflow_doctor` 或 CLI `doctor`
393
-
394
- ## 12. 常见问题
395
-
396
- ### Q1:`install` 无法改写 OpenCode 配置怎么办?
397
-
398
- 手工编辑 OpenCode 配置,把发布版插件路径或本地构建路径加入 `plugin` 数组。例如:
399
-
400
- ```json
401
- {
402
- "plugin": [
403
- "file:///Users/<your-user>/.config/opencode/plugins/autopilot/plugin.js"
404
- ]
405
- }
406
- ```
407
-
408
- 如果你是源码开发场景,也可以指向本地的 `dist/plugin.js`。
409
-
410
- 如果你使用 npm 插件模式,则只需要这样配置:
411
-
412
- ```json
413
- {
414
- "plugin": ["@fkqfkq123/opencode-autopilot"]
415
- }
416
- ```
417
-
418
- ### Q2:为什么 build 以后还是看不到 workflow 命令?
419
-
420
- 通常是宿主集成层还没有把导出的 `workflowCommands` 真正注册到宿主命令面板 / tool surface。
421
-
422
- ### Q3:我应该先验证什么?
423
-
424
- 建议先按这个顺序验证:
425
-
426
- 1. 宿主能导入插件文件
427
- 2. 宿主能调用默认导出
428
- 3. 宿主能收到一个 plugin-like 对象
429
-
430
- 不要一开始就先验证 UI。
431
-
432
- ### Q4:插件根入口有什么约束?
433
-
434
- 根入口 `plugin.ts` 应只暴露一个宿主可调用的默认导出,不要在根入口额外暴露内部 class 或 helper function。
435
-
436
- ## 13. 推荐阅读
437
-
438
- | 文档 | 用途 |
439
- |---|---|
440
- | `README.md` | 安装、发布、使用总入口 |
441
- | `WORKFLOW_SKILL_PROFILE_ARCHITECTURE_CN.md` | skill / profile 配置设计 |
442
- | `OPENCODE_WORKFLOW_AGENT_GUIDE.md` | agent / tool 调用顺序 |
443
- | `REQUIREMENT_TEMPLATE.md` | 需求输入模板 |
444
-
445
- 内部规划稿、验收草案、状态记录等可以保存在本地 `docs_internal/` 中,该目录默认已忽略。
446
-
447
- ## 14. 最快可用路径
448
-
449
- 如果你只想最快跑起源码开发环境:
450
-
451
- ```bash
452
- bun install
453
- bun run src/cli.ts install
454
- bun run src/cli.ts doctor
455
- bun run build
456
- opencode
457
- ```
458
-
459
- 然后:
460
-
461
- 1. 确认 `.workflow-harness/workflow.json` 已生成
462
- 2. 确认 `dist/plugin.js` 已生成
463
- 3. 如果 OpenCode 没有自动加载插件,手工把 `file:///ABSOLUTE_PATH_TO_PROJECT/dist/plugin.js` 加到配置里
464
- 4. 在宿主中验证 `workflow_open`、`workflow_attach`、`workflow_status` 是否可见