agentweaver 0.1.13 → 0.1.15
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 +24 -19
- package/dist/artifacts.js +6 -1
- package/dist/doctor/checks/cwd-context.js +4 -3
- package/dist/doctor/checks/env-diagnostics.js +168 -71
- package/dist/doctor/checks/flow-readiness.js +210 -198
- package/dist/doctor/index.js +1 -1
- package/dist/doctor/orchestrator.js +18 -7
- package/dist/doctor/runner.js +9 -8
- package/dist/doctor/types.js +12 -0
- package/dist/index.js +119 -55
- package/dist/interactive-ui.js +25 -25
- package/dist/pipeline/declarative-flows.js +1 -0
- package/dist/pipeline/flow-catalog.js +4 -0
- package/dist/pipeline/flow-specs/auto-common.json +1 -0
- package/dist/pipeline/flow-specs/auto-golang.json +2 -1
- package/dist/pipeline/flow-specs/bugz/bug-analyze.json +1 -0
- package/dist/pipeline/flow-specs/bugz/bug-fix.json +1 -0
- package/dist/pipeline/flow-specs/design-review.json +239 -0
- package/dist/pipeline/flow-specs/git-commit.json +1 -0
- package/dist/pipeline/flow-specs/gitlab/gitlab-diff-review.json +3 -2
- package/dist/pipeline/flow-specs/gitlab/gitlab-review.json +3 -2
- package/dist/pipeline/flow-specs/gitlab/mr-description.json +1 -0
- package/dist/pipeline/flow-specs/go/run-go-linter-loop.json +3 -2
- package/dist/pipeline/flow-specs/go/run-go-tests-loop.json +3 -2
- package/dist/pipeline/flow-specs/implement.json +13 -0
- package/dist/pipeline/flow-specs/plan-revise.json +261 -0
- package/dist/pipeline/flow-specs/plan.json +2 -1
- package/dist/pipeline/flow-specs/review/review-fix.json +1 -0
- package/dist/pipeline/flow-specs/review/review-loop.json +1 -0
- package/dist/pipeline/flow-specs/review/review-project.json +1 -0
- package/dist/pipeline/flow-specs/review/review.json +2 -1
- package/dist/pipeline/flow-specs/task-describe.json +67 -8
- package/dist/pipeline/node-registry.js +8 -0
- package/dist/pipeline/nodes/ensure-summary-json-node.js +59 -0
- package/dist/pipeline/nodes/git-commit-node.js +1 -1
- package/dist/pipeline/nodes/git-status-node.js +1 -1
- package/dist/pipeline/nodes/review-findings-form-node.js +8 -8
- package/dist/pipeline/nodes/user-input-node.js +2 -2
- package/dist/pipeline/prompt-registry.js +3 -1
- package/dist/pipeline/spec-types.js +2 -0
- package/dist/pipeline/value-resolver.js +11 -1
- package/dist/prompts.js +49 -2
- package/dist/runtime/design-review-input-contract.js +112 -0
- package/dist/runtime/plan-revise-input-contract.js +144 -0
- package/dist/runtime/process-runner.js +2 -2
- package/dist/runtime/ready-to-merge.js +10 -0
- package/dist/scope.js +13 -4
- package/dist/structured-artifact-schema-registry.js +1 -0
- package/dist/structured-artifact-schemas.json +117 -0
- package/dist/structured-artifacts.js +6 -0
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { existsSync,
|
|
2
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import process from "node:process";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
|
-
import {
|
|
6
|
+
import { bugAnalyzeArtifacts, bugAnalyzeJsonFile, bugFixDesignJsonFile, bugFixPlanJsonFile, designReviewFile, designReviewJsonFile, designJsonFile, gitlabDiffFile, gitlabDiffJsonFile, ensureScopeWorkspaceDir, gitlabReviewFile, gitlabReviewJsonFile, latestArtifactIteration, nextArtifactIteration, planJsonFile, planArtifacts, qaJsonFile, readyToMergeFile, requireArtifacts, reviewAssessmentFile, reviewAssessmentJsonFile, reviewFile, reviewFixSelectionJsonFile, reviewJsonFile, scopeWorkspaceDir, flowStateFile, taskSummaryFile, } from "./artifacts.js";
|
|
7
7
|
import { FlowInterruptedError, TaskRunnerError } from "./errors.js";
|
|
8
8
|
import { createFlowRunState, hasResumableFlowState, loadFlowRunState, prepareFlowStateForResume, resetFlowRunState, rewindFlowRunStateToPhase, saveFlowRunState, stripExecutionStatePayload, } from "./flow-state.js";
|
|
9
9
|
import { requireJiraTaskFile } from "./jira.js";
|
|
@@ -20,11 +20,14 @@ import { resolveCmd } from "./runtime/command-resolution.js";
|
|
|
20
20
|
import { loadTieredEnv } from "./runtime/env-loader.js";
|
|
21
21
|
import { agentweaverHome } from "./runtime/agentweaver-home.js";
|
|
22
22
|
import { runCommand } from "./runtime/process-runner.js";
|
|
23
|
+
import { resolveDesignReviewInputContract } from "./runtime/design-review-input-contract.js";
|
|
24
|
+
import { resolvePlanReviseInputContract } from "./runtime/plan-revise-input-contract.js";
|
|
25
|
+
import { clearReadyToMergeFile } from "./runtime/ready-to-merge.js";
|
|
23
26
|
import { InteractiveUi } from "./interactive-ui.js";
|
|
24
27
|
import { bye, printError, printInfo, printPanel, printSummary, setFlowExecutionState, stripAnsi, } from "./tui.js";
|
|
25
28
|
import { requestUserInputInTerminal } from "./user-input.js";
|
|
26
29
|
import { runDoctorCommand } from "./doctor/index.js";
|
|
27
|
-
import {
|
|
30
|
+
import { detectGitBranchName, requestJiraContext, resolveProjectScope, } from "./scope.js";
|
|
28
31
|
const COMMANDS = [
|
|
29
32
|
"auto-golang",
|
|
30
33
|
"auto-common",
|
|
@@ -32,12 +35,14 @@ const COMMANDS = [
|
|
|
32
35
|
"auto-reset",
|
|
33
36
|
"bug-analyze",
|
|
34
37
|
"bug-fix",
|
|
38
|
+
"design-review",
|
|
35
39
|
"doctor",
|
|
36
40
|
"git-commit",
|
|
37
41
|
"gitlab-diff-review",
|
|
38
42
|
"gitlab-review",
|
|
39
43
|
"mr-description",
|
|
40
44
|
"plan",
|
|
45
|
+
"plan-revise",
|
|
41
46
|
"task-describe",
|
|
42
47
|
"implement",
|
|
43
48
|
"review",
|
|
@@ -84,7 +89,7 @@ function formatProcessFailure(error) {
|
|
|
84
89
|
if (!preview) {
|
|
85
90
|
return baseMessage;
|
|
86
91
|
}
|
|
87
|
-
return `${baseMessage}\n
|
|
92
|
+
return `${baseMessage}\nReason:\n${preview}`;
|
|
88
93
|
}
|
|
89
94
|
function escapeRegExp(value) {
|
|
90
95
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -99,9 +104,11 @@ function usage() {
|
|
|
99
104
|
agentweaver gitlab-review [--dry] [--verbose] [--prompt <text>] [--scope <name>]
|
|
100
105
|
agentweaver bug-analyze [--dry] [--verbose] [--prompt <text>] <jira-browse-url|jira-issue-key>
|
|
101
106
|
agentweaver bug-fix [--dry] [--verbose] [--prompt <text>] <jira-browse-url|jira-issue-key>
|
|
107
|
+
agentweaver design-review [--dry] [--verbose] [--prompt <text>] <jira-browse-url|jira-issue-key>
|
|
102
108
|
agentweaver doctor [<category>|<check-id>] [--json]
|
|
103
109
|
agentweaver mr-description [--dry] [--verbose] [--prompt <text>] <jira-browse-url|jira-issue-key>
|
|
104
110
|
agentweaver plan [--dry] [--verbose] [--prompt <text>] [--md-lang <en|ru>] [<jira-browse-url|jira-issue-key>]
|
|
111
|
+
agentweaver plan-revise [--dry] [--verbose] [--prompt <text>] <jira-browse-url|jira-issue-key>
|
|
105
112
|
agentweaver task-describe [--dry] [--verbose] [--prompt <text>] [<jira-browse-url|jira-issue-key>]
|
|
106
113
|
agentweaver implement [--dry] [--verbose] [--prompt <text>] [--scope <name>] [<jira-browse-url|jira-issue-key>]
|
|
107
114
|
agentweaver review [--dry] [--verbose] [--prompt <text>] [--scope <name>] [<jira-browse-url|jira-issue-key>]
|
|
@@ -188,8 +195,8 @@ function launchProfileSelectionForm() {
|
|
|
188
195
|
const defaultExecutor = DEFAULT_LAUNCH_PROFILE.executor;
|
|
189
196
|
return {
|
|
190
197
|
formId: "flow-launch-profile",
|
|
191
|
-
title: "
|
|
192
|
-
description:
|
|
198
|
+
title: "LLM Launch Settings",
|
|
199
|
+
description: `Select an executor for the flow. Current default: ${defaultExecutor}.`,
|
|
193
200
|
submitLabel: "Continue",
|
|
194
201
|
fields: [
|
|
195
202
|
{
|
|
@@ -215,8 +222,8 @@ function launchModelSelectionForm(executor) {
|
|
|
215
222
|
}));
|
|
216
223
|
return {
|
|
217
224
|
formId: "flow-launch-model",
|
|
218
|
-
title: "
|
|
219
|
-
description:
|
|
225
|
+
title: "LLM Launch Settings",
|
|
226
|
+
description: `Select a model for the flow. Current default for ${resolvedExecutor}: ${defaultModel}.`,
|
|
220
227
|
submitLabel: "Start",
|
|
221
228
|
fields: [
|
|
222
229
|
{
|
|
@@ -364,17 +371,19 @@ function scopeWithRestoredJiraContext(scope, state) {
|
|
|
364
371
|
if (scope.jiraRef || !state?.jiraRef?.trim()) {
|
|
365
372
|
return scope;
|
|
366
373
|
}
|
|
367
|
-
return
|
|
374
|
+
return resolveProjectScope(null, state.jiraRef);
|
|
375
|
+
}
|
|
376
|
+
function buildInteractiveBaseConfig(flowId, scope) {
|
|
377
|
+
return buildBaseConfig(flowId, {
|
|
378
|
+
...(scope.jiraRef ? { jiraRef: scope.jiraRef } : {}),
|
|
379
|
+
});
|
|
368
380
|
}
|
|
369
381
|
function lookupInteractiveFlowResume(flowEntry, currentScope) {
|
|
370
382
|
const directState = loadFlowRunState(currentScope.scopeKey, flowEntry.id);
|
|
371
383
|
if (directState && hasResumableFlowState(directState)) {
|
|
372
384
|
try {
|
|
373
385
|
const effectiveScope = scopeWithRestoredJiraContext(currentScope, directState);
|
|
374
|
-
const baseConfig =
|
|
375
|
-
...(effectiveScope.jiraRef ? { jiraRef: effectiveScope.jiraRef } : {}),
|
|
376
|
-
scopeName: effectiveScope.scopeKey,
|
|
377
|
-
});
|
|
386
|
+
const baseConfig = buildInteractiveBaseConfig(flowEntry.id, effectiveScope);
|
|
378
387
|
const config = buildRuntimeConfig(baseConfig, effectiveScope);
|
|
379
388
|
validateDeclarativeFlowResumeState(flowEntry, config, directState, directState.launchProfile);
|
|
380
389
|
return {
|
|
@@ -410,21 +419,10 @@ function printAutoCommonPhasesHelp() {
|
|
|
410
419
|
printPanel("Auto-Common Phases", phaseLines.join("\n"), "magenta");
|
|
411
420
|
}
|
|
412
421
|
function nextReviewIterationForTask(taskKey) {
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
}
|
|
418
|
-
for (const entry of readdirSync(workspaceDir, { withFileTypes: true })) {
|
|
419
|
-
if (!entry.isFile()) {
|
|
420
|
-
continue;
|
|
421
|
-
}
|
|
422
|
-
const match = REVIEW_FILE_RE.exec(entry.name);
|
|
423
|
-
if (match && match[1] === taskKey) {
|
|
424
|
-
maxIndex = Math.max(maxIndex, Number.parseInt(match[2] ?? "0", 10));
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
return maxIndex + 1;
|
|
422
|
+
return nextArtifactIteration(taskKey, "review");
|
|
423
|
+
}
|
|
424
|
+
function nextDesignReviewIterationForTask(taskKey) {
|
|
425
|
+
return nextArtifactIteration(taskKey, "design-review");
|
|
428
426
|
}
|
|
429
427
|
function buildBaseConfig(command, options = {}) {
|
|
430
428
|
return {
|
|
@@ -442,8 +440,10 @@ function buildBaseConfig(command, options = {}) {
|
|
|
442
440
|
}
|
|
443
441
|
function commandRequiresTask(command) {
|
|
444
442
|
return (command === "plan" ||
|
|
443
|
+
command === "plan-revise" ||
|
|
445
444
|
command === "bug-analyze" ||
|
|
446
445
|
command === "bug-fix" ||
|
|
446
|
+
command === "design-review" ||
|
|
447
447
|
command === "mr-description" ||
|
|
448
448
|
command === "auto-golang" ||
|
|
449
449
|
command === "auto-common" ||
|
|
@@ -525,32 +525,12 @@ function autoFlowParams(config, forceRefreshSummary = false) {
|
|
|
525
525
|
runGoLinterIteration: nextArtifactIteration(config.taskKey, "run-go-linter-result", "json"),
|
|
526
526
|
};
|
|
527
527
|
}
|
|
528
|
-
const FLOW_DESCRIPTIONS = {
|
|
529
|
-
"auto-golang": "Full task pipeline: planning, implementation, checks, review, review replies, and repeated iterations until ready to merge.",
|
|
530
|
-
"bug-analyze": "Analyzes bug from Jira and creates structured artifacts: root cause hypothesis, fix design, and implementation plan.",
|
|
531
|
-
"git-commit": "Collects git status/diff, generates commit message via LLM, allows file selection and commit confirmation.",
|
|
532
|
-
"gitlab-diff-review": "Requests GitLab MR URL via user-input, downloads merge request diff via API, and runs code review with markdown and structured JSON artifacts.",
|
|
533
|
-
"gitlab-review": "Requests GitLab MR URL via user-input, downloads code review comments via API, assesses which findings are fair and proposes fixes, then runs review-fix for the selected findings.",
|
|
534
|
-
"bug-fix": "Takes bug-analyze results as source of truth and implements the bug fix in code.",
|
|
535
|
-
"mr-description": "Prepares a brief intent description for a merge request based on the task and current changes.",
|
|
536
|
-
plan: "Loads task from Jira and creates design, implementation plan, and QA plan in structured JSON and markdown.",
|
|
537
|
-
"task-describe": "Builds a brief task description either from Jira or from quick user-input without Jira.",
|
|
538
|
-
implement: "Implements the task from approved design/plan artifacts and runs post-verify builds if needed.",
|
|
539
|
-
review: "Runs code review of current changes and writes structured findings artifacts.",
|
|
540
|
-
"review-fix": "Fixes issues after review-reply, updates code, and runs mandatory checks after modifications.",
|
|
541
|
-
"review-loop": "Iteratively runs review and review-fix cycles up to 5 times until ready-to-merge is achieved.",
|
|
542
|
-
"run-go-tests-loop": "Cycles through `./run_go_tests.py` locally, analyzes the last error, and fixes code until successful or attempts exhausted.",
|
|
543
|
-
"run-go-linter-loop": "Cycles through `./run_go_linter.py` locally, fixes linter or generation issues, and retries until success.",
|
|
544
|
-
};
|
|
545
|
-
function flowDescription(id) {
|
|
546
|
-
return FLOW_DESCRIPTIONS[id] ?? "Описание для этого flow пока не задано.";
|
|
547
|
-
}
|
|
548
528
|
function interactiveFlowDefinition(entry) {
|
|
549
529
|
const flow = entry.flow;
|
|
550
530
|
return {
|
|
551
531
|
id: entry.id,
|
|
552
532
|
label: entry.id,
|
|
553
|
-
description:
|
|
533
|
+
description: flow.description ?? "No description available for this flow.",
|
|
554
534
|
source: entry.source,
|
|
555
535
|
treePath: [...entry.treePath],
|
|
556
536
|
...(entry.source === "project-local" ? { sourcePath: entry.absolutePath } : {}),
|
|
@@ -885,6 +865,90 @@ async function executeCommand(baseConfig, runFollowupVerify = true, requestUserI
|
|
|
885
865
|
}, launchProfile ? { launchProfile } : {}, requestUserInput, setSummary, launchMode, runtime);
|
|
886
866
|
return false;
|
|
887
867
|
}
|
|
868
|
+
if (config.command === "design-review") {
|
|
869
|
+
const iteration = nextDesignReviewIterationForTask(config.taskKey);
|
|
870
|
+
const inputContract = resolveDesignReviewInputContract(config.taskKey);
|
|
871
|
+
if (!config.dryRun) {
|
|
872
|
+
clearReadyToMergeFile(config.taskKey);
|
|
873
|
+
}
|
|
874
|
+
await runDeclarativeFlowBySpecFile("design-review.json", config, {
|
|
875
|
+
taskKey: config.taskKey,
|
|
876
|
+
iteration,
|
|
877
|
+
planningIteration: inputContract.planningIteration,
|
|
878
|
+
designFile: inputContract.designFile,
|
|
879
|
+
designJsonFile: inputContract.designJsonFile,
|
|
880
|
+
planFile: inputContract.planFile,
|
|
881
|
+
planJsonFile: inputContract.planJsonFile,
|
|
882
|
+
hasQaArtifacts: inputContract.hasQaArtifacts,
|
|
883
|
+
qaFilePath: inputContract.qaFilePath,
|
|
884
|
+
qaJsonFilePath: inputContract.qaJsonFilePath,
|
|
885
|
+
qaFile: inputContract.qaFile,
|
|
886
|
+
qaJsonFile: inputContract.qaJsonFile,
|
|
887
|
+
hasJiraTaskFile: inputContract.hasJiraTaskFile,
|
|
888
|
+
jiraTaskFilePath: inputContract.jiraTaskFilePath,
|
|
889
|
+
jiraTaskFile: inputContract.jiraTaskFile,
|
|
890
|
+
hasJiraAttachmentsManifestFile: inputContract.hasJiraAttachmentsManifestFile,
|
|
891
|
+
jiraAttachmentsManifestFilePath: inputContract.jiraAttachmentsManifestFilePath,
|
|
892
|
+
jiraAttachmentsManifestFile: inputContract.jiraAttachmentsManifestFile,
|
|
893
|
+
hasJiraAttachmentsContextFile: inputContract.hasJiraAttachmentsContextFile,
|
|
894
|
+
jiraAttachmentsContextFilePath: inputContract.jiraAttachmentsContextFilePath,
|
|
895
|
+
jiraAttachmentsContextFile: inputContract.jiraAttachmentsContextFile,
|
|
896
|
+
hasPlanningAnswersJsonFile: inputContract.hasPlanningAnswersJsonFile,
|
|
897
|
+
planningAnswersJsonFilePath: inputContract.planningAnswersJsonFilePath,
|
|
898
|
+
planningAnswersJsonFile: inputContract.planningAnswersJsonFile,
|
|
899
|
+
extraPrompt: config.extraPrompt,
|
|
900
|
+
}, launchProfile ? { launchProfile } : {}, requestUserInput, undefined, launchMode, runtime);
|
|
901
|
+
if (!config.dryRun) {
|
|
902
|
+
printSummary("Design Review", `Artifacts:\n${designReviewFile(config.taskKey, iteration)}\n${designReviewJsonFile(config.taskKey, iteration)}`);
|
|
903
|
+
}
|
|
904
|
+
return false;
|
|
905
|
+
}
|
|
906
|
+
if (config.command === "plan-revise") {
|
|
907
|
+
const inputContract = resolvePlanReviseInputContract(config.taskKey);
|
|
908
|
+
if (!config.dryRun) {
|
|
909
|
+
clearReadyToMergeFile(config.taskKey);
|
|
910
|
+
}
|
|
911
|
+
await runDeclarativeFlowBySpecFile("plan-revise.json", config, {
|
|
912
|
+
taskKey: config.taskKey,
|
|
913
|
+
reviewIteration: inputContract.reviewIteration,
|
|
914
|
+
reviewFile: inputContract.reviewFile,
|
|
915
|
+
reviewJsonFile: inputContract.reviewJsonFile,
|
|
916
|
+
sourcePlanningIteration: inputContract.sourcePlanningIteration,
|
|
917
|
+
outputIteration: inputContract.outputIteration,
|
|
918
|
+
designFile: inputContract.designFile,
|
|
919
|
+
designJsonFile: inputContract.designJsonFile,
|
|
920
|
+
planFile: inputContract.planFile,
|
|
921
|
+
planJsonFile: inputContract.planJsonFile,
|
|
922
|
+
hasQaArtifacts: inputContract.hasQaArtifacts,
|
|
923
|
+
qaFilePath: inputContract.qaFilePath,
|
|
924
|
+
qaJsonFilePath: inputContract.qaJsonFilePath,
|
|
925
|
+
qaFile: inputContract.qaFile,
|
|
926
|
+
qaJsonFile: inputContract.qaJsonFile,
|
|
927
|
+
revisedDesignFile: inputContract.revisedDesignFile,
|
|
928
|
+
revisedDesignJsonFile: inputContract.revisedDesignJsonFile,
|
|
929
|
+
revisedPlanFile: inputContract.revisedPlanFile,
|
|
930
|
+
revisedPlanJsonFile: inputContract.revisedPlanJsonFile,
|
|
931
|
+
revisedQaFile: inputContract.revisedQaFile,
|
|
932
|
+
revisedQaJsonFile: inputContract.revisedQaJsonFile,
|
|
933
|
+
hasJiraTaskFile: inputContract.hasJiraTaskFile,
|
|
934
|
+
jiraTaskFilePath: inputContract.jiraTaskFilePath,
|
|
935
|
+
jiraTaskFile: inputContract.jiraTaskFile,
|
|
936
|
+
hasJiraAttachmentsManifestFile: inputContract.hasJiraAttachmentsManifestFile,
|
|
937
|
+
jiraAttachmentsManifestFilePath: inputContract.jiraAttachmentsManifestFilePath,
|
|
938
|
+
jiraAttachmentsManifestFile: inputContract.jiraAttachmentsManifestFile,
|
|
939
|
+
hasJiraAttachmentsContextFile: inputContract.hasJiraAttachmentsContextFile,
|
|
940
|
+
jiraAttachmentsContextFilePath: inputContract.jiraAttachmentsContextFilePath,
|
|
941
|
+
jiraAttachmentsContextFile: inputContract.jiraAttachmentsContextFile,
|
|
942
|
+
hasPlanningAnswersJsonFile: inputContract.hasPlanningAnswersJsonFile,
|
|
943
|
+
planningAnswersJsonFilePath: inputContract.planningAnswersJsonFilePath,
|
|
944
|
+
planningAnswersJsonFile: inputContract.planningAnswersJsonFile,
|
|
945
|
+
extraPrompt: config.extraPrompt,
|
|
946
|
+
}, launchProfile ? { launchProfile } : {}, requestUserInput, undefined, launchMode, runtime);
|
|
947
|
+
if (!config.dryRun) {
|
|
948
|
+
printSummary("Plan Revise", `Artifacts:\n${inputContract.revisedDesignFile}\n${inputContract.revisedDesignJsonFile}\n${inputContract.revisedPlanFile}\n${inputContract.revisedPlanJsonFile}\n${inputContract.revisedQaFile}\n${inputContract.revisedQaJsonFile}`);
|
|
949
|
+
}
|
|
950
|
+
return false;
|
|
951
|
+
}
|
|
888
952
|
if (config.command === "gitlab-review") {
|
|
889
953
|
const iteration = nextReviewIterationForTask(config.taskKey);
|
|
890
954
|
const gitlabReviewIteration = nextArtifactIteration(config.taskKey, "gitlab-review");
|
|
@@ -1202,17 +1266,14 @@ async function runInteractive(jiraRef, forceRefresh = false, scopeName) {
|
|
|
1202
1266
|
throw new TaskRunnerError("Resume is impossible because launch profile was not saved. Use restart.");
|
|
1203
1267
|
}
|
|
1204
1268
|
const previousScopeKey = currentScope.scopeKey;
|
|
1205
|
-
const baseConfig =
|
|
1206
|
-
...(currentScope.jiraRef ? { jiraRef: currentScope.jiraRef } : {}),
|
|
1207
|
-
scopeName: currentScope.scopeKey,
|
|
1208
|
-
});
|
|
1269
|
+
const baseConfig = buildInteractiveBaseConfig(flowId, currentScope);
|
|
1209
1270
|
if (flowEntry.source === "built-in" && isBuiltInCommandFlowId(flowId)) {
|
|
1210
1271
|
const nextScope = await resolveScopeForCommand(baseConfig, (form) => ui.requestUserInput(form));
|
|
1211
1272
|
currentScope = nextScope;
|
|
1212
1273
|
}
|
|
1213
1274
|
else if (flowRequiresTaskScope(flowEntry) && !currentScope.jiraRef) {
|
|
1214
1275
|
const jiraContext = await requestJiraContext((form) => ui.requestUserInput(form));
|
|
1215
|
-
currentScope =
|
|
1276
|
+
currentScope = resolveProjectScope(null, jiraContext.jiraRef);
|
|
1216
1277
|
}
|
|
1217
1278
|
ui.setScope(currentScope.scopeKey, currentScope.jiraIssueKey ?? null);
|
|
1218
1279
|
if (previousScopeKey !== currentScope.scopeKey || currentScope.jiraIssueKey) {
|
|
@@ -1303,7 +1364,10 @@ export async function main(argv = process.argv.slice(2)) {
|
|
|
1303
1364
|
return await runInteractive(args[0] ?? "", forceRefresh);
|
|
1304
1365
|
}
|
|
1305
1366
|
const parsedArgs = parseCliArgs(args);
|
|
1306
|
-
await executeCommand(buildConfigFromArgs(parsedArgs));
|
|
1367
|
+
const commandCompleted = await executeCommand(buildConfigFromArgs(parsedArgs));
|
|
1368
|
+
if (parsedArgs.command === "doctor") {
|
|
1369
|
+
return commandCompleted ? 0 : 1;
|
|
1370
|
+
}
|
|
1307
1371
|
return 0;
|
|
1308
1372
|
}
|
|
1309
1373
|
catch (error) {
|
package/dist/interactive-ui.js
CHANGED
|
@@ -213,7 +213,7 @@ export class InteractiveUi {
|
|
|
213
213
|
top: 3,
|
|
214
214
|
left: 0,
|
|
215
215
|
width: "34%",
|
|
216
|
-
height: "50%-
|
|
216
|
+
height: "50%-4",
|
|
217
217
|
tags: true,
|
|
218
218
|
label: " Current Flow ",
|
|
219
219
|
padding: {
|
|
@@ -232,10 +232,10 @@ export class InteractiveUi {
|
|
|
232
232
|
});
|
|
233
233
|
this.flowList = blessed.list({
|
|
234
234
|
parent: this.screen,
|
|
235
|
-
top: "50
|
|
235
|
+
top: "50%-1",
|
|
236
236
|
left: 0,
|
|
237
237
|
width: "34%",
|
|
238
|
-
bottom:
|
|
238
|
+
bottom: 14,
|
|
239
239
|
keys: true,
|
|
240
240
|
vi: true,
|
|
241
241
|
mouse: true,
|
|
@@ -395,7 +395,7 @@ export class InteractiveUi {
|
|
|
395
395
|
bottom: 6,
|
|
396
396
|
left: 0,
|
|
397
397
|
width: "34%",
|
|
398
|
-
height:
|
|
398
|
+
height: 8,
|
|
399
399
|
tags: true,
|
|
400
400
|
label: " Flow Description ",
|
|
401
401
|
padding: {
|
|
@@ -806,19 +806,19 @@ export class InteractiveUi {
|
|
|
806
806
|
this.help.setContent(renderMarkdownToTerminal([
|
|
807
807
|
"AgentWeaver interactive mode",
|
|
808
808
|
"",
|
|
809
|
-
"
|
|
810
|
-
"Up / Down
|
|
811
|
-
"Right
|
|
812
|
-
"Left
|
|
813
|
-
"Enter
|
|
814
|
-
"Enter
|
|
815
|
-
"Esc
|
|
816
|
-
"F1
|
|
817
|
-
"Tab
|
|
818
|
-
"Ctrl+L
|
|
819
|
-
"q / Ctrl+C
|
|
809
|
+
"Keys:",
|
|
810
|
+
"Up / Down select folder or flow",
|
|
811
|
+
"Right expand folder",
|
|
812
|
+
"Left collapse folder or go to parent",
|
|
813
|
+
"Enter expand folder or launch flow",
|
|
814
|
+
"Enter confirm launch in modal",
|
|
815
|
+
"Esc close help/modal or interrupt running flow",
|
|
816
|
+
"F1 open or close help",
|
|
817
|
+
"Tab switch pane",
|
|
818
|
+
"Ctrl+L clear log",
|
|
819
|
+
"q / Ctrl+C exit",
|
|
820
820
|
"",
|
|
821
|
-
"
|
|
821
|
+
"Available flows:",
|
|
822
822
|
...this.options.flows.map((flow) => flow.treePath.join("/")),
|
|
823
823
|
].join("\n")));
|
|
824
824
|
this.footer.setContent(" Up/Down: select | Left/Right: fold | Enter: toggle/run | Esc: close/interrupt | h: help | Tab: switch pane | q: exit ");
|
|
@@ -1522,20 +1522,20 @@ export class InteractiveUi {
|
|
|
1522
1522
|
if (selectedItem.kind === "folder") {
|
|
1523
1523
|
const kindLabel = selectedItem.pathSegments[0] === "custom" ? "project-local" : "built-in";
|
|
1524
1524
|
const folderDescription = [
|
|
1525
|
-
|
|
1525
|
+
`Flow folder \`${selectedItem.pathSegments.join("/")}\`.`,
|
|
1526
1526
|
"",
|
|
1527
|
-
|
|
1528
|
-
|
|
1527
|
+
`Source: ${kindLabel}`,
|
|
1528
|
+
`State: ${this.expandedFlowFolders.has(selectedItem.key) ? "expanded" : "collapsed"}`,
|
|
1529
1529
|
].join("\n");
|
|
1530
1530
|
this.description.setContent(renderMarkdownToTerminal(stripAnsi(folderDescription)));
|
|
1531
1531
|
return;
|
|
1532
1532
|
}
|
|
1533
1533
|
const { flow } = selectedItem;
|
|
1534
|
-
const description = flow.description?.trim() || "
|
|
1534
|
+
const description = flow.description?.trim() || "No description available for this flow.";
|
|
1535
1535
|
const details = [
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
flow.source === "project-local" && flow.sourcePath ?
|
|
1536
|
+
`Path: ${flow.treePath.join("/")}`,
|
|
1537
|
+
`Source: ${flow.source === "project-local" ? "project-local" : "built-in"}`,
|
|
1538
|
+
flow.source === "project-local" && flow.sourcePath ? `File: ${flow.sourcePath}` : "",
|
|
1539
1539
|
]
|
|
1540
1540
|
.filter((line) => line.length > 0)
|
|
1541
1541
|
.join("\n");
|
|
@@ -1579,7 +1579,7 @@ export class InteractiveUi {
|
|
|
1579
1579
|
renderProgress() {
|
|
1580
1580
|
const flow = this.progressFlowDefinition();
|
|
1581
1581
|
if (!flow) {
|
|
1582
|
-
this.progress.setContent("
|
|
1582
|
+
this.progress.setContent("Select a flow in the tree to see its progress.");
|
|
1583
1583
|
return;
|
|
1584
1584
|
}
|
|
1585
1585
|
const flowState = this.flowState.flowId === flow.id
|
|
@@ -1932,7 +1932,7 @@ export class InteractiveUi {
|
|
|
1932
1932
|
flowId,
|
|
1933
1933
|
resumeAvailable: true,
|
|
1934
1934
|
hasExistingState: true,
|
|
1935
|
-
details: "
|
|
1935
|
+
details: "The current flow will be stopped. State will be saved and can be continued via Resume.",
|
|
1936
1936
|
selectedAction: "stop",
|
|
1937
1937
|
};
|
|
1938
1938
|
this.renderConfirm();
|
|
@@ -8,11 +8,13 @@ export const BUILT_IN_COMMAND_FLOW_IDS = [
|
|
|
8
8
|
"auto-common",
|
|
9
9
|
"bug-analyze",
|
|
10
10
|
"bug-fix",
|
|
11
|
+
"design-review",
|
|
11
12
|
"git-commit",
|
|
12
13
|
"gitlab-diff-review",
|
|
13
14
|
"gitlab-review",
|
|
14
15
|
"mr-description",
|
|
15
16
|
"plan",
|
|
17
|
+
"plan-revise",
|
|
16
18
|
"task-describe",
|
|
17
19
|
"implement",
|
|
18
20
|
"review",
|
|
@@ -26,11 +28,13 @@ const BUILT_IN_COMMAND_FLOW_FILES = {
|
|
|
26
28
|
"auto-common": "auto-common.json",
|
|
27
29
|
"bug-analyze": "bugz/bug-analyze.json",
|
|
28
30
|
"bug-fix": "bugz/bug-fix.json",
|
|
31
|
+
"design-review": "design-review.json",
|
|
29
32
|
"git-commit": "git-commit.json",
|
|
30
33
|
"gitlab-diff-review": "gitlab/gitlab-diff-review.json",
|
|
31
34
|
"gitlab-review": "gitlab/gitlab-review.json",
|
|
32
35
|
"mr-description": "gitlab/mr-description.json",
|
|
33
36
|
plan: "plan.json",
|
|
37
|
+
"plan-revise": "plan-revise.json",
|
|
34
38
|
"task-describe": "task-describe.json",
|
|
35
39
|
implement: "implement.json",
|
|
36
40
|
review: "review/review.json",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"kind": "auto-flow",
|
|
3
3
|
"version": 1,
|
|
4
|
+
"description": "End-to-end resumable pipeline without language-specific checks. Runs: plan (with Jira fetch and Q&A) → implement → review loop. Simplified alternative to auto-golang for projects that do not need Go linter/test loops.",
|
|
4
5
|
"phases": [
|
|
5
6
|
{
|
|
6
7
|
"id": "plan",
|
|
@@ -1,8 +1,9 @@
|
|
|
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: plan (with Jira fetch and Q&A) → 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
5
|
"constants": {
|
|
5
|
-
"autoReviewFixExtraPrompt": "
|
|
6
|
+
"autoReviewFixExtraPrompt": "Fix only blockers, criticals, and important findings"
|
|
6
7
|
},
|
|
7
8
|
"phases": [
|
|
8
9
|
{
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"kind": "bug-analyze-flow",
|
|
3
3
|
"version": 1,
|
|
4
|
+
"description": "Fetches a Bug-type Jira issue, validates the issue type, generates or reuses a cached task summary, and produces structured bug analysis: root cause hypothesis, fix design, and step-by-step fix plan.",
|
|
4
5
|
"phases": [
|
|
5
6
|
{
|
|
6
7
|
"id": "bug_analyze",
|