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.
Files changed (50) hide show
  1. package/README.md +47 -7
  2. package/dist/artifacts.js +9 -0
  3. package/dist/executors/git-commit-executor.js +24 -6
  4. package/dist/flow-state.js +3 -8
  5. package/dist/git/git-diff-parser.js +223 -0
  6. package/dist/git/git-service.js +562 -0
  7. package/dist/git/git-stage-selection.js +24 -0
  8. package/dist/git/git-status-parser.js +171 -0
  9. package/dist/git/git-types.js +1 -0
  10. package/dist/index.js +450 -108
  11. package/dist/interactive/auto-flow.js +644 -0
  12. package/dist/interactive/controller.js +417 -9
  13. package/dist/interactive/progress.js +194 -1
  14. package/dist/interactive/state.js +25 -0
  15. package/dist/interactive/web/index.js +97 -12
  16. package/dist/interactive/web/protocol.js +216 -1
  17. package/dist/interactive/web/server.js +72 -14
  18. package/dist/interactive/web/static/app.js +1603 -49
  19. package/dist/interactive/web/static/index.html +76 -11
  20. package/dist/interactive/web/static/styles.css +1 -1
  21. package/dist/interactive/web/static/styles.input.css +901 -47
  22. package/dist/pipeline/auto-flow-blocks.js +307 -0
  23. package/dist/pipeline/auto-flow-config.js +273 -0
  24. package/dist/pipeline/auto-flow-identity.js +49 -0
  25. package/dist/pipeline/auto-flow-presets.js +52 -0
  26. package/dist/pipeline/auto-flow-resolver.js +830 -0
  27. package/dist/pipeline/auto-flow-types.js +17 -0
  28. package/dist/pipeline/context.js +1 -0
  29. package/dist/pipeline/declarative-flows.js +27 -1
  30. package/dist/pipeline/flow-specs/auto-common-guided.json +11 -0
  31. package/dist/pipeline/flow-specs/auto-golang.json +12 -1
  32. package/dist/pipeline/flow-specs/bugz/bug-analyze.json +54 -1
  33. package/dist/pipeline/flow-specs/gitlab/gitlab-diff-review.json +19 -1
  34. package/dist/pipeline/flow-specs/gitlab/gitlab-review.json +33 -1
  35. package/dist/pipeline/flow-specs/review/review-project.json +19 -1
  36. package/dist/pipeline/flow-specs/task-source/manual-jira-input.json +70 -0
  37. package/dist/pipeline/node-registry.js +9 -0
  38. package/dist/pipeline/nodes/codex-prompt-node.js +8 -1
  39. package/dist/pipeline/nodes/flow-run-node.js +5 -3
  40. package/dist/pipeline/nodes/git-status-node.js +2 -168
  41. package/dist/pipeline/nodes/manual-jira-task-input-node.js +146 -0
  42. package/dist/pipeline/nodes/opencode-prompt-node.js +8 -1
  43. package/dist/pipeline/nodes/plan-codex-node.js +8 -1
  44. package/dist/pipeline/spec-loader.js +14 -4
  45. package/dist/runtime/artifact-catalog.js +29 -5
  46. package/dist/runtime/settings.js +114 -0
  47. package/dist/scope.js +14 -4
  48. package/package.json +1 -1
  49. package/dist/pipeline/flow-specs/auto-common.json +0 -179
  50. 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
+ ];
@@ -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 = await loadNamedDeclarativeFlow(nestedFlowName.const, cwd, options);
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: Jira fetch → 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.",
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) => ({ kind: "artifact", path, required: true })),
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 = await loadNamedDeclarativeFlow(fileName, context.cwd, {
225
- ...(context.registryContext ? { registryContext: context.registryContext } : {}),
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
- function unquoteGitPath(s) {
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 });