agentweaver 0.1.9 → 0.1.11

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 (101) hide show
  1. package/README.md +226 -200
  2. package/dist/artifacts.js +101 -56
  3. package/dist/errors.js +7 -0
  4. package/dist/executors/{codex-local-executor.js → codex-executor.js} +4 -4
  5. package/dist/executors/configs/{codex-local-config.js → codex-config.js} +1 -1
  6. package/dist/executors/configs/jira-fetch-config.js +2 -0
  7. package/dist/executors/configs/telegram-notifier-config.js +3 -0
  8. package/dist/executors/fetch-gitlab-diff-executor.js +1 -1
  9. package/dist/executors/fetch-gitlab-review-executor.js +1 -1
  10. package/dist/executors/git-commit-executor.js +25 -0
  11. package/dist/executors/telegram-notifier-executor.js +54 -0
  12. package/dist/flow-state.js +46 -1
  13. package/dist/gitlab.js +13 -8
  14. package/dist/index.js +507 -520
  15. package/dist/interactive-ui.js +495 -87
  16. package/dist/jira.js +52 -5
  17. package/dist/pipeline/auto-flow.js +6 -6
  18. package/dist/pipeline/context.js +1 -0
  19. package/dist/pipeline/declarative-flows.js +7 -4
  20. package/dist/pipeline/flow-catalog.js +60 -23
  21. package/dist/pipeline/flow-model-settings.js +77 -0
  22. package/dist/pipeline/flow-specs/auto-common.json +446 -0
  23. package/dist/pipeline/flow-specs/auto-golang.json +563 -0
  24. package/dist/pipeline/flow-specs/{bug-analyze.json → bugz/bug-analyze.json} +43 -25
  25. package/dist/pipeline/flow-specs/{bug-fix.json → bugz/bug-fix.json} +5 -4
  26. package/dist/pipeline/flow-specs/git-commit.json +196 -0
  27. package/dist/pipeline/flow-specs/{gitlab-diff-review.json → gitlab/gitlab-diff-review.json} +20 -50
  28. package/dist/pipeline/flow-specs/gitlab/gitlab-review.json +165 -0
  29. package/dist/pipeline/flow-specs/{mr-description.json → gitlab/mr-description.json} +17 -10
  30. package/dist/pipeline/flow-specs/{run-go-linter-loop.json → go/run-go-linter-loop.json} +40 -14
  31. package/dist/pipeline/flow-specs/{run-go-tests-loop.json → go/run-go-tests-loop.json} +40 -14
  32. package/dist/pipeline/flow-specs/implement.json +5 -4
  33. package/dist/pipeline/flow-specs/plan.json +40 -148
  34. package/dist/pipeline/flow-specs/{review-fix.json → review/review-fix.json} +73 -13
  35. package/dist/pipeline/flow-specs/review/review-loop.json +280 -0
  36. package/dist/pipeline/flow-specs/review/review-project.json +87 -0
  37. package/dist/pipeline/flow-specs/review/review.json +126 -0
  38. package/dist/pipeline/flow-specs/task-describe.json +191 -11
  39. package/dist/pipeline/launch-profile-config.js +38 -0
  40. package/dist/pipeline/node-registry.js +75 -45
  41. package/dist/pipeline/nodes/build-failure-summary-node.js +16 -29
  42. package/dist/pipeline/nodes/build-review-fix-prompt-node.js +36 -0
  43. package/dist/pipeline/nodes/codex-prompt-node.js +41 -0
  44. package/dist/pipeline/nodes/commit-message-form-node.js +79 -0
  45. package/dist/pipeline/nodes/git-commit-form-node.js +138 -0
  46. package/dist/pipeline/nodes/git-commit-node.js +28 -0
  47. package/dist/pipeline/nodes/git-status-node.js +221 -0
  48. package/dist/pipeline/nodes/gitlab-review-artifacts-node.js +10 -6
  49. package/dist/pipeline/nodes/jira-context-node.js +10 -0
  50. package/dist/pipeline/nodes/llm-prompt-node.js +62 -0
  51. package/dist/pipeline/nodes/plan-codex-node.js +1 -1
  52. package/dist/pipeline/nodes/read-file-node.js +11 -0
  53. package/dist/pipeline/nodes/review-findings-form-node.js +18 -14
  54. package/dist/pipeline/nodes/select-files-form-node.js +72 -0
  55. package/dist/pipeline/nodes/telegram-notifier-node.js +28 -0
  56. package/dist/pipeline/nodes/user-input-node.js +29 -8
  57. package/dist/pipeline/nodes/write-selection-file-node.js +46 -0
  58. package/dist/pipeline/prompt-registry.js +2 -4
  59. package/dist/pipeline/prompt-runtime.js +13 -3
  60. package/dist/pipeline/registry.js +6 -8
  61. package/dist/pipeline/spec-compiler.js +5 -0
  62. package/dist/pipeline/spec-loader.js +18 -7
  63. package/dist/pipeline/spec-types.js +7 -3
  64. package/dist/pipeline/spec-validator.js +4 -0
  65. package/dist/pipeline/types.js +1 -0
  66. package/dist/pipeline/value-resolver.js +40 -38
  67. package/dist/prompts.js +104 -110
  68. package/dist/runtime/agentweaver-home.js +8 -0
  69. package/dist/runtime/command-resolution.js +0 -38
  70. package/dist/runtime/env-loader.js +43 -0
  71. package/dist/runtime/process-runner.js +45 -1
  72. package/dist/structured-artifact-schema-registry.js +53 -0
  73. package/dist/structured-artifact-schemas.json +0 -20
  74. package/dist/structured-artifacts.js +3 -43
  75. package/dist/user-input.js +30 -2
  76. package/package.json +2 -6
  77. package/Dockerfile.codex +0 -56
  78. package/dist/executors/claude-executor.js +0 -46
  79. package/dist/executors/codex-docker-executor.js +0 -27
  80. package/dist/executors/configs/claude-config.js +0 -12
  81. package/dist/executors/configs/codex-docker-config.js +0 -10
  82. package/dist/executors/configs/verify-build-config.js +0 -7
  83. package/dist/executors/verify-build-executor.js +0 -123
  84. package/dist/pipeline/flow-specs/auto.json +0 -979
  85. package/dist/pipeline/flow-specs/gitlab-review.json +0 -317
  86. package/dist/pipeline/flow-specs/plan-opencode.json +0 -603
  87. package/dist/pipeline/flow-specs/preflight.json +0 -206
  88. package/dist/pipeline/flow-specs/review-project.json +0 -243
  89. package/dist/pipeline/flow-specs/review.json +0 -312
  90. package/dist/pipeline/flow-specs/run-linter-loop.json +0 -155
  91. package/dist/pipeline/flow-specs/run-tests-loop.json +0 -155
  92. package/dist/pipeline/flows/preflight-flow.js +0 -19
  93. package/dist/pipeline/nodes/claude-prompt-node.js +0 -54
  94. package/dist/pipeline/nodes/codex-docker-prompt-node.js +0 -32
  95. package/dist/pipeline/nodes/codex-local-prompt-node.js +0 -32
  96. package/dist/pipeline/nodes/review-claude-node.js +0 -38
  97. package/dist/pipeline/nodes/review-reply-codex-node.js +0 -40
  98. package/dist/pipeline/nodes/verify-build-node.js +0 -15
  99. package/dist/runtime/docker-runtime.js +0 -51
  100. package/docker-compose.yml +0 -445
  101. package/verify_build.sh +0 -105
