@devcxl/opencode-cabbage 1.2.0 → 2.0.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.
Files changed (104) hide show
  1. package/.codex-plugin/plugin.json +36 -0
  2. package/README.md +67 -21
  3. package/README.zh.md +26 -13
  4. package/assets/agents/dev-lifecycle.md +6 -0
  5. package/assets/prompts/bootstrap.md +4 -0
  6. package/assets/skills/flow-change/SKILL.md +109 -0
  7. package/assets/skills/flow-design/SKILL.md +15 -0
  8. package/assets/skills/flow-docs/SKILL.md +112 -0
  9. package/assets/skills/flow-incident/SKILL.md +98 -0
  10. package/assets/skills/flow-research/SKILL.md +9 -0
  11. package/assets/skills/flow-setup/SKILL.md +13 -0
  12. package/codex-skills/agent-architect/SKILL.md +79 -0
  13. package/codex-skills/agent-dev-lifecycle/SKILL.md +311 -0
  14. package/codex-skills/agent-developer/SKILL.md +51 -0
  15. package/codex-skills/agent-goal-verify/SKILL.md +45 -0
  16. package/codex-skills/agent-researcher/SKILL.md +32 -0
  17. package/codex-skills/agent-reviewer/SKILL.md +109 -0
  18. package/codex-skills/flow-change/SKILL.md +109 -0
  19. package/codex-skills/flow-code/SKILL.md +71 -0
  20. package/codex-skills/flow-design/SKILL.md +161 -0
  21. package/codex-skills/flow-docs/SKILL.md +112 -0
  22. package/codex-skills/flow-incident/SKILL.md +98 -0
  23. package/codex-skills/flow-release/SKILL.md +90 -0
  24. package/codex-skills/flow-requirements/SKILL.md +90 -0
  25. package/codex-skills/flow-research/SKILL.md +86 -0
  26. package/codex-skills/flow-review/SKILL.md +110 -0
  27. package/codex-skills/flow-setup/SKILL.md +88 -0
  28. package/codex-skills/flow-tasks/SKILL.md +220 -0
  29. package/codex-skills/flow-tdd/SKILL.md +235 -0
  30. package/dist/hooks/session-start.d.ts +1 -0
  31. package/dist/hooks/session-start.js +72 -0
  32. package/dist/hooks/session-start.js.map +1 -0
  33. package/dist/index.d.ts +2 -5
  34. package/dist/index.js +1 -4
  35. package/dist/index.js.map +1 -1
  36. package/dist/plugin/agents.d.ts +20 -0
  37. package/dist/plugin/agents.js +79 -0
  38. package/dist/plugin/agents.js.map +1 -1
  39. package/dist/plugin/cabbage-cli.d.ts +28 -0
  40. package/dist/plugin/cabbage-cli.js +92 -0
  41. package/dist/plugin/cabbage-cli.js.map +1 -0
  42. package/dist/plugin/cabbage-tool.d.ts +103 -0
  43. package/dist/plugin/cabbage-tool.js +169 -0
  44. package/dist/plugin/cabbage-tool.js.map +1 -0
  45. package/dist/plugin/commands.d.ts +10 -0
  46. package/dist/plugin/commands.js +1 -1
  47. package/dist/plugin/commands.js.map +1 -1
  48. package/dist/plugin/continuation.d.ts +22 -0
  49. package/dist/plugin/continuation.js +233 -0
  50. package/dist/plugin/continuation.js.map +1 -0
  51. package/dist/plugin/goal-store.d.ts +64 -0
  52. package/dist/plugin/goal-store.js +57 -0
  53. package/dist/plugin/goal-store.js.map +1 -0
  54. package/dist/plugin/goal.d.ts +95 -38
  55. package/dist/plugin/goal.js +208 -199
  56. package/dist/plugin/goal.js.map +1 -1
  57. package/dist/plugin/install-dir.d.ts +13 -0
  58. package/dist/plugin/install-dir.js +46 -0
  59. package/dist/plugin/install-dir.js.map +1 -0
  60. package/dist/plugin/server.d.ts +4 -12
  61. package/dist/plugin/server.js +279 -423
  62. package/dist/plugin/server.js.map +1 -1
  63. package/dist/plugin/session-abort.d.ts +5 -0
  64. package/dist/plugin/session-abort.js +26 -0
  65. package/dist/plugin/session-abort.js.map +1 -0
  66. package/dist/plugin/skills.d.ts +15 -0
  67. package/dist/plugin/skills.js +47 -50
  68. package/dist/plugin/skills.js.map +1 -1
  69. package/dist/plugin.d.ts +2 -2
  70. package/dist/plugin.js +6 -2
  71. package/dist/plugin.js.map +1 -1
  72. package/dist/util/paths.d.ts +0 -6
  73. package/dist/util/paths.js +0 -15
  74. package/dist/util/paths.js.map +1 -1
  75. package/hooks/hooks.json +17 -0
  76. package/package.json +13 -8
  77. package/vendor/cabbage/MANIFEST.json +8 -0
  78. package/vendor/cabbage/cabbage_cli/__init__.py +1 -0
  79. package/vendor/cabbage/cabbage_cli/__main__.py +2 -0
  80. package/vendor/cabbage/cabbage_cli/assets/docs-site/.vitepress/config.ts +78 -0
  81. package/vendor/cabbage/cabbage_cli/assets/docs-site/README.md +31 -0
  82. package/vendor/cabbage/cabbage_cli/assets/docs-site/package.json +16 -0
  83. package/vendor/cabbage/cabbage_cli/assets/docs-site/pnpm-lock.yaml +2504 -0
  84. package/vendor/cabbage/cabbage_cli/assets/integrations/cabbage.yml +127 -0
  85. package/vendor/cabbage/cabbage_cli/assets/templates/adr.md +47 -0
  86. package/vendor/cabbage/cabbage_cli/assets/templates/api-design.md +45 -0
  87. package/vendor/cabbage/cabbage_cli/assets/templates/change-record.md +21 -0
  88. package/vendor/cabbage/cabbage_cli/assets/templates/database-design.md +37 -0
  89. package/vendor/cabbage/cabbage_cli/assets/templates/generic.md +20 -0
  90. package/vendor/cabbage/cabbage_cli/assets/templates/impact.md +41 -0
  91. package/vendor/cabbage/cabbage_cli/assets/templates/incident.md +48 -0
  92. package/vendor/cabbage/cabbage_cli/assets/templates/postmortem.md +43 -0
  93. package/vendor/cabbage/cabbage_cli/assets/templates/prd.md +71 -0
  94. package/vendor/cabbage/cabbage_cli/assets/templates/release-plan.md +45 -0
  95. package/vendor/cabbage/cabbage_cli/assets/templates/rfc.md +44 -0
  96. package/vendor/cabbage/cabbage_cli/assets/templates/security-review.md +35 -0
  97. package/vendor/cabbage/cabbage_cli/assets/templates/tasks.md +62 -0
  98. package/vendor/cabbage/cabbage_cli/assets/templates/tech-spec.md +87 -0
  99. package/vendor/cabbage/cabbage_cli/assets/templates/test-plan.md +44 -0
  100. package/vendor/cabbage/cabbage_cli/assets/workflows/change.yaml +11 -0
  101. package/vendor/cabbage/cabbage_cli/assets/workflows/incident.yaml +4 -0
  102. package/vendor/cabbage/cabbage_cli/cli.py +283 -0
  103. package/vendor/cabbage/cabbage_cli/core.py +606 -0
  104. package/vendor/cabbage/cabbage_cli/scaffold.py +313 -0
