agentweaver 0.1.16 → 0.1.18

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 (74) hide show
  1. package/README.md +148 -27
  2. package/dist/artifacts.js +114 -3
  3. package/dist/doctor/checks/executors.js +2 -2
  4. package/dist/flow-state.js +138 -1
  5. package/dist/index.js +421 -82
  6. package/dist/interactive/controller.js +305 -36
  7. package/dist/interactive/ink/index.js +24 -3
  8. package/dist/interactive/state.js +1 -0
  9. package/dist/interactive/tree.js +2 -2
  10. package/dist/interactive/web/index.js +179 -0
  11. package/dist/interactive/web/protocol.js +154 -0
  12. package/dist/interactive/web/server.js +575 -0
  13. package/dist/interactive/web/static/app.js +709 -0
  14. package/dist/interactive/web/static/index.html +77 -0
  15. package/dist/interactive/web/static/styles.css +2 -0
  16. package/dist/interactive/web/static/styles.input.css +469 -0
  17. package/dist/pipeline/auto-flow.js +9 -6
  18. package/dist/pipeline/context.js +6 -5
  19. package/dist/pipeline/declarative-flows.js +39 -20
  20. package/dist/pipeline/flow-catalog.js +40 -14
  21. package/dist/pipeline/flow-specs/auto-common-guided.json +313 -0
  22. package/dist/pipeline/flow-specs/auto-common.json +4 -1
  23. package/dist/pipeline/flow-specs/auto-golang.json +27 -1
  24. package/dist/pipeline/flow-specs/design-review/design-review-loop.json +15 -1
  25. package/dist/pipeline/flow-specs/design-review.json +2 -0
  26. package/dist/pipeline/flow-specs/implement.json +3 -1
  27. package/dist/pipeline/flow-specs/plan.json +8 -2
  28. package/dist/pipeline/flow-specs/playbook-init.json +199 -0
  29. package/dist/pipeline/flow-specs/review/review-fix.json +3 -1
  30. package/dist/pipeline/flow-specs/review/review-loop.json +4 -0
  31. package/dist/pipeline/flow-specs/review/review.json +2 -0
  32. package/dist/pipeline/launch-profile-config.js +30 -18
  33. package/dist/pipeline/node-contract.js +1 -0
  34. package/dist/pipeline/node-registry.js +119 -5
  35. package/dist/pipeline/nodes/flow-run-node.js +200 -173
  36. package/dist/pipeline/nodes/llm-prompt-node.js +15 -33
  37. package/dist/pipeline/nodes/playbook-ensure-node.js +115 -0
  38. package/dist/pipeline/nodes/playbook-inventory-node.js +51 -0
  39. package/dist/pipeline/nodes/playbook-questions-form-node.js +166 -0
  40. package/dist/pipeline/nodes/playbook-write-node.js +243 -0
  41. package/dist/pipeline/nodes/project-guidance-node.js +69 -0
  42. package/dist/pipeline/plugin-loader.js +389 -0
  43. package/dist/pipeline/plugin-types.js +1 -0
  44. package/dist/pipeline/prompt-registry.js +4 -1
  45. package/dist/pipeline/prompt-runtime.js +6 -2
  46. package/dist/pipeline/registry.js +71 -4
  47. package/dist/pipeline/spec-compiler.js +1 -0
  48. package/dist/pipeline/spec-loader.js +14 -0
  49. package/dist/pipeline/spec-types.js +19 -0
  50. package/dist/pipeline/spec-validator.js +6 -0
  51. package/dist/pipeline/value-resolver.js +41 -2
  52. package/dist/playbook/practice-candidates.js +12 -0
  53. package/dist/playbook/repo-inventory.js +208 -0
  54. package/dist/plugin-sdk.js +1 -0
  55. package/dist/prompts.js +31 -0
  56. package/dist/runtime/artifact-registry.js +3 -0
  57. package/dist/runtime/execution-routing.js +25 -19
  58. package/dist/runtime/interactive-execution-routing.js +66 -57
  59. package/dist/runtime/playbook.js +485 -0
  60. package/dist/runtime/project-guidance.js +339 -0
  61. package/dist/structured-artifact-schema-registry.js +8 -0
  62. package/dist/structured-artifact-schemas.json +235 -0
  63. package/dist/structured-artifacts.js +7 -1
  64. package/docs/declarative-workflows.md +565 -0
  65. package/docs/example/.flows/examples/claude-example.json +50 -0
  66. package/docs/example/.plugins/claude-example-plugin/index.js +149 -0
  67. package/docs/example/.plugins/claude-example-plugin/plugin.json +8 -0
  68. package/docs/examples/.flows/claude-example.json +50 -0
  69. package/docs/examples/.plugins/claude-example-plugin/index.js +149 -0
  70. package/docs/examples/.plugins/claude-example-plugin/plugin.json +8 -0
  71. package/docs/features.md +77 -0
  72. package/docs/playbook.md +327 -0
  73. package/docs/plugin-sdk.md +731 -0
  74. package/package.json +13 -4
