agentweaver 0.1.10 → 0.1.12
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 +218 -224
- package/dist/artifacts.js +109 -55
- package/dist/executors/{codex-local-executor.js → codex-executor.js} +6 -5
- package/dist/executors/configs/{codex-local-config.js → codex-config.js} +1 -1
- package/dist/executors/configs/jira-fetch-config.js +2 -0
- package/dist/executors/configs/telegram-notifier-config.js +3 -0
- package/dist/executors/fetch-gitlab-diff-executor.js +1 -1
- package/dist/executors/fetch-gitlab-review-executor.js +1 -1
- package/dist/executors/git-commit-executor.js +25 -0
- package/dist/executors/jira-fetch-executor.js +1 -0
- package/dist/executors/opencode-executor.js +22 -11
- package/dist/executors/process-executor.js +3 -0
- package/dist/executors/telegram-notifier-executor.js +54 -0
- package/dist/flow-state.js +46 -1
- package/dist/gitlab.js +13 -8
- package/dist/index.js +477 -514
- package/dist/interactive-ui.js +609 -88
- package/dist/jira.js +109 -5
- package/dist/pipeline/auto-flow.js +6 -6
- package/dist/pipeline/context.js +1 -0
- package/dist/pipeline/flow-catalog.js +34 -4
- package/dist/pipeline/flow-model-settings.js +77 -0
- package/dist/pipeline/flow-specs/auto-common.json +446 -0
- package/dist/pipeline/flow-specs/auto-golang.json +563 -0
- package/dist/pipeline/flow-specs/{bug-analyze.json → bugz/bug-analyze.json} +43 -25
- package/dist/pipeline/flow-specs/{bug-fix.json → bugz/bug-fix.json} +5 -4
- package/dist/pipeline/flow-specs/git-commit.json +196 -0
- package/dist/pipeline/flow-specs/{gitlab-diff-review.json → gitlab/gitlab-diff-review.json} +20 -50
- package/dist/pipeline/flow-specs/{gitlab-review.json → gitlab/gitlab-review.json} +65 -133
- package/dist/pipeline/flow-specs/{mr-description.json → gitlab/mr-description.json} +17 -10
- package/dist/pipeline/flow-specs/{run-go-linter-loop.json → go/run-go-linter-loop.json} +40 -14
- package/dist/pipeline/flow-specs/{run-go-tests-loop.json → go/run-go-tests-loop.json} +40 -14
- package/dist/pipeline/flow-specs/implement.json +5 -4
- package/dist/pipeline/flow-specs/plan.json +40 -148
- package/dist/pipeline/flow-specs/{review-fix.json → review/review-fix.json} +74 -13
- package/dist/pipeline/flow-specs/review/review-loop.json +282 -0
- package/dist/pipeline/flow-specs/review/review-project.json +87 -0
- package/dist/pipeline/flow-specs/review/review.json +126 -0
- package/dist/pipeline/flow-specs/task-describe.json +252 -11
- package/dist/pipeline/launch-profile-config.js +38 -0
- package/dist/pipeline/node-registry.js +75 -45
- package/dist/pipeline/nodes/build-failure-summary-node.js +16 -29
- package/dist/pipeline/nodes/build-review-fix-prompt-node.js +36 -0
- package/dist/pipeline/nodes/codex-prompt-node.js +41 -0
- package/dist/pipeline/nodes/commit-message-form-node.js +79 -0
- package/dist/pipeline/nodes/git-commit-form-node.js +138 -0
- package/dist/pipeline/nodes/git-commit-node.js +28 -0
- package/dist/pipeline/nodes/git-status-node.js +221 -0
- package/dist/pipeline/nodes/gitlab-review-artifacts-node.js +10 -6
- package/dist/pipeline/nodes/jira-context-node.js +10 -0
- package/dist/pipeline/nodes/jira-fetch-node.js +3 -0
- package/dist/pipeline/nodes/llm-prompt-node.js +62 -0
- package/dist/pipeline/nodes/plan-codex-node.js +1 -1
- package/dist/pipeline/nodes/read-file-node.js +11 -0
- package/dist/pipeline/nodes/review-findings-form-node.js +48 -14
- package/dist/pipeline/nodes/select-files-form-node.js +72 -0
- package/dist/pipeline/nodes/telegram-notifier-node.js +28 -0
- package/dist/pipeline/nodes/user-input-node.js +43 -8
- package/dist/pipeline/nodes/write-selection-file-node.js +46 -0
- package/dist/pipeline/prompt-registry.js +3 -4
- package/dist/pipeline/prompt-runtime.js +13 -3
- package/dist/pipeline/registry.js +6 -8
- package/dist/pipeline/spec-compiler.js +5 -0
- package/dist/pipeline/spec-types.js +9 -3
- package/dist/pipeline/spec-validator.js +4 -0
- package/dist/pipeline/types.js +1 -0
- package/dist/pipeline/value-resolver.js +50 -38
- package/dist/prompts.js +119 -110
- package/dist/runtime/agentweaver-home.js +8 -0
- package/dist/runtime/command-resolution.js +0 -38
- package/dist/runtime/env-loader.js +43 -0
- package/dist/runtime/process-runner.js +9 -3
- package/dist/structured-artifact-schema-registry.js +54 -0
- package/dist/structured-artifact-schemas.json +22 -20
- package/dist/structured-artifacts.js +3 -43
- package/dist/user-input.js +38 -3
- package/package.json +2 -6
- package/Dockerfile.codex +0 -56
- package/dist/executors/claude-executor.js +0 -46
- package/dist/executors/codex-docker-executor.js +0 -27
- package/dist/executors/configs/claude-config.js +0 -12
- package/dist/executors/configs/codex-docker-config.js +0 -10
- package/dist/executors/configs/verify-build-config.js +0 -7
- package/dist/executors/verify-build-executor.js +0 -123
- package/dist/pipeline/flow-specs/auto.json +0 -979
- package/dist/pipeline/flow-specs/opencode/auto-opencode.json +0 -1365
- package/dist/pipeline/flow-specs/opencode/bugz/bug-analyze-opencode.json +0 -382
- package/dist/pipeline/flow-specs/opencode/bugz/bug-fix-opencode.json +0 -56
- package/dist/pipeline/flow-specs/opencode/gitlab/gitlab-diff-review-opencode.json +0 -308
- package/dist/pipeline/flow-specs/opencode/gitlab/gitlab-review-opencode.json +0 -437
- package/dist/pipeline/flow-specs/opencode/gitlab/mr-description-opencode.json +0 -117
- package/dist/pipeline/flow-specs/opencode/go/run-go-linter-loop-opencode.json +0 -321
- package/dist/pipeline/flow-specs/opencode/go/run-go-tests-loop-opencode.json +0 -321
- package/dist/pipeline/flow-specs/opencode/implement-opencode.json +0 -64
- package/dist/pipeline/flow-specs/opencode/plan-opencode.json +0 -603
- package/dist/pipeline/flow-specs/opencode/review/review-fix-opencode.json +0 -209
- package/dist/pipeline/flow-specs/opencode/review/review-opencode.json +0 -452
- package/dist/pipeline/flow-specs/opencode/task-describe-opencode.json +0 -148
- package/dist/pipeline/flow-specs/review-project.json +0 -243
- package/dist/pipeline/flow-specs/review.json +0 -312
- package/dist/pipeline/flows/preflight-flow.js +0 -19
- package/dist/pipeline/nodes/claude-prompt-node.js +0 -54
- package/dist/pipeline/nodes/codex-docker-prompt-node.js +0 -32
- package/dist/pipeline/nodes/codex-local-prompt-node.js +0 -32
- package/dist/pipeline/nodes/review-claude-node.js +0 -38
- package/dist/pipeline/nodes/review-reply-codex-node.js +0 -40
- package/dist/pipeline/nodes/verify-build-node.js +0 -15
- package/dist/runtime/docker-runtime.js +0 -51
- package/docker-compose.yml +0 -445
- package/verify_build.sh +0 -105
|
@@ -6,7 +6,7 @@ export const planCodexNode = {
|
|
|
6
6
|
async run(context, params) {
|
|
7
7
|
printInfo("Running Codex planning mode");
|
|
8
8
|
printPrompt("Codex", params.prompt);
|
|
9
|
-
const executor = context.executors.get("codex
|
|
9
|
+
const executor = context.executors.get("codex");
|
|
10
10
|
const input = {
|
|
11
11
|
prompt: params.prompt,
|
|
12
12
|
env: { ...context.env },
|
|
@@ -6,20 +6,44 @@ export const reviewFindingsFormNode = {
|
|
|
6
6
|
async run(_context, params) {
|
|
7
7
|
let parsed;
|
|
8
8
|
try {
|
|
9
|
-
parsed = JSON.parse(readFileSync(params.
|
|
9
|
+
parsed = JSON.parse(readFileSync(params.reviewFindingsJsonFile, "utf8"));
|
|
10
10
|
}
|
|
11
11
|
catch (error) {
|
|
12
|
-
throw new TaskRunnerError(`Failed to read review
|
|
12
|
+
throw new TaskRunnerError(`Failed to read review findings from ${params.reviewFindingsJsonFile}: ${error.message}`);
|
|
13
13
|
}
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
14
|
+
const reviewFindings = parsed;
|
|
15
|
+
let reviewAssessment = null;
|
|
16
|
+
if (typeof params.reviewAssessmentJsonFile === "string" && params.reviewAssessmentJsonFile.trim().length > 0) {
|
|
17
|
+
try {
|
|
18
|
+
reviewAssessment = JSON.parse(readFileSync(params.reviewAssessmentJsonFile, "utf8"));
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
throw new TaskRunnerError(`Failed to read review assessment from ${params.reviewAssessmentJsonFile}: ${error.message}`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
const assessmentByTitle = new Map();
|
|
25
|
+
for (const record of reviewAssessment?.assessments ?? []) {
|
|
26
|
+
const findingTitle = typeof record.finding_title === "string" ? record.finding_title.trim() : "";
|
|
27
|
+
const verdict = typeof record.verdict === "string" ? record.verdict.trim() : "";
|
|
28
|
+
const rationale = typeof record.rationale === "string" ? record.rationale.trim() : "";
|
|
29
|
+
const proposedFix = typeof record.proposed_fix === "string" ? record.proposed_fix.trim() : "";
|
|
30
|
+
const fixRequired = typeof record.fix_required === "boolean" ? record.fix_required : null;
|
|
31
|
+
if (findingTitle.length === 0 || assessmentByTitle.has(findingTitle)) {
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
assessmentByTitle.set(findingTitle, { verdict, rationale, proposedFix, fixRequired });
|
|
35
|
+
}
|
|
36
|
+
const findings = Array.isArray(reviewFindings.findings) ? reviewFindings.findings : [];
|
|
37
|
+
const selectableFindings = findings
|
|
38
|
+
.map((finding) => ({
|
|
39
|
+
severity: typeof finding.severity === "string" ? finding.severity.trim().toLowerCase() : "",
|
|
40
|
+
title: typeof finding.title === "string" ? finding.title.trim() : "",
|
|
41
|
+
description: typeof finding.description === "string" ? finding.description.trim() : "",
|
|
42
|
+
disposition: typeof finding.disposition === "string" ? finding.disposition.trim().toLowerCase() : null,
|
|
43
|
+
assessment: assessmentByTitle.get(typeof finding.title === "string" ? finding.title.trim() : "") ?? null,
|
|
21
44
|
}))
|
|
22
|
-
.filter((
|
|
45
|
+
.filter((finding) => finding.title.length > 0 &&
|
|
46
|
+
finding.disposition !== "resolved");
|
|
23
47
|
const fields = [
|
|
24
48
|
{
|
|
25
49
|
id: "apply_all",
|
|
@@ -35,10 +59,20 @@ export const reviewFindingsFormNode = {
|
|
|
35
59
|
type: "multi-select",
|
|
36
60
|
label: "Какие findings исправить сейчас",
|
|
37
61
|
help: "Space переключает пункт. Если apply_all=false, выберите хотя бы один finding.",
|
|
38
|
-
options: selectableFindings.map((
|
|
39
|
-
value:
|
|
40
|
-
label: `${
|
|
41
|
-
|
|
62
|
+
options: selectableFindings.map((finding) => ({
|
|
63
|
+
value: finding.title,
|
|
64
|
+
label: `${finding.title} | ${finding.severity || "-"}`,
|
|
65
|
+
description: [
|
|
66
|
+
finding.description,
|
|
67
|
+
finding.assessment?.verdict ? `Verdict: ${finding.assessment.verdict}` : "",
|
|
68
|
+
finding.assessment?.rationale ? `Rationale: ${finding.assessment.rationale}` : "",
|
|
69
|
+
finding.assessment?.proposedFix ? `Proposed fix: ${finding.assessment.proposedFix}` : "",
|
|
70
|
+
typeof finding.assessment?.fixRequired === "boolean"
|
|
71
|
+
? `Fix required: ${finding.assessment.fixRequired ? "yes" : "no"}`
|
|
72
|
+
: "",
|
|
73
|
+
]
|
|
74
|
+
.filter((item) => item.trim().length > 0)
|
|
75
|
+
.join("\n\n"),
|
|
42
76
|
})),
|
|
43
77
|
default: [],
|
|
44
78
|
});
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync, mkdirSync } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { TaskRunnerError } from "../../errors.js";
|
|
4
|
+
import { validateUserInputValues } from "../../user-input.js";
|
|
5
|
+
export const selectFilesFormNode = {
|
|
6
|
+
kind: "select-files-form",
|
|
7
|
+
version: 1,
|
|
8
|
+
async run(context, params) {
|
|
9
|
+
let gitStatusFiles;
|
|
10
|
+
try {
|
|
11
|
+
const statusContent = readFileSync(params.gitStatusJsonFile, "utf8");
|
|
12
|
+
const statusParsed = JSON.parse(statusContent);
|
|
13
|
+
gitStatusFiles = (statusParsed.files ?? []);
|
|
14
|
+
}
|
|
15
|
+
catch (error) {
|
|
16
|
+
throw new TaskRunnerError(`Failed to read git status from ${params.gitStatusJsonFile}: ${error.message}`);
|
|
17
|
+
}
|
|
18
|
+
const fileOptions = gitStatusFiles.map((file) => ({
|
|
19
|
+
value: file.file,
|
|
20
|
+
label: file.originalFile
|
|
21
|
+
? `${file.xy} ${file.originalFile} -> ${file.file}`
|
|
22
|
+
: `${file.xy} ${file.file}`,
|
|
23
|
+
}));
|
|
24
|
+
const form = {
|
|
25
|
+
formId: params.formId,
|
|
26
|
+
title: params.title,
|
|
27
|
+
...(params.description ? { description: params.description } : {}),
|
|
28
|
+
submitLabel: "Next",
|
|
29
|
+
fields: [
|
|
30
|
+
{
|
|
31
|
+
id: "selected_files",
|
|
32
|
+
type: "multi-select",
|
|
33
|
+
label: "Select files to commit",
|
|
34
|
+
help: "Choose the files you want to include in this commit",
|
|
35
|
+
required: true,
|
|
36
|
+
options: fileOptions,
|
|
37
|
+
default: gitStatusFiles.map((f) => f.file),
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
};
|
|
41
|
+
const requester = context.requestUserInput ?? (await import("../../user-input.js")).requestUserInputInTerminal;
|
|
42
|
+
const result = await requester(form);
|
|
43
|
+
const selectedFilesValue = result.values.selected_files;
|
|
44
|
+
if (!Array.isArray(selectedFilesValue) || selectedFilesValue.length === 0) {
|
|
45
|
+
throw new TaskRunnerError("At least one file must be selected for commit.");
|
|
46
|
+
}
|
|
47
|
+
validateUserInputValues(form, result.values);
|
|
48
|
+
const outputDir = path.dirname(params.outputFile);
|
|
49
|
+
mkdirSync(outputDir, { recursive: true });
|
|
50
|
+
const outputContent = {
|
|
51
|
+
form_id: result.formId,
|
|
52
|
+
submitted_at: result.submittedAt,
|
|
53
|
+
values: result.values,
|
|
54
|
+
};
|
|
55
|
+
writeFileSync(params.outputFile, `${JSON.stringify(outputContent, null, 2)}\n`, "utf8");
|
|
56
|
+
return {
|
|
57
|
+
value: {
|
|
58
|
+
formId: result.formId,
|
|
59
|
+
submittedAt: result.submittedAt,
|
|
60
|
+
values: result.values,
|
|
61
|
+
outputFile: params.outputFile,
|
|
62
|
+
},
|
|
63
|
+
outputs: [
|
|
64
|
+
{
|
|
65
|
+
kind: "artifact",
|
|
66
|
+
path: params.outputFile,
|
|
67
|
+
required: true,
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
};
|
|
71
|
+
},
|
|
72
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { printInfo } from "../../tui.js";
|
|
2
|
+
import { toExecutorContext } from "../types.js";
|
|
3
|
+
export const telegramNotifierNode = {
|
|
4
|
+
kind: "telegram-notify",
|
|
5
|
+
version: 1,
|
|
6
|
+
async run(context, params) {
|
|
7
|
+
const labelText = params.label ?? "Sending Telegram notification";
|
|
8
|
+
printInfo(labelText);
|
|
9
|
+
const chatId = context.env.TELEGRAM_CHAT_ID;
|
|
10
|
+
if (!chatId) {
|
|
11
|
+
printInfo("Telegram notification skipped: chat_id environment variable is not set");
|
|
12
|
+
return { value: { success: false } };
|
|
13
|
+
}
|
|
14
|
+
const executor = context.executors.get("telegram-notifier");
|
|
15
|
+
const input = {
|
|
16
|
+
chatId,
|
|
17
|
+
text: params.message,
|
|
18
|
+
};
|
|
19
|
+
const value = await executor.execute(toExecutorContext(context), input, executor.defaultConfig);
|
|
20
|
+
if (value.success) {
|
|
21
|
+
printInfo(`Telegram notification sent successfully`);
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
printInfo(`Telegram notification failed`);
|
|
25
|
+
}
|
|
26
|
+
return { value };
|
|
27
|
+
},
|
|
28
|
+
};
|
|
@@ -18,24 +18,59 @@ function buildReviewFixPromptSuffix(params, values) {
|
|
|
18
18
|
throw new TaskRunnerError("Review-fix requires selecting at least one finding or enabling 'apply all'.");
|
|
19
19
|
}
|
|
20
20
|
const selectionSummary = applyAll
|
|
21
|
-
? "
|
|
22
|
-
:
|
|
21
|
+
? "All findings selected."
|
|
22
|
+
: `Selected findings:\n- ${selectedFindings.join("\n- ")}`;
|
|
23
23
|
const promptSuffix = [
|
|
24
|
-
"
|
|
25
|
-
|
|
24
|
+
"Use the user selection below as source of truth for the current review-fix scope.",
|
|
25
|
+
`Selection file: ${params.outputFile}`,
|
|
26
26
|
`apply_all: ${applyAll ? "true" : "false"}`,
|
|
27
|
-
applyAll ? "
|
|
28
|
-
extraNotes ?
|
|
27
|
+
applyAll ? "Fix all findings in the current iteration." : `Fix only selected findings:\n- ${selectedFindings.join("\n- ")}`,
|
|
28
|
+
extraNotes ? `User additional instructions:\n${extraNotes}` : "",
|
|
29
29
|
]
|
|
30
30
|
.filter((item) => item.trim().length > 0)
|
|
31
31
|
.join("\n\n");
|
|
32
|
-
const summaryText = extraNotes ? `${selectionSummary}\n\n
|
|
32
|
+
const summaryText = extraNotes ? `${selectionSummary}\n\nNote:\n${extraNotes}` : selectionSummary;
|
|
33
33
|
return { promptSuffix, summaryText };
|
|
34
34
|
}
|
|
35
|
+
function buildTaskDescribePromptSuffix(params, values) {
|
|
36
|
+
const jiraRef = typeof values.jira_ref === "string" ? values.jira_ref.trim() : "";
|
|
37
|
+
const taskDescription = typeof values.task_description === "string" ? values.task_description.trim() : "";
|
|
38
|
+
const additionalInstructions = typeof values.additional_instructions === "string" ? values.additional_instructions.trim() : "";
|
|
39
|
+
if (jiraRef) {
|
|
40
|
+
return {
|
|
41
|
+
promptSuffix: additionalInstructions
|
|
42
|
+
? [
|
|
43
|
+
"Use the user-provided additional instructions together with the Jira task.",
|
|
44
|
+
`User input file: ${params.outputFile}`,
|
|
45
|
+
`Additional instructions:\n${additionalInstructions}`,
|
|
46
|
+
].join("\n\n")
|
|
47
|
+
: "",
|
|
48
|
+
summaryText: additionalInstructions
|
|
49
|
+
? `Источник задачи: Jira\nJira: ${jiraRef}\n\nДополнительные указания:\n${additionalInstructions}`
|
|
50
|
+
: `Источник задачи: Jira\nJira: ${jiraRef}`,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
promptSuffix: [
|
|
55
|
+
"Use the user task description as source of truth.",
|
|
56
|
+
`User input file: ${params.outputFile}`,
|
|
57
|
+
`Task description:\n${taskDescription}`,
|
|
58
|
+
additionalInstructions ? `Additional instructions:\n${additionalInstructions}` : "",
|
|
59
|
+
]
|
|
60
|
+
.filter((item) => item.trim().length > 0)
|
|
61
|
+
.join("\n\n"),
|
|
62
|
+
summaryText: additionalInstructions
|
|
63
|
+
? `Task source: user-input\n\n${taskDescription}\n\nAdditional instructions:\n${additionalInstructions}`
|
|
64
|
+
: `Task source: user-input\n\n${taskDescription}`,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
35
67
|
function buildPromptSuffix(params, values) {
|
|
36
68
|
if (params.formId === "review-fix-selection") {
|
|
37
69
|
return buildReviewFixPromptSuffix(params, values);
|
|
38
70
|
}
|
|
71
|
+
if (params.formId === "task-describe-source-input") {
|
|
72
|
+
return buildTaskDescribePromptSuffix(params, values);
|
|
73
|
+
}
|
|
39
74
|
if (params.fields.length === 0) {
|
|
40
75
|
return {
|
|
41
76
|
promptSuffix: "",
|
|
@@ -58,7 +93,7 @@ function buildPromptSuffix(params, values) {
|
|
|
58
93
|
});
|
|
59
94
|
const summaryText = lines.join("\n");
|
|
60
95
|
return {
|
|
61
|
-
promptSuffix:
|
|
96
|
+
promptSuffix: `Use user input from file ${params.outputFile}.\n\n${summaryText}`,
|
|
62
97
|
summaryText,
|
|
63
98
|
};
|
|
64
99
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { writeFileSync } from "node:fs";
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import { TaskRunnerError } from "../../errors.js";
|
|
4
|
+
const SEVERITY_AUTO_SELECT = ["blocker", "critical"];
|
|
5
|
+
export const writeSelectionFileNode = {
|
|
6
|
+
kind: "write-selection-file",
|
|
7
|
+
version: 1,
|
|
8
|
+
async run(_context, params) {
|
|
9
|
+
let parsed;
|
|
10
|
+
try {
|
|
11
|
+
parsed = JSON.parse(readFileSync(params.reviewFindingsJsonFile, "utf8"));
|
|
12
|
+
}
|
|
13
|
+
catch (error) {
|
|
14
|
+
throw new TaskRunnerError(`Failed to read review findings from ${params.reviewFindingsJsonFile}: ${error.message}`);
|
|
15
|
+
}
|
|
16
|
+
const reviewFindings = parsed;
|
|
17
|
+
const findings = Array.isArray(reviewFindings.findings) ? reviewFindings.findings : [];
|
|
18
|
+
const selectedFindings = findings
|
|
19
|
+
.filter((finding) => {
|
|
20
|
+
const severity = typeof finding.severity === "string" ? finding.severity.trim().toLowerCase() : "";
|
|
21
|
+
const disposition = typeof finding.disposition === "string" ? finding.disposition.trim().toLowerCase() : null;
|
|
22
|
+
return SEVERITY_AUTO_SELECT.includes(severity) && disposition !== "resolved" && disposition != null;
|
|
23
|
+
})
|
|
24
|
+
.map((finding) => finding.title)
|
|
25
|
+
.filter((title) => typeof title === "string" && title.trim().length > 0);
|
|
26
|
+
const applyAll = selectedFindings.length === 0;
|
|
27
|
+
const artifact = {
|
|
28
|
+
form_id: "review-fix-selection",
|
|
29
|
+
submitted_at: new Date().toISOString(),
|
|
30
|
+
values: {
|
|
31
|
+
apply_all: applyAll,
|
|
32
|
+
selected_findings: selectedFindings,
|
|
33
|
+
extra_notes: "",
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
writeFileSync(params.outputFile, `${JSON.stringify(artifact, null, 2)}\n`, "utf8");
|
|
37
|
+
return {
|
|
38
|
+
value: {
|
|
39
|
+
outputFile: params.outputFile,
|
|
40
|
+
findingsCount: selectedFindings.length,
|
|
41
|
+
selectedFindings,
|
|
42
|
+
applyAll,
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
},
|
|
46
|
+
};
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { BUG_ANALYZE_PROMPT_TEMPLATE, GITLAB_DIFF_REVIEW_PROMPT_TEMPLATE, BUG_FIX_PROMPT_TEMPLATE, IMPLEMENT_PROMPT_TEMPLATE, JIRA_DESCRIPTION_PROMPT_TEMPLATE, MR_DESCRIPTION_PROMPT_TEMPLATE, PLAN_QUESTIONS_PROMPT_TEMPLATE, PLAN_PROMPT_TEMPLATE, REVIEW_FIX_PROMPT_TEMPLATE, REVIEW_PROJECT_PROMPT_TEMPLATE, REVIEW_PROMPT_TEMPLATE,
|
|
1
|
+
import { BUG_ANALYZE_PROMPT_TEMPLATE, COMMIT_MESSAGE_PROMPT_TEMPLATE, GITLAB_DIFF_REVIEW_PROMPT_TEMPLATE, GITLAB_REVIEW_PROMPT_TEMPLATE, BUG_FIX_PROMPT_TEMPLATE, IMPLEMENT_PROMPT_TEMPLATE, JIRA_DESCRIPTION_PROMPT_TEMPLATE, MR_DESCRIPTION_PROMPT_TEMPLATE, PLAN_QUESTIONS_PROMPT_TEMPLATE, PLAN_PROMPT_TEMPLATE, REVIEW_FIX_PROMPT_TEMPLATE, REVIEW_PROJECT_PROMPT_TEMPLATE, REVIEW_PROMPT_TEMPLATE, REVIEW_SUMMARY_PROMPT_TEMPLATE, RUN_GO_LINTER_LOOP_FIX_PROMPT_TEMPLATE, RUN_GO_TESTS_LOOP_FIX_PROMPT_TEMPLATE, TASK_SUMMARY_PROMPT_TEMPLATE, } from "../prompts.js";
|
|
2
2
|
const promptTemplates = {
|
|
3
3
|
"bug-analyze": BUG_ANALYZE_PROMPT_TEMPLATE,
|
|
4
4
|
"bug-fix": BUG_FIX_PROMPT_TEMPLATE,
|
|
5
|
+
"commit-message": COMMIT_MESSAGE_PROMPT_TEMPLATE,
|
|
5
6
|
"gitlab-diff-review": GITLAB_DIFF_REVIEW_PROMPT_TEMPLATE,
|
|
7
|
+
"gitlab-review": GITLAB_REVIEW_PROMPT_TEMPLATE,
|
|
6
8
|
implement: IMPLEMENT_PROMPT_TEMPLATE,
|
|
7
9
|
"task-describe": JIRA_DESCRIPTION_PROMPT_TEMPLATE,
|
|
8
10
|
"mr-description": MR_DESCRIPTION_PROMPT_TEMPLATE,
|
|
@@ -11,9 +13,6 @@ const promptTemplates = {
|
|
|
11
13
|
review: REVIEW_PROMPT_TEMPLATE,
|
|
12
14
|
"review-project": REVIEW_PROJECT_PROMPT_TEMPLATE,
|
|
13
15
|
"review-fix": REVIEW_FIX_PROMPT_TEMPLATE,
|
|
14
|
-
"review-reply": REVIEW_REPLY_PROMPT_TEMPLATE,
|
|
15
|
-
"review-reply-project": REVIEW_REPLY_PROJECT_PROMPT_TEMPLATE,
|
|
16
|
-
"review-reply-summary": REVIEW_REPLY_SUMMARY_PROMPT_TEMPLATE,
|
|
17
16
|
"review-summary": REVIEW_SUMMARY_PROMPT_TEMPLATE,
|
|
18
17
|
"run-go-linter-loop-fix": RUN_GO_LINTER_LOOP_FIX_PROMPT_TEMPLATE,
|
|
19
18
|
"run-go-tests-loop-fix": RUN_GO_TESTS_LOOP_FIX_PROMPT_TEMPLATE,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { TaskRunnerError } from "../errors.js";
|
|
2
|
-
import { formatPrompt, formatTemplate } from "../prompts.js";
|
|
2
|
+
import { STRUCTURED_JSON_LANGUAGE_INSTRUCTION, formatPrompt, formatTemplate } from "../prompts.js";
|
|
3
3
|
import { getPromptTemplate } from "./prompt-registry.js";
|
|
4
4
|
import { resolveValue } from "./value-resolver.js";
|
|
5
5
|
export function renderPrompt(binding, context) {
|
|
@@ -11,8 +11,18 @@ export function renderPrompt(binding, context) {
|
|
|
11
11
|
const basePrompt = formatTemplate(baseTemplate, vars);
|
|
12
12
|
const resolvedExtraPrompt = binding.extraPrompt ? resolveValue(binding.extraPrompt, context) : null;
|
|
13
13
|
const extraPrompt = resolvedExtraPrompt === null || resolvedExtraPrompt === undefined ? null : String(resolvedExtraPrompt);
|
|
14
|
+
const mdLang = context.flowParams.mdLang;
|
|
15
|
+
const jsonInstruction = STRUCTURED_JSON_LANGUAGE_INSTRUCTION.trim();
|
|
16
|
+
let langInstruction = null;
|
|
17
|
+
if (mdLang === "en") {
|
|
18
|
+
langInstruction = "Generate all markdown output files in English language.";
|
|
19
|
+
}
|
|
20
|
+
else if (mdLang === "ru" || mdLang === null || mdLang === undefined) {
|
|
21
|
+
langInstruction = "Generate all markdown output files in Russian language.";
|
|
22
|
+
}
|
|
23
|
+
const finalExtraPrompt = [extraPrompt, jsonInstruction, langInstruction].filter(Boolean).join("\n");
|
|
14
24
|
if ((binding.format ?? "task-prompt") === "plain") {
|
|
15
|
-
return basePrompt;
|
|
25
|
+
return finalExtraPrompt ? `${basePrompt}\n\n${finalExtraPrompt}` : basePrompt;
|
|
16
26
|
}
|
|
17
|
-
return formatPrompt(basePrompt,
|
|
27
|
+
return formatPrompt(basePrompt, finalExtraPrompt);
|
|
18
28
|
}
|
|
@@ -1,24 +1,22 @@
|
|
|
1
1
|
import { commandCheckExecutor } from "../executors/command-check-executor.js";
|
|
2
|
-
import {
|
|
3
|
-
import { codexDockerExecutor } from "../executors/codex-docker-executor.js";
|
|
4
|
-
import { codexLocalExecutor } from "../executors/codex-local-executor.js";
|
|
2
|
+
import { codexExecutor } from "../executors/codex-executor.js";
|
|
5
3
|
import { fetchGitLabDiffExecutor } from "../executors/fetch-gitlab-diff-executor.js";
|
|
6
4
|
import { fetchGitLabReviewExecutor } from "../executors/fetch-gitlab-review-executor.js";
|
|
5
|
+
import { gitCommitExecutor } from "../executors/git-commit-executor.js";
|
|
7
6
|
import { jiraFetchExecutor } from "../executors/jira-fetch-executor.js";
|
|
8
7
|
import { opencodeExecutor } from "../executors/opencode-executor.js";
|
|
9
8
|
import { processExecutor } from "../executors/process-executor.js";
|
|
10
|
-
import {
|
|
9
|
+
import { telegramNotifierExecutor } from "../executors/telegram-notifier-executor.js";
|
|
11
10
|
const builtInExecutors = {
|
|
12
11
|
process: processExecutor,
|
|
13
12
|
"command-check": commandCheckExecutor,
|
|
14
13
|
"fetch-gitlab-diff": fetchGitLabDiffExecutor,
|
|
15
14
|
"fetch-gitlab-review": fetchGitLabReviewExecutor,
|
|
15
|
+
"git-commit": gitCommitExecutor,
|
|
16
16
|
"jira-fetch": jiraFetchExecutor,
|
|
17
|
-
|
|
18
|
-
"codex-docker": codexDockerExecutor,
|
|
17
|
+
codex: codexExecutor,
|
|
19
18
|
opencode: opencodeExecutor,
|
|
20
|
-
|
|
21
|
-
"verify-build": verifyBuildExecutor,
|
|
19
|
+
"telegram-notifier": telegramNotifierExecutor,
|
|
22
20
|
};
|
|
23
21
|
export function createExecutorRegistry() {
|
|
24
22
|
return {
|
|
@@ -54,6 +54,11 @@ function interpolateValueSpec(value, repeatVars) {
|
|
|
54
54
|
},
|
|
55
55
|
};
|
|
56
56
|
}
|
|
57
|
+
if ("add" in value) {
|
|
58
|
+
return {
|
|
59
|
+
add: value.add.map((candidate) => interpolateValueSpec(candidate, repeatVars)),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
57
62
|
if ("concat" in value) {
|
|
58
63
|
return {
|
|
59
64
|
concat: value.concat.map((candidate) => interpolateValueSpec(candidate, repeatVars)),
|
|
@@ -29,15 +29,21 @@ export const ARTIFACT_REF_KINDS = [
|
|
|
29
29
|
"ready-to-merge-file",
|
|
30
30
|
"review-file",
|
|
31
31
|
"review-json-file",
|
|
32
|
+
"review-assessment-file",
|
|
33
|
+
"review-assessment-json-file",
|
|
32
34
|
"review-fix-file",
|
|
33
35
|
"review-fix-json-file",
|
|
34
|
-
"review-reply-file",
|
|
35
|
-
"review-reply-json-file",
|
|
36
36
|
"run-go-linter-result-json-file",
|
|
37
37
|
"run-go-tests-result-json-file",
|
|
38
|
-
"review-reply-summary-file",
|
|
39
38
|
"review-summary-file",
|
|
40
39
|
"task-summary-file",
|
|
41
40
|
"task-summary-json-file",
|
|
41
|
+
"task-describe-input-json-file",
|
|
42
|
+
"git-status-json-file",
|
|
43
|
+
"git-diff-file",
|
|
44
|
+
"git-commit-message-json-file",
|
|
45
|
+
"git-commit-input-json-file",
|
|
46
|
+
"select-files-output-json-file",
|
|
47
|
+
"commit-message-output-json-file",
|
|
42
48
|
];
|
|
43
49
|
export const ARTIFACT_LIST_REF_KINDS = ["bug-analyze-artifacts", "plan-artifacts"];
|
|
@@ -51,6 +51,10 @@ function validateValueSpec(value, path) {
|
|
|
51
51
|
validateValueSpec(value.appendPrompt.suffix, `${path}.appendPrompt.suffix`);
|
|
52
52
|
return;
|
|
53
53
|
}
|
|
54
|
+
if ("add" in value) {
|
|
55
|
+
value.add.forEach((candidate, index) => validateValueSpec(candidate, `${path}.add[${index}]`));
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
54
58
|
if ("concat" in value) {
|
|
55
59
|
value.concat.forEach((candidate, index) => validateValueSpec(candidate, `${path}.concat[${index}]`));
|
|
56
60
|
return;
|
package/dist/pipeline/types.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
|
-
import { artifactFile, bugAnalyzeArtifacts, bugAnalyzeFile, bugAnalyzeJsonFile, bugFixDesignFile, bugFixDesignJsonFile, bugFixPlanFile, bugFixPlanJsonFile, designFile, designJsonFile, gitlabDiffFile, gitlabDiffJsonFile, gitlabDiffReviewInputJsonFile, gitlabReviewFile, gitlabReviewInputJsonFile, gitlabReviewJsonFile, jiraAttachmentsContextFile, jiraAttachmentsManifestFile, jiraDescriptionFile, jiraDescriptionJsonFile, jiraTaskFile, mrDescriptionFile, mrDescriptionJsonFile, planningAnswersJsonFile, planningQuestionsJsonFile, planArtifacts, planFile, planJsonFile, qaFile, qaJsonFile, readyToMergeFile, reviewFile, reviewFixFile, reviewFixJsonFile, reviewJsonFile,
|
|
2
|
+
import { artifactFile, bugAnalyzeArtifacts, bugAnalyzeFile, bugAnalyzeJsonFile, bugFixDesignFile, bugFixDesignJsonFile, bugFixPlanFile, bugFixPlanJsonFile, designFile, designJsonFile, gitlabDiffFile, gitlabDiffJsonFile, gitlabDiffReviewInputJsonFile, gitlabReviewFile, gitlabReviewInputJsonFile, gitlabReviewJsonFile, jiraAttachmentsContextFile, jiraAttachmentsManifestFile, jiraDescriptionFile, jiraDescriptionJsonFile, jiraTaskFile, mrDescriptionFile, mrDescriptionJsonFile, planningAnswersJsonFile, planningQuestionsJsonFile, planArtifacts, planFile, planJsonFile, qaFile, qaJsonFile, readyToMergeFile, reviewAssessmentFile, reviewAssessmentJsonFile, reviewFile, reviewFixFile, reviewFixJsonFile, reviewJsonFile, runGoLinterResultJsonFile, runGoTestsResultJsonFile, taskSummaryFile, taskDescribeInputJsonFile, taskSummaryJsonFile, gitStatusJsonFile, gitCommitMessageJsonFile, gitCommitInputJsonFile, selectFilesOutputJsonFile, commitMessageOutputJsonFile, gitDiffFile as gitDiffFileHelper, } from "../artifacts.js";
|
|
3
3
|
import { TaskRunnerError } from "../errors.js";
|
|
4
4
|
import { formatTemplate } from "../prompts.js";
|
|
5
5
|
function readStepRef(segments, context, originalPath) {
|
|
@@ -73,59 +73,59 @@ function resolveArtifact(spec, context) {
|
|
|
73
73
|
const iteration = spec.iteration === undefined ? undefined : Number(resolveValue(spec.iteration, context));
|
|
74
74
|
switch (spec.kind) {
|
|
75
75
|
case "bug-analyze-file":
|
|
76
|
-
return bugAnalyzeFile(taskKey);
|
|
76
|
+
return bugAnalyzeFile(taskKey, iteration);
|
|
77
77
|
case "bug-analyze-json-file":
|
|
78
|
-
return bugAnalyzeJsonFile(taskKey);
|
|
78
|
+
return bugAnalyzeJsonFile(taskKey, iteration);
|
|
79
79
|
case "bug-fix-design-file":
|
|
80
|
-
return bugFixDesignFile(taskKey);
|
|
80
|
+
return bugFixDesignFile(taskKey, iteration);
|
|
81
81
|
case "bug-fix-design-json-file":
|
|
82
|
-
return bugFixDesignJsonFile(taskKey);
|
|
82
|
+
return bugFixDesignJsonFile(taskKey, iteration);
|
|
83
83
|
case "bug-fix-plan-file":
|
|
84
|
-
return bugFixPlanFile(taskKey);
|
|
84
|
+
return bugFixPlanFile(taskKey, iteration);
|
|
85
85
|
case "bug-fix-plan-json-file":
|
|
86
|
-
return bugFixPlanJsonFile(taskKey);
|
|
86
|
+
return bugFixPlanJsonFile(taskKey, iteration);
|
|
87
87
|
case "design-file":
|
|
88
|
-
return designFile(taskKey);
|
|
88
|
+
return designFile(taskKey, iteration);
|
|
89
89
|
case "design-json-file":
|
|
90
|
-
return designJsonFile(taskKey);
|
|
90
|
+
return designJsonFile(taskKey, iteration);
|
|
91
91
|
case "gitlab-diff-file":
|
|
92
|
-
return gitlabDiffFile(taskKey);
|
|
92
|
+
return gitlabDiffFile(taskKey, iteration);
|
|
93
93
|
case "gitlab-diff-json-file":
|
|
94
|
-
return gitlabDiffJsonFile(taskKey);
|
|
94
|
+
return gitlabDiffJsonFile(taskKey, iteration);
|
|
95
95
|
case "gitlab-diff-review-input-json-file":
|
|
96
96
|
return gitlabDiffReviewInputJsonFile(taskKey);
|
|
97
97
|
case "gitlab-review-file":
|
|
98
|
-
return gitlabReviewFile(taskKey);
|
|
98
|
+
return gitlabReviewFile(taskKey, iteration);
|
|
99
99
|
case "gitlab-review-input-json-file":
|
|
100
100
|
return gitlabReviewInputJsonFile(taskKey);
|
|
101
101
|
case "gitlab-review-json-file":
|
|
102
|
-
return gitlabReviewJsonFile(taskKey);
|
|
102
|
+
return gitlabReviewJsonFile(taskKey, iteration);
|
|
103
103
|
case "jira-attachments-context-file":
|
|
104
104
|
return jiraAttachmentsContextFile(taskKey);
|
|
105
105
|
case "jira-attachments-manifest-file":
|
|
106
106
|
return jiraAttachmentsManifestFile(taskKey);
|
|
107
107
|
case "jira-description-file":
|
|
108
|
-
return jiraDescriptionFile(taskKey);
|
|
108
|
+
return jiraDescriptionFile(taskKey, iteration);
|
|
109
109
|
case "jira-description-json-file":
|
|
110
|
-
return jiraDescriptionJsonFile(taskKey);
|
|
110
|
+
return jiraDescriptionJsonFile(taskKey, iteration);
|
|
111
111
|
case "jira-task-file":
|
|
112
112
|
return jiraTaskFile(taskKey);
|
|
113
113
|
case "mr-description-file":
|
|
114
|
-
return mrDescriptionFile(taskKey);
|
|
114
|
+
return mrDescriptionFile(taskKey, iteration);
|
|
115
115
|
case "mr-description-json-file":
|
|
116
|
-
return mrDescriptionJsonFile(taskKey);
|
|
116
|
+
return mrDescriptionJsonFile(taskKey, iteration);
|
|
117
117
|
case "planning-answers-json-file":
|
|
118
118
|
return planningAnswersJsonFile(taskKey);
|
|
119
119
|
case "planning-questions-json-file":
|
|
120
120
|
return planningQuestionsJsonFile(taskKey);
|
|
121
121
|
case "plan-file":
|
|
122
|
-
return planFile(taskKey);
|
|
122
|
+
return planFile(taskKey, iteration);
|
|
123
123
|
case "plan-json-file":
|
|
124
|
-
return planJsonFile(taskKey);
|
|
124
|
+
return planJsonFile(taskKey, iteration);
|
|
125
125
|
case "qa-file":
|
|
126
|
-
return qaFile(taskKey);
|
|
126
|
+
return qaFile(taskKey, iteration);
|
|
127
127
|
case "qa-json-file":
|
|
128
|
-
return qaJsonFile(taskKey);
|
|
128
|
+
return qaJsonFile(taskKey, iteration);
|
|
129
129
|
case "ready-to-merge-file":
|
|
130
130
|
return readyToMergeFile(taskKey);
|
|
131
131
|
case "review-file":
|
|
@@ -138,6 +138,16 @@ function resolveArtifact(spec, context) {
|
|
|
138
138
|
throw new TaskRunnerError("review-json-file requires iteration");
|
|
139
139
|
}
|
|
140
140
|
return reviewJsonFile(taskKey, iteration);
|
|
141
|
+
case "review-assessment-file":
|
|
142
|
+
if (iteration === undefined) {
|
|
143
|
+
throw new TaskRunnerError("review-assessment-file requires iteration");
|
|
144
|
+
}
|
|
145
|
+
return reviewAssessmentFile(taskKey, iteration);
|
|
146
|
+
case "review-assessment-json-file":
|
|
147
|
+
if (iteration === undefined) {
|
|
148
|
+
throw new TaskRunnerError("review-assessment-json-file requires iteration");
|
|
149
|
+
}
|
|
150
|
+
return reviewAssessmentJsonFile(taskKey, iteration);
|
|
141
151
|
case "review-fix-file":
|
|
142
152
|
if (iteration === undefined) {
|
|
143
153
|
throw new TaskRunnerError("review-fix-file requires iteration");
|
|
@@ -148,16 +158,6 @@ function resolveArtifact(spec, context) {
|
|
|
148
158
|
throw new TaskRunnerError("review-fix-json-file requires iteration");
|
|
149
159
|
}
|
|
150
160
|
return reviewFixJsonFile(taskKey, iteration);
|
|
151
|
-
case "review-reply-file":
|
|
152
|
-
if (iteration === undefined) {
|
|
153
|
-
throw new TaskRunnerError("review-reply-file requires iteration");
|
|
154
|
-
}
|
|
155
|
-
return reviewReplyFile(taskKey, iteration);
|
|
156
|
-
case "review-reply-json-file":
|
|
157
|
-
if (iteration === undefined) {
|
|
158
|
-
throw new TaskRunnerError("review-reply-json-file requires iteration");
|
|
159
|
-
}
|
|
160
|
-
return reviewReplyJsonFile(taskKey, iteration);
|
|
161
161
|
case "run-go-linter-result-json-file":
|
|
162
162
|
if (iteration === undefined) {
|
|
163
163
|
throw new TaskRunnerError("run-go-linter-result-json-file requires iteration");
|
|
@@ -168,20 +168,29 @@ function resolveArtifact(spec, context) {
|
|
|
168
168
|
throw new TaskRunnerError("run-go-tests-result-json-file requires iteration");
|
|
169
169
|
}
|
|
170
170
|
return runGoTestsResultJsonFile(taskKey, iteration);
|
|
171
|
-
case "review-reply-summary-file":
|
|
172
|
-
if (iteration === undefined) {
|
|
173
|
-
throw new TaskRunnerError("review-reply-summary-file requires iteration");
|
|
174
|
-
}
|
|
175
|
-
return artifactFile("review-reply-summary", taskKey, iteration);
|
|
176
171
|
case "review-summary-file":
|
|
177
172
|
if (iteration === undefined) {
|
|
178
173
|
throw new TaskRunnerError("review-summary-file requires iteration");
|
|
179
174
|
}
|
|
180
175
|
return artifactFile("review-summary", taskKey, iteration);
|
|
181
176
|
case "task-summary-file":
|
|
182
|
-
return taskSummaryFile(taskKey);
|
|
177
|
+
return taskSummaryFile(taskKey, iteration);
|
|
183
178
|
case "task-summary-json-file":
|
|
184
|
-
return taskSummaryJsonFile(taskKey);
|
|
179
|
+
return taskSummaryJsonFile(taskKey, iteration);
|
|
180
|
+
case "task-describe-input-json-file":
|
|
181
|
+
return taskDescribeInputJsonFile(taskKey);
|
|
182
|
+
case "git-status-json-file":
|
|
183
|
+
return gitStatusJsonFile(taskKey);
|
|
184
|
+
case "git-diff-file":
|
|
185
|
+
return gitDiffFileHelper(taskKey);
|
|
186
|
+
case "git-commit-message-json-file":
|
|
187
|
+
return gitCommitMessageJsonFile(taskKey);
|
|
188
|
+
case "git-commit-input-json-file":
|
|
189
|
+
return gitCommitInputJsonFile(taskKey);
|
|
190
|
+
case "select-files-output-json-file":
|
|
191
|
+
return selectFilesOutputJsonFile(taskKey);
|
|
192
|
+
case "commit-message-output-json-file":
|
|
193
|
+
return commitMessageOutputJsonFile(taskKey);
|
|
185
194
|
}
|
|
186
195
|
}
|
|
187
196
|
function resolveArtifactList(spec, context) {
|
|
@@ -223,6 +232,9 @@ export function resolveValue(value, context) {
|
|
|
223
232
|
}
|
|
224
233
|
return `${baseText}\n${suffixText}`;
|
|
225
234
|
}
|
|
235
|
+
if ("add" in value) {
|
|
236
|
+
return value.add.reduce((sum, candidate) => sum + Number(resolveValue(candidate, context)), 0);
|
|
237
|
+
}
|
|
226
238
|
if ("concat" in value) {
|
|
227
239
|
return value.concat
|
|
228
240
|
.map((candidate) => resolveValue(candidate, context))
|