@devcxl/opencode-cabbage 0.2.0 → 0.3.0
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 +57 -54
- package/README.zh.md +91 -0
- package/assets/agents/dev-lifecycle.md +28 -22
- package/assets/agents/team/architect.md +14 -0
- package/assets/agents/team/backend.md +14 -0
- package/assets/agents/team/frontend.md +14 -0
- package/assets/agents/team/goal-verify.md +54 -0
- package/assets/agents/team/reviewer.md +10 -0
- package/assets/skills/flow-code/SKILL.md +13 -0
- package/assets/skills/flow-review/SKILL.md +7 -0
- package/assets/skills/flow-tasks/SKILL.md +42 -0
- package/assets/skills/flow-tdd/SKILL.md +208 -0
- package/dist/flowrun/adapter.d.ts +49 -0
- package/dist/flowrun/adapter.js +293 -0
- package/dist/flowrun/adapter.js.map +1 -0
- package/dist/flowrun/ci.d.ts +64 -0
- package/dist/flowrun/ci.js +184 -0
- package/dist/flowrun/ci.js.map +1 -0
- package/dist/flowrun/coverage.d.ts +70 -0
- package/dist/flowrun/coverage.js +207 -0
- package/dist/flowrun/coverage.js.map +1 -0
- package/dist/flowrun/digest.d.ts +17 -0
- package/dist/flowrun/digest.js +301 -0
- package/dist/flowrun/digest.js.map +1 -0
- package/dist/flowrun/evaluator.d.ts +38 -0
- package/dist/flowrun/evaluator.js +185 -0
- package/dist/flowrun/evaluator.js.map +1 -0
- package/dist/flowrun/gate.d.ts +20 -0
- package/dist/flowrun/gate.js +40 -3
- package/dist/flowrun/gate.js.map +1 -1
- package/dist/flowrun/github.d.ts +13 -9
- package/dist/flowrun/github.js +46 -26
- package/dist/flowrun/github.js.map +1 -1
- package/dist/flowrun/index.d.ts +12 -4
- package/dist/flowrun/index.js +11 -3
- package/dist/flowrun/index.js.map +1 -1
- package/dist/flowrun/merge.d.ts +35 -2
- package/dist/flowrun/merge.js +72 -8
- package/dist/flowrun/merge.js.map +1 -1
- package/dist/flowrun/migration.d.ts +11 -0
- package/dist/flowrun/migration.js +276 -0
- package/dist/flowrun/migration.js.map +1 -0
- package/dist/flowrun/pr.d.ts +132 -0
- package/dist/flowrun/pr.js +343 -0
- package/dist/flowrun/pr.js.map +1 -0
- package/dist/flowrun/state.d.ts +79 -0
- package/dist/flowrun/state.js +363 -0
- package/dist/flowrun/state.js.map +1 -0
- package/dist/flowrun/transitions.d.ts +66 -0
- package/dist/flowrun/transitions.js +168 -0
- package/dist/flowrun/transitions.js.map +1 -0
- package/dist/flowrun/types.d.ts +279 -4
- package/dist/flowrun/types.js +2 -1
- package/dist/flowrun/types.js.map +1 -1
- package/dist/flowrun/validator.d.ts +15 -5
- package/dist/flowrun/validator.js +117 -5
- package/dist/flowrun/validator.js.map +1 -1
- package/dist/plugin/agents.d.ts +4 -0
- package/dist/plugin/agents.js +19 -0
- package/dist/plugin/agents.js.map +1 -1
- package/dist/plugin/broker.d.ts +73 -0
- package/dist/plugin/broker.js +140 -0
- package/dist/plugin/broker.js.map +1 -0
- package/dist/plugin/flow-pr-tool.d.ts +37 -0
- package/dist/plugin/flow-pr-tool.js +176 -0
- package/dist/plugin/flow-pr-tool.js.map +1 -0
- package/dist/plugin/goal.d.ts +39 -1
- package/dist/plugin/goal.js +80 -1
- package/dist/plugin/goal.js.map +1 -1
- package/dist/plugin/prompt-lint.js +129 -0
- package/dist/plugin/prompt-lint.js.map +1 -1
- package/dist/plugin/server.d.ts +8 -0
- package/dist/plugin/server.js +306 -11
- package/dist/plugin/server.js.map +1 -1
- package/dist/plugin/shell.d.ts +37 -0
- package/dist/plugin/shell.js +144 -0
- package/dist/plugin/shell.js.map +1 -0
- package/dist/plugin/tdd-tool.d.ts +62 -0
- package/dist/plugin/tdd-tool.js +336 -0
- package/dist/plugin/tdd-tool.js.map +1 -0
- package/dist/util/gh.d.ts +8 -1
- package/dist/util/gh.js +10 -2
- package/dist/util/gh.js.map +1 -1
- package/package.json +2 -1
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { FlowRun } from "../flowrun/types.js";
|
|
2
|
+
export interface BrokerCredentials {
|
|
3
|
+
/** 独立 GitHub API token(不传入 Agent shell) */
|
|
4
|
+
token: string;
|
|
5
|
+
}
|
|
6
|
+
export interface MutateResult<R> {
|
|
7
|
+
flowRun: FlowRun;
|
|
8
|
+
result: R;
|
|
9
|
+
shouldPersist: boolean;
|
|
10
|
+
}
|
|
11
|
+
export type WriteResult<R> = {
|
|
12
|
+
ok: true;
|
|
13
|
+
flowRun: FlowRun;
|
|
14
|
+
result: R;
|
|
15
|
+
persisted: boolean;
|
|
16
|
+
} | {
|
|
17
|
+
ok: false;
|
|
18
|
+
code: "PERSIST_CONFLICT" | "READ_FAILED";
|
|
19
|
+
message: string;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* 单进程 broker,负责:
|
|
23
|
+
* 1. 按 parentIssueNumber 的 keyed mutex 串行所有 FlowRun 写入
|
|
24
|
+
* 2. read-modify-write 循环(乐观锁)
|
|
25
|
+
* 3. 检测外部 body 变化 → PERSIST_CONFLICT
|
|
26
|
+
* 4. 持有独立 GitHub API 凭证,Agent shell 不可访问
|
|
27
|
+
*
|
|
28
|
+
* 所有 FlowRun/Task/Evidence 写入必须经过 broker,不直接暴露 GitHub API。
|
|
29
|
+
*
|
|
30
|
+
* 凭证安全:credentials 存储在闭包变量中,不挂载在 this 上,
|
|
31
|
+
* JSON.stringify / Object.keys 无法访问。
|
|
32
|
+
*/
|
|
33
|
+
export declare class FlowBroker {
|
|
34
|
+
#private;
|
|
35
|
+
private mutex;
|
|
36
|
+
/**
|
|
37
|
+
* @param credentials 可选。独立 GitHub API 凭证。
|
|
38
|
+
* 传入时:所有 gh 操作使用该 token,而非 ambient 环境。
|
|
39
|
+
* 不传时:降级使用 ambient 环境变量(GH_TOKEN etc.)。
|
|
40
|
+
*/
|
|
41
|
+
constructor(credentials?: BrokerCredentials);
|
|
42
|
+
/**
|
|
43
|
+
* 获取凭证对应的环境变量覆盖(仅内部使用)。
|
|
44
|
+
* 返回 undefined 表示无独立凭证,应使用 ambient 环境。
|
|
45
|
+
*/
|
|
46
|
+
private get ghEnv();
|
|
47
|
+
/**
|
|
48
|
+
* 验证 broker 持有的 GitHub 凭证是否有效。
|
|
49
|
+
*
|
|
50
|
+
* 调用 `gh auth status` 检查 token 可用性。
|
|
51
|
+
* 无凭证时返回 ok: false。
|
|
52
|
+
*/
|
|
53
|
+
verifyCredentials(): Promise<{
|
|
54
|
+
ok: boolean;
|
|
55
|
+
message: string;
|
|
56
|
+
}>;
|
|
57
|
+
/**
|
|
58
|
+
* 将操作加入 keyed mutex 队列。
|
|
59
|
+
*
|
|
60
|
+
* 用于需要串行化但对 FlowRun 无影响的通用操作。
|
|
61
|
+
*/
|
|
62
|
+
enqueue<T>(parentIssueNumber: number, op: () => Promise<T>): Promise<T>;
|
|
63
|
+
/**
|
|
64
|
+
* read-modify-write 循环:读取 FlowRun → 应用 handler 变更 → 乐观锁写回。
|
|
65
|
+
*
|
|
66
|
+
* - handler 返回 { flowRun, result, shouldPersist }
|
|
67
|
+
* - shouldPersist=false 时跳过写入(如校验失败)
|
|
68
|
+
* - 自动增加 revision 和时间戳
|
|
69
|
+
* - body 不匹配时返回 PERSIST_CONFLICT
|
|
70
|
+
* - 使用 broker 独立凭证执行 gh 操作
|
|
71
|
+
*/
|
|
72
|
+
writeFlowRunWithLock<R>(issueNumber: number, handler: (flowRun: FlowRun) => MutateResult<R>): Promise<WriteResult<R>>;
|
|
73
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { readFlowRunWithLock, writeFlowRunWithLock as ghWriteFlowRunWithLock } from "../flowrun/github.js";
|
|
2
|
+
// ─── Keyed Mutex ───
|
|
3
|
+
/**
|
|
4
|
+
* 按 key 隔离的互斥锁,用于单进程内串行化并发操作。
|
|
5
|
+
*
|
|
6
|
+
* 每个 key(parentIssueNumber)维护独立的 promise 链,
|
|
7
|
+
* 相同 key 的操作依次执行,不同 key 的操作可以并行。
|
|
8
|
+
*/
|
|
9
|
+
class KeyedMutex {
|
|
10
|
+
locks = new Map();
|
|
11
|
+
async runExclusive(key, fn) {
|
|
12
|
+
const prev = this.locks.get(key) ?? Promise.resolve();
|
|
13
|
+
let release;
|
|
14
|
+
const next = new Promise(r => {
|
|
15
|
+
release = r;
|
|
16
|
+
});
|
|
17
|
+
this.locks.set(key, next);
|
|
18
|
+
await prev;
|
|
19
|
+
try {
|
|
20
|
+
return await fn();
|
|
21
|
+
}
|
|
22
|
+
finally {
|
|
23
|
+
release();
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
// ─── FlowBroker ───
|
|
28
|
+
/**
|
|
29
|
+
* 单进程 broker,负责:
|
|
30
|
+
* 1. 按 parentIssueNumber 的 keyed mutex 串行所有 FlowRun 写入
|
|
31
|
+
* 2. read-modify-write 循环(乐观锁)
|
|
32
|
+
* 3. 检测外部 body 变化 → PERSIST_CONFLICT
|
|
33
|
+
* 4. 持有独立 GitHub API 凭证,Agent shell 不可访问
|
|
34
|
+
*
|
|
35
|
+
* 所有 FlowRun/Task/Evidence 写入必须经过 broker,不直接暴露 GitHub API。
|
|
36
|
+
*
|
|
37
|
+
* 凭证安全:credentials 存储在闭包变量中,不挂载在 this 上,
|
|
38
|
+
* JSON.stringify / Object.keys 无法访问。
|
|
39
|
+
*/
|
|
40
|
+
export class FlowBroker {
|
|
41
|
+
mutex = new KeyedMutex();
|
|
42
|
+
#credentials;
|
|
43
|
+
/**
|
|
44
|
+
* @param credentials 可选。独立 GitHub API 凭证。
|
|
45
|
+
* 传入时:所有 gh 操作使用该 token,而非 ambient 环境。
|
|
46
|
+
* 不传时:降级使用 ambient 环境变量(GH_TOKEN etc.)。
|
|
47
|
+
*/
|
|
48
|
+
constructor(credentials) {
|
|
49
|
+
this.#credentials = credentials ?? null;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* 获取凭证对应的环境变量覆盖(仅内部使用)。
|
|
53
|
+
* 返回 undefined 表示无独立凭证,应使用 ambient 环境。
|
|
54
|
+
*/
|
|
55
|
+
get ghEnv() {
|
|
56
|
+
if (!this.#credentials)
|
|
57
|
+
return undefined;
|
|
58
|
+
return {
|
|
59
|
+
GH_TOKEN: this.#credentials.token,
|
|
60
|
+
GITHUB_TOKEN: this.#credentials.token,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* 验证 broker 持有的 GitHub 凭证是否有效。
|
|
65
|
+
*
|
|
66
|
+
* 调用 `gh auth status` 检查 token 可用性。
|
|
67
|
+
* 无凭证时返回 ok: false。
|
|
68
|
+
*/
|
|
69
|
+
async verifyCredentials() {
|
|
70
|
+
if (!this.#credentials) {
|
|
71
|
+
return { ok: false, message: "No broker credentials configured" };
|
|
72
|
+
}
|
|
73
|
+
try {
|
|
74
|
+
const { gh } = await import("../util/gh.js");
|
|
75
|
+
await gh("auth status", 15_000, this.ghEnv);
|
|
76
|
+
return { ok: true, message: "Broker credentials are valid" };
|
|
77
|
+
}
|
|
78
|
+
catch (err) {
|
|
79
|
+
return { ok: false, message: `Broker credentials verification failed: ${String(err)}` };
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* 将操作加入 keyed mutex 队列。
|
|
84
|
+
*
|
|
85
|
+
* 用于需要串行化但对 FlowRun 无影响的通用操作。
|
|
86
|
+
*/
|
|
87
|
+
async enqueue(parentIssueNumber, op) {
|
|
88
|
+
return this.mutex.runExclusive(parentIssueNumber, op);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* read-modify-write 循环:读取 FlowRun → 应用 handler 变更 → 乐观锁写回。
|
|
92
|
+
*
|
|
93
|
+
* - handler 返回 { flowRun, result, shouldPersist }
|
|
94
|
+
* - shouldPersist=false 时跳过写入(如校验失败)
|
|
95
|
+
* - 自动增加 revision 和时间戳
|
|
96
|
+
* - body 不匹配时返回 PERSIST_CONFLICT
|
|
97
|
+
* - 使用 broker 独立凭证执行 gh 操作
|
|
98
|
+
*/
|
|
99
|
+
async writeFlowRunWithLock(issueNumber, handler) {
|
|
100
|
+
return this.mutex.runExclusive(issueNumber, async () => {
|
|
101
|
+
// ── 读取(broker 凭证) ──
|
|
102
|
+
const { flowRunResult, currentBody } = await readFlowRunWithLock(issueNumber, this.ghEnv);
|
|
103
|
+
if (!flowRunResult.ok || currentBody === null) {
|
|
104
|
+
return {
|
|
105
|
+
ok: false,
|
|
106
|
+
code: "READ_FAILED",
|
|
107
|
+
message: `Failed to read FlowRun from issue #${issueNumber}: ${flowRunResult.ok ? "missing body" : flowRunResult.code}`,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
// ── 修改 ──
|
|
111
|
+
const { flowRun: updated, result, shouldPersist } = handler(flowRunResult.data);
|
|
112
|
+
if (!shouldPersist) {
|
|
113
|
+
return {
|
|
114
|
+
ok: true,
|
|
115
|
+
flowRun: flowRunResult.data,
|
|
116
|
+
result,
|
|
117
|
+
persisted: false,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
// ── 写入(乐观锁,broker 凭证) ──
|
|
121
|
+
updated.revision += 1;
|
|
122
|
+
updated.lastTickAt = new Date().toISOString();
|
|
123
|
+
const writeResult = await ghWriteFlowRunWithLock(issueNumber, updated, currentBody, this.ghEnv);
|
|
124
|
+
if (!writeResult.success) {
|
|
125
|
+
return {
|
|
126
|
+
ok: false,
|
|
127
|
+
code: "PERSIST_CONFLICT",
|
|
128
|
+
message: writeResult.error ?? "Issue body changed since last read — external modification detected",
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
return {
|
|
132
|
+
ok: true,
|
|
133
|
+
flowRun: updated,
|
|
134
|
+
result,
|
|
135
|
+
persisted: true,
|
|
136
|
+
};
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=broker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"broker.js","sourceRoot":"","sources":["../../src/plugin/broker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { FlowBroker } from "./broker.js";
|
|
2
|
+
export interface FlowPRCreateRequest {
|
|
3
|
+
op: string;
|
|
4
|
+
parentIssueNumber: number;
|
|
5
|
+
taskId?: string;
|
|
6
|
+
currentHeadSha?: string;
|
|
7
|
+
prTitle?: string;
|
|
8
|
+
prBody?: string;
|
|
9
|
+
baseBranch?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface FlowPRCreateResponse {
|
|
12
|
+
ok: boolean;
|
|
13
|
+
conflictPause: boolean;
|
|
14
|
+
persisted: boolean;
|
|
15
|
+
prNumber?: number;
|
|
16
|
+
prUrl?: string;
|
|
17
|
+
created?: boolean;
|
|
18
|
+
taskStatus?: string;
|
|
19
|
+
error?: {
|
|
20
|
+
code: string;
|
|
21
|
+
message: string;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* 通过 FlowBroker 执行 flow_pr create 操作。
|
|
26
|
+
*
|
|
27
|
+
* 流程:
|
|
28
|
+
* 1. 通过 broker.writeFlowRunWithLock 读取 FlowRun
|
|
29
|
+
* 2. 提取目标 TaskState,执行 preflight
|
|
30
|
+
* 3. 调用 createOrReusePR(幂等:已有 PR 则复用)
|
|
31
|
+
* 4. 写入 prNumber + 初始化 prCheckpoints → task status → "reviewing"
|
|
32
|
+
* 5. 成功时持久化回 Issue(broker 自动处理 revision + 乐观锁)
|
|
33
|
+
* 6. PERSIST_CONFLICT 时设置 conflictPause=true
|
|
34
|
+
*
|
|
35
|
+
* 补偿:GitHub 创建成功但 FlowRun 写入失败 → 重试时通过 head branch 找回同一 PR
|
|
36
|
+
*/
|
|
37
|
+
export declare function handleFlowPrCreateWithBroker(broker: FlowBroker, req: FlowPRCreateRequest): Promise<FlowPRCreateResponse>;
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { preflightPRCreate, createOrReusePR } from "../flowrun/pr.js";
|
|
2
|
+
// ─── 内部辅助 ───
|
|
3
|
+
function initPRCheckpoints(prNumber) {
|
|
4
|
+
return {
|
|
5
|
+
prNumber,
|
|
6
|
+
localChecks: { name: "localChecks", status: "pending", evidence: [] },
|
|
7
|
+
ciChecks: { name: "ciChecks", status: "pending", evidence: [] },
|
|
8
|
+
reviewerApproval: { name: "reviewerApproval", status: "pending", evidence: [] },
|
|
9
|
+
goalVerification: { name: "goalVerification", status: "pending", evidence: [] },
|
|
10
|
+
branchProtection: { name: "branchProtection", status: "pending", evidence: [] },
|
|
11
|
+
mergeResult: { name: "mergeResult", status: "pending", evidence: [] },
|
|
12
|
+
tddCompliance: null,
|
|
13
|
+
verification: null,
|
|
14
|
+
coverage: null,
|
|
15
|
+
qualityContractDigest: null,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
// ─── Broker-aware handler ───
|
|
19
|
+
/**
|
|
20
|
+
* 通过 FlowBroker 执行 flow_pr create 操作。
|
|
21
|
+
*
|
|
22
|
+
* 流程:
|
|
23
|
+
* 1. 通过 broker.writeFlowRunWithLock 读取 FlowRun
|
|
24
|
+
* 2. 提取目标 TaskState,执行 preflight
|
|
25
|
+
* 3. 调用 createOrReusePR(幂等:已有 PR 则复用)
|
|
26
|
+
* 4. 写入 prNumber + 初始化 prCheckpoints → task status → "reviewing"
|
|
27
|
+
* 5. 成功时持久化回 Issue(broker 自动处理 revision + 乐观锁)
|
|
28
|
+
* 6. PERSIST_CONFLICT 时设置 conflictPause=true
|
|
29
|
+
*
|
|
30
|
+
* 补偿:GitHub 创建成功但 FlowRun 写入失败 → 重试时通过 head branch 找回同一 PR
|
|
31
|
+
*/
|
|
32
|
+
export async function handleFlowPrCreateWithBroker(broker, req) {
|
|
33
|
+
const taskId = req.taskId;
|
|
34
|
+
const currentHeadSha = req.currentHeadSha;
|
|
35
|
+
const prTitle = req.prTitle;
|
|
36
|
+
const prBody = req.prBody;
|
|
37
|
+
const baseBranch = req.baseBranch ?? "main";
|
|
38
|
+
if (!taskId) {
|
|
39
|
+
return {
|
|
40
|
+
ok: false,
|
|
41
|
+
conflictPause: false,
|
|
42
|
+
persisted: false,
|
|
43
|
+
error: { code: "POLICY_INVALID", message: "task_id is required for pr-create" },
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
if (!currentHeadSha) {
|
|
47
|
+
return {
|
|
48
|
+
ok: false,
|
|
49
|
+
conflictPause: false,
|
|
50
|
+
persisted: false,
|
|
51
|
+
error: { code: "POLICY_INVALID", message: "current_head_sha is required for pr-create" },
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
if (!prTitle) {
|
|
55
|
+
return {
|
|
56
|
+
ok: false,
|
|
57
|
+
conflictPause: false,
|
|
58
|
+
persisted: false,
|
|
59
|
+
error: { code: "POLICY_INVALID", message: "pr_title is required for pr-create" },
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
if (!prBody) {
|
|
63
|
+
return {
|
|
64
|
+
ok: false,
|
|
65
|
+
conflictPause: false,
|
|
66
|
+
persisted: false,
|
|
67
|
+
error: { code: "POLICY_INVALID", message: "pr_body is required for pr-create" },
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
// ── 先创建/复用 PR(可能已经存在) ──
|
|
71
|
+
let prResult;
|
|
72
|
+
try {
|
|
73
|
+
// Step 1: 读取 FlowRun 获取 repo + branch 信息
|
|
74
|
+
const { flowRunResult, currentBody } = await (async () => {
|
|
75
|
+
const mod = await import("../flowrun/github.js");
|
|
76
|
+
return mod.readFlowRunWithLock(req.parentIssueNumber);
|
|
77
|
+
})();
|
|
78
|
+
if (!flowRunResult.ok || currentBody === null) {
|
|
79
|
+
return {
|
|
80
|
+
ok: false,
|
|
81
|
+
conflictPause: false,
|
|
82
|
+
persisted: false,
|
|
83
|
+
error: {
|
|
84
|
+
code: "READ_FAILED",
|
|
85
|
+
message: `Failed to read FlowRun from issue #${req.parentIssueNumber}`,
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
const flowRun = flowRunResult.data;
|
|
90
|
+
const task = flowRun.tasks[taskId];
|
|
91
|
+
if (!task) {
|
|
92
|
+
return {
|
|
93
|
+
ok: false,
|
|
94
|
+
conflictPause: false,
|
|
95
|
+
persisted: false,
|
|
96
|
+
error: { code: "TASK_NOT_FOUND", message: `Task "${taskId}" not found in FlowRun` },
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
// Step 2: Preflight 检查(无副作用)
|
|
100
|
+
const preflight = preflightPRCreate(task, currentHeadSha);
|
|
101
|
+
if (!preflight.ok) {
|
|
102
|
+
return {
|
|
103
|
+
ok: false,
|
|
104
|
+
conflictPause: false,
|
|
105
|
+
persisted: false,
|
|
106
|
+
error: preflight,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
// Step 3: 确定 head branch(从 executionBinding)
|
|
110
|
+
const headBranch = task.executionBinding?.branch ?? taskId;
|
|
111
|
+
// Step 4: 创建或复用 PR
|
|
112
|
+
prResult = await createOrReusePR({
|
|
113
|
+
repo: flowRun.repo,
|
|
114
|
+
headBranch,
|
|
115
|
+
baseBranch,
|
|
116
|
+
title: prTitle,
|
|
117
|
+
body: prBody,
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
catch (err) {
|
|
121
|
+
return {
|
|
122
|
+
ok: false,
|
|
123
|
+
conflictPause: false,
|
|
124
|
+
persisted: false,
|
|
125
|
+
error: { code: "INTERNAL_ERROR", message: String(err) },
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
// Step 5: 通过 broker 持久化(乐观锁写入)
|
|
129
|
+
const writeResult = await broker.writeFlowRunWithLock(req.parentIssueNumber, (flowRun) => {
|
|
130
|
+
const task = flowRun.tasks[taskId];
|
|
131
|
+
if (!task) {
|
|
132
|
+
return {
|
|
133
|
+
flowRun,
|
|
134
|
+
result: { prNumber: 0, prUrl: "", created: false, taskStatus: "" },
|
|
135
|
+
shouldPersist: false,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
// 写入 prNumber 和 checkpoints
|
|
139
|
+
task.prNumber = prResult.prNumber;
|
|
140
|
+
task.prCheckpoints = initPRCheckpoints(prResult.prNumber);
|
|
141
|
+
task.status = "reviewing";
|
|
142
|
+
return {
|
|
143
|
+
flowRun,
|
|
144
|
+
result: {
|
|
145
|
+
prNumber: prResult.prNumber,
|
|
146
|
+
prUrl: prResult.prUrl,
|
|
147
|
+
created: prResult.created,
|
|
148
|
+
taskStatus: task.status,
|
|
149
|
+
},
|
|
150
|
+
shouldPersist: true,
|
|
151
|
+
};
|
|
152
|
+
});
|
|
153
|
+
if (!writeResult.ok) {
|
|
154
|
+
// PERSIST_CONFLICT or READ_FAILED
|
|
155
|
+
return {
|
|
156
|
+
ok: false,
|
|
157
|
+
conflictPause: writeResult.code === "PERSIST_CONFLICT",
|
|
158
|
+
persisted: false,
|
|
159
|
+
prNumber: prResult.prNumber, // 补偿信息:PR 已创建,重试时可找回
|
|
160
|
+
error: {
|
|
161
|
+
code: writeResult.code,
|
|
162
|
+
message: writeResult.message,
|
|
163
|
+
},
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
return {
|
|
167
|
+
ok: true,
|
|
168
|
+
conflictPause: false,
|
|
169
|
+
persisted: writeResult.persisted,
|
|
170
|
+
prNumber: writeResult.result.prNumber,
|
|
171
|
+
prUrl: writeResult.result.prUrl,
|
|
172
|
+
created: writeResult.result.created,
|
|
173
|
+
taskStatus: writeResult.result.taskStatus,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
//# sourceMappingURL=flow-pr-tool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flow-pr-tool.js","sourceRoot":"","sources":["../../src/plugin/flow-pr-tool.ts"],"names":[],"mappings":"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"}
|
package/dist/plugin/goal.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ToolContext, ToolResult } from "@opencode-ai/plugin";
|
|
2
2
|
import { createOpencodeClient } from "@opencode-ai/sdk/v2";
|
|
3
3
|
import type { Session } from "@opencode-ai/sdk/v2";
|
|
4
|
+
import type { GoalFlowRunRef } from "../flowrun/types.js";
|
|
4
5
|
export type GoalStatus = "active" | "paused" | "complete";
|
|
5
6
|
export interface GoalData {
|
|
6
7
|
objective: string;
|
|
@@ -19,7 +20,44 @@ export declare function readGoal(client: ReturnType<typeof createOpencodeClient>
|
|
|
19
20
|
session: Session | null;
|
|
20
21
|
}>;
|
|
21
22
|
export declare function writeGoal(client: ReturnType<typeof createOpencodeClient>, sessionID: string, goal: GoalData | null, existingSession?: Session | null): Promise<void>;
|
|
22
|
-
|
|
23
|
+
/**
|
|
24
|
+
* 读取 session metadata 中的 GoalFlowRunRef。
|
|
25
|
+
* 返回 null 表示尚未绑定。
|
|
26
|
+
*/
|
|
27
|
+
export declare function readFlowRunRef(client: ReturnType<typeof createOpencodeClient>, sessionID: string): Promise<GoalFlowRunRef | null>;
|
|
28
|
+
/**
|
|
29
|
+
* Goal → FlowRun 绑定结果。
|
|
30
|
+
*/
|
|
31
|
+
export type BindFlowRunResult = {
|
|
32
|
+
ok: true;
|
|
33
|
+
} | {
|
|
34
|
+
ok: false;
|
|
35
|
+
code: "GOAL_FLOW_CONFLICT";
|
|
36
|
+
message: string;
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* 原子绑定 Goal → FlowRun。
|
|
40
|
+
*
|
|
41
|
+
* 规则:
|
|
42
|
+
* - 未绑定 → 写入 flowRunRef,返回 ok
|
|
43
|
+
* - 已绑定同一 FlowRun(repo + parentIssueNumber + flowRunId 相同)→ 幂等,返回 ok
|
|
44
|
+
* - 已绑定不同 FlowRun → 返回 GOAL_FLOW_CONFLICT
|
|
45
|
+
*/
|
|
46
|
+
export declare function bindFlowRunRef(client: ReturnType<typeof createOpencodeClient>, sessionID: string, ref: GoalFlowRunRef): Promise<BindFlowRunResult>;
|
|
47
|
+
/**
|
|
48
|
+
* 解析 GoalFlowRunRef 的显示名称。
|
|
49
|
+
*/
|
|
50
|
+
export declare function formatFlowRunRef(ref: GoalFlowRunRef): string;
|
|
51
|
+
/**
|
|
52
|
+
* 验证 FlowRun 终态 — 检查是否满足 Goal complete 的前提条件。
|
|
53
|
+
*
|
|
54
|
+
* 返回 null 表示允许完成;
|
|
55
|
+
* 返回错误信息字符串表示阻止完成。
|
|
56
|
+
*
|
|
57
|
+
* @param flowRunStatus FlowRun 当前状态,null 表示无绑定的 FlowRun
|
|
58
|
+
*/
|
|
59
|
+
export declare function checkFlowRunBlockers(flowRunStatus: string | null): string | null;
|
|
60
|
+
export declare function createGoalTool(client: ReturnType<typeof createOpencodeClient>, onBeforeComplete?: (parentSessionID: string) => Promise<string | null>): {
|
|
23
61
|
description: string;
|
|
24
62
|
args: {
|
|
25
63
|
op: import("zod").ZodEnum<{
|
package/dist/plugin/goal.js
CHANGED
|
@@ -98,7 +98,79 @@ export async function writeGoal(client, sessionID, goal, existingSession) {
|
|
|
98
98
|
: { ...existing, goal };
|
|
99
99
|
await client.session.update({ sessionID, metadata });
|
|
100
100
|
}
|
|
101
|
-
|
|
101
|
+
// ─── GoalFlowRunRef 绑定 ───
|
|
102
|
+
/**
|
|
103
|
+
* 读取 session metadata 中的 GoalFlowRunRef。
|
|
104
|
+
* 返回 null 表示尚未绑定。
|
|
105
|
+
*/
|
|
106
|
+
export async function readFlowRunRef(client, sessionID) {
|
|
107
|
+
try {
|
|
108
|
+
const result = await client.session.get({ sessionID });
|
|
109
|
+
const session = result?.data ?? null;
|
|
110
|
+
const ref = session?.metadata?.flowRunRef;
|
|
111
|
+
return ref ?? null;
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* 原子绑定 Goal → FlowRun。
|
|
119
|
+
*
|
|
120
|
+
* 规则:
|
|
121
|
+
* - 未绑定 → 写入 flowRunRef,返回 ok
|
|
122
|
+
* - 已绑定同一 FlowRun(repo + parentIssueNumber + flowRunId 相同)→ 幂等,返回 ok
|
|
123
|
+
* - 已绑定不同 FlowRun → 返回 GOAL_FLOW_CONFLICT
|
|
124
|
+
*/
|
|
125
|
+
export async function bindFlowRunRef(client, sessionID, ref) {
|
|
126
|
+
const result = await client.session.get({ sessionID });
|
|
127
|
+
const session = result?.data ?? null;
|
|
128
|
+
if (!session)
|
|
129
|
+
return { ok: false, code: "GOAL_FLOW_CONFLICT", message: "Session not found" };
|
|
130
|
+
const existingRef = session.metadata?.flowRunRef;
|
|
131
|
+
if (existingRef) {
|
|
132
|
+
const isSame = existingRef.repo === ref.repo &&
|
|
133
|
+
existingRef.parentIssueNumber === ref.parentIssueNumber &&
|
|
134
|
+
existingRef.flowRunId === ref.flowRunId;
|
|
135
|
+
if (!isSame) {
|
|
136
|
+
return {
|
|
137
|
+
ok: false,
|
|
138
|
+
code: "GOAL_FLOW_CONFLICT",
|
|
139
|
+
message: `Goal is already bound to FlowRun "${existingRef.flowRunId}", cannot bind to "${ref.flowRunId}"`,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
// 同一 FlowRun → 幂等
|
|
143
|
+
return { ok: true };
|
|
144
|
+
}
|
|
145
|
+
// 未绑定 → 写入
|
|
146
|
+
const existing = session.metadata ?? {};
|
|
147
|
+
const metadata = { ...existing, flowRunRef: ref };
|
|
148
|
+
await client.session.update({ sessionID, metadata });
|
|
149
|
+
return { ok: true };
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* 解析 GoalFlowRunRef 的显示名称。
|
|
153
|
+
*/
|
|
154
|
+
export function formatFlowRunRef(ref) {
|
|
155
|
+
return `${ref.repo}#${ref.parentIssueNumber} (${ref.flowRunId})`;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* 验证 FlowRun 终态 — 检查是否满足 Goal complete 的前提条件。
|
|
159
|
+
*
|
|
160
|
+
* 返回 null 表示允许完成;
|
|
161
|
+
* 返回错误信息字符串表示阻止完成。
|
|
162
|
+
*
|
|
163
|
+
* @param flowRunStatus FlowRun 当前状态,null 表示无绑定的 FlowRun
|
|
164
|
+
*/
|
|
165
|
+
export function checkFlowRunBlockers(flowRunStatus) {
|
|
166
|
+
if (flowRunStatus === null)
|
|
167
|
+
return null; // 无 FlowRun 绑定,允许完成
|
|
168
|
+
if (flowRunStatus !== "completed" && flowRunStatus !== "cancelled") {
|
|
169
|
+
return `FlowRun is not in terminal state (status: ${flowRunStatus}). Run flow_control({op:"run-finalize"}) to finalize first.`;
|
|
170
|
+
}
|
|
171
|
+
return null;
|
|
172
|
+
}
|
|
173
|
+
export function createGoalTool(client, onBeforeComplete) {
|
|
102
174
|
return tool({
|
|
103
175
|
description: `Manage the active goal-mode objective.
|
|
104
176
|
|
|
@@ -133,6 +205,13 @@ Use a single op field:
|
|
|
133
205
|
if (parent.goal.status !== "active") {
|
|
134
206
|
return `Parent session goal is not active (status: ${parent.goal.status}).`;
|
|
135
207
|
}
|
|
208
|
+
// 验证 FlowRun 终态(如绑定了 FlowRunRef)
|
|
209
|
+
if (onBeforeComplete) {
|
|
210
|
+
const blockReason = await onBeforeComplete(targetSessionID);
|
|
211
|
+
if (blockReason !== null) {
|
|
212
|
+
return `Goal completion blocked: ${blockReason}`;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
136
215
|
parent.goal.status = "complete";
|
|
137
216
|
await writeGoal(client, targetSessionID, parent.goal, parent.session);
|
|
138
217
|
return `Goal completed and verified: "${parent.goal.objective}"`;
|
package/dist/plugin/goal.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"goal.js","sourceRoot":"","sources":["../../src/plugin/goal.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAA;AAC/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"goal.js","sourceRoot":"","sources":["../../src/plugin/goal.ts"],"names":[],"mappings":"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"}
|