@moxxy/cli 0.0.7 → 0.0.9

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/index.js CHANGED
@@ -1045,15 +1045,45 @@ var init_stream_parser = __esm({
1045
1045
  }
1046
1046
  try {
1047
1047
  return JSON.parse(line);
1048
- } catch (error2) {
1048
+ } catch {
1049
1049
  return null;
1050
1050
  }
1051
1051
  }
1052
1052
  /**
1053
1053
  * Convert stream event to chat stream chunk
1054
+ * Handles both CLI format and API format events
1054
1055
  */
1055
1056
  toChunk(event) {
1056
1057
  switch (event.type) {
1058
+ // --- Claude CLI format events ---
1059
+ case "assistant": {
1060
+ const message = event.message;
1061
+ if (!message?.content) return null;
1062
+ const textBlocks = message.content.filter((b) => b.type === "text");
1063
+ const text = textBlocks.map((b) => b.text || "").join("");
1064
+ const thinkingBlocks = message.content.filter((b) => b.type === "thinking");
1065
+ const thinking = thinkingBlocks.length > 0 ? thinkingBlocks.map((b) => b.thinking || b.text || "").join("") : void 0;
1066
+ if (!text && !thinking) return null;
1067
+ return {
1068
+ content: text,
1069
+ thinking,
1070
+ done: false,
1071
+ sessionKey: this.sessionKey,
1072
+ timestamp: Date.now()
1073
+ };
1074
+ }
1075
+ case "result": {
1076
+ const resultText = event.result || "";
1077
+ return {
1078
+ content: resultText,
1079
+ done: true,
1080
+ sessionKey: this.sessionKey,
1081
+ timestamp: Date.now()
1082
+ };
1083
+ }
1084
+ case "system":
1085
+ return null;
1086
+ // --- Anthropic API format events (legacy/fallback) ---
1057
1087
  case "content_block_delta": {
1058
1088
  const text = event.delta?.text || "";
1059
1089
  return {
@@ -1179,23 +1209,24 @@ var init_chat = __esm({
1179
1209
  });
1180
1210
  this.events.emit("chat:stream:start", sessionKey, agentId);
1181
1211
  options.onStart?.(sessionKey, agentId);
1182
- let proc = processManager.get(sessionKey);
1183
- if (!proc) {
1184
- proc = await processManager.spawn({
1185
- sessionKey,
1186
- model: transport.config.model,
1187
- thinking: options.thinking,
1188
- permissionMode: transport.config.permissionMode,
1189
- workingDirectory: transport.config.workingDirectory,
1190
- timeout: options.timeout
1191
- });
1212
+ const existingProc = processManager.get(sessionKey);
1213
+ if (existingProc) {
1214
+ processManager.kill(sessionKey);
1192
1215
  }
1216
+ const proc = await processManager.spawn({
1217
+ sessionKey,
1218
+ model: transport.config.model,
1219
+ thinking: options.thinking,
1220
+ permissionMode: transport.config.permissionMode,
1221
+ workingDirectory: transport.config.workingDirectory,
1222
+ timeout: options.timeout,
1223
+ message: options.message,
1224
+ outputFormat: "stream-json"
1225
+ });
1193
1226
  processManager.setStatus(sessionKey, "busy");
1194
1227
  let fullResponse = "";
1195
1228
  let thinking;
1196
1229
  try {
1197
- proc.process.stdin?.write(options.message + "\n");
1198
- proc.process.stdin?.end();
1199
1230
  const parser = new ClaudeStreamParser(sessionKey);
1200
1231
  for await (const chunk of parser.parseStream(proc.process.stdout)) {
1201
1232
  if (chunk.content) {
@@ -1371,10 +1402,11 @@ var init_process_manager = __esm({
1371
1402
  );
1372
1403
  }
1373
1404
  const args = this.buildArgs(options);
1405
+ const stdinMode = options.message ? "ignore" : "pipe";
1374
1406
  const proc = (0, import_node_child_process.spawn)(this.config.cliPath, args, {
1375
1407
  cwd: options.workingDirectory || this.config.workingDirectory || process.cwd(),
1376
1408
  env: process.env,
1377
- stdio: ["pipe", "pipe", "pipe"]
1409
+ stdio: [stdinMode, "pipe", "pipe"]
1378
1410
  });
1379
1411
  const claudeProc = {
1380
1412
  sessionKey: options.sessionKey,
@@ -1392,25 +1424,32 @@ var init_process_manager = __esm({
1392
1424
  * Build CLI arguments
1393
1425
  */
1394
1426
  buildArgs(options) {
1427
+ const outputFormat = options.outputFormat || "json";
1395
1428
  const args = [
1396
1429
  "--print",
1397
- "--output-format=stream-json",
1398
- `--session-id=${options.sessionKey}`
1430
+ "--output-format",
1431
+ outputFormat
1399
1432
  ];
1433
+ if (outputFormat === "stream-json") {
1434
+ args.push("--verbose");
1435
+ }
1400
1436
  const model = options.model || this.config.model;
1401
1437
  if (model) {
1402
- args.push(`--model=${model}`);
1438
+ args.push("--model", model);
1403
1439
  }
1404
1440
  if (options.thinking && options.thinking !== "none") {
1405
- args.push(`--thinking=${options.thinking}`);
1441
+ args.push("--thinking", options.thinking);
1406
1442
  }
1407
1443
  const permissionMode = options.permissionMode || this.config.permissionMode;
1408
1444
  if (permissionMode) {
1409
- args.push(`--permission-mode=${permissionMode}`);
1445
+ args.push("--permission-mode", permissionMode);
1410
1446
  }
1411
1447
  const workingDir = options.workingDirectory || this.config.workingDirectory;
1412
1448
  if (workingDir) {
1413
- args.push(`--add-dir=${workingDir}`);
1449
+ args.push("--add-dir", workingDir);
1450
+ }
1451
+ if (options.message) {
1452
+ args.push(options.message);
1414
1453
  }
1415
1454
  return args;
1416
1455
  }
@@ -1708,7 +1747,6 @@ var init_cli = __esm({
1708
1747
  import_node_util = require("util");
1709
1748
  init_process_manager();
1710
1749
  init_session();
1711
- init_parsers();
1712
1750
  init_errors2();
1713
1751
  execAsync = (0, import_node_util.promisify)(import_node_child_process2.exec);
1714
1752
  CLITransport = class {
@@ -1833,6 +1871,7 @@ var init_cli = __esm({
1833
1871
  }
1834
1872
  /**
1835
1873
  * Handle chat.send request
1874
+ * Uses --output-format=json for single-shot responses
1836
1875
  */
1837
1876
  async handleChatSend(options) {
1838
1877
  const sessionKey = options.sessionKey || `claude-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
@@ -1844,26 +1883,37 @@ var init_cli = __esm({
1844
1883
  content: options.message,
1845
1884
  timestamp: Date.now()
1846
1885
  });
1847
- let proc = this.processManager.get(sessionKey);
1848
- if (!proc) {
1849
- proc = await this.processManager.spawn({
1850
- sessionKey,
1851
- model: this.config.model,
1852
- thinking: options.thinking,
1853
- permissionMode: this.config.permissionMode,
1854
- workingDirectory: this.config.workingDirectory,
1855
- timeout
1856
- });
1886
+ const existingProc = this.processManager.get(sessionKey);
1887
+ if (existingProc) {
1888
+ this.processManager.kill(sessionKey);
1857
1889
  }
1890
+ const proc = await this.processManager.spawn({
1891
+ sessionKey,
1892
+ model: this.config.model,
1893
+ thinking: options.thinking,
1894
+ permissionMode: this.config.permissionMode,
1895
+ workingDirectory: this.config.workingDirectory,
1896
+ timeout,
1897
+ message: options.message,
1898
+ outputFormat: "json"
1899
+ });
1858
1900
  this.processManager.setStatus(sessionKey, "busy");
1859
1901
  try {
1860
- proc.process.stdin?.write(options.message + "\n");
1861
- proc.process.stdin?.end();
1862
- const parser = new ClaudeStreamParser(sessionKey);
1863
- const { content, thinking } = await Promise.race([
1864
- parser.collectFullResponse(proc.process.stdout),
1902
+ const output = await Promise.race([
1903
+ this.collectStdout(proc.process),
1865
1904
  this.createTimeoutPromise(timeout)
1866
1905
  ]);
1906
+ let content = "";
1907
+ let thinking;
1908
+ try {
1909
+ const parsed = JSON.parse(output);
1910
+ content = parsed.result || "";
1911
+ if (parsed.thinking) {
1912
+ thinking = parsed.thinking;
1913
+ }
1914
+ } catch {
1915
+ content = output.trim();
1916
+ }
1867
1917
  this.sessionManager.addMessage(sessionKey, {
1868
1918
  role: "assistant",
1869
1919
  content,
@@ -1884,6 +1934,31 @@ var init_cli = __esm({
1884
1934
  throw error2;
1885
1935
  }
1886
1936
  }
1937
+ /**
1938
+ * Collect full stdout from a child process as a string.
1939
+ * Also captures stderr — if the process exits with no stdout, throws with stderr.
1940
+ */
1941
+ collectStdout(proc) {
1942
+ return new Promise((resolve, reject) => {
1943
+ const stdoutChunks = [];
1944
+ const stderrChunks = [];
1945
+ proc.stdout?.on("data", (chunk) => stdoutChunks.push(chunk));
1946
+ proc.stderr?.on("data", (chunk) => stderrChunks.push(chunk));
1947
+ proc.stdout?.on("error", reject);
1948
+ proc.on("error", reject);
1949
+ proc.on("close", (code) => {
1950
+ const stdout = Buffer.concat(stdoutChunks).toString("utf-8").trim();
1951
+ const stderr = Buffer.concat(stderrChunks).toString("utf-8").trim();
1952
+ if (stdout) {
1953
+ resolve(stdout);
1954
+ } else if (code !== 0 || stderr) {
1955
+ reject(new Error(`Claude CLI exited with code ${code}${stderr ? `: ${stderr}` : ""}`));
1956
+ } else {
1957
+ resolve("");
1958
+ }
1959
+ });
1960
+ });
1961
+ }
1887
1962
  /**
1888
1963
  * Handle sessions.list request
1889
1964
  */
@@ -3488,7 +3563,7 @@ var init_dist2 = __esm({
3488
3563
  if (event.message?.content) {
3489
3564
  const content = event.message.content;
3490
3565
  if (Array.isArray(content)) {
3491
- fullResponse = content.map((c) => c.text || "").join("");
3566
+ fullResponse = content.map((c2) => c2.text || "").join("");
3492
3567
  } else if (typeof content === "string") {
3493
3568
  fullResponse = content;
3494
3569
  }
@@ -5513,7 +5588,7 @@ var require_logger = __commonJS({
5513
5588
  return level;
5514
5589
  },
5515
5590
  // Can be overridden in the host environment
5516
- log: function log3(level) {
5591
+ log: function log4(level) {
5517
5592
  level = logger.lookupLevel(level);
5518
5593
  if (typeof console !== "undefined" && logger.lookupLevel(logger.level) <= level) {
5519
5594
  var method = logger.methodMap[level];
@@ -5707,8 +5782,8 @@ var require_base = __commonJS({
5707
5782
  _internalProtoAccess.resetLoggedProperties();
5708
5783
  }
5709
5784
  };
5710
- var log3 = _logger2["default"].log;
5711
- exports2.log = log3;
5785
+ var log4 = _logger2["default"].log;
5786
+ exports2.log = log4;
5712
5787
  exports2.createFrame = _utils.createFrame;
5713
5788
  exports2.logger = _logger2["default"];
5714
5789
  }
@@ -6614,8 +6689,8 @@ var require_parser = __commonJS({
6614
6689
  },
6615
6690
  showPosition: function showPosition() {
6616
6691
  var pre = this.pastInput();
6617
- var c = new Array(pre.length + 1).join("-");
6618
- return pre + this.upcomingInput() + "\n" + c + "^";
6692
+ var c2 = new Array(pre.length + 1).join("-");
6693
+ return pre + this.upcomingInput() + "\n" + c2 + "^";
6619
6694
  },
6620
6695
  next: function next() {
6621
6696
  if (this.done) {
@@ -8738,8 +8813,8 @@ var require_source_map_consumer = __commonJS({
8738
8813
  }
8739
8814
  });
8740
8815
  SourceMapConsumer.prototype._charIsMappingSeparator = function SourceMapConsumer_charIsMappingSeparator(aStr, index) {
8741
- var c = aStr.charAt(index);
8742
- return c === ";" || c === ",";
8816
+ var c2 = aStr.charAt(index);
8817
+ return c2 === ";" || c2 === ",";
8743
8818
  };
8744
8819
  SourceMapConsumer.prototype._parseMappings = function SourceMapConsumer_parseMappings(aStr, aSourceRoot) {
8745
8820
  throw new Error("Subclasses must implement _parseMappings");
@@ -10424,19 +10499,19 @@ var require_javascript_compiler = __commonJS({
10424
10499
  }
10425
10500
  },
10426
10501
  replaceStack: function replaceStack(callback) {
10427
- var prefix = ["("], stack = void 0, createdStack = void 0, usedLiteral = void 0;
10502
+ var prefix2 = ["("], stack = void 0, createdStack = void 0, usedLiteral = void 0;
10428
10503
  if (!this.isInline()) {
10429
10504
  throw new _exception2["default"]("replaceStack on non-inline");
10430
10505
  }
10431
10506
  var top = this.popStack(true);
10432
10507
  if (top instanceof Literal) {
10433
10508
  stack = [top.value];
10434
- prefix = ["(", stack];
10509
+ prefix2 = ["(", stack];
10435
10510
  usedLiteral = true;
10436
10511
  } else {
10437
10512
  createdStack = true;
10438
10513
  var _name = this.incrStack();
10439
- prefix = ["((", this.push(_name), " = ", top, ")"];
10514
+ prefix2 = ["((", this.push(_name), " = ", top, ")"];
10440
10515
  stack = this.topStack();
10441
10516
  }
10442
10517
  var item = callback.call(this, stack);
@@ -10446,7 +10521,7 @@ var require_javascript_compiler = __commonJS({
10446
10521
  if (createdStack) {
10447
10522
  this.stackSlot--;
10448
10523
  }
10449
- this.push(prefix.concat(item, ")"));
10524
+ this.push(prefix2.concat(item, ")"));
10450
10525
  },
10451
10526
  incrStack: function incrStack() {
10452
10527
  this.stackSlot++;
@@ -10979,22 +11054,22 @@ function formatArgs(args) {
10979
11054
  return String(arg);
10980
11055
  }).join(" ");
10981
11056
  }
10982
- function formatLogMessage(level, prefix, message, args, category = "agent") {
11057
+ function formatLogMessage(level, prefix2, message, args, category = "agent") {
10983
11058
  const { reset, dim, blue, gray } = ANSI_COLORS;
10984
11059
  const levelColor = LEVEL_COLORS[level];
10985
11060
  const levelName = LEVEL_NAMES[level];
10986
11061
  const time = `${dim}${formatTime5()}${reset}`;
10987
11062
  const levelStr = `${levelColor}${levelName}${reset}`;
10988
- const ctx = `${blue}[${prefix}]${reset}`;
11063
+ const ctx = `${blue}[${prefix2}]${reset}`;
10989
11064
  const cat = `${gray}[${category}]${reset}`;
10990
11065
  const argsStr = args.length > 0 ? ` ${dim}${formatArgs(args)}${reset}` : "";
10991
11066
  return `${time} ${levelStr} ${ctx}${cat} ${message}${argsStr}`;
10992
11067
  }
10993
- function createAgentLogger(prefix, category = "agent") {
10994
- return new ConsoleLogger(prefix, category);
11068
+ function createAgentLogger(prefix2, category = "agent") {
11069
+ return new ConsoleLogger(prefix2, category);
10995
11070
  }
10996
- function log(level, prefix, message, ...args) {
10997
- const formatted = formatLogMessage(level, prefix, message, args);
11071
+ function log(level, prefix2, message, ...args) {
11072
+ const formatted = formatLogMessage(level, prefix2, message, args);
10998
11073
  switch (level) {
10999
11074
  case "debug":
11000
11075
  console.debug(formatted);
@@ -11048,11 +11123,11 @@ function createCustomAgent(type, id) {
11048
11123
  function formatTime6() {
11049
11124
  return (/* @__PURE__ */ new Date()).toTimeString().slice(0, 8);
11050
11125
  }
11051
- function log2(level, prefix, message) {
11126
+ function log2(level, prefix2, message) {
11052
11127
  const time = `${colors5.dim}${formatTime6()}${colors5.reset}`;
11053
11128
  const levelColor = level === "ERROR" ? colors5.red : colors5.cyan;
11054
11129
  const levelStr = `${levelColor}${level === "INFO" ? "INFO " : "ERROR"}${colors5.reset}`;
11055
- const ctx = `${colors5.blue}[${prefix}]${colors5.reset}`;
11130
+ const ctx = `${colors5.blue}[${prefix2}]${colors5.reset}`;
11056
11131
  const consoleFn = level === "ERROR" ? console.error : console.info;
11057
11132
  consoleFn(`${time} ${levelStr} ${ctx}${colors5.gray}[agent]${colors5.reset} ${message}`);
11058
11133
  }
@@ -11841,7 +11916,7 @@ Return the authentication confirmation.`;
11841
11916
  prompt: `Please redo the previous work. Reason: ${reason}
11842
11917
 
11843
11918
  ${constraints.length > 0 ? `Constraints:
11844
- ${constraints.map((c) => `- ${c}`).join("\n")}` : ""}`
11919
+ ${constraints.map((c2) => `- ${c2}`).join("\n")}` : ""}`
11845
11920
  };
11846
11921
  }
11847
11922
  /**
@@ -13375,8 +13450,8 @@ git stash drop
13375
13450
  * @param prefix - Context prefix (e.g., agent name)
13376
13451
  * @param category - Log category (default: 'agent')
13377
13452
  */
13378
- constructor(prefix, category = "agent") {
13379
- this.prefix = prefix;
13453
+ constructor(prefix2, category = "agent") {
13454
+ this.prefix = prefix2;
13380
13455
  this.category = category;
13381
13456
  }
13382
13457
  category;
@@ -13820,7 +13895,7 @@ ${code}
13820
13895
  parts.push(...this.sections);
13821
13896
  if (this.constraints.length > 0) {
13822
13897
  parts.push("## Constraints\n");
13823
- parts.push(this.constraints.map((c) => `- ${c}`).join("\n"));
13898
+ parts.push(this.constraints.map((c2) => `- ${c2}`).join("\n"));
13824
13899
  }
13825
13900
  if (this.outputFormats.length > 0) {
13826
13901
  parts.push("\n## Expected Output\n");
@@ -16475,8 +16550,8 @@ Your PRDs should include:
16475
16550
  }
16476
16551
  };
16477
16552
  LoggingHook = class {
16478
- constructor(prefix = "Agent") {
16479
- this.prefix = prefix;
16553
+ constructor(prefix2 = "Agent") {
16554
+ this.prefix = prefix2;
16480
16555
  }
16481
16556
  async beforeInitialize(agent) {
16482
16557
  log2("INFO", this.prefix, `Initializing agent: ${agent.name}`);
@@ -17375,6 +17450,122 @@ var init_repo = __esm({
17375
17450
  }
17376
17451
  });
17377
17452
 
17453
+ // src/utils/pipeline-logger.ts
17454
+ function formatDuration(ms) {
17455
+ if (ms < 1e3) return `${ms}ms`;
17456
+ const seconds = ms / 1e3;
17457
+ if (seconds < 60) return `${seconds.toFixed(1)}s`;
17458
+ const minutes = Math.floor(seconds / 60);
17459
+ const remainingSeconds = Math.floor(seconds % 60);
17460
+ return `${minutes}m ${remainingSeconds}s`;
17461
+ }
17462
+ function prefix(issueKey) {
17463
+ return `${import_chalk3.default.magenta("[Pipeline]")} ${import_chalk3.default.cyan(issueKey)}`;
17464
+ }
17465
+ var import_chalk3, import_ora2, STAGE_LABELS, SpinnerPipelineLogger;
17466
+ var init_pipeline_logger = __esm({
17467
+ "src/utils/pipeline-logger.ts"() {
17468
+ "use strict";
17469
+ import_chalk3 = __toESM(require("chalk"));
17470
+ import_ora2 = __toESM(require("ora"));
17471
+ STAGE_LABELS = {
17472
+ triage: "Classifying issue",
17473
+ research: "Researching codebase",
17474
+ inspect: "Inspecting files",
17475
+ plan: "Planning implementation",
17476
+ implement: "Implementing changes"
17477
+ };
17478
+ SpinnerPipelineLogger = class {
17479
+ spinner = null;
17480
+ stageIndex = 0;
17481
+ totalStages = 0;
17482
+ pipelineStart(issueKey, title, stages, skipped) {
17483
+ this.stageIndex = 0;
17484
+ this.totalStages = stages.length;
17485
+ console.log();
17486
+ console.log(
17487
+ `${prefix(issueKey)} ${import_chalk3.default.bold("Pipeline started")} \u2014 ${title}`
17488
+ );
17489
+ const flow = stages.map((s) => import_chalk3.default.bold(s)).join(import_chalk3.default.dim(" \u2192 "));
17490
+ const skipNote = skipped.length ? import_chalk3.default.dim(` (skipped: ${skipped.join(", ")})`) : "";
17491
+ console.log(`${prefix(issueKey)} ${flow}${skipNote}`);
17492
+ }
17493
+ stageStart(issueKey, stage) {
17494
+ this.stageIndex++;
17495
+ const label = STAGE_LABELS[stage] || stage;
17496
+ const progress = import_chalk3.default.dim(`[${this.stageIndex}/${this.totalStages}]`);
17497
+ if (this.spinner) {
17498
+ this.spinner.stop();
17499
+ this.spinner = null;
17500
+ }
17501
+ this.spinner = (0, import_ora2.default)({
17502
+ text: `${prefix(issueKey)} ${progress} ${label}...`,
17503
+ color: "cyan"
17504
+ }).start();
17505
+ }
17506
+ stageSkip(issueKey, stage) {
17507
+ console.log(
17508
+ `${prefix(issueKey)} ${import_chalk3.default.gray("SKIP")} ${import_chalk3.default.dim(stage)} \u2014 using defaults`
17509
+ );
17510
+ }
17511
+ stageComplete(issueKey, stage, durationMs) {
17512
+ const duration = import_chalk3.default.dim(`(${formatDuration(durationMs)})`);
17513
+ if (this.spinner) {
17514
+ this.spinner.succeed(
17515
+ `${prefix(issueKey)} ${import_chalk3.default.bold(stage)} ${import_chalk3.default.green("completed")} ${duration}`
17516
+ );
17517
+ this.spinner = null;
17518
+ } else {
17519
+ console.log(
17520
+ `${prefix(issueKey)} ${import_chalk3.default.green("\u2714")} ${import_chalk3.default.bold(stage)} completed ${duration}`
17521
+ );
17522
+ }
17523
+ }
17524
+ stageFail(issueKey, stage, error2, durationMs) {
17525
+ const duration = import_chalk3.default.dim(`(${formatDuration(durationMs)})`);
17526
+ if (this.spinner) {
17527
+ this.spinner.fail(
17528
+ `${prefix(issueKey)} ${import_chalk3.default.bold(stage)} ${import_chalk3.default.red("failed")} ${duration} \u2014 ${error2}`
17529
+ );
17530
+ this.spinner = null;
17531
+ } else {
17532
+ console.log(
17533
+ `${prefix(issueKey)} ${import_chalk3.default.red("\u2716")} ${import_chalk3.default.bold(stage)} failed ${duration} \u2014 ${error2}`
17534
+ );
17535
+ }
17536
+ }
17537
+ info(issueKey, message) {
17538
+ const wasSpinning = this.spinner?.isSpinning;
17539
+ if (wasSpinning) this.spinner.stop();
17540
+ console.log(`${prefix(issueKey)} ${import_chalk3.default.dim(message)}`);
17541
+ if (wasSpinning) this.spinner.start();
17542
+ }
17543
+ pipelineComplete(issueKey, durationMs, prNumber, branch) {
17544
+ if (this.spinner) {
17545
+ this.spinner.stop();
17546
+ this.spinner = null;
17547
+ }
17548
+ console.log();
17549
+ console.log(
17550
+ `${prefix(issueKey)} ${import_chalk3.default.green.bold("\u2714 Pipeline completed")} in ${import_chalk3.default.bold(formatDuration(durationMs))} \u2014 PR ${import_chalk3.default.cyan(`#${prNumber}`)} on ${import_chalk3.default.cyan(branch)}`
17551
+ );
17552
+ console.log();
17553
+ }
17554
+ pipelineFail(issueKey, durationMs, error2) {
17555
+ if (this.spinner) {
17556
+ this.spinner.stop();
17557
+ this.spinner = null;
17558
+ }
17559
+ console.log();
17560
+ console.log(
17561
+ `${prefix(issueKey)} ${import_chalk3.default.red.bold("\u2716 Pipeline failed")} after ${import_chalk3.default.bold(formatDuration(durationMs))} \u2014 ${error2}`
17562
+ );
17563
+ console.log();
17564
+ }
17565
+ };
17566
+ }
17567
+ });
17568
+
17378
17569
  // ../integration-base/dist/index.mjs
17379
17570
  var dist_exports3 = {};
17380
17571
  __export(dist_exports3, {
@@ -17839,8 +18030,8 @@ function encodeReserved(str) {
17839
18030
  }).join("");
17840
18031
  }
17841
18032
  function encodeUnreserved(str) {
17842
- return encodeURIComponent(str).replace(/[!'()*]/g, function(c) {
17843
- return "%" + c.charCodeAt(0).toString(16).toUpperCase();
18033
+ return encodeURIComponent(str).replace(/[!'()*]/g, function(c2) {
18034
+ return "%" + c2.charCodeAt(0).toString(16).toUpperCase();
17844
18035
  });
17845
18036
  }
17846
18037
  function encodeValue(operator, value, key) {
@@ -18216,7 +18407,7 @@ async function fetchWrapper(requestOptions) {
18216
18407
  "fetch is not set. Please pass a fetch implementation as new Octokit({ request: { fetch }}). Learn more at https://github.com/octokit/octokit.js/#fetch-missing"
18217
18408
  );
18218
18409
  }
18219
- const log3 = requestOptions.request?.log || console;
18410
+ const log4 = requestOptions.request?.log || console;
18220
18411
  const parseSuccessResponseBody = requestOptions.request?.parseSuccessResponseBody !== false;
18221
18412
  const body = isPlainObject2(requestOptions.body) || Array.isArray(requestOptions.body) ? JSON.stringify(requestOptions.body) : requestOptions.body;
18222
18413
  const requestHeaders = Object.fromEntries(
@@ -18274,7 +18465,7 @@ async function fetchWrapper(requestOptions) {
18274
18465
  if ("deprecation" in responseHeaders) {
18275
18466
  const matches = responseHeaders.link && responseHeaders.link.match(/<([^<>]+)>; rel="deprecation"/);
18276
18467
  const deprecationLink = matches && matches.pop();
18277
- log3.warn(
18468
+ log4.warn(
18278
18469
  `[@octokit/request] "${requestOptions.method} ${requestOptions.url}" is deprecated. It is scheduled to be removed on ${responseHeaders.sunset}${deprecationLink ? `. See ${deprecationLink}` : ""}`
18279
18470
  );
18280
18471
  }
@@ -22042,7 +22233,7 @@ var init_html = __esm({
22042
22233
  } else {
22043
22234
  buffer = [str];
22044
22235
  }
22045
- const resStr = Promise.all(callbacks.map((c) => c({ phase, buffer, context }))).then(
22236
+ const resStr = Promise.all(callbacks.map((c2) => c2({ phase, buffer, context }))).then(
22046
22237
  (res) => Promise.all(
22047
22238
  res.filter(Boolean).map((str2) => resolveCallback(str2, phase, false, context, buffer))
22048
22239
  ).then(() => buffer[0])
@@ -22503,16 +22694,16 @@ var init_hono_base = __esm({
22503
22694
  init_router();
22504
22695
  init_constants2();
22505
22696
  init_url();
22506
- notFoundHandler = (c) => {
22507
- return c.text("404 Not Found", 404);
22697
+ notFoundHandler = (c2) => {
22698
+ return c2.text("404 Not Found", 404);
22508
22699
  };
22509
- errorHandler = (err, c) => {
22700
+ errorHandler = (err, c2) => {
22510
22701
  if ("getResponse" in err) {
22511
22702
  const res = err.getResponse();
22512
- return c.newResponse(res.body, res);
22703
+ return c2.newResponse(res.body, res);
22513
22704
  }
22514
22705
  console.error(err);
22515
- return c.text("Internal Server Error", 500);
22706
+ return c2.text("Internal Server Error", 500);
22516
22707
  };
22517
22708
  Hono = class _Hono {
22518
22709
  get;
@@ -22614,7 +22805,7 @@ var init_hono_base = __esm({
22614
22805
  if (app.errorHandler === errorHandler) {
22615
22806
  handler2 = r.handler;
22616
22807
  } else {
22617
- handler2 = async (c, next) => (await compose([], app.errorHandler)(c, () => r.handler(c, next))).res;
22808
+ handler2 = async (c2, next) => (await compose([], app.errorHandler)(c2, () => r.handler(c2, next))).res;
22618
22809
  handler2[COMPOSED_HANDLER] = r.handler;
22619
22810
  }
22620
22811
  subApp.#addRoute(r.method, r.path, handler2);
@@ -22725,16 +22916,16 @@ var init_hono_base = __esm({
22725
22916
  }
22726
22917
  }
22727
22918
  }
22728
- const getOptions = optionHandler ? (c) => {
22729
- const options2 = optionHandler(c);
22919
+ const getOptions = optionHandler ? (c2) => {
22920
+ const options2 = optionHandler(c2);
22730
22921
  return Array.isArray(options2) ? options2 : [options2];
22731
- } : (c) => {
22922
+ } : (c2) => {
22732
22923
  let executionContext = void 0;
22733
22924
  try {
22734
- executionContext = c.executionCtx;
22925
+ executionContext = c2.executionCtx;
22735
22926
  } catch {
22736
22927
  }
22737
- return [c.env, executionContext];
22928
+ return [c2.env, executionContext];
22738
22929
  };
22739
22930
  replaceRequest ||= (() => {
22740
22931
  const mergedPath = mergePath(this._basePath, path);
@@ -22745,8 +22936,8 @@ var init_hono_base = __esm({
22745
22936
  return new Request(url, request2);
22746
22937
  };
22747
22938
  })();
22748
- const handler2 = async (c, next) => {
22749
- const res = await applicationHandler(replaceRequest(c.req.raw), ...getOptions(c));
22939
+ const handler2 = async (c2, next) => {
22940
+ const res = await applicationHandler(replaceRequest(c2.req.raw), ...getOptions(c2));
22750
22941
  if (res) {
22751
22942
  return res;
22752
22943
  }
@@ -22762,9 +22953,9 @@ var init_hono_base = __esm({
22762
22953
  this.router.add(method, path, [handler2, r]);
22763
22954
  this.routes.push(r);
22764
22955
  }
22765
- #handleError(err, c) {
22956
+ #handleError(err, c2) {
22766
22957
  if (err instanceof Error) {
22767
- return this.errorHandler(err, c);
22958
+ return this.errorHandler(err, c2);
22768
22959
  }
22769
22960
  throw err;
22770
22961
  }
@@ -22774,7 +22965,7 @@ var init_hono_base = __esm({
22774
22965
  }
22775
22966
  const path = this.getPath(request2, { env });
22776
22967
  const matchResult = this.router.match(method, path);
22777
- const c = new Context(request2, {
22968
+ const c2 = new Context(request2, {
22778
22969
  path,
22779
22970
  matchResult,
22780
22971
  env,
@@ -22784,20 +22975,20 @@ var init_hono_base = __esm({
22784
22975
  if (matchResult[0].length === 1) {
22785
22976
  let res;
22786
22977
  try {
22787
- res = matchResult[0][0][0][0](c, async () => {
22788
- c.res = await this.#notFoundHandler(c);
22978
+ res = matchResult[0][0][0][0](c2, async () => {
22979
+ c2.res = await this.#notFoundHandler(c2);
22789
22980
  });
22790
22981
  } catch (err) {
22791
- return this.#handleError(err, c);
22982
+ return this.#handleError(err, c2);
22792
22983
  }
22793
22984
  return res instanceof Promise ? res.then(
22794
- (resolved) => resolved || (c.finalized ? c.res : this.#notFoundHandler(c))
22795
- ).catch((err) => this.#handleError(err, c)) : res ?? this.#notFoundHandler(c);
22985
+ (resolved) => resolved || (c2.finalized ? c2.res : this.#notFoundHandler(c2))
22986
+ ).catch((err) => this.#handleError(err, c2)) : res ?? this.#notFoundHandler(c2);
22796
22987
  }
22797
22988
  const composed = compose(matchResult[0], this.errorHandler, this.#notFoundHandler);
22798
22989
  return (async () => {
22799
22990
  try {
22800
- const context = await composed(c);
22991
+ const context = await composed(c2);
22801
22992
  if (!context.finalized) {
22802
22993
  throw new Error(
22803
22994
  "Context is not finalized. Did you forget to return a Response object or `await next()`?"
@@ -22805,7 +22996,7 @@ var init_hono_base = __esm({
22805
22996
  }
22806
22997
  return context.res;
22807
22998
  } catch (err) {
22808
- return this.#handleError(err, c);
22999
+ return this.#handleError(err, c2);
22809
23000
  }
22810
23001
  })();
22811
23002
  }
@@ -22999,8 +23190,8 @@ var init_node = __esm({
22999
23190
  buildRegExpStr() {
23000
23191
  const childKeys = Object.keys(this.#children).sort(compareKey);
23001
23192
  const strList = childKeys.map((k) => {
23002
- const c = this.#children[k];
23003
- return (typeof c.#varIndex === "number" ? `(${k})@${c.#varIndex}` : regExpMetaChars.has(k) ? `\\${k}` : k) + c.buildRegExpStr();
23193
+ const c2 = this.#children[k];
23194
+ return (typeof c2.#varIndex === "number" ? `(${k})@${c2.#varIndex}` : regExpMetaChars.has(k) ? `\\${k}` : k) + c2.buildRegExpStr();
23004
23195
  });
23005
23196
  if (typeof this.#index === "number") {
23006
23197
  strList.unshift(`#${this.#index}`);
@@ -24157,6 +24348,7 @@ var init_dist6 = __esm({
24157
24348
  // ../integration-github/dist/index.mjs
24158
24349
  var dist_exports4 = {};
24159
24350
  __export(dist_exports4, {
24351
+ ConsolePipelineLogger: () => ConsolePipelineLogger,
24160
24352
  GitHubAuthError: () => GitHubAuthError,
24161
24353
  GitHubClient: () => GitHubClient,
24162
24354
  GitHubError: () => GitHubError,
@@ -24171,7 +24363,7 @@ __export(dist_exports4, {
24171
24363
  parseIssuePayload: () => parseIssuePayload,
24172
24364
  verifyWebhookSignature: () => verifyWebhookSignature
24173
24365
  });
24174
- function formatDuration(ms) {
24366
+ function formatDuration2(ms) {
24175
24367
  if (ms < 1e3) return `${ms}ms`;
24176
24368
  const seconds = ms / 1e3;
24177
24369
  if (seconds < 60) return `${seconds.toFixed(1)}s`;
@@ -24192,7 +24384,7 @@ function statusIcon(status) {
24192
24384
  }
24193
24385
  }
24194
24386
  function buildStartComment(payload, enabledStages) {
24195
- const stageFlow = enabledStages.map((s) => STAGE_LABELS[s]).join(" \u2192 ");
24387
+ const stageFlow = enabledStages.map((s) => STAGE_LABELS2[s]).join(" \u2192 ");
24196
24388
  return [
24197
24389
  `> **Moxxy** is working on this issue`,
24198
24390
  "",
@@ -24210,16 +24402,16 @@ function buildSuccessComment(run2, _payload) {
24210
24402
  lines.push(`> **Moxxy** has completed this issue`);
24211
24403
  lines.push("");
24212
24404
  if (run2.classification) {
24213
- const c = run2.classification;
24405
+ const c2 = run2.classification;
24214
24406
  lines.push("| | |");
24215
24407
  lines.push("|---|---|");
24216
- lines.push(`| **Type** | ${c.type} |`);
24217
- lines.push(`| **Priority** | ${c.priority} |`);
24218
- lines.push(`| **Complexity** | ${c.complexity} |`);
24219
- lines.push(`| **Confidence** | ${(c.confidence * 100).toFixed(0)}% |`);
24408
+ lines.push(`| **Type** | ${c2.type} |`);
24409
+ lines.push(`| **Priority** | ${c2.priority} |`);
24410
+ lines.push(`| **Complexity** | ${c2.complexity} |`);
24411
+ lines.push(`| **Confidence** | ${(c2.confidence * 100).toFixed(0)}% |`);
24220
24412
  lines.push("");
24221
- if (c.reasoning) {
24222
- lines.push(`> ${c.reasoning}`);
24413
+ if (c2.reasoning) {
24414
+ lines.push(`> ${c2.reasoning}`);
24223
24415
  lines.push("");
24224
24416
  }
24225
24417
  }
@@ -24227,8 +24419,8 @@ function buildSuccessComment(run2, _payload) {
24227
24419
  lines.push("|-------|--------|----------|");
24228
24420
  for (const stage of run2.stages) {
24229
24421
  const icon = statusIcon(stage.status);
24230
- const duration = stage.duration_ms != null ? formatDuration(stage.duration_ms) : "\u2014";
24231
- lines.push(`| ${STAGE_LABELS[stage.stage]} | ${icon} ${stage.status} | ${duration} |`);
24422
+ const duration = stage.duration_ms != null ? formatDuration2(stage.duration_ms) : "\u2014";
24423
+ lines.push(`| ${STAGE_LABELS2[stage.stage]} | ${icon} ${stage.status} | ${duration} |`);
24232
24424
  }
24233
24425
  lines.push("");
24234
24426
  if (run2.prNumber) {
@@ -24247,8 +24439,8 @@ function buildFailureComment(run2, error2) {
24247
24439
  lines.push("|-------|--------|----------|");
24248
24440
  for (const stage of run2.stages) {
24249
24441
  const icon = statusIcon(stage.status);
24250
- const duration = stage.duration_ms != null ? formatDuration(stage.duration_ms) : "\u2014";
24251
- lines.push(`| ${STAGE_LABELS[stage.stage]} | ${icon} ${stage.status} | ${duration} |`);
24442
+ const duration = stage.duration_ms != null ? formatDuration2(stage.duration_ms) : "\u2014";
24443
+ lines.push(`| ${STAGE_LABELS2[stage.stage]} | ${icon} ${stage.status} | ${duration} |`);
24252
24444
  }
24253
24445
  lines.push("");
24254
24446
  }
@@ -24260,6 +24452,21 @@ function buildFailureComment(run2, error2) {
24260
24452
  lines.push("<sub>Automated by Moxxy</sub>");
24261
24453
  return lines.join("\n");
24262
24454
  }
24455
+ function formatTime7() {
24456
+ return (/* @__PURE__ */ new Date()).toTimeString().slice(0, 8);
24457
+ }
24458
+ function log3(level, issueKey, message) {
24459
+ const time = `${c.dim}${formatTime7()}${c.reset}`;
24460
+ const tag = `${c.magenta}[Pipeline]${c.reset}`;
24461
+ const issue = `${c.cyan}${issueKey}${c.reset}`;
24462
+ const levels = {
24463
+ info: `${c.blue}INFO ${c.reset}`,
24464
+ ok: `${c.green}OK ${c.reset}`,
24465
+ fail: `${c.red}FAIL ${c.reset}`,
24466
+ skip: `${c.gray}SKIP ${c.reset}`
24467
+ };
24468
+ console.log(`${time} ${levels[level]}${tag} ${issue} ${message}`);
24469
+ }
24263
24470
  async function implementIssue(supervisor, agentId, payload, workflow) {
24264
24471
  const instruction = {
24265
24472
  prompt: `Execute this workflow for issue #${payload.issueNumber}: ${payload.title}
@@ -24488,7 +24695,7 @@ Automated by Moxxy.`,
24488
24695
  base: defaultBranch
24489
24696
  });
24490
24697
  }
24491
- var import_crypto4, GitHubError, GitHubAuthError, GitHubWebhookError, GitHubPipelineError, GitHubClient, STAGE_LABELS, DEFAULT_CLASSIFICATION, DEFAULT_RESEARCH, DEFAULT_INSPECT, IssuePipeline, WebhookServer, GitHubIntegration;
24698
+ var import_crypto4, GitHubError, GitHubAuthError, GitHubWebhookError, GitHubPipelineError, GitHubClient, STAGE_LABELS2, c, ConsolePipelineLogger, DEFAULT_CLASSIFICATION, DEFAULT_RESEARCH, DEFAULT_INSPECT, IssuePipeline, WebhookServer, GitHubIntegration;
24492
24699
  var init_dist7 = __esm({
24493
24700
  "../integration-github/dist/index.mjs"() {
24494
24701
  "use strict";
@@ -24591,13 +24798,53 @@ var init_dist7 = __esm({
24591
24798
  return data;
24592
24799
  }
24593
24800
  };
24594
- STAGE_LABELS = {
24801
+ STAGE_LABELS2 = {
24595
24802
  triage: "Triage",
24596
24803
  research: "Research",
24597
24804
  inspect: "Inspect",
24598
24805
  plan: "Plan",
24599
24806
  implement: "Implement"
24600
24807
  };
24808
+ c = {
24809
+ reset: "\x1B[0m",
24810
+ bold: "\x1B[1m",
24811
+ dim: "\x1B[2m",
24812
+ red: "\x1B[31m",
24813
+ green: "\x1B[32m",
24814
+ yellow: "\x1B[33m",
24815
+ blue: "\x1B[34m",
24816
+ magenta: "\x1B[35m",
24817
+ cyan: "\x1B[36m",
24818
+ gray: "\x1B[90m"
24819
+ };
24820
+ ConsolePipelineLogger = class {
24821
+ pipelineStart(issueKey, title, stages, skipped) {
24822
+ log3("info", issueKey, `${c.bold}Pipeline started${c.reset} \u2014 ${title}`);
24823
+ const skipNote = skipped.length ? ` ${c.dim}(skipped: ${skipped.join(", ")})${c.reset}` : "";
24824
+ log3("info", issueKey, `Stages: ${stages.join(" \u2192 ")}${skipNote}`);
24825
+ }
24826
+ stageStart(issueKey, stage) {
24827
+ log3("info", issueKey, `Stage ${c.bold}${stage}${c.reset} starting...`);
24828
+ }
24829
+ stageSkip(issueKey, stage) {
24830
+ log3("skip", issueKey, `Stage ${stage} skipped \u2014 using defaults`);
24831
+ }
24832
+ stageComplete(issueKey, stage, durationMs) {
24833
+ log3("ok", issueKey, `Stage ${c.bold}${stage}${c.reset} completed in ${formatDuration2(durationMs)}`);
24834
+ }
24835
+ stageFail(issueKey, stage, error2, durationMs) {
24836
+ log3("fail", issueKey, `Stage ${c.bold}${stage}${c.reset} failed in ${formatDuration2(durationMs)} \u2014 ${error2}`);
24837
+ }
24838
+ info(issueKey, message) {
24839
+ log3("info", issueKey, message);
24840
+ }
24841
+ pipelineComplete(issueKey, durationMs, prNumber, branch) {
24842
+ log3("ok", issueKey, `${c.bold}Pipeline completed${c.reset} in ${formatDuration2(durationMs)} \u2014 PR #${prNumber} on branch ${branch}`);
24843
+ }
24844
+ pipelineFail(issueKey, durationMs, error2) {
24845
+ log3("fail", issueKey, `${c.bold}Pipeline failed${c.reset} after ${formatDuration2(durationMs)} \u2014 ${error2}`);
24846
+ }
24847
+ };
24601
24848
  DEFAULT_CLASSIFICATION = {
24602
24849
  type: "feature",
24603
24850
  priority: "medium",
@@ -24618,7 +24865,7 @@ var init_dist7 = __esm({
24618
24865
  estimatedChanges: []
24619
24866
  };
24620
24867
  IssuePipeline = class {
24621
- constructor(supervisor, moltAgentId, github, enabledStages) {
24868
+ constructor(supervisor, moltAgentId, github, enabledStages, logger) {
24622
24869
  this.supervisor = supervisor;
24623
24870
  this.moltAgentId = moltAgentId;
24624
24871
  this.github = github;
@@ -24626,8 +24873,10 @@ var init_dist7 = __esm({
24626
24873
  if (!stages.includes("plan")) stages.push("plan");
24627
24874
  if (!stages.includes("implement")) stages.push("implement");
24628
24875
  this.enabledStages = new Set(stages);
24876
+ this.logger = logger ?? new ConsolePipelineLogger();
24629
24877
  }
24630
24878
  enabledStages;
24879
+ logger;
24631
24880
  async run(payload) {
24632
24881
  const pipelineRun = {
24633
24882
  id: `pipeline-${Date.now()}`,
@@ -24638,8 +24887,12 @@ var init_dist7 = __esm({
24638
24887
  createdAt: Date.now(),
24639
24888
  updatedAt: Date.now()
24640
24889
  };
24890
+ const issueKey = `#${payload.issueNumber}`;
24641
24891
  const activeStages = PIPELINE_STAGES.filter((s) => this.enabledStages.has(s));
24892
+ const skippedStages = PIPELINE_STAGES.filter((s) => !this.enabledStages.has(s));
24893
+ this.logger.pipelineStart(issueKey, payload.title, activeStages, skippedStages);
24642
24894
  let commentId;
24895
+ const pipelineStart = Date.now();
24643
24896
  try {
24644
24897
  commentId = await this.github.commentOnIssue(
24645
24898
  payload.repo.owner,
@@ -24649,60 +24902,75 @@ var init_dist7 = __esm({
24649
24902
  );
24650
24903
  let classification;
24651
24904
  if (this.enabledStages.has("triage")) {
24905
+ this.logger.stageStart(issueKey, "triage");
24652
24906
  const triageResult = await this.runStage(
24653
24907
  "triage",
24654
24908
  () => triageIssue(this.supervisor, this.moltAgentId, payload)
24655
24909
  );
24656
24910
  pipelineRun.stages.push(triageResult);
24911
+ this.logStageResult(issueKey, triageResult);
24657
24912
  if (triageResult.status === "failed")
24658
24913
  throw new Error(`Triage failed: ${triageResult.error}`);
24659
24914
  classification = triageResult.output;
24915
+ this.logger.info(issueKey, `Classification: ${classification.type} / ${classification.priority} priority / ${classification.complexity} complexity (confidence: ${classification.confidence})`);
24660
24916
  } else {
24917
+ this.logger.stageSkip(issueKey, "triage");
24661
24918
  classification = DEFAULT_CLASSIFICATION;
24662
24919
  }
24663
24920
  pipelineRun.classification = classification;
24664
24921
  let researchOutput;
24665
24922
  if (this.enabledStages.has("research")) {
24923
+ this.logger.stageStart(issueKey, "research");
24666
24924
  const researchResult = await this.runStage(
24667
24925
  "research",
24668
24926
  () => researchIssue(this.supervisor, this.moltAgentId, payload, classification)
24669
24927
  );
24670
24928
  pipelineRun.stages.push(researchResult);
24929
+ this.logStageResult(issueKey, researchResult);
24671
24930
  if (researchResult.status === "failed")
24672
24931
  throw new Error(`Research failed: ${researchResult.error}`);
24673
24932
  researchOutput = researchResult.output;
24674
24933
  } else {
24934
+ this.logger.stageSkip(issueKey, "research");
24675
24935
  researchOutput = DEFAULT_RESEARCH;
24676
24936
  }
24677
24937
  let inspectOutput;
24678
24938
  if (this.enabledStages.has("inspect")) {
24939
+ this.logger.stageStart(issueKey, "inspect");
24679
24940
  const inspectResult = await this.runStage(
24680
24941
  "inspect",
24681
24942
  () => inspectIssue(this.supervisor, this.moltAgentId, payload, researchOutput)
24682
24943
  );
24683
24944
  pipelineRun.stages.push(inspectResult);
24945
+ this.logStageResult(issueKey, inspectResult);
24684
24946
  if (inspectResult.status === "failed")
24685
24947
  throw new Error(`Inspect failed: ${inspectResult.error}`);
24686
24948
  inspectOutput = inspectResult.output;
24687
24949
  } else {
24950
+ this.logger.stageSkip(issueKey, "inspect");
24688
24951
  inspectOutput = DEFAULT_INSPECT;
24689
24952
  }
24953
+ this.logger.stageStart(issueKey, "plan");
24690
24954
  const planResult = await this.runStage(
24691
24955
  "plan",
24692
24956
  () => planIssue(this.supervisor, this.moltAgentId, payload, inspectOutput)
24693
24957
  );
24694
24958
  pipelineRun.stages.push(planResult);
24959
+ this.logStageResult(issueKey, planResult);
24695
24960
  if (planResult.status === "failed") throw new Error(`Plan failed: ${planResult.error}`);
24696
24961
  const branchName = `moxxy/issue-${payload.issueNumber}`;
24697
24962
  const workflow = buildWorkflow(payload, planResult.output, branchName);
24963
+ this.logger.stageStart(issueKey, "implement");
24698
24964
  const implementResult = await this.runStage(
24699
24965
  "implement",
24700
24966
  () => implementIssue(this.supervisor, this.moltAgentId, payload, workflow)
24701
24967
  );
24702
24968
  pipelineRun.stages.push(implementResult);
24969
+ this.logStageResult(issueKey, implementResult);
24703
24970
  if (implementResult.status === "failed")
24704
24971
  throw new Error(`Implement failed: ${implementResult.error}`);
24705
24972
  pipelineRun.branchName = branchName;
24973
+ this.logger.info(issueKey, "Creating pull request...");
24706
24974
  const classificationNote = pipelineRun.classification ? `
24707
24975
 
24708
24976
  **Classification:** ${pipelineRun.classification.type} (${pipelineRun.classification.priority} priority, ${pipelineRun.classification.complexity} complexity)` : "";
@@ -24717,6 +24985,7 @@ Automated implementation by Moxxy.${classificationNote}`,
24717
24985
  pipelineRun.prNumber = prNumber;
24718
24986
  pipelineRun.status = "completed";
24719
24987
  pipelineRun.updatedAt = Date.now();
24988
+ this.logger.pipelineComplete(issueKey, Date.now() - pipelineStart, prNumber, branchName);
24720
24989
  if (commentId) {
24721
24990
  await this.github.updateComment(
24722
24991
  payload.repo.owner,
@@ -24729,6 +24998,8 @@ Automated implementation by Moxxy.${classificationNote}`,
24729
24998
  } catch (error2) {
24730
24999
  pipelineRun.status = "failed";
24731
25000
  pipelineRun.updatedAt = Date.now();
25001
+ const errMsg = error2 instanceof Error ? error2.message : String(error2);
25002
+ this.logger.pipelineFail(issueKey, Date.now() - pipelineStart, errMsg);
24732
25003
  if (commentId) {
24733
25004
  await this.github.updateComment(
24734
25005
  payload.repo.owner,
@@ -24741,6 +25012,13 @@ Automated implementation by Moxxy.${classificationNote}`,
24741
25012
  return pipelineRun;
24742
25013
  }
24743
25014
  }
25015
+ logStageResult(issueKey, result) {
25016
+ if (result.status === "completed") {
25017
+ this.logger.stageComplete(issueKey, result.stage, result.duration_ms ?? 0);
25018
+ } else {
25019
+ this.logger.stageFail(issueKey, result.stage, result.error ?? "Unknown error", result.duration_ms ?? 0);
25020
+ }
25021
+ }
24744
25022
  async runStage(stage, fn) {
24745
25023
  const start = Date.now();
24746
25024
  try {
@@ -24771,23 +25049,23 @@ Automated implementation by Moxxy.${classificationNote}`,
24771
25049
  this.setupRoutes();
24772
25050
  }
24773
25051
  setupRoutes() {
24774
- this.app.get("/health", (c) => {
24775
- return c.json({ status: "ok", timestamp: Date.now() });
25052
+ this.app.get("/health", (c2) => {
25053
+ return c2.json({ status: "ok", timestamp: Date.now() });
24776
25054
  });
24777
- this.app.post(this.config.path, async (c) => {
25055
+ this.app.post(this.config.path, async (c2) => {
24778
25056
  try {
24779
- const rawBody = await c.req.text();
25057
+ const rawBody = await c2.req.text();
24780
25058
  if (this.config.secret) {
24781
- const signature = c.req.header("x-hub-signature-256") || "";
25059
+ const signature = c2.req.header("x-hub-signature-256") || "";
24782
25060
  if (!signature) {
24783
- return c.json({ error: "Missing signature" }, 401);
25061
+ return c2.json({ error: "Missing signature" }, 401);
24784
25062
  }
24785
25063
  if (!verifyWebhookSignature(rawBody, signature, this.config.secret)) {
24786
- return c.json({ error: "Invalid signature" }, 401);
25064
+ return c2.json({ error: "Invalid signature" }, 401);
24787
25065
  }
24788
25066
  }
24789
25067
  const body = JSON.parse(rawBody);
24790
- const event = c.req.header("x-github-event") || "";
25068
+ const event = c2.req.header("x-github-event") || "";
24791
25069
  if (event === "issues") {
24792
25070
  const payload = parseIssuePayload(body);
24793
25071
  if (payload) {
@@ -24796,7 +25074,7 @@ Automated implementation by Moxxy.${classificationNote}`,
24796
25074
  });
24797
25075
  }
24798
25076
  }
24799
- return c.json({ received: true });
25077
+ return c2.json({ received: true });
24800
25078
  } catch (error2) {
24801
25079
  const message = error2 instanceof Error ? error2.message : String(error2);
24802
25080
  throw new GitHubWebhookError(
@@ -24852,7 +25130,8 @@ Automated implementation by Moxxy.${classificationNote}`,
24852
25130
  this.config.supervisor,
24853
25131
  this.config.moltAgentId,
24854
25132
  this.client,
24855
- this.config.enabledStages
25133
+ this.config.enabledStages,
25134
+ this.config.pipelineLogger
24856
25135
  );
24857
25136
  await this.client.verifyAuth();
24858
25137
  this.webhookServer = new WebhookServer({
@@ -25005,7 +25284,8 @@ function registerStartCommand(program) {
25005
25284
  sdk,
25006
25285
  supervisor,
25007
25286
  moltAgentId: agentId || "",
25008
- enabledStages: config.pipeline?.enabledStages
25287
+ enabledStages: config.pipeline?.enabledStages,
25288
+ pipelineLogger: new SpinnerPipelineLogger()
25009
25289
  });
25010
25290
  webhookSpinner.succeed(
25011
25291
  `Webhook server listening on ${import_chalk.default.cyan(`${webhookConfig.host}:${webhookConfig.port}${webhookConfig.path}`)}`
@@ -25050,6 +25330,7 @@ var init_start = __esm({
25050
25330
  "use strict";
25051
25331
  init_config_manager();
25052
25332
  init_logger();
25333
+ init_pipeline_logger();
25053
25334
  SDK_NAMES2 = {
25054
25335
  molt: "Molt Gateway",
25055
25336
  claude: "Claude CLI"
@@ -25145,7 +25426,7 @@ __export(cli_exports, {
25145
25426
  });
25146
25427
  function createProgram() {
25147
25428
  const program = new import_commander.Command();
25148
- program.name("moxxy").description("Moxxy - Agent orchestration platform").version("0.0.7");
25429
+ program.name("moxxy").description("Moxxy - Agent orchestration platform").version("0.0.9");
25149
25430
  registerStartCommand(program);
25150
25431
  registerRepoCommand(program);
25151
25432
  registerConfigCommand(program);