agentweaver 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +24 -0
  2. package/dist/executors/claude-executor.js +36 -0
  3. package/dist/executors/claude-summary-executor.js +31 -0
  4. package/dist/executors/codex-docker-executor.js +27 -0
  5. package/dist/executors/codex-local-executor.js +25 -0
  6. package/dist/executors/command-check-executor.js +14 -0
  7. package/dist/executors/configs/claude-config.js +11 -0
  8. package/dist/executors/configs/claude-summary-config.js +8 -0
  9. package/dist/executors/configs/codex-docker-config.js +10 -0
  10. package/dist/executors/configs/codex-local-config.js +8 -0
  11. package/dist/executors/configs/jira-fetch-config.js +4 -0
  12. package/dist/executors/configs/process-config.js +3 -0
  13. package/dist/executors/configs/verify-build-config.js +7 -0
  14. package/dist/executors/jira-fetch-executor.js +11 -0
  15. package/dist/executors/process-executor.js +21 -0
  16. package/dist/executors/types.js +1 -0
  17. package/dist/executors/verify-build-executor.js +22 -0
  18. package/dist/index.js +270 -450
  19. package/dist/interactive-ui.js +109 -12
  20. package/dist/pipeline/build-failure-summary.js +6 -0
  21. package/dist/pipeline/checks.js +15 -0
  22. package/dist/pipeline/context.js +17 -0
  23. package/dist/pipeline/flow-runner.js +13 -0
  24. package/dist/pipeline/flow-types.js +1 -0
  25. package/dist/pipeline/flows/implement-flow.js +48 -0
  26. package/dist/pipeline/flows/plan-flow.js +42 -0
  27. package/dist/pipeline/flows/preflight-flow.js +59 -0
  28. package/dist/pipeline/flows/review-fix-flow.js +63 -0
  29. package/dist/pipeline/flows/review-flow.js +120 -0
  30. package/dist/pipeline/flows/test-fix-flow.js +13 -0
  31. package/dist/pipeline/flows/test-flow.js +32 -0
  32. package/dist/pipeline/node-runner.js +14 -0
  33. package/dist/pipeline/nodes/build-failure-summary-node.js +71 -0
  34. package/dist/pipeline/nodes/claude-summary-node.js +32 -0
  35. package/dist/pipeline/nodes/codex-docker-prompt-node.js +31 -0
  36. package/dist/pipeline/nodes/command-check-node.js +10 -0
  37. package/dist/pipeline/nodes/implement-codex-node.js +16 -0
  38. package/dist/pipeline/nodes/jira-fetch-node.js +25 -0
  39. package/dist/pipeline/nodes/plan-codex-node.js +32 -0
  40. package/dist/pipeline/nodes/review-claude-node.js +38 -0
  41. package/dist/pipeline/nodes/review-reply-codex-node.js +40 -0
  42. package/dist/pipeline/nodes/task-summary-node.js +36 -0
  43. package/dist/pipeline/nodes/verify-build-node.js +14 -0
  44. package/dist/pipeline/registry.js +25 -0
  45. package/dist/pipeline/types.js +10 -0
  46. package/dist/runtime/command-resolution.js +139 -0
  47. package/dist/runtime/docker-runtime.js +51 -0
  48. package/dist/runtime/process-runner.js +111 -0
  49. package/dist/tui.js +34 -0
  50. package/package.json +2 -1