@@ -0,0 +1,103 @@
1
+ import type { CabbageCliRuntime } from "./cabbage-cli.js";
2
+ /**
3
+ * `cabbage` 工具:把内置 Cabbage 引擎(变更记录 / 任务与文档 / 验证与归档)暴露为
4
+ * 一等工具。与 goal 工具相同的双层门控:权限规则层(agent permissions)隐藏/放行,
5
+ * 工具内自检兜底(仅 dev-lifecycle 编排器可用)。
6
+ */
7
+ export declare const CABBAGE_ALLOWED_AGENTS: Set<string>;
8
+ export interface CabbageToolInput {
9
+ op: "init" | "new" | "status" | "next" | "impact" | "validate" | "verify" | "gate" | "sync" | "archive" | "tasks" | "discard" | "adopt";
10
+ change?: string;
11
+ stage?: string;
12
+ target?: string;
13
+ type?: "change" | "incident";
14
+ impact?: string[];
15
+ }
16
+ export interface CabbageToolContext {
17
+ sessionID: string;
18
+ agent?: string;
19
+ }
20
+ export interface CabbageToolResult {
21
+ content: string;
22
+ }
23
+ export declare const CABBAGE_TOOL_INPUT_SCHEMA: {
24
+ readonly type: "object";
25
+ readonly properties: {
26
+ readonly op: {
27
+ readonly type: "string";
28
+ readonly enum: readonly ["init", "new", "status", "next", "impact", "validate", "verify", "gate", "sync", "archive", "tasks", "discard", "adopt"];
29
+ readonly description: "Cabbage operation";
30
+ };
31
+ readonly change: {
32
+ readonly type: "string";
33
+ readonly description: "Change id in kebab-case (required by new/next/impact/verify/gate/sync/archive/tasks/discard; optional for status/validate)";
34
+ };
35
+ readonly stage: {
36
+ readonly type: "string";
37
+ readonly description: "Stage id for verify — use the stage ids that `next` reports (new projects: `tasks`)";
38
+ };
39
+ readonly target: {
40
+ readonly type: "string";
41
+ readonly description: "Gate target for gate: a stage id (checks the stages before it), or `merge` / `archive`";
42
+ };
43
+ readonly type: {
44
+ readonly type: "string";
45
+ readonly enum: readonly ["change", "incident"];
46
+ readonly description: "Change type for new (default: change)";
47
+ };
48
+ readonly impact: {
49
+ readonly type: "array";
50
+ readonly items: {
51
+ readonly type: "string";
52
+ };
53
+ readonly description: "Impact entries for impact, e.g. [\"api=true\", \"design=true\"] — design/rfc/adr/api/database/security/deployment open specialist documents";
54
+ };
55
+ };
56
+ readonly required: readonly ["op"];
57
+ readonly additionalProperties: false;
58
+ };
59
+ export declare const CABBAGE_TOOL_DESCRIPTION = "Manage this project's Cabbage change records \u2014 the built-in tasks-and-docs workflow (the engine is bundled; Python 3.10+ required).\n\nOps:\n- init: scaffold .cabbage/ (workflows, docs skeleton, CI template, vendored CLI) \u2014 run once per project\n- adopt: inventory existing markdown outside the docs tree and write .cabbage/adoption-report.md (advisory; moves stay manual)\n- new: create a record (type: change|incident; change: kebab-case id)\n- status: list active records and per-stage state (change optional)\n- next: show ready and blocked stages for a record\n- impact: declare risks, e.g. impact:[\"api=true\",\"design=true\"] \u2014 opens specialist docs (design/rfc/adr/api/database/security/release)\n- verify: verify one stage artifact (stage required; use ids from next)\n- gate: check a milestone (target: stage id | merge | archive)\n- validate: structural checks (all records when change omitted)\n- sync: copy mapped documents into docs/\n- archive: gate, sync, and move the record to .cabbage/archive/ (only after the merge is confirmed)\n- tasks: read-only task checklist view\n- discard: delete an abandoned record\n\nLight path: new \u2192 fill tasks.md (Goal/Design/Tasks/Verification) \u2192 verify tasks \u2192 gate merge \u2192 archive after merge. Records live in .cabbage/changes/<id>/; state.json and change.yaml are CLI-owned \u2014 never edit them by hand.";
60
+ export declare function buildCabbageTool(cli: CabbageCliRuntime, projectDir: string): {
61
+ name: string;
62
+ description: string;
63
+ input: {
64
+ readonly type: "object";
65
+ readonly properties: {
66
+ readonly op: {
67
+ readonly type: "string";
68
+ readonly enum: readonly ["init", "new", "status", "next", "impact", "validate", "verify", "gate", "sync", "archive", "tasks", "discard", "adopt"];
69
+ readonly description: "Cabbage operation";
70
+ };
71
+ readonly change: {
72
+ readonly type: "string";
73
+ readonly description: "Change id in kebab-case (required by new/next/impact/verify/gate/sync/archive/tasks/discard; optional for status/validate)";
74
+ };
75
+ readonly stage: {
76
+ readonly type: "string";
77
+ readonly description: "Stage id for verify — use the stage ids that `next` reports (new projects: `tasks`)";
78
+ };
79
+ readonly target: {
80
+ readonly type: "string";
81
+ readonly description: "Gate target for gate: a stage id (checks the stages before it), or `merge` / `archive`";
82
+ };
83
+ readonly type: {
84
+ readonly type: "string";
85
+ readonly enum: readonly ["change", "incident"];
86
+ readonly description: "Change type for new (default: change)";
87
+ };
88
+ readonly impact: {
89
+ readonly type: "array";
90
+ readonly items: {
91
+ readonly type: "string";
92
+ };
93
+ readonly description: "Impact entries for impact, e.g. [\"api=true\", \"design=true\"] — design/rfc/adr/api/database/security/deployment open specialist documents";
94
+ };
95
+ };
96
+ readonly required: readonly ["op"];
97
+ readonly additionalProperties: false;
98
+ };
99
+ options: {
100
+ permission: string;
101
+ };
102
+ execute(input: CabbageToolInput, context: CabbageToolContext): Promise<CabbageToolResult>;
103
+ };
@@ -0,0 +1,169 @@
1
+ import { runCabbage } from "./cabbage-cli.js";
2
+ /**
3
+ * `cabbage` 工具:把内置 Cabbage 引擎(变更记录 / 任务与文档 / 验证与归档)暴露为
4
+ * 一等工具。与 goal 工具相同的双层门控:权限规则层(agent permissions)隐藏/放行,
5
+ * 工具内自检兜底(仅 dev-lifecycle 编排器可用)。
6
+ */
7
+ export const CABBAGE_ALLOWED_AGENTS = new Set(["dev-lifecycle"]);
8
+ const OPS = ["init", "new", "status", "next", "impact", "validate", "verify", "gate", "sync", "archive", "tasks", "discard", "adopt"];
9
+ export const CABBAGE_TOOL_INPUT_SCHEMA = {
10
+ type: "object",
11
+ properties: {
12
+ op: {
13
+ type: "string",
14
+ enum: [...OPS],
15
+ description: "Cabbage operation",
16
+ },
17
+ change: {
18
+ type: "string",
19
+ description: "Change id in kebab-case (required by new/next/impact/verify/gate/sync/archive/tasks/discard; optional for status/validate)",
20
+ },
21
+ stage: {
22
+ type: "string",
23
+ description: "Stage id for verify — use the stage ids that `next` reports (new projects: `tasks`)",
24
+ },
25
+ target: {
26
+ type: "string",
27
+ description: "Gate target for gate: a stage id (checks the stages before it), or `merge` / `archive`",
28
+ },
29
+ type: {
30
+ type: "string",
31
+ enum: ["change", "incident"],
32
+ description: "Change type for new (default: change)",
33
+ },
34
+ impact: {
35
+ type: "array",
36
+ items: { type: "string" },
37
+ description: "Impact entries for impact, e.g. [\"api=true\", \"design=true\"] — design/rfc/adr/api/database/security/deployment open specialist documents",
38
+ },
39
+ },
40
+ required: ["op"],
41
+ additionalProperties: false,
42
+ };
43
+ export const CABBAGE_TOOL_DESCRIPTION = `Manage this project's Cabbage change records — the built-in tasks-and-docs workflow (the engine is bundled; Python 3.10+ required).
44
+
45
+ Ops:
46
+ - init: scaffold .cabbage/ (workflows, docs skeleton, CI template, vendored CLI) — run once per project
47
+ - adopt: inventory existing markdown outside the docs tree and write .cabbage/adoption-report.md (advisory; moves stay manual)
48
+ - new: create a record (type: change|incident; change: kebab-case id)
49
+ - status: list active records and per-stage state (change optional)
50
+ - next: show ready and blocked stages for a record
51
+ - impact: declare risks, e.g. impact:["api=true","design=true"] — opens specialist docs (design/rfc/adr/api/database/security/release)
52
+ - verify: verify one stage artifact (stage required; use ids from next)
53
+ - gate: check a milestone (target: stage id | merge | archive)
54
+ - validate: structural checks (all records when change omitted)
55
+ - sync: copy mapped documents into docs/
56
+ - archive: gate, sync, and move the record to .cabbage/archive/ (only after the merge is confirmed)
57
+ - tasks: read-only task checklist view
58
+ - discard: delete an abandoned record
59
+
60
+ Light path: new → fill tasks.md (Goal/Design/Tasks/Verification) → verify tasks → gate merge → archive after merge. Records live in .cabbage/changes/<id>/; state.json and change.yaml are CLI-owned — never edit them by hand.`;
61
+ function buildArgs(input) {
62
+ const change = input.change?.trim();
63
+ const requireChange = (op) => change ?? { error: `Error: op \`${op}\` requires \`change\`.` };
64
+ switch (input.op) {
65
+ case "init":
66
+ return ["init"];
67
+ case "adopt":
68
+ return ["adopt"];
69
+ case "new": {
70
+ if (!change || typeof change !== "string")
71
+ return { error: "Error: op `new` requires `change` (kebab-case id)." };
72
+ return ["new", input.type ?? "change", change];
73
+ }
74
+ case "status":
75
+ return change ? ["status", change] : ["status"];
76
+ case "next": {
77
+ const c = requireChange("next");
78
+ if (typeof c !== "string")
79
+ return c;
80
+ return ["next", c];
81
+ }
82
+ case "impact": {
83
+ const c = requireChange("impact");
84
+ if (typeof c !== "string")
85
+ return c;
86
+ const entries = (input.impact ?? []).filter((x) => typeof x === "string" && x.trim() !== "");
87
+ if (entries.length === 0)
88
+ return { error: "Error: op `impact` requires a non-empty `impact` array, e.g. [\"api=true\"]." };
89
+ return ["impact", c, ...entries.flatMap((entry) => ["--set", entry.trim()])];
90
+ }
91
+ case "validate":
92
+ return change ? ["validate", change] : ["validate", "--all"];
93
+ case "verify": {
94
+ const c = requireChange("verify");
95
+ if (typeof c !== "string")
96
+ return c;
97
+ const stage = input.stage?.trim();
98
+ if (!stage)
99
+ return { error: "Error: op `verify` requires `stage` (use the ids from `next`)." };
100
+ return ["verify", c, stage];
101
+ }
102
+ case "gate": {
103
+ const c = requireChange("gate");
104
+ if (typeof c !== "string")
105
+ return c;
106
+ const target = input.target?.trim();
107
+ if (!target)
108
+ return { error: "Error: op `gate` requires `target` (a stage id, `merge`, or `archive`)." };
109
+ return ["gate", c, target];
110
+ }
111
+ case "sync": {
112
+ const c = requireChange("sync");
113
+ if (typeof c !== "string")
114
+ return c;
115
+ return ["sync", c];
116
+ }
117
+ case "archive": {
118
+ const c = requireChange("archive");
119
+ if (typeof c !== "string")
120
+ return c;
121
+ return ["archive", c];
122
+ }
123
+ case "tasks": {
124
+ const c = requireChange("tasks");
125
+ if (typeof c !== "string")
126
+ return c;
127
+ return ["tasks", c];
128
+ }
129
+ case "discard": {
130
+ const c = requireChange("discard");
131
+ if (typeof c !== "string")
132
+ return c;
133
+ return ["discard", c];
134
+ }
135
+ default:
136
+ return { error: `Error: unknown op \`${String(input.op)}\`.` };
137
+ }
138
+ }
139
+ export function buildCabbageTool(cli, projectDir) {
140
+ return {
141
+ name: "cabbage",
142
+ description: CABBAGE_TOOL_DESCRIPTION,
143
+ input: CABBAGE_TOOL_INPUT_SCHEMA,
144
+ options: { permission: "cabbage" },
145
+ async execute(input, context) {
146
+ if (!context.agent || !CABBAGE_ALLOWED_AGENTS.has(context.agent)) {
147
+ return { content: `Error: the cabbage tool is restricted to the dev-lifecycle orchestrator. Agent "${context.agent ?? "unknown"}" is not authorized.` };
148
+ }
149
+ if (!cli.available) {
150
+ return { content: `Error: cabbage CLI unavailable: ${cli.reason ?? "unknown reason"}. The bundled engine needs Python 3.10+; install it and restart.` };
151
+ }
152
+ const built = buildArgs(input);
153
+ if ("error" in built)
154
+ return { content: built.error };
155
+ try {
156
+ const result = await runCabbage(cli, built, projectDir);
157
+ const parts = [result.stdout.trim()];
158
+ if (result.stderr.trim())
159
+ parts.push(`[stderr]\n${result.stderr.trim()}`);
160
+ parts.push(`exit=${result.code}`);
161
+ return { content: parts.filter(Boolean).join("\n") };
162
+ }
163
+ catch (err) {
164
+ return { content: `Error: failed to run cabbage ${built.join(" ")}: ${err?.message ?? err}` };
165
+ }
166
+ },
167
+ };
168
+ }
169
+ //# sourceMappingURL=cabbage-tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cabbage-tool.js","sourceRoot":"","sources":["../../src/plugin/cabbage-tool.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,13 @@
1
+ /**
2
+ * 解析并剥离 Markdown 文件的 frontmatter
3
+ *
4
+ * Frontmatter 是位于文件开头的 --- 包裹的 YAML 格式元数据,
5
+ * 例如:---\ntitle: foo\n---\n正文内容
6
+ */
7
+ export declare function extractAndStripFrontmatter(content: string): {
8
+ frontmatter: Record<string, string>;
9
+ content: string;
10
+ };
1
11
  /** 解析后的 slash command 结构 */
