agentweaver 0.1.19 → 0.1.20
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 +47 -7
- package/dist/artifacts.js +9 -0
- package/dist/executors/git-commit-executor.js +24 -6
- package/dist/flow-state.js +3 -8
- package/dist/git/git-diff-parser.js +223 -0
- package/dist/git/git-service.js +562 -0
- package/dist/git/git-stage-selection.js +24 -0
- package/dist/git/git-status-parser.js +171 -0
- package/dist/git/git-types.js +1 -0
- package/dist/index.js +450 -108
- package/dist/interactive/auto-flow.js +644 -0
- package/dist/interactive/controller.js +417 -9
- package/dist/interactive/progress.js +194 -1
- package/dist/interactive/state.js +25 -0
- package/dist/interactive/web/index.js +97 -12
- package/dist/interactive/web/protocol.js +216 -1
- package/dist/interactive/web/server.js +72 -14
- package/dist/interactive/web/static/app.js +1603 -49
- package/dist/interactive/web/static/index.html +76 -11
- package/dist/interactive/web/static/styles.css +1 -1
- package/dist/interactive/web/static/styles.input.css +901 -47
- package/dist/pipeline/auto-flow-blocks.js +307 -0
- package/dist/pipeline/auto-flow-config.js +273 -0
- package/dist/pipeline/auto-flow-identity.js +49 -0
- package/dist/pipeline/auto-flow-presets.js +52 -0
- package/dist/pipeline/auto-flow-resolver.js +830 -0
- package/dist/pipeline/auto-flow-types.js +17 -0
- package/dist/pipeline/context.js +1 -0
- package/dist/pipeline/declarative-flows.js +27 -1
- package/dist/pipeline/flow-specs/auto-common-guided.json +11 -0
- package/dist/pipeline/flow-specs/auto-golang.json +12 -1
- package/dist/pipeline/flow-specs/bugz/bug-analyze.json +54 -1
- package/dist/pipeline/flow-specs/gitlab/gitlab-diff-review.json +19 -1
- package/dist/pipeline/flow-specs/gitlab/gitlab-review.json +33 -1
- package/dist/pipeline/flow-specs/review/review-project.json +19 -1
- package/dist/pipeline/flow-specs/task-source/manual-jira-input.json +70 -0
- package/dist/pipeline/node-registry.js +9 -0
- package/dist/pipeline/nodes/codex-prompt-node.js +8 -1
- package/dist/pipeline/nodes/flow-run-node.js +5 -3
- package/dist/pipeline/nodes/git-status-node.js +2 -168
- package/dist/pipeline/nodes/manual-jira-task-input-node.js +146 -0
- package/dist/pipeline/nodes/opencode-prompt-node.js +8 -1
- package/dist/pipeline/nodes/plan-codex-node.js +8 -1
- package/dist/pipeline/spec-loader.js +14 -4
- package/dist/runtime/artifact-catalog.js +29 -5
- package/dist/runtime/settings.js +114 -0
- package/dist/scope.js +14 -4
- package/package.json +1 -1
- package/dist/pipeline/flow-specs/auto-common.json +0 -179
- package/dist/pipeline/flow-specs/auto-simple.json +0 -141
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export const AUTO_FLOW_SLOT_IDS = [
|
|
2
|
+
"source",
|
|
3
|
+
"normalize",
|
|
4
|
+
"planning",
|
|
5
|
+
"designReview",
|
|
6
|
+
"implementation",
|
|
7
|
+
"postImplementationChecks",
|
|
8
|
+
"review",
|
|
9
|
+
"final",
|
|
10
|
+
];
|
|
11
|
+
export const AUTO_FLOW_SUMMARY_STATUSES = [
|
|
12
|
+
"enabled",
|
|
13
|
+
"disabled",
|
|
14
|
+
"skipped",
|
|
15
|
+
"auto-disabled",
|
|
16
|
+
"invalid",
|
|
17
|
+
];
|
package/dist/pipeline/context.js
CHANGED
|
@@ -19,5 +19,6 @@ export async function createPipelineContext(input) {
|
|
|
19
19
|
...(input.setSummary ? { setSummary: input.setSummary } : {}),
|
|
20
20
|
...(input.requestUserInput ? { requestUserInput: input.requestUserInput } : {}),
|
|
21
21
|
...(input.executionRouting ? { executionRouting: input.executionRouting } : {}),
|
|
22
|
+
...(input.inMemoryFlows ? { inMemoryFlows: input.inMemoryFlows } : {}),
|
|
22
23
|
};
|
|
23
24
|
}
|
|
@@ -43,6 +43,31 @@ export async function loadDeclarativeFlow(flow, options = {}) {
|
|
|
43
43
|
cache.set(cacheKey(ref, registryContext), loaded);
|
|
44
44
|
return loaded;
|
|
45
45
|
}
|
|
46
|
+
export async function loadDeclarativeFlowFromSpec(spec, metadata, options = {}) {
|
|
47
|
+
const cwd = path.resolve(options.cwd ?? options.registryContext?.cwd ?? process.cwd());
|
|
48
|
+
const registryContext = options.registryContext ?? await createPipelineRegistryContext(cwd);
|
|
49
|
+
validateFlowSpec(spec, registryContext.nodes, registryContext.executors, {
|
|
50
|
+
resolveFlowByName: (fileName) => {
|
|
51
|
+
if (options.inMemoryFlows?.[fileName]) {
|
|
52
|
+
return options.inMemoryFlows[fileName];
|
|
53
|
+
}
|
|
54
|
+
return resolveNamedDeclarativeFlowRef(fileName, cwd);
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
const phases = compileFlowSpec(spec);
|
|
58
|
+
validateExpandedPhases(phases);
|
|
59
|
+
return {
|
|
60
|
+
kind: spec.kind,
|
|
61
|
+
version: spec.version,
|
|
62
|
+
...(spec.description !== undefined ? { description: spec.description } : {}),
|
|
63
|
+
...(spec.catalogVisibility !== undefined ? { catalogVisibility: spec.catalogVisibility } : {}),
|
|
64
|
+
constants: spec.constants ?? {},
|
|
65
|
+
phases,
|
|
66
|
+
source: metadata.source ?? "generated",
|
|
67
|
+
fileName: metadata.fileName,
|
|
68
|
+
absolutePath: metadata.absolutePath ?? `in-memory:${metadata.fileName}`,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
46
71
|
export function resolveNamedDeclarativeFlowRef(fileName, cwd) {
|
|
47
72
|
const projectMatches = listProjectFlowSpecFiles(cwd).filter((candidate) => path.basename(candidate) === fileName);
|
|
48
73
|
const globalMatches = listGlobalFlowSpecFiles().filter((candidate) => path.basename(candidate) === fileName);
|
|
@@ -99,7 +124,8 @@ export async function collectFlowRoutingGroups(flow, cwd, visited = new Set(), o
|
|
|
99
124
|
if (!nestedFlowName || !("const" in nestedFlowName) || typeof nestedFlowName.const !== "string") {
|
|
100
125
|
continue;
|
|
101
126
|
}
|
|
102
|
-
const nestedFlow =
|
|
127
|
+
const nestedFlow = options.inMemoryFlows?.[nestedFlowName.const]
|
|
128
|
+
?? await loadNamedDeclarativeFlow(nestedFlowName.const, cwd, options);
|
|
103
129
|
for (const nestedGroup of await collectFlowRoutingGroups(nestedFlow, cwd, visited, options)) {
|
|
104
130
|
groups.add(nestedGroup);
|
|
105
131
|
}
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
"steps": [
|
|
9
9
|
{
|
|
10
10
|
"id": "fetch_jira_source",
|
|
11
|
+
"when": { "ref": "params.jiraApiUrl" },
|
|
11
12
|
"node": "flow-run",
|
|
12
13
|
"params": {
|
|
13
14
|
"fileName": { "const": "jira-fetch.json" },
|
|
@@ -15,6 +16,16 @@
|
|
|
15
16
|
"jiraApiUrl": { "ref": "params.jiraApiUrl" },
|
|
16
17
|
"taskKey": { "ref": "params.taskKey" }
|
|
17
18
|
}
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"id": "collect_manual_source",
|
|
22
|
+
"when": { "not": { "ref": "params.jiraApiUrl" } },
|
|
23
|
+
"node": "flow-run",
|
|
24
|
+
"params": {
|
|
25
|
+
"fileName": { "const": "manual-jira-input.json" },
|
|
26
|
+
"labelText": { "const": "Collecting manual Jira task source" },
|
|
27
|
+
"taskKey": { "ref": "params.taskKey" }
|
|
28
|
+
}
|
|
18
29
|
}
|
|
19
30
|
]
|
|
20
31
|
},
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"kind": "auto-flow",
|
|
3
3
|
"version": 1,
|
|
4
|
-
"description": "End-to-end resumable pipeline for Go projects. Runs the full sequence:
|
|
4
|
+
"description": "End-to-end resumable pipeline for Go projects. Runs the full sequence: task source collection → task source normalization → plan → design-review loop → implement → linter loop → test loop → review loop → final linter loop → final test loop. Supports --from to restart from a specific phase and auto-status/auto-reset for state management.",
|
|
5
5
|
"constants": {
|
|
6
6
|
"autoReviewFixExtraPrompt": "Fix only blockers, criticals, and important findings"
|
|
7
7
|
},
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
"steps": [
|
|
12
12
|
{
|
|
13
13
|
"id": "fetch_jira_source",
|
|
14
|
+
"when": { "ref": "params.jiraApiUrl" },
|
|
14
15
|
"node": "flow-run",
|
|
15
16
|
"params": {
|
|
16
17
|
"fileName": { "const": "jira-fetch.json" },
|
|
@@ -18,6 +19,16 @@
|
|
|
18
19
|
"jiraApiUrl": { "ref": "params.jiraApiUrl" },
|
|
19
20
|
"taskKey": { "ref": "params.taskKey" }
|
|
20
21
|
}
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"id": "collect_manual_source",
|
|
25
|
+
"when": { "not": { "ref": "params.jiraApiUrl" } },
|
|
26
|
+
"node": "flow-run",
|
|
27
|
+
"params": {
|
|
28
|
+
"fileName": { "const": "manual-jira-input.json" },
|
|
29
|
+
"labelText": { "const": "Collecting manual Jira task source" },
|
|
30
|
+
"taskKey": { "ref": "params.taskKey" }
|
|
31
|
+
}
|
|
21
32
|
}
|
|
22
33
|
]
|
|
23
34
|
},
|
|
@@ -128,6 +128,13 @@
|
|
|
128
128
|
},
|
|
129
129
|
"requiredArtifacts": {
|
|
130
130
|
"list": [
|
|
131
|
+
{
|
|
132
|
+
"artifact": {
|
|
133
|
+
"kind": "task-summary-file",
|
|
134
|
+
"taskKey": { "ref": "params.taskKey" },
|
|
135
|
+
"iteration": { "ref": "params.taskSummaryIteration" }
|
|
136
|
+
}
|
|
137
|
+
},
|
|
131
138
|
{
|
|
132
139
|
"artifact": {
|
|
133
140
|
"kind": "task-summary-json-file",
|
|
@@ -251,7 +258,53 @@
|
|
|
251
258
|
"params": {
|
|
252
259
|
"labelText": { "const": "Running bug analysis mode" },
|
|
253
260
|
"model": { "ref": "params.llmModel" },
|
|
254
|
-
"executor": { "ref": "params.llmExecutor" }
|
|
261
|
+
"executor": { "ref": "params.llmExecutor" },
|
|
262
|
+
"requiredArtifacts": {
|
|
263
|
+
"list": [
|
|
264
|
+
{
|
|
265
|
+
"artifact": {
|
|
266
|
+
"kind": "bug-analyze-file",
|
|
267
|
+
"taskKey": { "ref": "params.taskKey" },
|
|
268
|
+
"iteration": { "ref": "params.bugAnalyzeIteration" }
|
|
269
|
+
}
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
"artifact": {
|
|
273
|
+
"kind": "bug-analyze-json-file",
|
|
274
|
+
"taskKey": { "ref": "params.taskKey" },
|
|
275
|
+
"iteration": { "ref": "params.bugAnalyzeIteration" }
|
|
276
|
+
}
|
|
277
|
+
},
|
|
278
|
+
{
|
|
279
|
+
"artifact": {
|
|
280
|
+
"kind": "bug-fix-design-file",
|
|
281
|
+
"taskKey": { "ref": "params.taskKey" },
|
|
282
|
+
"iteration": { "ref": "params.bugFixDesignIteration" }
|
|
283
|
+
}
|
|
284
|
+
},
|
|
285
|
+
{
|
|
286
|
+
"artifact": {
|
|
287
|
+
"kind": "bug-fix-design-json-file",
|
|
288
|
+
"taskKey": { "ref": "params.taskKey" },
|
|
289
|
+
"iteration": { "ref": "params.bugFixDesignIteration" }
|
|
290
|
+
}
|
|
291
|
+
},
|
|
292
|
+
{
|
|
293
|
+
"artifact": {
|
|
294
|
+
"kind": "bug-fix-plan-file",
|
|
295
|
+
"taskKey": { "ref": "params.taskKey" },
|
|
296
|
+
"iteration": { "ref": "params.bugFixPlanIteration" }
|
|
297
|
+
}
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
"artifact": {
|
|
301
|
+
"kind": "bug-fix-plan-json-file",
|
|
302
|
+
"taskKey": { "ref": "params.taskKey" },
|
|
303
|
+
"iteration": { "ref": "params.bugFixPlanIteration" }
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
]
|
|
307
|
+
}
|
|
255
308
|
},
|
|
256
309
|
"expect": [
|
|
257
310
|
{
|
|
@@ -154,7 +154,25 @@
|
|
|
154
154
|
}
|
|
155
155
|
},
|
|
156
156
|
"model": { "ref": "params.llmModel" },
|
|
157
|
-
"executor": { "ref": "params.llmExecutor" }
|
|
157
|
+
"executor": { "ref": "params.llmExecutor" },
|
|
158
|
+
"requiredArtifacts": {
|
|
159
|
+
"list": [
|
|
160
|
+
{
|
|
161
|
+
"artifact": {
|
|
162
|
+
"kind": "review-file",
|
|
163
|
+
"taskKey": { "ref": "params.taskKey" },
|
|
164
|
+
"iteration": { "ref": "params.iteration" }
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
"artifact": {
|
|
169
|
+
"kind": "review-json-file",
|
|
170
|
+
"taskKey": { "ref": "params.taskKey" },
|
|
171
|
+
"iteration": { "ref": "params.iteration" }
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
]
|
|
175
|
+
}
|
|
158
176
|
},
|
|
159
177
|
"expect": [
|
|
160
178
|
{
|
|
@@ -162,7 +162,39 @@
|
|
|
162
162
|
}
|
|
163
163
|
},
|
|
164
164
|
"model": { "ref": "params.llmModel" },
|
|
165
|
-
"executor": { "ref": "params.llmExecutor" }
|
|
165
|
+
"executor": { "ref": "params.llmExecutor" },
|
|
166
|
+
"requiredArtifacts": {
|
|
167
|
+
"list": [
|
|
168
|
+
{
|
|
169
|
+
"artifact": {
|
|
170
|
+
"kind": "review-file",
|
|
171
|
+
"taskKey": { "ref": "params.taskKey" },
|
|
172
|
+
"iteration": { "ref": "params.iteration" }
|
|
173
|
+
}
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
"artifact": {
|
|
177
|
+
"kind": "review-json-file",
|
|
178
|
+
"taskKey": { "ref": "params.taskKey" },
|
|
179
|
+
"iteration": { "ref": "params.iteration" }
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
"artifact": {
|
|
184
|
+
"kind": "review-assessment-file",
|
|
185
|
+
"taskKey": { "ref": "params.taskKey" },
|
|
186
|
+
"iteration": { "ref": "params.iteration" }
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
"artifact": {
|
|
191
|
+
"kind": "review-assessment-json-file",
|
|
192
|
+
"taskKey": { "ref": "params.taskKey" },
|
|
193
|
+
"iteration": { "ref": "params.iteration" }
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
]
|
|
197
|
+
}
|
|
166
198
|
},
|
|
167
199
|
"expect": [
|
|
168
200
|
{
|
|
@@ -46,7 +46,25 @@
|
|
|
46
46
|
}
|
|
47
47
|
},
|
|
48
48
|
"model": { "ref": "params.llmModel" },
|
|
49
|
-
"executor": { "ref": "params.llmExecutor" }
|
|
49
|
+
"executor": { "ref": "params.llmExecutor" },
|
|
50
|
+
"requiredArtifacts": {
|
|
51
|
+
"list": [
|
|
52
|
+
{
|
|
53
|
+
"artifact": {
|
|
54
|
+
"kind": "review-file",
|
|
55
|
+
"taskKey": { "ref": "params.taskKey" },
|
|
56
|
+
"iteration": { "ref": "params.iteration" }
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"artifact": {
|
|
61
|
+
"kind": "review-json-file",
|
|
62
|
+
"taskKey": { "ref": "params.taskKey" },
|
|
63
|
+
"iteration": { "ref": "params.iteration" }
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
]
|
|
67
|
+
}
|
|
50
68
|
},
|
|
51
69
|
"expect": [
|
|
52
70
|
{
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{
|
|
2
|
+
"kind": "task-source-manual-jira-flow",
|
|
3
|
+
"version": 1,
|
|
4
|
+
"description": "Collects pasted task text when Jira access is unavailable and stores it as raw Jira task context artifacts for subsequent normalization.",
|
|
5
|
+
"catalogVisibility": "hidden",
|
|
6
|
+
"phases": [
|
|
7
|
+
{
|
|
8
|
+
"id": "source",
|
|
9
|
+
"steps": [
|
|
10
|
+
{
|
|
11
|
+
"id": "collect_manual_jira_task",
|
|
12
|
+
"node": "manual-jira-task-input",
|
|
13
|
+
"params": {
|
|
14
|
+
"taskKey": { "ref": "params.taskKey" },
|
|
15
|
+
"outputFile": {
|
|
16
|
+
"artifact": {
|
|
17
|
+
"kind": "jira-task-file",
|
|
18
|
+
"taskKey": { "ref": "params.taskKey" }
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"attachmentsManifestFile": {
|
|
22
|
+
"artifact": {
|
|
23
|
+
"kind": "jira-attachments-manifest-file",
|
|
24
|
+
"taskKey": { "ref": "params.taskKey" }
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"attachmentsContextFile": {
|
|
28
|
+
"artifact": {
|
|
29
|
+
"kind": "jira-attachments-context-file",
|
|
30
|
+
"taskKey": { "ref": "params.taskKey" }
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"expect": [
|
|
35
|
+
{
|
|
36
|
+
"kind": "require-file",
|
|
37
|
+
"path": {
|
|
38
|
+
"artifact": {
|
|
39
|
+
"kind": "jira-task-file",
|
|
40
|
+
"taskKey": { "ref": "params.taskKey" }
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"message": "Manual Jira task input did not produce the Jira task file."
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"kind": "require-file",
|
|
47
|
+
"path": {
|
|
48
|
+
"artifact": {
|
|
49
|
+
"kind": "jira-attachments-manifest-file",
|
|
50
|
+
"taskKey": { "ref": "params.taskKey" }
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
"message": "Manual Jira task input did not produce the Jira attachments manifest file."
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"kind": "require-file",
|
|
57
|
+
"path": {
|
|
58
|
+
"artifact": {
|
|
59
|
+
"kind": "jira-attachments-context-file",
|
|
60
|
+
"taskKey": { "ref": "params.taskKey" }
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
"message": "Manual Jira task input did not produce the Jira attachments context file."
|
|
64
|
+
}
|
|
65
|
+
]
|
|
66
|
+
}
|
|
67
|
+
]
|
|
68
|
+
}
|
|
69
|
+
]
|
|
70
|
+
}
|
|
@@ -19,6 +19,7 @@ import { jiraContextNode } from "./nodes/jira-context-node.js";
|
|
|
19
19
|
import { jiraIssueCheckNode } from "./nodes/jira-issue-check-node.js";
|
|
20
20
|
import { localScriptCheckNode } from "./nodes/local-script-check-node.js";
|
|
21
21
|
import { llmPromptNode } from "./nodes/llm-prompt-node.js";
|
|
22
|
+
import { manualJiraTaskInputNode } from "./nodes/manual-jira-task-input-node.js";
|
|
22
23
|
import { opencodePromptNode } from "./nodes/opencode-prompt-node.js";
|
|
23
24
|
import { planCodexNode } from "./nodes/plan-codex-node.js";
|
|
24
25
|
import { playbookInventoryNode } from "./nodes/playbook-inventory-node.js";
|
|
@@ -60,6 +61,7 @@ export const BUILT_IN_NODE_KINDS = [
|
|
|
60
61
|
"jira-issue-check",
|
|
61
62
|
"local-script-check",
|
|
62
63
|
"llm-prompt",
|
|
64
|
+
"manual-jira-task-input",
|
|
63
65
|
"opencode-prompt",
|
|
64
66
|
"plan-codex",
|
|
65
67
|
"playbook-inventory",
|
|
@@ -101,6 +103,7 @@ const builtInNodes = {
|
|
|
101
103
|
"jira-issue-check": jiraIssueCheckNode,
|
|
102
104
|
"local-script-check": localScriptCheckNode,
|
|
103
105
|
"llm-prompt": llmPromptNode,
|
|
106
|
+
"manual-jira-task-input": manualJiraTaskInputNode,
|
|
104
107
|
"opencode-prompt": opencodePromptNode,
|
|
105
108
|
"plan-codex": planCodexNode,
|
|
106
109
|
"playbook-inventory": playbookInventoryNode,
|
|
@@ -235,6 +238,12 @@ const builtInNodeMetadata = {
|
|
|
235
238
|
requiredParams: ["labelText"],
|
|
236
239
|
executors: ["codex", "opencode"],
|
|
237
240
|
},
|
|
241
|
+
"manual-jira-task-input": {
|
|
242
|
+
kind: "manual-jira-task-input",
|
|
243
|
+
version: 1,
|
|
244
|
+
prompt: "forbidden",
|
|
245
|
+
requiredParams: ["taskKey", "outputFile"],
|
|
246
|
+
},
|
|
238
247
|
"opencode-prompt": { kind: "opencode-prompt", version: 1, prompt: "required", requiredParams: ["labelText"] },
|
|
239
248
|
"plan-codex": {
|
|
240
249
|
kind: "plan-codex",
|
|
@@ -21,7 +21,14 @@ export const codexPromptNode = {
|
|
|
21
21
|
}
|
|
22
22
|
return {
|
|
23
23
|
value,
|
|
24
|
-
outputs: outputPaths.map((path) => ({
|
|
24
|
+
outputs: outputPaths.map((path) => ({
|
|
25
|
+
kind: "artifact",
|
|
26
|
+
path,
|
|
27
|
+
required: true,
|
|
28
|
+
manifest: {
|
|
29
|
+
publish: true,
|
|
30
|
+
},
|
|
31
|
+
})),
|
|
25
32
|
};
|
|
26
33
|
},
|
|
27
34
|
checks(_context, params) {
|
|
@@ -221,9 +221,11 @@ export const flowRunNode = {
|
|
|
221
221
|
if (labelText) {
|
|
222
222
|
printInfo(String(labelText));
|
|
223
223
|
}
|
|
224
|
-
const flow =
|
|
225
|
-
|
|
226
|
-
|
|
224
|
+
const flow = context.inMemoryFlows?.[fileName]
|
|
225
|
+
?? await loadNamedDeclarativeFlow(fileName, context.cwd, {
|
|
226
|
+
...(context.registryContext ? { registryContext: context.registryContext } : {}),
|
|
227
|
+
...(context.inMemoryFlows ? { inMemoryFlows: context.inMemoryFlows } : {}),
|
|
228
|
+
});
|
|
227
229
|
const resolvedFlowParams = resolveNestedFlowParams(flow.kind, {
|
|
228
230
|
projectGuidanceFile: "not provided",
|
|
229
231
|
projectGuidanceJsonFile: "not provided",
|
|
@@ -1,175 +1,9 @@
|
|
|
1
1
|
import { mkdirSync, writeFileSync } from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { TaskRunnerError } from "../../errors.js";
|
|
4
|
+
import { parsePorcelain } from "../../git/git-status-parser.js";
|
|
4
5
|
import { printInfo } from "../../tui.js";
|
|
5
|
-
|
|
6
|
-
if (s.length < 2 || s[0] !== '"' || s[s.length - 1] !== '"') {
|
|
7
|
-
return s;
|
|
8
|
-
}
|
|
9
|
-
const inner = s.slice(1, -1);
|
|
10
|
-
const decoder = new TextDecoder();
|
|
11
|
-
let result = "";
|
|
12
|
-
const byteBuf = [];
|
|
13
|
-
const flushBytes = () => {
|
|
14
|
-
if (byteBuf.length > 0) {
|
|
15
|
-
result += decoder.decode(new Uint8Array(byteBuf));
|
|
16
|
-
byteBuf.length = 0;
|
|
17
|
-
}
|
|
18
|
-
};
|
|
19
|
-
for (let i = 0; i < inner.length; i++) {
|
|
20
|
-
if (inner[i] === "\\" && i + 1 < inner.length) {
|
|
21
|
-
const next = inner[i + 1];
|
|
22
|
-
switch (next) {
|
|
23
|
-
case "\\":
|
|
24
|
-
flushBytes();
|
|
25
|
-
result += "\\";
|
|
26
|
-
i++;
|
|
27
|
-
break;
|
|
28
|
-
case '"':
|
|
29
|
-
flushBytes();
|
|
30
|
-
result += '"';
|
|
31
|
-
i++;
|
|
32
|
-
break;
|
|
33
|
-
case "a":
|
|
34
|
-
flushBytes();
|
|
35
|
-
result += "\x07";
|
|
36
|
-
i++;
|
|
37
|
-
break;
|
|
38
|
-
case "b":
|
|
39
|
-
flushBytes();
|
|
40
|
-
result += "\b";
|
|
41
|
-
i++;
|
|
42
|
-
break;
|
|
43
|
-
case "f":
|
|
44
|
-
flushBytes();
|
|
45
|
-
result += "\f";
|
|
46
|
-
i++;
|
|
47
|
-
break;
|
|
48
|
-
case "n":
|
|
49
|
-
flushBytes();
|
|
50
|
-
result += "\n";
|
|
51
|
-
i++;
|
|
52
|
-
break;
|
|
53
|
-
case "r":
|
|
54
|
-
flushBytes();
|
|
55
|
-
result += "\r";
|
|
56
|
-
i++;
|
|
57
|
-
break;
|
|
58
|
-
case "t":
|
|
59
|
-
flushBytes();
|
|
60
|
-
result += "\t";
|
|
61
|
-
i++;
|
|
62
|
-
break;
|
|
63
|
-
case "v":
|
|
64
|
-
flushBytes();
|
|
65
|
-
result += "\v";
|
|
66
|
-
i++;
|
|
67
|
-
break;
|
|
68
|
-
default: {
|
|
69
|
-
if (next >= "0" && next <= "7") {
|
|
70
|
-
let octal = next;
|
|
71
|
-
let consumed = 0;
|
|
72
|
-
for (let j = 1; j <= 2 && i + 1 + j < inner.length; j++) {
|
|
73
|
-
const ch = inner[i + 1 + j];
|
|
74
|
-
if (ch !== undefined && ch >= "0" && ch <= "7") {
|
|
75
|
-
octal += ch;
|
|
76
|
-
consumed = j;
|
|
77
|
-
}
|
|
78
|
-
else {
|
|
79
|
-
break;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
byteBuf.push(parseInt(octal, 8) & 0xff);
|
|
83
|
-
i += 1 + consumed;
|
|
84
|
-
}
|
|
85
|
-
else {
|
|
86
|
-
flushBytes();
|
|
87
|
-
result += inner[i];
|
|
88
|
-
}
|
|
89
|
-
break;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
else {
|
|
94
|
-
flushBytes();
|
|
95
|
-
result += inner[i];
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
flushBytes();
|
|
99
|
-
return result;
|
|
100
|
-
}
|
|
101
|
-
function splitRename(raw) {
|
|
102
|
-
let inQuote = false;
|
|
103
|
-
for (let i = 0; i <= raw.length - 4; i++) {
|
|
104
|
-
if (raw[i] === "\\" && inQuote) {
|
|
105
|
-
i++;
|
|
106
|
-
continue;
|
|
107
|
-
}
|
|
108
|
-
if (raw[i] === '"') {
|
|
109
|
-
inQuote = !inQuote;
|
|
110
|
-
continue;
|
|
111
|
-
}
|
|
112
|
-
if (!inQuote && raw.slice(i, i + 4) === " -> ") {
|
|
113
|
-
return { original: raw.slice(0, i), file: raw.slice(i + 4) };
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
return null;
|
|
117
|
-
}
|
|
118
|
-
export function parsePorcelain(output) {
|
|
119
|
-
const lines = output.split(/\r?\n/);
|
|
120
|
-
const files = [];
|
|
121
|
-
for (const line of lines) {
|
|
122
|
-
if (!line.trim()) {
|
|
123
|
-
continue;
|
|
124
|
-
}
|
|
125
|
-
const xy = line.slice(0, 2);
|
|
126
|
-
const rawFile = line.slice(3);
|
|
127
|
-
const indexStatus = xy[0] ?? " ";
|
|
128
|
-
const workTreeStatus = xy[1] ?? " ";
|
|
129
|
-
const staged = indexStatus !== " " && indexStatus !== "?";
|
|
130
|
-
let type;
|
|
131
|
-
if (indexStatus === "A" || workTreeStatus === "A") {
|
|
132
|
-
type = "added";
|
|
133
|
-
}
|
|
134
|
-
else if (indexStatus === "D" || workTreeStatus === "D") {
|
|
135
|
-
type = "deleted";
|
|
136
|
-
}
|
|
137
|
-
else if (indexStatus === "R") {
|
|
138
|
-
type = "renamed";
|
|
139
|
-
}
|
|
140
|
-
else if (indexStatus === "?" && workTreeStatus === "?") {
|
|
141
|
-
type = "untracked";
|
|
142
|
-
}
|
|
143
|
-
else {
|
|
144
|
-
type = "modified";
|
|
145
|
-
}
|
|
146
|
-
let file;
|
|
147
|
-
let originalFile;
|
|
148
|
-
if (indexStatus === "R" || indexStatus === "C") {
|
|
149
|
-
const parts = splitRename(rawFile);
|
|
150
|
-
if (parts) {
|
|
151
|
-
originalFile = unquoteGitPath(parts.original);
|
|
152
|
-
file = unquoteGitPath(parts.file);
|
|
153
|
-
}
|
|
154
|
-
else {
|
|
155
|
-
file = unquoteGitPath(rawFile);
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
else {
|
|
159
|
-
file = unquoteGitPath(rawFile);
|
|
160
|
-
}
|
|
161
|
-
files.push({
|
|
162
|
-
xy,
|
|
163
|
-
indexStatus,
|
|
164
|
-
workTreeStatus,
|
|
165
|
-
file,
|
|
166
|
-
...(originalFile !== undefined ? { originalFile } : {}),
|
|
167
|
-
staged,
|
|
168
|
-
type,
|
|
169
|
-
});
|
|
170
|
-
}
|
|
171
|
-
return files;
|
|
172
|
-
}
|
|
6
|
+
export { parsePorcelain } from "../../git/git-status-parser.js";
|
|
173
7
|
function persistGitStatus(filePath, result) {
|
|
174
8
|
const dir = path.dirname(filePath);
|
|
175
9
|
mkdirSync(dir, { recursive: true });
|