@@ -0,0 +1,111 @@
1
+ import path from "node:path";
2
+ import process from "node:process";
3
+ import { spawn } from "node:child_process";
4
+ import { dim, formatDone, getOutputAdapter, setCurrentExecutor } from "../tui.js";
5
+ import { shellQuote } from "./command-resolution.js";
6
+ export function formatCommand(argv, env) {
7
+ const envParts = Object.entries(env ?? {})
8
+ .filter(([key, value]) => value !== undefined && process.env[key] !== value)
9
+ .map(([key, value]) => `${key}=${shellQuote(value ?? "")}`);
10
+ const command = argv.map(shellQuote).join(" ");
11
+ return envParts.length > 0 ? `${envParts.join(" ")} ${command}` : command;
12
+ }
13
+ export function formatDuration(ms) {
14
+ const totalSeconds = Math.max(0, Math.floor(ms / 1000));
15
+ const minutes = String(Math.floor(totalSeconds / 60)).padStart(2, "0");
16
+ const seconds = String(totalSeconds % 60).padStart(2, "0");
17
+ return `${minutes}:${seconds}`;
18
+ }
19
+ export async function runCommand(argv, options = {}) {
20
+ const { env, dryRun = false, verbose = false, label, printFailureOutput = true } = options;
21
+ const outputAdapter = getOutputAdapter();
22
+ if (dryRun) {
23
+ setCurrentExecutor(label ?? path.basename(argv[0] ?? argv.join(" ")));
24
+ outputAdapter.writeStdout(`${formatCommand(argv, env)}\n`);
25
+ setCurrentExecutor(null);
26
+ return "";
27
+ }
28
+ if (verbose && outputAdapter.supportsPassthrough) {
29
+ await new Promise((resolve, reject) => {
30
+ const child = spawn(argv[0] ?? "", argv.slice(1), {
31
+ stdio: "inherit",
32
+ env,
33
+ });
34
+ child.on("exit", (code) => (code === 0 ? resolve() : reject(new Error(String(code ?? 1)))));
35
+ child.on("error", reject);
36
+ }).catch((error) => {
37
+ const code = Number.parseInt(error.message, 10);
38
+ throw Object.assign(new Error(`Command failed with exit code ${Number.isNaN(code) ? 1 : code}`), {
39
+ returnCode: Number.isNaN(code) ? 1 : code,
40
+ output: "",
41
+ });
42
+ });
43
+ return "";
44
+ }
45
+ const startedAt = Date.now();
46
+ const statusLabel = label ?? path.basename(argv[0] ?? argv.join(" "));
47
+ const frames = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
48
+ let frameIndex = 0;
49
+ let output = "";
50
+ const child = spawn(argv[0] ?? "", argv.slice(1), {
51
+ env,
52
+ stdio: ["ignore", "pipe", "pipe"],
53
+ });
54
+ setCurrentExecutor(statusLabel);
55
+ child.stdout?.on("data", (chunk) => {
56
+ const text = String(chunk);
57
+ output += text;
58
+ if (!outputAdapter.supportsTransientStatus || verbose) {
59
+ outputAdapter.writeStdout(text);
60
+ }
61
+ });
62
+ child.stderr?.on("data", (chunk) => {
63
+ const text = String(chunk);
64
+ output += text;
65
+ if (!outputAdapter.supportsTransientStatus || verbose) {
66
+ outputAdapter.writeStderr(text);
67
+ }
68
+ });
69
+ if (!outputAdapter.supportsTransientStatus && outputAdapter.renderAuxiliaryOutput !== false) {
70
+ outputAdapter.writeStdout(`Running ${statusLabel}\n`);
71
+ }
72
+ const timer = outputAdapter.supportsTransientStatus
73
+ ? setInterval(() => {
74
+ const elapsed = formatDuration(Date.now() - startedAt);
75
+ process.stdout.write(`\r${frames[frameIndex]} ${statusLabel} ${dim(elapsed)}`);
76
+ frameIndex = (frameIndex + 1) % frames.length;
77
+ }, 200)
78
+ : null;
79
+ try {
80
+ const exitCode = await new Promise((resolve, reject) => {
81
+ child.on("error", reject);
82
+ child.on("exit", (code) => resolve(code ?? 1));
83
+ });
84
+ if (timer) {
85
+ clearInterval(timer);
86
+ process.stdout.write(`\r${" ".repeat(80)}\r${formatDone(formatDuration(Date.now() - startedAt))}\n`);
87
+ }
88
+ else if (outputAdapter.renderAuxiliaryOutput !== false) {
89
+ outputAdapter.writeStdout(`Done ${formatDuration(Date.now() - startedAt)}\n`);
90
+ }
91
+ if (exitCode !== 0) {
92
+ if (output && printFailureOutput && outputAdapter.supportsTransientStatus) {
93
+ process.stderr.write(output);
94
+ if (!output.endsWith("\n")) {
95
+ process.stderr.write("\n");
96
+ }
97
+ }
98
+ throw Object.assign(new Error(`Command failed with exit code ${exitCode}`), {
99
+ returnCode: exitCode,
100
+ output,
101
+ });
102
+ }
103
+ return output;
104
+ }
105
+ finally {
106
+ setCurrentExecutor(null);
107
+ if (timer) {
108
+ clearInterval(timer);
109
+ }
110
+ }
111
+ }
package/dist/tui.js CHANGED
@@ -17,8 +17,13 @@ const defaultAdapter = {
17
17
  },