package/dist/jira.js CHANGED
@@ -5,6 +5,57 @@ import { TaskRunnerError } from "./errors.js";
5
5
  const ISSUE_KEY_RE = /^[A-Z][A-Z0-9_]*-[0-9]+$/;
6
6
  const TEXT_ATTACHMENT_EXTENSIONS = new Set([".md", ".json", ".txt"]);
7
7
  const DOWNLOAD_ONLY_ATTACHMENT_EXTENSIONS = new Set([".doc"]);
8
+ const JIRA_AUTH_MODES = new Set(["auto", "basic", "bearer"]);
9
+ function parseJiraAuthMode(rawMode) {
10
+ const mode = rawMode?.trim().toLowerCase() || "auto";
11
+ if (!JIRA_AUTH_MODES.has(mode)) {
12
+ throw new TaskRunnerError("JIRA_AUTH_MODE must be one of: auto, basic, bearer.");
13
+ }
14
+ return mode;
15
+ }
16
+ export function detectJiraDeployment(url) {
17
+ try {
18
+ return new URL(url).hostname.toLowerCase().includes("atlassian") ? "cloud" : "server";
19
+ }
20
+ catch {
21
+ return url.toLowerCase().includes("atlassian") ? "cloud" : "server";
22
+ }
23
+ }
24
+ export function resolveJiraAuthMode(url) {
25
+ const authMode = parseJiraAuthMode(process.env.JIRA_AUTH_MODE);
26
+ if (authMode !== "auto") {
27
+ return authMode;
28
+ }
29
+ return detectJiraDeployment(url) === "cloud" ? "basic" : "bearer";
30
+ }
31
+ export function buildJiraAuthHeaders(url) {
32
+ const jiraApiKey = process.env.JIRA_API_KEY?.trim();
33
+ if (!jiraApiKey) {
34
+ throw new TaskRunnerError("JIRA_API_KEY is required for Jira authentication.");
35
+ }
36
+ const authMode = resolveJiraAuthMode(url);
37
+ if (authMode === "bearer") {
38
+ return {
39
+ Authorization: `Bearer ${jiraApiKey}`,
40
+ };
41
+ }
42
+ const jiraUsername = process.env.JIRA_USERNAME?.trim();
43
+ if (!jiraUsername) {
44
+ const host = (() => {
45
+ try {
46
+ return new URL(url).host;
47
+ }
48
+ catch {
49
+ return "unknown";
50
+ }
51
+ })();
52
+ throw new TaskRunnerError(`JIRA_USERNAME is required for Jira Cloud Basic auth (detected from URL host: ${host}).`);
53
+ }
54
+ const encodedCredentials = Buffer.from(`${jiraUsername}:${jiraApiKey}`).toString("base64");
55
+ return {
56
+ Authorization: `Basic ${encodedCredentials}`,
57
+ };
58
+ }
8
59
  function sanitizeAttachmentFileName(fileName) {
9
60
  const parsed = path.parse(fileName);
10
61
  const baseName = parsed.name
@@ -29,13 +80,9 @@ function parseJiraAttachments(issueBody) {
29
80
  }
30
81
  }