2
12
  export interface ParsedCommand {
3
13
  name: string;
@@ -6,7 +6,7 @@ import path from "node:path";
6
6
  * Frontmatter 是位于文件开头的 --- 包裹的 YAML 格式元数据,
7
7
  * 例如:---\ntitle: foo\n---\n正文内容
8
8
  */
9
- function extractAndStripFrontmatter(content) {
9
+ export function extractAndStripFrontmatter(content) {
10
10
  const match = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
11
11
  if (!match)
12
12
  return { frontmatter: {}, content };
@@ -1 +1 @@
1
- {"version":3,"file":"commands.js","sourceRoot":"","sources":["../../src/plugin/commands.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"commands.js","sourceRoot":"","sources":["../../src/plugin/commands.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import type { Plugin } from "@opencode/plugin";
2
+ import type { GoalStore } from "./goal-store.js";
3
+ type Context = Plugin.Context;
4
+ /**
5
+ * 子会话活动跟踪(V2 无 session.list/children 查询 API,改用事件溯源):
6
+ * - session.created(带 parentID)建立父子关系
7
+ * - execution.started / retry.scheduled → busy;execution.succeeded/failed/interrupted → idle
8
+ *
9
+ * 局限:重启后内存清空,重启瞬间仍在运行且未再发事件的子会话不被识别(窗口小,可接受;
10
+ * 子代理结果注入父会话会重新触发事件流)。V1 依赖实时查询,此为 V2 的降级替代。
11
+ */
12
+ export declare class SessionActivityTracker {
13
+ private parentOf;
14
+ private busy;
15
+ onCreated(sessionID: string, parentID?: string): void;
16
+ onBusy(sessionID: string): void;
17
+ onIdle(sessionID: string): void;
18
+ hasWorkingChildren(sessionID: string): boolean;
19
+ }
20
+ export declare function queueContinuation(ctx: Context, store: GoalStore, sessionID: string, projectDir: string, tracker: SessionActivityTracker): Promise<void>;
21
+ export declare function autoResume(ctx: Context, store: GoalStore, projectDir: string): Promise<void>;
22
+ export {};
@@ -0,0 +1,233 @@
1
+ import { MAX_CONTINUATIONS, budgetReached, continuationPrompt, formatGoal, isBlockedReport, isDoneReport, mutateGoal, normalizeProfileModel, snapshotTokenTotal, } from "./goal.js";
2
+ import { consumeAborted } from "./session-abort.js";
3
+ import { readIndex, updateFlowSession, removeFlowSession } from "../kernel/session-index.js";
4
+ import { getContextBlock, formatContextBlock } from "../kernel/context.js";
5
+ const continuationInFlight = new Set();
6
+ const COMPACTION_THRESHOLD = 20;
7
+ /** autoResume 跳过窗口:索引 30s 内更新过续接的 flow 不恢复(可能刚续接过,立即恢复会双发) */
8
+ const AUTO_RESUME_SKIP_WINDOW_MS = 30_000;
9
+ /**
10
+ * 子会话活动跟踪(V2 无 session.list/children 查询 API,改用事件溯源):
11
+ * - session.created(带 parentID)建立父子关系
12
+ * - execution.started / retry.scheduled → busy;execution.succeeded/failed/interrupted → idle
13
+ *
14
+ * 局限:重启后内存清空,重启瞬间仍在运行且未再发事件的子会话不被识别(窗口小,可接受;
15
+ * 子代理结果注入父会话会重新触发事件流)。V1 依赖实时查询,此为 V2 的降级替代。
16
+ */
17
+ export class SessionActivityTracker {
18
+ parentOf = new Map();
19
+ busy = new Set();
20
+ onCreated(sessionID, parentID) {
21
+ if (parentID)
22
+ this.parentOf.set(sessionID, parentID);
23
+ }
24
+ onBusy(sessionID) {
25
+ this.busy.add(sessionID);
26
+ }
27
+ onIdle(sessionID) {
28
+ this.busy.delete(sessionID);
29
+ }
30
+ hasWorkingChildren(sessionID) {
31
+ for (const [child, parent] of this.parentOf) {
32
+ if (parent === sessionID && this.busy.has(child))
33
+ return true;
34
+ }
35
+ return false;
36
+ }
37
+ }
38
+ /** 续接前注入会话快照的 agent/模型,防回落默认值(switch 为幂等调用) */
39
+ async function restoreSessionProfile(ctx, sessionID, profile) {
40
+ if (profile?.agent) {
41
+ await ctx.session.switchAgent({ sessionID, agent: profile.agent }).catch((error) => {
42
+ console.warn("[cabbage] switchAgent failed:", error?.message ?? error);
43
+ });
44
+ }
45
+ const model = normalizeProfileModel(profile?.model);
46
+ if (model) {
47
+ await ctx.session.switchModel({ sessionID, model }).catch((error) => {
48
+ console.warn("[cabbage] switchModel failed:", error?.message ?? error);
49
+ });
50
+ }
51
+ }
52
+ export async function queueContinuation(ctx, store, sessionID, projectDir, tracker) {
53
+ if (continuationInFlight.has(sessionID))
54
+ return;
55
+ continuationInFlight.add(sessionID);
56
+ try {
57
+ const decision = await mutateGoal(store, sessionID, async (goal) => {
58
+ // 读改写与事件处理同锁串行,杜绝续接计数/状态被并发覆盖
59
+ if (!goal || goal.status !== "active")
60
+ return { goal, value: null };
61
+ await updateFlowSession(projectDir, goal.parentIssueNumber, { status: goal.status, continuationCount: goal.continuationCount }).catch(() => undefined);
62
+ if (consumeAborted(sessionID)) {
63
+ goal.status = "paused";
64
+ goal.statusReason = "aborted by user";
65
+ await updateFlowSession(projectDir, goal.parentIssueNumber, { status: "paused" }).catch(() => undefined);
66
+ return { goal, value: null };
67
+ }
68
+ if (goal.continuationCount >= MAX_CONTINUATIONS) {
69
+ goal.status = "paused";
70
+ await updateFlowSession(projectDir, goal.parentIssueNumber, { status: "paused" }).catch(() => undefined);
71
+ return { goal, value: null };
72
+ }
73
+ // 子会话活动闸:后台 subagent 仍 busy 时跳过续接(父会话轮次结束不代表任务静默)
74
+ if (tracker.hasWorkingChildren(sessionID)) {
75
+ return { goal, value: null };
76
+ }
77
+ // 尾部静默检查:轮次结束后仍可能有新 user 消息在途或 synthetic 尚未消费。
78
+ // 最后一条是 user/synthetic、或最后 assistant 未完成(无 completed 时间)→ 跳过,
79
+ // 等这些消息各自触发的新轮次结束事件重新驱动续接。
80
+ const messages = await store.context(sessionID);
81
+ if (!messages || messages.length === 0)
82
+ return { goal, value: null };
83
+ const lastMessage = messages[messages.length - 1];
84
+ if (lastMessage?.type === "user" || lastMessage?.type === "synthetic")
85
+ return { goal, value: null };
86
+ let lastAssistant = null;
87
+ for (let i = messages.length - 1; i >= 0; i -= 1) {
88
+ if (messages[i]?.type === "assistant") {
89
+ lastAssistant = messages[i];
90
+ break;
91
+ }
92
+ }
93
+ if (!lastAssistant)
94
+ return { goal, value: null };
95
+ const completed = lastAssistant.time?.completed;
96
+ if (!(typeof completed === "number" && completed > 0))
97
+ return { goal, value: null };
98
+ // [BLOCKED:] 阻塞报告 / [DONE:] 完成报告:agent 明确信号 → 暂停 goal 请用户/验证介入
99
+ // (防空转烧 token;完成报告后应由 dev-lifecycle 派 goal-verify 做最终独立验证)。
100
+ // resume 后首次 tick 豁免(statusReason='resumed' 被消费清除),
101
+ // 否则 resume 会立即被上一轮旧报告再次暂停成死路。
102
+ const assistantText = (lastAssistant.content ?? [])
103
+ .filter((part) => part?.type === "text" && typeof part.text === "string")
104
+ .map((part) => part.text)
105
+ .join("\n");
106
+ const agentSignaled = isBlockedReport(assistantText) || isDoneReport(assistantText);
107
+ if (agentSignaled) {
108
+ if (goal.statusReason === "resumed") {
109
+ goal.statusReason = "";
110
+ }
111
+ else {
112
+ goal.status = "paused";
113
+ goal.statusReason = isBlockedReport(assistantText) ? "blocked report" : "done report";
114
+ await updateFlowSession(projectDir, goal.parentIssueNumber, { status: "paused" }).catch(() => undefined);
115
+ return { goal, value: null };
116
+ }
117
+ }
118
+ else if (goal.statusReason === "resumed") {
119
+ // 豁免消费:resume 后的首次 tick 无论是否命中信号都清除 kickoff 标记。
120
+ // 若不消费,首 tick 正常推进后 statusReason 残留,后续真实信号会被误豁免一次。
121
+ goal.statusReason = "";
122
+ }
123
+ // Token 记账(会话累计快照):used = 当前会话累计 − create 基线,单调不减。
124
+ // cache.read 已含此前轮次付费 token,compaction 不做分段(预算为护栏非账单)。
125
+ const tokensBaseline = goal.tokensBaseline ?? 0;
126
+ const tokensUsed = Math.max(goal.tokensUsed ?? 0, Math.max(0, snapshotTokenTotal(await store.sessionTokens(sessionID)) - tokensBaseline));
127
+ goal.tokensBaseline = tokensBaseline;
128
+ goal.tokensUsed = tokensUsed;
129
+ // token 预算护栏:达限即暂停(用户需提高预算后 resume,护栏优先)
130
+ if (budgetReached(goal)) {
131
+ goal.status = "paused";
132
+ goal.statusReason = "token budget reached";
133
+ await updateFlowSession(projectDir, goal.parentIssueNumber, { status: "paused" }).catch(() => undefined);
134
+ return { goal, value: null };
135
+ }
136
+ // 先写计数后发 prompt:崩溃窗口只会"少发一次续接"(等下次轮次结束重试),
137
+ // 不会"prompt 已发但计数未落盘"导致重启 autoResume 双发。
138
+ goal.continuationCount++;
139
+ await updateFlowSession(projectDir, goal.parentIssueNumber, {
140
+ continuationCount: goal.continuationCount,
141
+ lastContinuedAt: Date.now(),
142
+ }).catch(() => undefined);
143
+ return { goal, value: { proceed: true, goal } };
144
+ });
145
+ if (!decision?.proceed || !decision.goal)
146
+ return;
147
+ // abort 二次检查:轮次结束事件与 abort 事件并发时,避免对已中断的会话发出续接
148
+ if (consumeAborted(sessionID)) {
149
+ await mutateGoal(store, sessionID, async (goal) => {
150
+ if (!goal)
151
+ return { goal, value: null };
152
+ goal.status = "paused";
153
+ goal.continuationCount = Math.max(0, goal.continuationCount - 1);
154
+ await updateFlowSession(projectDir, goal.parentIssueNumber, { status: "paused" }).catch(() => undefined);
155
+ return { goal, value: null };
156
+ }).catch(() => undefined);
157
+ return;
158
+ }
159
+ // 每 20 次续接主动 compact 会话历史(原生压缩;失败不阻塞续接)
160
+ if (decision.goal.continuationCount > 0 && decision.goal.continuationCount % COMPACTION_THRESHOLD === 0) {
161
+ try {
162
+ await ctx.session.compact({ sessionID });
163
+ }
164
+ catch (err) {
165
+ console.warn("[cabbage] compaction failed:", err);
166
+ }
167
+ }
168
+ const contextBlock = await getContextBlock(projectDir);
169
+ const contextText = contextBlock ? `${formatContextBlock(contextBlock)}\n\n` : "";
170
+ try {
171
+ await restoreSessionProfile(ctx, sessionID, decision.goal.sessionProfile);
172
+ await ctx.session.synthetic({
173
+ sessionID,
174
+ text: contextText + continuationPrompt(decision.goal.parentIssueNumber),
175
+ });
176
+ }
177
+ catch (err) {
178
+ // 发送失败 → 回滚计数(尽力;回滚失败只会少一次续接,方向安全)
179
+ console.error("[cabbage] continuation prompt failed, rolling back counter:", err);
180
+ await mutateGoal(store, sessionID, async (goal) => {
181
+ if (!goal)
182
+ return { goal, value: null };
183
+ goal.continuationCount = Math.max(0, goal.continuationCount - 1);
184
+ await updateFlowSession(projectDir, goal.parentIssueNumber, { continuationCount: goal.continuationCount }).catch(() => undefined);
185
+ return { goal, value: null };
186
+ }).catch(() => undefined);
187
+ }
188
+ }
189
+ catch (err) {
190
+ console.error("[cabbage] continuation failed:", err);
191
+ }
192
+ finally {
193
+ continuationInFlight.delete(sessionID);
194
+ }
195
+ }
196
+ export async function autoResume(ctx, store, projectDir) {
197
+ const index = await readIndex(projectDir);
198
+ for (const [parentIssueNumber, entry] of Object.entries(index.flows)) {
199
+ if (entry.status !== "active")
200
+ continue;
201
+ // 重启双发防护:仅跳过"最近实际续接过"的 flow(lastContinuedAt 在发送续接时写入)。
202
+ // 不用 updatedAt——它被 queueContinuation 开头的索引心跳无条件刷新,反映"最近轮次结束",
203
+ // 崩溃前频繁结束的 flow 会被误跳过且无再武装(静默卡住)。
204
+ // 无 lastContinuedAt 的旧 entry 不跳过(兼容升级前索引)。跳过时告警保证可观测。
205
+ if (entry.lastContinuedAt && Date.now() - entry.lastContinuedAt < AUTO_RESUME_SKIP_WINDOW_MS) {
206
+ console.warn(`[cabbage] auto-resume: skip #${parentIssueNumber} (continued ${Math.round((Date.now() - entry.lastContinuedAt) / 1000)}s ago; next turn end re-arms)`);
207
+ continue;
208
+ }
209
+ const { goal } = await store.read(entry.sessionID);
210
+ // 索引一致性自愈:entry 指向的 goal 已是别的 Flow(edit 换 Flow 后旧 entry 残留/rebind 失败)→
211
+ // 删除陈旧 entry,防止每次重启对同一会话重复续接
212
+ if (goal && goal.parentIssueNumber !== Number(parentIssueNumber)) {
213
+ console.warn(`[cabbage] auto-resume: index #${parentIssueNumber} points to goal of Flow #${goal.parentIssueNumber}; removing stale entry`);
214
+ await removeFlowSession(projectDir, Number(parentIssueNumber));
215
+ continue;
216
+ }
217
+ if (!goal || goal.status !== "active") {
218
+ await updateFlowSession(projectDir, Number(parentIssueNumber), { status: "paused" });
219
+ continue;
220
+ }
221
+ try {
222
+ await restoreSessionProfile(ctx, entry.sessionID, goal.sessionProfile);
223
+ await ctx.session.synthetic({
224
+ sessionID: entry.sessionID,
225
+ text: `[auto-resume] Plugin restarted. Resuming previous goal:\n\n${formatGoal(goal)}\n\nContinue working.`,
226
+ });
227
+ }
228
+ catch (err) {
229
+ console.error("[cabbage] auto-resume failed:", err);
230
+ }
231
+ }
232
+ }
233
+ //# sourceMappingURL=continuation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"continuation.js","sourceRoot":"","sources":["../../src/plugin/continuation.ts"],"names":[],"mappings":"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"}