18
18
  supportsTransientStatus: true,
19
19
  supportsPassthrough: true,
20
+ renderAuxiliaryOutput: true,
20
21
  };
21
22
  let outputAdapter = defaultAdapter;
23
+ let executionState = {
24
+ node: null,
25
+ executor: null,
26
+ };
22
27
  function color(text, ansi) {
23
28
  return `${ansi}${text}${RESET}`;
24
29
  }
@@ -30,6 +35,7 @@ function visibleLength(text) {
30
35
  }
31
36
  export function setOutputAdapter(adapter) {
32
37
  outputAdapter = adapter ?? defaultAdapter;
38
+ outputAdapter.setExecutionState?.(executionState);
33
39
  }
34
40
  export function getOutputAdapter() {
35
41
  return outputAdapter;
@@ -51,18 +57,30 @@ export function renderPanel(title, body, borderColor) {
51
57
  return `${color(top, borderColor)}\n${color(`│ ${title.padEnd(width)} │`, borderColor)}\n${color(`├${"─".repeat(width + 2)}┤`, borderColor)}\n${middle}\n${color(bottom, borderColor)}`;
52
58
  }
53
59
  export function printInfo(message) {
60
+ if (outputAdapter.renderAuxiliaryOutput === false) {
61
+ return;
62
+ }
54
63
  outputAdapter.writeStdout(`${color(message, `${BOLD}${CYAN}`)}\n`);
55
64
  }
56
65
  export function printError(message) {
57
66
  outputAdapter.writeStderr(`${color(message, `${BOLD}${RED}`)}\n`);
58
67
  }
59
68
  export function printPrompt(toolName, prompt) {
69
+ if (outputAdapter.renderAuxiliaryOutput === false) {
70
+ return;
71
+ }
60
72
  outputAdapter.writeStdout(`${renderPanel(`${toolName} Prompt`, prompt, BLUE)}\n`);
61
73
  }
62
74
  export function printSummary(title, text) {
75
+ if (outputAdapter.renderAuxiliaryOutput === false) {
76
+ return;
77
+ }
63
78
  outputAdapter.writeStdout(`${renderPanel(title, text.trim() || "Empty summary", YELLOW)}\n`);
64
79
  }
65
80
  export function printPanel(title, text, tone) {
81
+ if (outputAdapter.renderAuxiliaryOutput === false) {
82
+ return;
83
+ }
66
84
  const borderColor = tone === "green" ? GREEN : tone === "yellow" ? YELLOW : tone === "magenta" ? MAGENTA : CYAN;
67
85
  outputAdapter.writeStdout(`${renderPanel(title, text, borderColor)}\n`);
68
86
  }
@@ -78,3 +96,19 @@ export function bold(text) {
78
96
  export function bye() {
79
97
  outputAdapter.writeStdout(`${color("Bye", CYAN)}\n`);
80
98
  }
99
+ function updateExecutionState(next) {
100
+ executionState = next;
101
+ outputAdapter.setExecutionState?.(executionState);
102
+ }
103
+ export function setCurrentNode(node) {
104
+ updateExecutionState({
105
+ ...executionState,
106
+ node,
107
+ });
108
+ }
109
+ export function setCurrentExecutor(executor) {
110
+ updateExecutionState({
111
+ ...executionState,
112
+ executor,
113
+ });
114
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentweaver",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "CLI orchestrator for Jira/Codex/Claude engineering workflows",
5
5
  "keywords": [
6
6
  "agent",
@@ -52,6 +52,7 @@
52
52
  "typescript": "^5.8.3"
53
53
  },
54
54
  "dependencies": {
55
+ "agentweaver": "^0.1.0",
55
56
  "markdown-it": "^14.1.1",
56
57
  "neo-blessed": "^0.2.0"
57
58
  }