@@ -54,7 +54,9 @@
54
54
  "taskKey": { "ref": "params.taskKey" },
55
55
  "iteration": { "ref": "params.planningIteration" }
56
56
  }
57
- }
57
+ },
58
+ "project_guidance_file": { "ref": "params.projectGuidanceFile" },
59
+ "project_guidance_json_file": { "ref": "params.projectGuidanceJsonFile" }
58
60
  },
59
61
  "extraPrompt": { "ref": "params.extraPrompt" },
60
62
  "format": "task-prompt"
@@ -65,6 +65,8 @@
65
65
  "iteration": { "ref": "params.taskContextIteration" }
66
66
  }
67
67
  },
68
+ "project_guidance_file": { "ref": "params.projectGuidanceFile" },
69
+ "project_guidance_json_file": { "ref": "params.projectGuidanceJsonFile" },
68
70
  "planning_questions_json_file": {
69
71
  "artifact": {
70
72
  "kind": "planning-questions-json-file",
@@ -203,6 +205,8 @@
203
205
  "taskKey": { "ref": "params.taskKey" }
204
206
  }
205
207
  },
208
+ "project_guidance_file": { "ref": "params.projectGuidanceFile" },
209
+ "project_guidance_json_file": { "ref": "params.projectGuidanceJsonFile" },
206
210
  "design_file": {
207
211
  "artifact": {
208
212
  "kind": "design-file",
@@ -258,7 +262,8 @@
258
262
  "requiredArtifacts": {
259
263
  "artifactList": {
260
264
  "kind": "plan-artifacts",
261
- "taskKey": { "ref": "params.taskKey" }
265
+ "taskKey": { "ref": "params.taskKey" },
266
+ "iteration": { "ref": "params.planIteration" }
262
267
  }
263
268
  }
264
269
  },
@@ -269,7 +274,8 @@
269
274
  "paths": {
270
275
  "artifactList": {
271
276
  "kind": "plan-artifacts",
272
- "taskKey": { "ref": "params.taskKey" }
277
+ "taskKey": { "ref": "params.taskKey" },
278
+ "iteration": { "ref": "params.planIteration" }
273
279
  }
274
280
  },
275
281
  "message": "Plan mode did not produce the required artifacts."
@@ -0,0 +1,199 @@
1
+ {
2
+ "kind": "playbook-init-flow",
3
+ "version": 1,
4
+ "description": "Initializes an evidence-backed project playbook from deterministic repository inventory, candidate practices, targeted questions, structured answers, a draft, and a guarded final write.",
5
+ "phases": [
6
+ {
7
+ "id": "playbook_init",
8
+ "steps": [
9
+ {
10
+ "id": "repo_inventory",
11
+ "node": "playbook-inventory",
12
+ "params": {
13
+ "outputJsonFile": { "artifact": { "kind": "repo-inventory-json-file", "taskKey": { "ref": "params.taskKey" } } },
14
+ "outputFile": { "artifact": { "kind": "repo-inventory-file", "taskKey": { "ref": "params.taskKey" } } }
15
+ },
16
+ "expect": [
17
+ {
18
+ "kind": "require-structured-artifacts",
19
+ "items": [
20
+ { "path": { "artifact": { "kind": "repo-inventory-json-file", "taskKey": { "ref": "params.taskKey" } } }, "schemaId": "repo-inventory/v1" }
21
+ ],
22
+ "message": "Playbook initialization requires a valid deterministic repository inventory."
23
+ }
24
+ ]
25
+ },
26
+ {
27
+ "id": "practice_candidates",
28
+ "node": "llm-prompt",
29
+ "routingGroup": "planning",
30
+ "prompt": {
31
+ "templateRef": "playbook-practice-candidates",
32
+ "vars": {
33
+ "repo_inventory_json_file": { "artifact": { "kind": "repo-inventory-json-file", "taskKey": { "ref": "params.taskKey" } } },
34
+ "practice_candidates_json_file": { "artifact": { "kind": "practice-candidates-json-file", "taskKey": { "ref": "params.taskKey" } } },
35
+ "practice_candidates_file": { "artifact": { "kind": "practice-candidates-file", "taskKey": { "ref": "params.taskKey" } } }
36
+ },
37
+ "extraPrompt": { "ref": "params.extraPrompt" },
38
+ "format": "task-prompt"
39
+ },
40
+ "params": {
41
+ "labelText": { "const": "Generating evidence-backed practice candidates" },
42
+ "model": { "ref": "params.llmModel" },
43
+ "executor": { "ref": "params.llmExecutor" },
44
+ "requiredArtifacts": {
45
+ "list": [
46
+ { "artifact": { "kind": "practice-candidates-json-file", "taskKey": { "ref": "params.taskKey" } } },
47
+ { "artifact": { "kind": "practice-candidates-file", "taskKey": { "ref": "params.taskKey" } } }
48
+ ]
49
+ }
50
+ },
51
+ "expect": [
52
+ {
53
+ "kind": "require-structured-artifacts",
54
+ "when": { "not": { "ref": "context.dryRun" } },
55
+ "items": [
56
+ { "path": { "artifact": { "kind": "practice-candidates-json-file", "taskKey": { "ref": "params.taskKey" } } }, "schemaId": "practice-candidates/v1" }
57
+ ],
58
+ "message": "Practice candidate generation produced invalid structured artifacts."
59
+ }
60
+ ]
61
+ },
62
+ {
63
+ "id": "clarification_questions",
64
+ "node": "llm-prompt",
65
+ "routingGroup": "planning",
66
+ "prompt": {
67
+ "templateRef": "playbook-questions",
68
+ "vars": {
69
+ "repo_inventory_json_file": { "artifact": { "kind": "repo-inventory-json-file", "taskKey": { "ref": "params.taskKey" } } },
70
+ "practice_candidates_json_file": { "artifact": { "kind": "practice-candidates-json-file", "taskKey": { "ref": "params.taskKey" } } },
71
+ "playbook_questions_json_file": { "artifact": { "kind": "playbook-questions-json-file", "taskKey": { "ref": "params.taskKey" } } }
72
+ },
73
+ "extraPrompt": { "ref": "params.extraPrompt" },
74
+ "format": "task-prompt"
75
+ },
76
+ "params": {
77
+ "labelText": { "const": "Generating targeted playbook questions" },
78
+ "model": { "ref": "params.llmModel" },
79
+ "executor": { "ref": "params.llmExecutor" },
80
+ "requiredArtifacts": {
81
+ "list": [
82
+ { "artifact": { "kind": "playbook-questions-json-file", "taskKey": { "ref": "params.taskKey" } } }
83
+ ]
84
+ }
85
+ },
86
+ "expect": [
87
+ {
88
+ "kind": "require-structured-artifacts",
89
+ "when": { "not": { "ref": "context.dryRun" } },
90
+ "items": [
91
+ { "path": { "artifact": { "kind": "playbook-questions-json-file", "taskKey": { "ref": "params.taskKey" } } }, "schemaId": "playbook-questions/v1" }
92
+ ],
93
+ "message": "Playbook question generation produced invalid structured artifacts."
94
+ }
95
+ ]
96
+ },
97
+ {
98
+ "id": "user_answers",
99
+ "node": "playbook-questions-form",
100
+ "params": {
101
+ "questionsJsonFile": { "artifact": { "kind": "playbook-questions-json-file", "taskKey": { "ref": "params.taskKey" } } },
102
+ "answersJsonFile": { "artifact": { "kind": "playbook-answers-json-file", "taskKey": { "ref": "params.taskKey" } } },
103
+ "formId": { "const": "playbook-clarifications" },
104
+ "title": { "const": "Playbook Clarifications" },
105
+ "mode": { "const": "clarifications" },
106
+ "acceptDraft": { "ref": "params.acceptPlaybookDraft" }
107
+ },
108
+ "expect": [
109
+ {
110
+ "kind": "require-structured-artifacts",
111
+ "items": [
112
+ { "path": { "artifact": { "kind": "playbook-answers-json-file", "taskKey": { "ref": "params.taskKey" } } }, "schemaId": "playbook-answers/v1" }
113
+ ],
114
+ "message": "Playbook answers are missing or invalid."
115
+ }
116
+ ]
117
+ },
118
+ {
119
+ "id": "playbook_draft",
120
+ "node": "llm-prompt",
121
+ "routingGroup": "planning",
122
+ "prompt": {
123
+ "templateRef": "playbook-draft",
124
+ "vars": {
125
+ "repo_inventory_json_file": { "artifact": { "kind": "repo-inventory-json-file", "taskKey": { "ref": "params.taskKey" } } },
126
+ "practice_candidates_json_file": { "artifact": { "kind": "practice-candidates-json-file", "taskKey": { "ref": "params.taskKey" } } },
127
+ "playbook_questions_json_file": { "artifact": { "kind": "playbook-questions-json-file", "taskKey": { "ref": "params.taskKey" } } },
128
+ "playbook_answers_json_file": { "artifact": { "kind": "playbook-answers-json-file", "taskKey": { "ref": "params.taskKey" } } },
129
+ "playbook_draft_json_file": { "artifact": { "kind": "playbook-draft-json-file", "taskKey": { "ref": "params.taskKey" } } },
130
+ "playbook_draft_file": { "artifact": { "kind": "playbook-draft-file", "taskKey": { "ref": "params.taskKey" } } }
131
+ },
132
+ "extraPrompt": { "ref": "params.extraPrompt" },
133
+ "format": "task-prompt"
134
+ },
135
+ "params": {
136
+ "labelText": { "const": "Generating playbook draft" },
137
+ "model": { "ref": "params.llmModel" },
138
+ "executor": { "ref": "params.llmExecutor" },
139
+ "requiredArtifacts": {
140
+ "list": [
141
+ { "artifact": { "kind": "playbook-draft-json-file", "taskKey": { "ref": "params.taskKey" } } },
142
+ { "artifact": { "kind": "playbook-draft-file", "taskKey": { "ref": "params.taskKey" } } }
143
+ ]
144
+ }
145
+ },
146
+ "expect": [
147
+ {
148
+ "kind": "require-structured-artifacts",
149
+ "when": { "not": { "ref": "context.dryRun" } },
150
+ "items": [
151
+ { "path": { "artifact": { "kind": "playbook-draft-json-file", "taskKey": { "ref": "params.taskKey" } } }, "schemaId": "playbook-draft/v1" }
152
+ ],
153
+ "message": "Playbook draft generation produced invalid structured artifacts."
154
+ }
155
+ ]
156
+ },
157
+ {
158
+ "id": "acceptance_confirmation",
159
+ "node": "playbook-questions-form",
160
+ "params": {
161
+ "questionsJsonFile": { "artifact": { "kind": "playbook-questions-json-file", "taskKey": { "ref": "params.taskKey" } } },
162
+ "answersJsonFile": { "artifact": { "kind": "playbook-answers-json-file", "taskKey": { "ref": "params.taskKey" } } },
163
+ "formId": { "const": "playbook-final-acceptance" },
164
+ "title": { "const": "Playbook Final Acceptance" },
165
+ "mode": { "const": "acceptance" },
166
+ "acceptDraft": { "ref": "params.acceptPlaybookDraft" }
167
+ },
168
+ "expect": [
169
+ {
170
+ "kind": "require-structured-artifacts",
171
+ "items": [
172
+ { "path": { "artifact": { "kind": "playbook-answers-json-file", "taskKey": { "ref": "params.taskKey" } } }, "schemaId": "playbook-answers/v1" }
173
+ ],
174
+ "message": "Playbook final acceptance is missing or invalid."
175
+ }
176
+ ]
177
+ },
178
+ {
179
+ "id": "write_playbook",
180
+ "node": "playbook-write",
181
+ "params": {
182
+ "draftJsonFile": { "artifact": { "kind": "playbook-draft-json-file", "taskKey": { "ref": "params.taskKey" } } },
183
+ "answersJsonFile": { "artifact": { "kind": "playbook-answers-json-file", "taskKey": { "ref": "params.taskKey" } } },
184
+ "writeResultJsonFile": { "artifact": { "kind": "playbook-write-result-json-file", "taskKey": { "ref": "params.taskKey" } } }
185
+ },
186
+ "expect": [
187
+ {
188
+ "kind": "require-structured-artifacts",
189
+ "items": [
190
+ { "path": { "artifact": { "kind": "playbook-write-result-json-file", "taskKey": { "ref": "params.taskKey" } } }, "schemaId": "playbook-write-result/v1" }
191
+ ],
192
+ "message": "Playbook write result is missing or invalid."
193
+ }
194
+ ]
195
+ }
196
+ ]
197
+ }
198
+ ]
199
+ }
@@ -147,7 +147,9 @@
147
147
  "taskKey": { "ref": "params.taskKey" },
148
148
  "iteration": { "ref": "params.latestIteration" }
149
149
  }