31
82
  async function fetchAuthorizedBuffer(url, accept) {
32
- const jiraApiKey = process.env.JIRA_API_KEY;
33
- if (!jiraApiKey) {
34
- throw new TaskRunnerError("JIRA_API_KEY is required for Jira fetch.");
35
- }
36
83
  const response = await fetch(url, {
37
84
  headers: {
38
- Authorization: `Bearer ${jiraApiKey}`,
85
+ ...buildJiraAuthHeaders(url),
39
86
  Accept: accept,
40
87
  },
41
88
  });
@@ -1,9 +1,9 @@
1
1
  import { loadDeclarativeFlow } from "./declarative-flows.js";
2
- let cachedAutoFlow = null;
3
- export function loadAutoFlow() {
4
- if (cachedAutoFlow) {
5
- return cachedAutoFlow;
2
+ let cachedAutoGolangFlow = null;
3
+ export function loadAutoGolangFlow() {
4
+ if (cachedAutoGolangFlow) {
5
+ return cachedAutoGolangFlow;
6
6
  }
7
- cachedAutoFlow = loadDeclarativeFlow({ source: "built-in", fileName: "auto.json" });
8
- return cachedAutoFlow;
7
+ cachedAutoGolangFlow = loadDeclarativeFlow({ source: "built-in", fileName: "auto-golang.json" });
8
+ return cachedAutoGolangFlow;
9
9
  }
@@ -11,6 +11,7 @@ export function createPipelineContext(input) {
11
11
  ui: getOutputAdapter(),
12
12
  dryRun: input.dryRun,
13
13
  verbose: input.verbose,
14
+ mdLang: input.mdLang ?? null,
14
15
  runtime: input.runtime,
15
16
  executors: createExecutorRegistry(),
16
17
  nodes: createNodeRegistry(),
@@ -39,18 +39,21 @@ export function loadDeclarativeFlow(flow) {
39
39
  }
40
40
  export function resolveNamedDeclarativeFlowRef(fileName, cwd) {
41
41
  const projectMatches = listProjectFlowSpecFiles(cwd).filter((candidate) => path.basename(candidate) === fileName);
42
- const builtInExists = listBuiltInFlowSpecFiles().includes(fileName);
43
- if (projectMatches.length > 0 && builtInExists) {
42
+ const builtInMatches = listBuiltInFlowSpecFiles().filter((candidate) => path.basename(candidate) === fileName);
43
+ if (projectMatches.length > 0 && builtInMatches.length > 0) {
44
44
  throw new Error(`Ambiguous nested flow '${fileName}': both built-in and project-local specs exist in ${projectFlowSpecsDir(cwd)}.`);
45
45
  }
46
46
  if (projectMatches.length > 1) {
47
47
  throw new Error(`Ambiguous project-local flow '${fileName}' in ${projectFlowSpecsDir(cwd)}.`);
48
48
  }
49
+ if (builtInMatches.length > 1) {
50
+ throw new Error(`Ambiguous built-in flow '${fileName}'. Use unique nested flow file names.`);
51
+ }
49
52
  if (projectMatches[0]) {
50
53
  return { source: "project-local", filePath: projectMatches[0] };
51
54
  }
52
- if (builtInExists) {
53
- return { source: "built-in", fileName };
55
+ if (builtInMatches[0]) {
56
+ return { source: "built-in", fileName: builtInMatches[0] };
54
57
  }
55
58
  throw new Error(`Nested flow '${fileName}' was not found.`);
56
59
  }
@@ -1,47 +1,84 @@
1
1
  import path from "node:path";
2
2
  import { TaskRunnerError } from "../errors.js";
3
- import { loadAutoFlow } from "./auto-flow.js";
3
+ import { loadAutoGolangFlow } from "./auto-flow.js";
4
4
  import { loadDeclarativeFlow } from "./declarative-flows.js";
5
- import { listProjectFlowSpecFiles } from "./spec-loader.js";
6
- export const INTERACTIVE_BUILT_IN_FLOWS = [
7
- { id: "auto", fileName: "auto.json" },
8
- { id: "bug-analyze", fileName: "bug-analyze.json" },
9
- { id: "bug-fix", fileName: "bug-fix.json" },
10
- { id: "gitlab-diff-review", fileName: "gitlab-diff-review.json" },
11
- { id: "gitlab-review", fileName: "gitlab-review.json" },
12
- { id: "mr-description", fileName: "mr-description.json" },
13
- { id: "plan", fileName: "plan.json" },
14
- { id: "task-describe", fileName: "task-describe.json" },
15
- { id: "implement", fileName: "implement.json" },
16
- { id: "review", fileName: "review.json" },
17
- { id: "review-fix", fileName: "review-fix.json" },
18
- { id: "run-go-tests-loop", fileName: "run-go-tests-loop.json" },
19
- { id: "run-go-linter-loop", fileName: "run-go-linter-loop.json" },
5
+ import { listBuiltInFlowSpecFiles, listProjectFlowSpecFiles, projectFlowSpecsDir } from "./spec-loader.js";
6
+ export const BUILT_IN_COMMAND_FLOW_IDS = [
7
+ "auto-golang",
8
+ "auto-common",
9
+ "bug-analyze",
10
+ "bug-fix",
11
+ "git-commit",
12
+ "gitlab-diff-review",
13
+ "gitlab-review",
14
+ "mr-description",
15
+ "plan",
16
+ "task-describe",
17
+ "implement",
18
+ "review",
19
+ "review-fix",
20
+ "review-loop",
21
+ "run-go-tests-loop",
22
+ "run-go-linter-loop",
20
23
  ];
21
- function loadBuiltInCatalogEntry(id, fileName) {
22
- const flow = id === "auto" ? loadAutoFlow() : loadDeclarativeFlow({ source: "built-in", fileName });
24
+ const BUILT_IN_COMMAND_FLOW_FILES = {
25
+ "auto-golang": "auto-golang.json",
26
+ "auto-common": "auto-common.json",
27
+ "bug-analyze": "bugz/bug-analyze.json",
28
+ "bug-fix": "bugz/bug-fix.json",
29
+ "git-commit": "git-commit.json",
30
+ "gitlab-diff-review": "gitlab/gitlab-diff-review.json",
31
+ "gitlab-review": "gitlab/gitlab-review.json",
32
+ "mr-description": "gitlab/mr-description.json",
33
+ plan: "plan.json",
34
+ "task-describe": "task-describe.json",
35
+ implement: "implement.json",
36
+ review: "review/review.json",
37
+ "review-fix": "review/review-fix.json",
38
+ "review-loop": "review/review-loop.json",
39
+ "run-go-tests-loop": "go/run-go-tests-loop.json",
40
+ "run-go-linter-loop": "go/run-go-linter-loop.json",
41
+ };
42
+ function builtInCommandIdForFile(fileName) {
43
+ for (const [flowId, candidate] of Object.entries(BUILT_IN_COMMAND_FLOW_FILES)) {
44
+ if (candidate === fileName) {
45
+ return flowId;
46
+ }
47
+ }
48
+ return null;
49
+ }
50
+ function loadBuiltInCatalogEntry(fileName) {
51
+ const commandId = builtInCommandIdForFile(fileName);
52
+ const relativePath = fileName.replace(/\.json$/i, "").split(/[\\/]+/).filter((segment) => segment.length > 0);
53
+ const id = commandId ?? relativePath.join("/");
54
+ const flow = id === "auto-golang" ? loadAutoGolangFlow() : loadDeclarativeFlow({ source: "built-in", fileName });
23
55
  return {
24
56
  id,
25
57
  source: "built-in",
26
58
  fileName,
27
59
  absolutePath: flow.absolutePath,
60
+ treePath: ["default", ...relativePath],
28
61
  flow,
29
62
  };
30
63
  }
31
- function loadProjectCatalogEntry(filePath) {
64
+ function loadProjectCatalogEntry(cwd, filePath) {
32
65
  const flow = loadDeclarativeFlow({ source: "project-local", filePath });
66
+ const relativeFilePath = path.relative(projectFlowSpecsDir(cwd), path.resolve(filePath));
67
+ const relativePathWithoutExt = relativeFilePath.replace(/\.json$/i, "");
68
+ const relativeSegments = relativePathWithoutExt.split(path.sep).filter((segment) => segment.length > 0);
33
69
  return {
34
- id: path.basename(filePath, path.extname(filePath)),
70
+ id: relativeSegments.join("/"),
35
71
  source: "project-local",
36
72
  fileName: path.basename(filePath),
37
73
  absolutePath: path.resolve(filePath),
74
+ treePath: ["custom", ...relativeSegments],
38
75
  flow,
39
76
  };
40
77
  }
41
78
  export function loadInteractiveFlowCatalog(cwd) {
42
- const entries = INTERACTIVE_BUILT_IN_FLOWS.map((entry) => loadBuiltInCatalogEntry(entry.id, entry.fileName));
79
+ const entries = listBuiltInFlowSpecFiles().map((fileName) => loadBuiltInCatalogEntry(fileName));
43
80
  for (const filePath of listProjectFlowSpecFiles(cwd)) {
44
- entries.push(loadProjectCatalogEntry(filePath));
81
+ entries.push(loadProjectCatalogEntry(cwd, filePath));
45
82
  }
46
83
  const byId = new Map();
47
84
  for (const entry of entries) {
@@ -57,7 +94,7 @@ export function findCatalogEntry(flowId, entries) {
57
94
  return entries.find((entry) => entry.id === flowId);
58
95
  }
59
96
  export function isBuiltInCommandFlowId(flowId) {
60
- return INTERACTIVE_BUILT_IN_FLOWS.some((entry) => entry.id === flowId);
97
+ return BUILT_IN_COMMAND_FLOW_IDS.includes(flowId);
61
98
  }
62
99
  export function toDeclarativeFlowRef(entry) {
63
100
  return entry.source === "built-in"
@@ -0,0 +1,77 @@
1
+ import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
2
+ import path from "node:path";
3
+ import { DEFAULT_MODEL_BY_EXECUTOR, defaultModelForExecutor } from "./launch-profile-config.js";
4
+ import { scopeArtifactsDir } from "../artifacts.js";
5
+ const FLOW_MODEL_SETTINGS_FILE = "agentweaver-flow-model-settings.json";
6
+ function flowModelSettingsPath(scopeKey) {
7
+ return path.join(scopeArtifactsDir(scopeKey), FLOW_MODEL_SETTINGS_FILE);
8
+ }
9
+ function ensureArtifactsDir(scopeKey) {
10
+ const artifactsDir = scopeArtifactsDir(scopeKey);
11
+ if (!existsSync(artifactsDir)) {
12
+ mkdirSync(artifactsDir, { recursive: true });
13
+ }
14
+ }
15
+ export function loadFlowModelSettings(scopeKey) {
16
+ const filePath = flowModelSettingsPath(scopeKey);
17
+ if (!existsSync(filePath)) {
18
+ return {};
19
+ }
20
+ try {
21
+ const content = readFileSync(filePath, "utf8");
22
+ const parsed = JSON.parse(content);
23
+ if (typeof parsed !== "object" || parsed === null) {
24
+ return {};
25
+ }
26
+ return parsed;
27
+ }
28
+ catch {
29
+ return {};
30
+ }
31
+ }
32
+ export function saveFlowModelSettings(scopeKey, store) {
33
+ ensureArtifactsDir(scopeKey);
34
+ const filePath = flowModelSettingsPath(scopeKey);
35
+ const tempPath = `${filePath}.tmp`;
36
+ const content = JSON.stringify(store, null, 2);
37
+ writeFileSync(tempPath, content, "utf8");
38
+ renameSync(tempPath, filePath);
39
+ }
40
+ export function getEffectiveModelForFlow(flowId, scopeKey, executor) {
41
+ const store = loadFlowModelSettings(scopeKey);
42
+ const flowSettings = store[flowId];
43
+ if (!flowSettings) {
44
+ return defaultModelForExecutor(executor);
45
+ }
46
+ if (flowSettings.lastSelectedModel && flowSettings.lastSelectedModel !== "default") {
47
+ return flowSettings.lastSelectedModel;
48
+ }
49
+ if (flowSettings.defaultModel && flowSettings.defaultModel !== "default") {
50
+ return flowSettings.defaultModel;
51
+ }
52
+ return defaultModelForExecutor(executor);
53
+ }
54
+ export function updateLastSelectedModel(flowId, scopeKey, executor, model) {
55
+ const store = loadFlowModelSettings(scopeKey);
56
+ const existingSettings = store[flowId];
57
+ if (existingSettings) {
58
+ store[flowId] = {
59
+ ...existingSettings,
60
+ executor,
61
+ defaultModel: model,
62
+ lastSelectedModel: model,
63
+ };
64
+ }
65
+ else {
66
+ store[flowId] = {
67
+ executor,
68
+ defaultModel: DEFAULT_MODEL_BY_EXECUTOR[executor],
69
+ lastSelectedModel: model,
70
+ };
71
+ }
72
+ saveFlowModelSettings(scopeKey, store);
73
+ }
74
+ export function getFlowModelSettings(flowId, scopeKey) {
75
+ const store = loadFlowModelSettings(scopeKey);
76
+ return store[flowId] ?? null;
77
+ }