agentweaver 0.1.11 → 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/dist/artifacts.js CHANGED
@@ -134,6 +134,9 @@ export function readyToMergeFile(taskKey) {
134
134
  export function jiraTaskFile(taskKey) {
135
135
  return taskArtifactsFile(taskKey, `${taskKey}.json`);
136
136
  }
137
+ export function jiraTaskEnrichedFile(taskKey) {
138
+ return taskArtifactsFile(taskKey, `${taskKey}-enriched.json`);
139
+ }
137
140
  export function jiraAttachmentsDir(taskKey) {
138
141
  return path.join(taskArtifactsDir(taskKey), "jira-attachments");
139
142
  }
@@ -222,6 +225,12 @@ export function reviewFixFile(taskKey, iteration) {
222
225
  export function reviewFixJsonFile(taskKey, iteration) {
223
226
  return artifactJsonFile("review-fix", taskKey, iteration);
224
227
  }
228
+ export function reviewAssessmentFile(taskKey, iteration) {
229
+ return artifactFile("review-assessment", taskKey, iteration);
230
+ }
231
+ export function reviewAssessmentJsonFile(taskKey, iteration) {
232
+ return artifactJsonFile("review-assessment", taskKey, iteration);
233
+ }
225
234
  export function reviewFixSelectionJsonFile(taskKey, iteration) {
226
235
  return artifactJsonFile("review-fix-selection", taskKey, iteration);
227
236
  }
@@ -12,9 +12,10 @@ export const codexExecutor = {
12
12
  const command = input.command ?? context.runtime.resolveCmd(config.defaultCommand, config.commandEnvVar);
13
13
  const model = input.model?.trim() || resolveModel(config, env);
14
14
  const result = await processExecutor.execute(context, {
15
- argv: [command, config.subcommand, "--model", model, config.fullAutoFlag, input.prompt],
15
+ argv: [command, config.subcommand, "--model", model, config.fullAutoFlag, "-"],
16
16
  env,
17
17
  label: `codex:${model}`,
18
+ stdin: input.prompt,
18
19
  }, processExecutor.defaultConfig);
19
20
  return {
20
21
  output: result.output,
@@ -12,6 +12,7 @@ export const jiraFetchExecutor = {
12
12
  planningContextAttachments: artifacts.planningContextAttachments,
13
13
  ...(artifacts.attachmentsManifestFile ? { attachmentsManifestFile: artifacts.attachmentsManifestFile } : {}),
14
14
  ...(artifacts.attachmentsContextFile ? { attachmentsContextFile: artifacts.attachmentsContextFile } : {}),
15
+ ...(artifacts.enrichedFile ? { enrichedFile: artifacts.enrichedFile } : {}),
15
16
  };
16
17
  },
17
18
  };
@@ -1,3 +1,6 @@
1
+ import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
2
+ import os from "node:os";
3
+ import path from "node:path";
1
4
  import { opencodeExecutorDefaultConfig } from "./configs/opencode-config.js";
2
5
  import { processExecutor } from "./process-executor.js";
3
6
  function resolveModel(config, inputModel, env) {
@@ -17,19 +20,27 @@ export const opencodeExecutor = {
17
20
  const command = input.command ?? context.runtime.resolveCmd(config.defaultCommand, config.commandEnvVar);
18
21
  const model = resolveModel(config, input.model, env);
19
22
  const argv = [command, config.subcommand];
23
+ const tempDir = mkdtempSync(path.join(os.tmpdir(), "agentweaver-opencode-"));
24
+ const promptFile = path.join(tempDir, "prompt.md");
25
+ writeFileSync(promptFile, input.prompt, "utf8");
20
26
  if (model) {
21
27
  argv.push("--model", model);
22
28
  }
23
- argv.push(input.prompt);
24
- const result = await processExecutor.execute(context, {
25
- argv,
26
- env,
27
- label: model ? `opencode:${model}` : "opencode",
28
- }, processExecutor.defaultConfig);
29
- return {
30
- output: result.output,
31
- command,
32
- ...(model ? { model } : {}),
33
- };
29
+ argv.push("--file", promptFile, "--", "Use the attached file as the full task prompt. Follow it exactly.");
30
+ try {
31
+ const result = await processExecutor.execute(context, {
32
+ argv,
33
+ env,
34
+ label: model ? `opencode:${model}` : "opencode",
35
+ }, processExecutor.defaultConfig);
36
+ return {
37
+ output: result.output,
38
+ command,
39
+ ...(model ? { model } : {}),
40
+ };
41
+ }
42
+ finally {
43
+ rmSync(tempDir, { recursive: true, force: true });
44
+ }
34
45
  },
35
46
  };
@@ -15,6 +15,9 @@ export const processExecutor = {
15
15
  if (input.label) {
16
16
  options.label = input.label;
17
17
  }
18
+ if (input.stdin !== undefined) {
19
+ options.stdin = input.stdin;
20
+ }
18
21
  const output = await context.runtime.runCommand(input.argv, options);
19
22
  return { output };
20
23
  },
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ import { existsSync, readdirSync, 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 { REVIEW_FILE_RE, bugAnalyzeArtifacts, bugAnalyzeJsonFile, bugFixDesignJsonFile, bugFixPlanJsonFile, designJsonFile, gitlabDiffFile, gitlabDiffJsonFile, ensureScopeWorkspaceDir, gitlabReviewFile, gitlabReviewJsonFile, latestArtifactIteration, nextArtifactIteration, planJsonFile, planArtifacts, qaJsonFile, readyToMergeFile, requireArtifacts, reviewFile, reviewFixSelectionJsonFile, reviewJsonFile, scopeWorkspaceDir, flowStateFile, taskSummaryFile, } from "./artifacts.js";
6
+ import { REVIEW_FILE_RE, bugAnalyzeArtifacts, bugAnalyzeJsonFile, bugFixDesignJsonFile, bugFixPlanJsonFile, 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";
@@ -194,14 +194,11 @@ function launchProfileSelectionForm() {
194
194
  type: "single-select",
195
195
  label: "Executor",
196
196
  required: true,
197
- default: "default",
198
- options: [
199
- { value: "default", label: `default (${defaultExecutor})` },
200
- ...LLM_EXECUTOR_IDS.map((id) => ({
201
- value: id,
202
- label: id === defaultExecutor ? `${id} [default]` : id,
203
- })),
204
- ],
197
+ default: defaultExecutor,
198
+ options: LLM_EXECUTOR_IDS.map((id) => ({
199
+ value: id,
200
+ label: id === defaultExecutor ? `${id} [default]` : id,
201
+ })),
205
202
  },
206
203
  ],
207
204
  };
@@ -209,15 +206,10 @@ function launchProfileSelectionForm() {
209
206
  function launchModelSelectionForm(executor) {
210
207
  const resolvedExecutor = executor === "default" ? DEFAULT_LAUNCH_PROFILE.executor : executor;
211
208
  const defaultModel = defaultModelForExecutor(resolvedExecutor);
212
- const options = executor === "default"
213
- ? [{ value: "default", label: `default (${DEFAULT_LAUNCH_PROFILE.model})` }]
214
- : [
215
- { value: "default", label: `default (${defaultModel})` },
216
- ...ALLOWED_MODELS_BY_EXECUTOR[executor].map((model) => ({
217
- value: model,
218
- label: model === defaultModel ? `${model} [default]` : model,
219
- })),
220
- ];
209
+ const options = ALLOWED_MODELS_BY_EXECUTOR[resolvedExecutor].map((model) => ({
210
+ value: model,
211
+ label: model === defaultModel ? `${model} [default]` : model,
212
+ }));
221
213
  return {
222
214
  formId: "flow-launch-model",
223
215
  title: "Настройки запуска LLM",
@@ -229,25 +221,38 @@ function launchModelSelectionForm(executor) {
229
221
  type: "single-select",
230
222
  label: "Model",
231
223
  required: true,
232
- default: "default",
224
+ default: defaultModel,
233
225
  options,
234
226
  },
235
227
  ],
236
228
  };
237
229
  }
230
+ function isFormCancellation(error, formId) {
231
+ return error instanceof TaskRunnerError && error.message === `User cancelled form '${formId}'.`;
232
+ }
238
233
  async function requestInteractiveLaunchProfile(requestUserInput) {
239
- const executorFormResult = await requestUserInput(launchProfileSelectionForm());
240
- const rawExecutor = String(executorFormResult.values.executor ?? "default");
241
- const executor = rawExecutor === "default" ? "default" : LLM_EXECUTOR_IDS.find((id) => id === rawExecutor);
242
- if (!executor) {
243
- throw new TaskRunnerError(`Unsupported launch executor '${rawExecutor}'.`);
244
- }
245
- const modelFormResult = await requestUserInput(launchModelSelectionForm(executor));
246
- const rawModel = String(modelFormResult.values.model ?? "default").trim();
247
- return resolveLaunchProfile({
248
- executor,
249
- model: rawModel.length > 0 ? rawModel : "default",
250
- }, DEFAULT_LAUNCH_PROFILE);
234
+ for (;;) {
235
+ const executorFormResult = await requestUserInput(launchProfileSelectionForm());
236
+ const rawExecutor = String(executorFormResult.values.executor ?? DEFAULT_LAUNCH_PROFILE.executor);
237
+ const executor = LLM_EXECUTOR_IDS.find((id) => id === rawExecutor);
238
+ if (!executor) {
239
+ throw new TaskRunnerError(`Unsupported launch executor '${rawExecutor}'.`);
240
+ }
241
+ try {
242
+ const modelFormResult = await requestUserInput(launchModelSelectionForm(executor));
243
+ const rawModel = String(modelFormResult.values.model ?? defaultModelForExecutor(executor)).trim();
244
+ return resolveLaunchProfile({
245
+ executor,
246
+ model: rawModel.length > 0 ? rawModel : defaultModelForExecutor(executor),
247
+ }, DEFAULT_LAUNCH_PROFILE);
248
+ }
249
+ catch (error) {
250
+ if (isFormCancellation(error, "flow-launch-model")) {
251
+ continue;
252
+ }
253
+ throw error;
254
+ }
255
+ }
251
256
  }
252
257
  function buildResolverContext(pipelineContext, flowParams, flowConstants, repeatVars, executionState) {
253
258
  return {
@@ -521,13 +526,13 @@ const FLOW_DESCRIPTIONS = {
521
526
  "bug-analyze": "Analyzes bug from Jira and creates structured artifacts: root cause hypothesis, fix design, and implementation plan.",
522
527
  "git-commit": "Collects git status/diff, generates commit message via LLM, allows file selection and commit confirmation.",
523
528
  "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.",
524
- "gitlab-review": "Requests GitLab MR URL via user-input, downloads code review comments via API, and saves markdown plus structured JSON artifact.",
529
+ "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.",
525
530
  "bug-fix": "Takes bug-analyze results as source of truth and implements the bug fix in code.",
526
531
  "mr-description": "Prepares a brief intent description for a merge request based on the task and current changes.",
527
532
  plan: "Loads task from Jira and creates design, implementation plan, and QA plan in structured JSON and markdown.",
528
533
  "task-describe": "Builds a brief task description either from Jira or from quick user-input without Jira.",
529
534
  implement: "Implements the task from approved design/plan artifacts and runs post-verify builds if needed.",
530
- review: "Runs code review of current changes, validates structured findings, then prepares a reply to comments.",
535
+ review: "Runs code review of current changes and writes structured findings artifacts.",
531
536
  "review-fix": "Fixes issues after review-reply, updates code, and runs mandatory checks after modifications.",
532
537
  "review-loop": "Iteratively runs review and review-fix cycles up to 5 times until ready-to-merge is achieved.",
533
538
  "run-go-tests-loop": "Cycles through `./run_go_tests.py` locally, analyzes the last error, and fixes code until successful or attempts exhausted.",
@@ -880,9 +885,11 @@ async function executeCommand(baseConfig, runFollowupVerify = true, requestUserI
880
885
  iteration,
881
886
  gitlabReviewIteration,
882
887
  extraPrompt: config.extraPrompt,
888
+ reviewFixSelectionJsonFile: reviewFixSelectionJsonFile(config.taskKey, iteration),
889
+ reviewFixPoints: config.reviewFixPoints,
883
890
  }, launchProfile ? { launchProfile } : {}, requestUserInput, undefined, launchMode, runtime);
884
891
  if (!config.dryRun) {
885
- printSummary("GitLab Review", `Artifacts:\n${gitlabReviewFile(config.taskKey)}\n${gitlabReviewJsonFile(config.taskKey)}`);
892
+ printSummary("GitLab Review", `Artifacts:\n${gitlabReviewFile(config.taskKey)}\n${gitlabReviewJsonFile(config.taskKey)}\n${reviewFile(config.taskKey, iteration)}\n${reviewJsonFile(config.taskKey, iteration)}\n${reviewAssessmentFile(config.taskKey, iteration)}\n${reviewAssessmentJsonFile(config.taskKey, iteration)}`);
886
893
  }
887
894
  return false;
888
895
  }
@@ -982,6 +989,7 @@ async function executeCommand(baseConfig, runFollowupVerify = true, requestUserI
982
989
  await runDeclarativeFlowBySpecFile("review/review-fix.json", config, {
983
990
  taskKey: config.taskKey,
984
991
  latestIteration,
992
+ reviewAssessmentJsonFile: null,
985
993
  reviewFixSelectionJsonFile: reviewFixSelectionJsonFile(config.taskKey, latestIteration),
986
994
  extraPrompt: config.extraPrompt,
987
995
  reviewFixPoints: config.reviewFixPoints,