150
- }
150
+ },
151
+ "project_guidance_file": { "ref": "params.projectGuidanceFile" },
152
+ "project_guidance_json_file": { "ref": "params.projectGuidanceJsonFile" }
151
153
  },
152
154
  "extraPrompt": {
153
155
  "appendPrompt": {
@@ -38,6 +38,8 @@
38
38
  "taskKey": { "ref": "params.taskKey" },
39
39
  "iteration": { "ref": "params.baseIteration" },
40
40
  "extraPrompt": { "ref": "params.extraPrompt" },
41
+ "projectGuidanceFile": { "ref": "params.projectGuidanceFile" },
42
+ "projectGuidanceJsonFile": { "ref": "params.projectGuidanceJsonFile" },
41
43
  "reviewBlockingSeverities": { "ref": "params.reviewBlockingSeverities" },
42
44
  "llmModel": { "ref": "params.llmModel" },
43
45
  "llmExecutor": { "ref": "params.llmExecutor" }
@@ -164,6 +166,8 @@
164
166
  },
165
167
  "reviewFixPoints": { "ref": "params.reviewFixPoints" },
166
168
  "reviewBlockingSeverities": { "ref": "params.reviewBlockingSeverities" },
169
+ "projectGuidanceFile": { "ref": "params.repairProjectGuidanceFile" },
170
+ "projectGuidanceJsonFile": { "ref": "params.repairProjectGuidanceJsonFile" },
167
171
  "extraPrompt": {
168
172
  "appendPrompt": {
169
173
  "base": { "ref": "params.extraPrompt" },
@@ -20,6 +20,8 @@
20
20
  "design_json_file": { "ref": "params.designJsonFile" },
21
21
  "plan_file": { "ref": "params.planFile" },
22
22
  "plan_json_file": { "ref": "params.planJsonFile" },
23
+ "project_guidance_file": { "ref": "params.projectGuidanceFile" },
24
+ "project_guidance_json_file": { "ref": "params.projectGuidanceJsonFile" },
23
25
  "review_file": {
24
26
  "artifact": {
25
27
  "kind": "review-file",
@@ -1,32 +1,44 @@
1
- export const LLM_EXECUTOR_IDS = ["codex", "opencode"];
2
- export const ALLOWED_MODELS_BY_EXECUTOR = {
3
- codex: ["gpt-5.4", "gpt-5.4-mini", "gpt-5.3-codex"],
4
- opencode: ["opencode/minimax-m2.5-free", "minimax-coding-plan/MiniMax-M2.7", "zhipuai-coding-plan/glm-5.1", "zhipuai-coding-plan/glm-4.7"],
5
- };
1
+ import { createExecutorRegistry } from "./registry.js";
2
+ const BUILT_IN_EXECUTOR_REGISTRY = createExecutorRegistry();
6
3
  export const DEFAULT_EXECUTOR = "opencode";
7
- export const DEFAULT_MODEL_BY_EXECUTOR = {
8
- codex: "gpt-5.4",
9
- opencode: "minimax-coding-plan/MiniMax-M2.7",
10
- };
11
4
  export const DEFAULT_LAUNCH_PROFILE = {
12
5
  executor: DEFAULT_EXECUTOR,
13
- model: DEFAULT_MODEL_BY_EXECUTOR[DEFAULT_EXECUTOR],
6
+ model: "minimax-coding-plan/MiniMax-M2.7",
14
7
  };
15
- export function defaultModelForExecutor(executor) {
16
- return DEFAULT_MODEL_BY_EXECUTOR[executor];
8
+ function registryOrBuiltIn(executors) {
9
+ return executors ?? BUILT_IN_EXECUTOR_REGISTRY;
10
+ }
11
+ export function llmExecutorIds(executors) {
12
+ return registryOrBuiltIn(executors).llmExecutors().map((entry) => entry.id);
13
+ }
14
+ export function defaultModelForExecutor(executor, executors) {
15
+ const routing = registryOrBuiltIn(executors).getRouting(executor);
16
+ if (!routing || routing.kind !== "llm") {
17
+ throw new Error(`Unsupported llm executor '${executor}'.`);
18
+ }
19
+ return routing.defaultModel;
20
+ }
21
+ export function isLlmExecutorId(value, executors) {
22
+ const routing = registryOrBuiltIn(executors).getRouting(value);
23
+ return routing?.kind === "llm";
17
24
  }
18
- export function isLlmExecutorId(value) {
19
- return LLM_EXECUTOR_IDS.includes(value);
25
+ export function isAllowedModelForExecutor(executor, model, executors) {
26
+ const routing = registryOrBuiltIn(executors).getRouting(executor);
27
+ return routing?.kind === "llm" ? routing.models.includes(model) : false;
20
28
  }
21
- export function isAllowedModelForExecutor(executor, model) {
22
- return ALLOWED_MODELS_BY_EXECUTOR[executor].includes(model);
29
+ export function allowedModelsForExecutor(executor, executors) {
30
+ const routing = registryOrBuiltIn(executors).getRouting(executor);
31
+ if (!routing || routing.kind !== "llm") {
32
+ throw new Error(`Unsupported llm executor '${executor}'.`);
33
+ }
34
+ return [...routing.models];
23
35
  }
24
- export function resolveLaunchProfile(selection, fallback = DEFAULT_LAUNCH_PROFILE) {
36
+ export function resolveLaunchProfile(selection, fallback = DEFAULT_LAUNCH_PROFILE, executors) {
25
37
  const executor = selection.executor === "default" ? fallback.executor : selection.executor;
26
38
  const model = selection.model === "default"
27
39
  ? selection.executor === "default"
28
40
  ? fallback.model
29
- : defaultModelForExecutor(executor)
41
+ : defaultModelForExecutor(executor, executors)
30
42
  : selection.model;
31
43
  return {
32
44
  executor,
@@ -0,0 +1 @@
1
+ export {};
@@ -21,8 +21,13 @@ import { localScriptCheckNode } from "./nodes/local-script-check-node.js";
21
21
  import { llmPromptNode } from "./nodes/llm-prompt-node.js";
22
22
  import { opencodePromptNode } from "./nodes/opencode-prompt-node.js";
23
23
  import { planCodexNode } from "./nodes/plan-codex-node.js";
24
+ import { playbookInventoryNode } from "./nodes/playbook-inventory-node.js";
25
+ import { playbookEnsureNode } from "./nodes/playbook-ensure-node.js";
26
+ import { playbookQuestionsFormNode } from "./nodes/playbook-questions-form-node.js";
27
+ import { playbookWriteNode } from "./nodes/playbook-write-node.js";
24
28
  import { planningBundleNode } from "./nodes/planning-bundle-node.js";
25
29
  import { planningQuestionsFormNode } from "./nodes/planning-questions-form-node.js";
30
+ import { projectGuidanceNode } from "./nodes/project-guidance-node.js";
26
31
  import { readFileNode } from "./nodes/read-file-node.js";
27
32
  import { reviewFindingsFormNode } from "./nodes/review-findings-form-node.js";
28
33
  import { reviewVerdictNode } from "./nodes/review-verdict-node.js";
@@ -32,6 +37,48 @@ import { summaryFileLoadNode } from "./nodes/summary-file-load-node.js";
32
37
  import { telegramNotifierNode } from "./nodes/telegram-notifier-node.js";
33
38
  import { userInputNode } from "./nodes/user-input-node.js";
34
39
  import { writeSelectionFileNode } from "./nodes/write-selection-file-node.js";
40
+ import { TaskRunnerError } from "../errors.js";
41
+ export const BUILT_IN_NODE_KINDS = [
42
+ "build-failure-summary",
43
+ "build-review-fix-prompt",
44
+ "clear-ready-to-merge",
45
+ "codex-prompt",
46
+ "command-check",
47
+ "commit-message-form",
48
+ "design-review-verdict",
49
+ "ensure-summary-json",
50
+ "fetch-gitlab-diff",
51
+ "fetch-gitlab-review",
52
+ "file-check",
53
+ "flow-run",
54
+ "git-commit",
55
+ "git-commit-form",
56
+ "git-status",
57
+ "gitlab-review-artifacts",
58
+ "jira-context",
59
+ "jira-fetch",
60
+ "jira-issue-check",
61
+ "local-script-check",
62
+ "llm-prompt",
63
+ "opencode-prompt",
64
+ "plan-codex",
65
+ "playbook-inventory",
66
+ "playbook-ensure",
67
+ "playbook-questions-form",
68
+ "playbook-write",
69
+ "planning-bundle",
70
+ "planning-questions-form",
71
+ "project-guidance",
72
+ "read-file",
73
+ "review-findings-form",
74
+ "review-verdict",
75
+ "select-files-form",
76
+ "structured-summary",
77
+ "summary-file-load",
78
+ "telegram-notify",
79
+ "user-input",
80
+ "write-selection-file",
81
+ ];
35
82
  const builtInNodes = {
36
83
  "build-failure-summary": buildFailureSummaryNode,
37
84
  "build-review-fix-prompt": buildReviewFixPromptNode,
@@ -56,8 +103,13 @@ const builtInNodes = {
56
103
  "llm-prompt": llmPromptNode,
57
104
  "opencode-prompt": opencodePromptNode,
58
105
  "plan-codex": planCodexNode,
106
+ "playbook-inventory": playbookInventoryNode,
107
+ "playbook-ensure": playbookEnsureNode,
108
+ "playbook-questions-form": playbookQuestionsFormNode,
109
+ "playbook-write": playbookWriteNode,
59
110
  "planning-bundle": planningBundleNode,
60
111
  "planning-questions-form": planningQuestionsFormNode,
112
+ "project-guidance": projectGuidanceNode,
61
113
  "read-file": readFileNode,
62
114
  "review-findings-form": reviewFindingsFormNode,
63
115
  "review-verdict": reviewVerdictNode,
@@ -191,6 +243,30 @@ const builtInNodeMetadata = {
191
243
  requiredParams: ["prompt", "requiredArtifacts"],
192
244
  executors: ["codex"],
193
245
  },
246
+ "playbook-inventory": {
247
+ kind: "playbook-inventory",
248
+ version: 1,
249
+ prompt: "forbidden",
250
+ requiredParams: ["outputJsonFile", "outputFile"],
251
+ },
252
+ "playbook-ensure": {
253
+ kind: "playbook-ensure",
254
+ version: 1,
255
+ prompt: "forbidden",
256
+ requiredParams: ["writeResultJsonFile"],
257
+ },
258
+ "playbook-questions-form": {
259
+ kind: "playbook-questions-form",
260
+ version: 1,
261
+ prompt: "forbidden",
262
+ requiredParams: ["questionsJsonFile", "answersJsonFile", "formId", "title"],
263
+ },
264
+ "playbook-write": {
265
+ kind: "playbook-write",
266
+ version: 1,
267
+ prompt: "forbidden",
268
+ requiredParams: ["draftJsonFile", "answersJsonFile", "writeResultJsonFile"],
269
+ },
194
270
  "planning-bundle": {
195
271
  kind: "planning-bundle",
196
272
  version: 1,
@@ -203,6 +279,12 @@ const builtInNodeMetadata = {
203
279
  prompt: "forbidden",
204
280
  requiredParams: ["planningQuestionsJsonFile", "formId", "title"],
205
281
  },
282
+ "project-guidance": {
283
+ kind: "project-guidance",
284
+ version: 1,
285
+ prompt: "forbidden",
286
+ requiredParams: ["taskContextJsonFile", "phase", "outputJsonFile", "outputFile"],
287
+ },
206
288
  "read-file": { kind: "read-file", version: 1, prompt: "forbidden", requiredParams: ["path"] },
207
289
  "review-findings-form": {
208
290
  kind: "review-findings-form",
@@ -249,19 +331,51 @@ const builtInNodeMetadata = {
249
331
  requiredParams: ["outputFile", "reviewFindingsJsonFile", "selectionMode"],
250
332
  },
251
333
  };
252
- export function createNodeRegistry() {
334
+ function coreOwner(id) {
335
+ return {
336
+ kind: "core",
337
+ id: `core:${id}`,
338
+ manifestPath: "built-in node registry",
339
+ };
340
+ }
341
+ export function createNodeRegistry(pluginNodes = []) {
342
+ const definitions = new Map(Object.entries(builtInNodes));
343
+ const metadata = new Map(Object.entries(builtInNodeMetadata));
344
+ const owners = new Map(Object.keys(builtInNodes).map((id) => [id, coreOwner(id)]));
345
+ for (const registration of pluginNodes) {
346
+ const existingOwner = owners.get(registration.id);
347
+ if (existingOwner) {
348
+ throw new TaskRunnerError(`Duplicate node id '${registration.id}' conflicts between ${existingOwner.id} (${existingOwner.manifestPath}) and plugin '${registration.pluginId}' (${registration.manifestPath}).`);
349
+ }
350
+ definitions.set(registration.id, registration.definition);
351
+ metadata.set(registration.id, registration.metadata);
352
+ owners.set(registration.id, {
353
+ kind: "plugin",
354
+ id: registration.pluginId,
355
+ manifestPath: registration.manifestPath,
356
+ entrypointPath: registration.entrypointPath,
357
+ });
358
+ }
253
359
  return {
254
360
  get(kind) {
255
- return builtInNodes[kind];
361
+ const definition = definitions.get(kind);
362
+ if (!definition) {
363
+ throw new TaskRunnerError(`Unknown node kind '${kind}'.`);
364
+ }
365
+ return definition;
256
366
  },
257
367
  getMeta(kind) {
258
- return builtInNodeMetadata[kind];
368
+ const definition = metadata.get(kind);
369
+ if (!definition) {
370
+ throw new TaskRunnerError(`Unknown node metadata '${kind}'.`);
371
+ }
372
+ return definition;
259
373
  },
260
374
  has(kind) {
261
- return kind in builtInNodes;
375
+ return definitions.has(kind);
262
376
  },
263
377
  kinds() {
264
- return Object.keys(builtInNodes);
378
+ return [...definitions.keys()];
265
379
  },
266
380
  };
267
381
  }