@wrongstack/cli 0.306.3 → 0.307.0

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 (76) hide show
  1. package/dist/{auth-L3WGSGDX.js → auth-TVOOHL4Q.js} +45 -106
  2. package/dist/boot/short-circuit-flags.d.ts +2 -2
  3. package/dist/chimera-cascade-evidence.d.ts +1 -1
  4. package/dist/chunk-2VMJ3E5Z.js +71 -0
  5. package/dist/{chunk-5N34EWJR.js → chunk-2ZNBRZ4W.js} +2 -2
  6. package/dist/{chunk-RHLQT3EV.js → chunk-CB35UVXO.js} +1636 -1528
  7. package/dist/{chunk-YKBRFSGL.js → chunk-DOJLAULS.js} +28 -28
  8. package/dist/{chunk-JUHRI6OV.js → chunk-G7337TTK.js} +24 -5
  9. package/dist/{chunk-KXN5HZDL.js → chunk-PKHGLWUJ.js} +24 -6
  10. package/dist/{chunk-HITHEXE3.js → chunk-TOG7OMKJ.js} +2 -2
  11. package/dist/{chunk-ARWGQUB3.js → chunk-XSG33WHN.js} +15 -5
  12. package/dist/{cli-main-3PUWFKSL.js → cli-main-YDOZZOZA.js} +29026 -28205
  13. package/dist/cli-main.d.ts +0 -20
  14. package/dist/{execution-4IG5XKOL.js → execution-CGT6J5ZN.js} +306 -274
  15. package/dist/fleet/host-learning-scheduler.d.ts +27 -0
  16. package/dist/fleet/host-shadow-manager.d.ts +64 -0
  17. package/dist/fleet/host.d.ts +5 -140
  18. package/dist/{hq-ZK6PGN3W.js → hq-PA6RH2UW.js} +2 -2
  19. package/dist/hq-server/mailbox-gateway-manager.d.ts +32 -0
  20. package/dist/hq-server/routes/auth/bootstrap-routes.d.ts +5 -0
  21. package/dist/hq-server/routes/auth/common.d.ts +11 -0
  22. package/dist/hq-server/routes/auth/password-routes.d.ts +9 -0
  23. package/dist/hq-server/routes/auth/session-audit-routes.d.ts +6 -0
  24. package/dist/hq-server/routes/auth/totp-routes.d.ts +9 -0
  25. package/dist/hq-server/routes/auth-handlers.d.ts +5 -132
  26. package/dist/hq-server/routes/command-handlers.d.ts +7 -0
  27. package/dist/hq-server/routes/data-handlers.d.ts +8 -0
  28. package/dist/hq-server/routes/mailbox-handlers.d.ts +22 -0
  29. package/dist/hq-server/routes.d.ts +3 -3
  30. package/dist/hq-server/server-lifecycle.d.ts +37 -0
  31. package/dist/hq-server/snapshot.d.ts +6 -5
  32. package/dist/hq-server/types.d.ts +4 -0
  33. package/dist/hq-server/upgrade-handler.d.ts +34 -0
  34. package/dist/hq-server/ws-client-events.d.ts +25 -0
  35. package/dist/hq-server/ws-leader.d.ts +47 -0
  36. package/dist/hq-server/ws-resume.d.ts +27 -0
  37. package/dist/hq-server/ws.d.ts +4 -71
  38. package/dist/{hq-server-IVZLVCFV.js → hq-server-PBRU275L.js} +2 -2
  39. package/dist/hq-server.d.ts +0 -38
  40. package/dist/index.js +1267 -122
  41. package/dist/{mcp-JNWEQ6T2.js → mcp-CMLFHRG2.js} +19 -9
  42. package/dist/mcp-serve.d.ts +31 -1
  43. package/dist/{modeldiag-6VS5KDP5.js → modeldiag-ICMPHT5L.js} +868 -831
  44. package/dist/{project-manifest-GE25PW4S.js → project-manifest-YFTJ3D5N.js} +2 -2
  45. package/dist/{project-picker-BOCWHBXP.js → project-picker-R5TYAE3Q.js} +3 -3
  46. package/dist/{providers-models-HQN3AT3K.js → providers-models-4FAKM2WO.js} +4 -4
  47. package/dist/repl-eternal-loop.d.ts +8 -0
  48. package/dist/repl-goal-banner.d.ts +21 -0
  49. package/dist/slash-commands/brain-council.d.ts +36 -0
  50. package/dist/slash-commands/brain-status.d.ts +12 -0
  51. package/dist/slash-commands/fallback.d.ts +6 -0
  52. package/dist/slash-commands/kanban-board-handlers.d.ts +13 -0
  53. package/dist/slash-commands/kanban-lifecycle-diagnostics.d.ts +16 -0
  54. package/dist/slash-commands/kanban-task-subcommands.d.ts +8 -0
  55. package/dist/slash-commands/memory-audience.d.ts +14 -0
  56. package/dist/slash-commands/memory-gather.d.ts +9 -0
  57. package/dist/slash-commands/memory-stats.d.ts +5 -0
  58. package/dist/slash-commands/settings-mutations.d.ts +6 -0
  59. package/dist/slash-commands/settings-view.d.ts +5 -0
  60. package/dist/subcommands/handlers/modeldiag-bench.d.ts +10 -0
  61. package/dist/subcommands/handlers/modeldiag-eval.d.ts +27 -0
  62. package/dist/subcommands/handlers/modeldiag-test.d.ts +8 -0
  63. package/dist/{version-help-ASKQYXDJ.js → version-help-TFD6VPF3.js} +2 -2
  64. package/dist/vibe-protocol-wiring.d.ts +10 -0
  65. package/dist/webui-server/credential-watcher.d.ts +15 -0
  66. package/dist/webui-server/domain-handlers.d.ts +21 -0
  67. package/dist/webui-server/route-contexts.d.ts +41 -0
  68. package/dist/{webui-server-FTG7JAZU.js → webui-server-IPHGJGXE.js} +515 -437
  69. package/dist/wiring/cli-execute-builder.d.ts +88 -0
  70. package/dist/wiring/cli-heap-watchdog.d.ts +33 -0
  71. package/dist/wiring/cli-prompt-and-tools-setup.d.ts +25 -0
  72. package/dist/wiring/cli-slash-commands-setup.d.ts +79 -0
  73. package/dist/wiring/heap-watchdog-setup.d.ts +53 -0
  74. package/dist/wiring/metrics.d.ts +1 -0
  75. package/dist/wiring/replay-governance-setup.d.ts +31 -0
  76. package/package.json +27 -27
@@ -29,27 +29,27 @@ import {
29
29
  import {
30
30
  theme
31
31
  } from "./chunk-QD544J2B.js";
32
- import {
33
- fmtTok
34
- } from "./chunk-TYO2OVAD.js";
35
32
  import {
36
33
  WEBUI_SESSION_CHILD_CAPABILITIES,
37
34
  writeWebuiSessionChildError,
38
35
  writeWebuiSessionChildReady
39
36
  } from "./chunk-3JPTNADJ.js";
40
37
  import {
41
- CLI_VERSION
42
- } from "./chunk-XJXDOF63.js";
38
+ fmtTok
39
+ } from "./chunk-TYO2OVAD.js";
43
40
  import {
44
41
  terminalLink,
45
42
  terminalText
46
43
  } from "./chunk-KE7E7DPX.js";
47
44
  import {
48
- resolveActiveApiKey
49
- } from "./chunk-SZ42FYPT.js";
45
+ CLI_VERSION
46
+ } from "./chunk-XJXDOF63.js";
50
47
  import {
51
48
  activeProfileConfigPath
52
49
  } from "./chunk-YMXXOOFN.js";
50
+ import {
51
+ resolveActiveApiKey
52
+ } from "./chunk-SZ42FYPT.js";
53
53
  import "./chunk-7OCVIDC7.js";
54
54
 
55
55
  // src/execution.ts
@@ -205,7 +205,7 @@ async function runWebUIDispatch(ctx) {
205
205
  const isSimpleUi = !isSessionChild && flags["simpleui"] === true;
206
206
  agent.disableInteractiveConfirmation();
207
207
  renderer.setSilent(true);
208
- const { runWebUI } = await import("./webui-server-FTG7JAZU.js");
208
+ const { runWebUI } = await import("./webui-server-IPHGJGXE.js");
209
209
  const flagValue = (names) => {
210
210
  for (const name of names) {
211
211
  if (!Object.hasOwn(flags, name)) continue;
@@ -870,7 +870,7 @@ function onSwitchToSession(ctx, _sessionId, targetRoot, projectName) {
870
870
  import * as path4 from "node:path";
871
871
  import { color as color3 } from "@wrongstack/core/utils";
872
872
  async function getProjectPickerItems(ctx) {
873
- const { buildPickerItems } = await import("./project-picker-BOCWHBXP.js");
873
+ const { buildPickerItems } = await import("./project-picker-R5TYAE3Q.js");
874
874
  return buildPickerItems({
875
875
  globalConfigPath: ctx.state.wpaths.globalConfig,
876
876
  currentProjectRoot: ctx.state.projectRoot
@@ -888,7 +888,7 @@ async function onProjectSelect(ctx, slug, kind) {
888
888
  }
889
889
  return;
890
890
  }
891
- const { loadManifest, saveManifest } = await import("./project-manifest-GE25PW4S.js");
891
+ const { loadManifest, saveManifest } = await import("./project-manifest-YFTJ3D5N.js");
892
892
  const manifest = await loadManifest(state.wpaths.globalConfig);
893
893
  const project = manifest.projects.find((p) => p.slug === slug);
894
894
  if (!project) return;
@@ -1318,7 +1318,7 @@ async function resumeSession(ctx, sessionId) {
1318
1318
  throw err;
1319
1319
  }
1320
1320
  writerSwapped = true;
1321
- state.sessionRef && (state.sessionRef.current = resumed.writer);
1321
+ if (state.sessionRef) state.sessionRef.current = resumed.writer;
1322
1322
  await agent.ctx.flushConversationJournal().catch((err) => {
1323
1323
  console.error(
1324
1324
  JSON.stringify({
@@ -1358,30 +1358,31 @@ async function resumeSession(ctx, sessionId) {
1358
1358
  const targetProviderId = typeof meta.provider === "string" && meta.provider.length > 0 ? meta.provider : currentProviderId;
1359
1359
  const targetModel = typeof meta.model === "string" && meta.model.length > 0 ? meta.model : agent.ctx.model;
1360
1360
  if (switchProviderAndModel && targetProviderId && (targetProviderId !== currentProviderId || targetModel !== agent.ctx.model)) {
1361
- await Promise.resolve(switchProviderAndModel(targetProviderId, targetModel)).catch(
1362
- (err) => {
1363
- console.error(
1364
- JSON.stringify({
1365
- level: "error",
1366
- event: "execution.resume_model_restore_failed",
1367
- provider: targetProviderId,
1368
- model: targetModel,
1369
- message: err instanceof Error ? err.message : String(err),
1370
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
1371
- })
1372
- );
1373
- }
1374
- );
1361
+ try {
1362
+ await Promise.resolve(switchProviderAndModel(targetProviderId, targetModel));
1363
+ } catch (err) {
1364
+ console.error(
1365
+ JSON.stringify({
1366
+ level: "error",
1367
+ event: "execution.resume_model_restore_failed",
1368
+ provider: targetProviderId,
1369
+ model: targetModel,
1370
+ message: err instanceof Error ? err.message : String(err),
1371
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
1372
+ })
1373
+ );
1374
+ }
1375
1375
  } else if (targetModel !== agent.ctx.model) {
1376
1376
  agent.ctx.model = targetModel;
1377
1377
  }
1378
- let oldWriterFinalize;
1378
+ let finalizeOldWriter;
1379
1379
  if (oldWriter && oldWriter !== resumed.writer) {
1380
+ const staleWriter = oldWriter;
1380
1381
  const endedUsage = tokenCounter.total();
1381
- oldWriterFinalize = void (async () => {
1382
+ finalizeOldWriter = async () => {
1382
1383
  let appendOk = false;
1383
1384
  try {
1384
- await oldWriter.append({
1385
+ await staleWriter.append({
1385
1386
  type: "session_end",
1386
1387
  ts: (/* @__PURE__ */ new Date()).toISOString(),
1387
1388
  usage: endedUsage
@@ -1399,7 +1400,7 @@ async function resumeSession(ctx, sessionId) {
1399
1400
  }
1400
1401
  if (appendOk) {
1401
1402
  try {
1402
- await oldWriter.close();
1403
+ await staleWriter.close();
1403
1404
  } catch (err) {
1404
1405
  console.error(
1405
1406
  JSON.stringify({
@@ -1411,7 +1412,7 @@ async function resumeSession(ctx, sessionId) {
1411
1412
  );
1412
1413
  }
1413
1414
  }
1414
- })();
1415
+ };
1415
1416
  }
1416
1417
  tokenCounter.reset();
1417
1418
  tokenCounter.account(resumed.data.usage, targetModel, targetProviderId);
@@ -1424,7 +1425,7 @@ async function resumeSession(ctx, sessionId) {
1424
1425
  sessionId: resumed.writer.id,
1425
1426
  contextSnapshot: { tokens, maxContext }
1426
1427
  };
1427
- void oldWriterFinalize;
1428
+ if (finalizeOldWriter) void finalizeOldWriter();
1428
1429
  return result;
1429
1430
  } catch (err) {
1430
1431
  if (!identityClaimed) await resumeClaim?.cancel().catch(() => void 0);
@@ -2750,18 +2751,26 @@ import { emitReviewIfChanged } from "@wrongstack/core/plugin";
2750
2751
 
2751
2752
  // src/chimera-cascade-evidence.ts
2752
2753
  import { spawn as spawn2 } from "node:child_process";
2753
- var JSON_BLOCK_RE = /```json\s*([\s\S]*?)```/gi;
2754
+ var JSON_BLOCK_RE = /```(?:json)?\s*([\s\S]*?)```/gi;
2755
+ function tryParseJson(raw) {
2756
+ try {
2757
+ return JSON.parse(raw);
2758
+ } catch {
2759
+ try {
2760
+ const cleaned = raw.replace(/,\s*([}\]])/g, "$1");
2761
+ return JSON.parse(cleaned);
2762
+ } catch {
2763
+ return null;
2764
+ }
2765
+ }
2766
+ }
2754
2767
  function extractCascadeEvidence(text) {
2755
2768
  if (!text) return null;
2756
2769
  for (const match of text.matchAll(JSON_BLOCK_RE)) {
2757
2770
  const body = match[1]?.trim();
2758
2771
  if (!body) continue;
2759
- let parsed;
2760
- try {
2761
- parsed = JSON.parse(body);
2762
- } catch {
2763
- continue;
2764
- }
2772
+ const parsed = tryParseJson(body);
2773
+ if (!parsed) continue;
2765
2774
  const evidence = parseEvidenceObject(parsed);
2766
2775
  if (evidence) return evidence;
2767
2776
  }
@@ -2822,7 +2831,7 @@ function isSafeCascadeCommand(command) {
2822
2831
  const tokens = command.trim().split(/\s+/);
2823
2832
  if (tokens.length === 0) return false;
2824
2833
  if (!SAFE_EXECUTABLES.has(tokens[0])) return false;
2825
- return tokens.every((token) => /^[A-Za-z0-9@/._:=~+*?\[\]-]+$/.test(token));
2834
+ return tokens.every((token) => /^[A-Za-z0-9@/._:=~+*?[\]-]+$/.test(token));
2826
2835
  }
2827
2836
  var runCascadeVerificationCommand = (command, cwd, timeoutMs) => {
2828
2837
  if (!isSafeCascadeCommand(command)) {
@@ -3656,6 +3665,10 @@ function installChimeraReviewHandler({
3656
3665
  const inScopeCited = citedFindings.filter((finding) => {
3657
3666
  const citedKey = normalizeFileKeyForCitation(finding.location.file, p.cwd);
3658
3667
  if (citedPaths.has(citedKey)) return true;
3668
+ const suffixMatches = [...citedPaths].filter(
3669
+ (cp) => cp.endsWith(`/${citedKey}`) || cp === citedKey
3670
+ );
3671
+ if (suffixMatches.length === 1) return true;
3659
3672
  const basename7 = path11.basename(finding.location.file).toLowerCase();
3660
3673
  const bucket = changedBasenameIndex.get(basename7);
3661
3674
  return !!(bucket && bucket.length === 1);
@@ -3672,7 +3685,7 @@ function installChimeraReviewHandler({
3672
3685
  const failedVerificationCount = inScopeCited.filter(
3673
3686
  (finding) => finding.verification?.status === "failed"
3674
3687
  ).length;
3675
- const effectiveHasFindings = reviewHasFindings && actionableFindings.length > 0;
3688
+ const effectiveHasFindings = reviewHasFindings && (actionableFindings.length > 0 || unverifiedInScope.length > 0);
3676
3689
  const verifiedCount = actionableFindings.length;
3677
3690
  const unverifiedCount = unverifiedInScope.length;
3678
3691
  const hallucinationNote = droppedCitations.length > 0 ? `
@@ -3958,13 +3971,11 @@ async function predictNextTasks(input, opts) {
3958
3971
 
3959
3972
  // src/repl.ts
3960
3973
  import { detectContinueIntent, InputBuilder, resolveContinuation } from "@wrongstack/core/agent";
3961
- import { goalFilePath, loadGoal, summarizeUsage } from "@wrongstack/core/goal";
3962
3974
  import {
3963
- color as color9,
3975
+ color as color11,
3964
3976
  estimateRequestTokensCalibrated as estimateRequestTokensCalibrated2,
3965
- expectDefined,
3966
3977
  hasOpenTodos as hasOpenTodos2,
3967
- toErrorMessage
3978
+ toErrorMessage as toErrorMessage3
3968
3979
  } from "@wrongstack/core/utils";
3969
3980
  import { readClipboardImage, routeImagesForModel } from "@wrongstack/runtime";
3970
3981
  import { createAutoProceedLoopGuard } from "@wrongstack/tools/auto-proceed-loop-guard";
@@ -4190,11 +4201,210 @@ function registerReplClient(opts) {
4190
4201
  };
4191
4202
  }
4192
4203
 
4204
+ // src/repl-eternal-loop.ts
4205
+ import { goalFilePath as goalFilePath2, summarizeUsage } from "@wrongstack/core/goal";
4206
+ import { color as color8, toErrorMessage as toErrorMessage2 } from "@wrongstack/core/utils";
4207
+
4208
+ // src/repl-goal-banner.ts
4209
+ import { goalFilePath, loadGoal } from "@wrongstack/core/goal";
4210
+ import { color as color7, expectDefined, toErrorMessage } from "@wrongstack/core/utils";
4211
+ async function loadGoalSafe(opts) {
4212
+ if (!opts.projectRoot) return null;
4213
+ try {
4214
+ return await loadGoal(goalFilePath(opts.projectRoot));
4215
+ } catch {
4216
+ return null;
4217
+ }
4218
+ }
4219
+ async function renderGoalBanner(opts) {
4220
+ const goal = await loadGoalSafe(opts);
4221
+ if (!goal) return;
4222
+ const summary = goal.goal.length > 80 ? `${goal.goal.slice(0, 77)}\u2026` : goal.goal;
4223
+ const stateColor = goal.goalState === "active" ? color7.green : goal.goalState === "paused" ? color7.amber : goal.goalState === "completed" ? color7.green : color7.dim;
4224
+ opts.renderer.write(
4225
+ color7.dim("Goal: ") + stateColor(summary) + color7.dim(` [${goal.goalState}] (iter ${goal.iterations})`) + "\n"
4226
+ );
4227
+ if (goal.journal.length > 0) {
4228
+ const lastEntry = expectDefined(goal.journal[goal.journal.length - 1]);
4229
+ const statusIcon = lastEntry.status === "success" ? "\u2713" : lastEntry.status === "failure" ? "\u2717" : lastEntry.status === "aborted" ? "\u2298" : lastEntry.status === "skipped" ? "\u229D" : "\xB7";
4230
+ opts.renderer.write(
4231
+ color7.dim(` Last: ${statusIcon} ${lastEntry.task} (${lastEntry.status})`) + "\n"
4232
+ );
4233
+ }
4234
+ if (goal.engineState === "running") {
4235
+ opts.renderer.write(
4236
+ color7.amber(" \u21BA Eternal engine was running when last session ended.") + "\n"
4237
+ );
4238
+ try {
4239
+ const answer = (await opts.reader.readLine(color7.dim(" Resume eternal mode? [y/N] "))).trim().toLowerCase();
4240
+ if (answer === "y" || answer === "yes") {
4241
+ try {
4242
+ await opts.slashRegistry.dispatch("/autonomy eternal", opts.agent.ctx);
4243
+ } catch (err) {
4244
+ opts.renderer.writeError(`Auto-resume failed: ${toErrorMessage(err)}`);
4245
+ }
4246
+ } else {
4247
+ opts.renderer.write(
4248
+ color7.dim(" Not resuming. Use `/autonomy eternal` later to continue.") + "\n"
4249
+ );
4250
+ }
4251
+ } catch {
4252
+ opts.renderer.write(color7.dim(" Use `/autonomy eternal` to resume.") + "\n");
4253
+ }
4254
+ } else if (goal.goalState === "paused") {
4255
+ opts.renderer.write(color7.amber(" \u23F8 Goal is paused. Use `/goal resume` to continue.") + "\n");
4256
+ } else if (goal.goalState === "completed") {
4257
+ opts.renderer.write(
4258
+ color7.green(" \u2713 Goal completed! Use `/goal clear` to set a new goal.") + "\n"
4259
+ );
4260
+ } else if (goal.goalState === "abandoned") {
4261
+ opts.renderer.write(color7.dim(" Use `/goal clear` to set a new goal.") + "\n");
4262
+ }
4263
+ opts.renderer.write("\n");
4264
+ }
4265
+
4266
+ // src/repl-eternal-loop.ts
4267
+ async function runReplEternalLoop(opts, onInterruptsReset) {
4268
+ const autonomy = opts.getAutonomy?.();
4269
+ if (autonomy === "eternal") {
4270
+ const engine = opts.getEternalEngine?.();
4271
+ if (!engine) {
4272
+ opts.renderer.writeWarning("Eternal mode set but no engine wired \u2014 falling back to off.");
4273
+ return false;
4274
+ }
4275
+ const beforeGoal = await loadGoalSafe(opts);
4276
+ const beforeIter = beforeGoal?.iterations ?? 0;
4277
+ opts.renderer.write(color8.dim(`
4278
+ \u21B3 [eternal #${beforeIter + 1}] running iteration\u2026
4279
+ `));
4280
+ onInterruptsReset();
4281
+ try {
4282
+ const ok = await engine.runOneIteration();
4283
+ const afterGoal = await loadGoalSafe(opts);
4284
+ const last = afterGoal?.journal[afterGoal.journal.length - 1];
4285
+ if (!ok && !last) {
4286
+ opts.renderer.write(color8.dim(" \u21B3 [eternal] iteration produced no progress.\n"));
4287
+ } else if (last) {
4288
+ const mark = last.status === "success" ? color8.green("\u2713") : last.status === "failure" ? color8.red("\u2717") : color8.amber("\u2298");
4289
+ const tail = last.note ? color8.dim(` \u2014 ${last.note.slice(0, 80)}`) : "";
4290
+ opts.renderer.write(
4291
+ ` ${mark} ${color8.dim(`#${last.iteration}`)} ${color8.dim(`[${last.source}]`)} ${last.task}${tail}
4292
+ `
4293
+ );
4294
+ }
4295
+ if (engine.currentState === "stopped") {
4296
+ const goal = await loadGoalSafe(opts);
4297
+ if (goal?.goalState === "completed") {
4298
+ const u = goal.journal.length > 0 ? summarizeUsage(goal) : null;
4299
+ const costLine = u && u.iterationsWithUsage > 0 ? color8.dim(
4300
+ ` \u2014 ${u.totalCostUsd.toFixed(4)} \xB7 ${u.totalInputTokens} in / ${u.totalOutputTokens} out \xB7 ${goal.iterations} iterations`
4301
+ ) : goal.iterations > 0 ? color8.dim(` \u2014 ${goal.iterations} iterations`) : "";
4302
+ opts.renderer.write(
4303
+ color8.green(`
4304
+ \u{1F3AF} Goal completed!${costLine}
4305
+
4306
+ `) + color8.dim(" Goal cleared. Use /goal set <mission> to create a new goal.\n")
4307
+ );
4308
+ if (opts.projectRoot) {
4309
+ try {
4310
+ const { unlink } = await import("node:fs/promises");
4311
+ await unlink(goalFilePath2(opts.projectRoot));
4312
+ } catch {
4313
+ }
4314
+ }
4315
+ }
4316
+ opts.onAutonomy?.("auto");
4317
+ return true;
4318
+ }
4319
+ } catch (err) {
4320
+ opts.renderer.writeError(`[eternal] ${toErrorMessage2(err)}`);
4321
+ }
4322
+ await new Promise((resolve3) => setTimeout(resolve3, 250));
4323
+ return true;
4324
+ }
4325
+ if (autonomy === "eternal-parallel") {
4326
+ const engine = opts.getParallelEngine?.();
4327
+ if (!engine) {
4328
+ opts.renderer.writeWarning(
4329
+ "Parallel mode set but no engine wired \u2014 falling back to off."
4330
+ );
4331
+ return false;
4332
+ }
4333
+ const beforeGoal = await loadGoalSafe(opts);
4334
+ const beforeIter = beforeGoal?.iterations ?? 0;
4335
+ const coord = engine.getCoordinator();
4336
+ if (coord) {
4337
+ const stats = coord.getStats();
4338
+ opts.renderer.write(
4339
+ color8.dim(
4340
+ ` \u250C\u2500 Fleet: ${stats.running} running, ${stats.idle} idle, ${stats.pending} pending, ${stats.completed} done`
4341
+ ) + "\n"
4342
+ );
4343
+ }
4344
+ opts.renderer.write(
4345
+ color8.magenta(` \u21B3 [parallel #${beforeIter + 1}] launching fan-out\u2026
4346
+ `)
4347
+ );
4348
+ onInterruptsReset();
4349
+ try {
4350
+ await engine.runOneIteration();
4351
+ const afterGoal = await loadGoalSafe(opts);
4352
+ const last = afterGoal?.journal[afterGoal.journal.length - 1];
4353
+ if (coord) {
4354
+ const stats = coord.getStats();
4355
+ opts.renderer.write(
4356
+ color8.dim(
4357
+ ` \u2514\u2500 Fleet: ${stats.running} running, ${stats.idle} idle, ${stats.completed} done
4358
+ `
4359
+ )
4360
+ );
4361
+ }
4362
+ if (last) {
4363
+ const mark = last.status === "success" ? color8.green("\u2713") : last.status === "failure" ? color8.red("\u2717") : color8.amber("\u2298");
4364
+ const tail = last.note ? color8.dim(` \u2014 ${last.note.slice(0, 80)}`) : "";
4365
+ opts.renderer.write(
4366
+ ` ${mark} ${color8.dim(`#${last.iteration}`)} ${color8.dim(`[${last.source}]`)} ${last.task}${tail}
4367
+ `
4368
+ );
4369
+ }
4370
+ if (engine.currentState === "stopped") {
4371
+ const goal = await loadGoalSafe(opts);
4372
+ if (goal?.goalState === "completed") {
4373
+ const u = goal.journal.length > 0 ? summarizeUsage(goal) : null;
4374
+ const costLine = u && u.iterationsWithUsage > 0 ? color8.dim(
4375
+ ` \u2014 ${u.totalCostUsd.toFixed(4)} \xB7 ${u.totalInputTokens} in / ${u.totalOutputTokens} out \xB7 ${goal.iterations} iterations`
4376
+ ) : goal.iterations > 0 ? color8.dim(` \u2014 ${goal.iterations} iterations`) : "";
4377
+ opts.renderer.write(
4378
+ color8.green(`
4379
+ \u{1F3AF} Goal completed!${costLine}
4380
+
4381
+ `) + color8.dim(" Goal cleared. Use /goal set <mission> to create a new goal.\n")
4382
+ );
4383
+ if (opts.projectRoot) {
4384
+ try {
4385
+ const { unlink } = await import("node:fs/promises");
4386
+ await unlink(goalFilePath2(opts.projectRoot));
4387
+ } catch {
4388
+ }
4389
+ }
4390
+ }
4391
+ opts.onAutonomy?.("auto");
4392
+ return true;
4393
+ }
4394
+ } catch (err) {
4395
+ opts.renderer.writeError(`[parallel] ${toErrorMessage2(err)}`);
4396
+ }
4397
+ await new Promise((resolve3) => setTimeout(resolve3, 250));
4398
+ return true;
4399
+ }
4400
+ return false;
4401
+ }
4402
+
4193
4403
  // src/repl-input.ts
4194
- import { color as color7 } from "@wrongstack/core/utils";
4404
+ import { color as color9 } from "@wrongstack/core/utils";
4195
4405
  async function readPossiblyMultiline(opts) {
4196
4406
  const firstPrompt = theme.primary("\u203A ");
4197
- const contPrompt = color7.dim("\xB7 ");
4407
+ const contPrompt = color9.dim("\xB7 ");
4198
4408
  const first = await opts.reader.readLine(firstPrompt);
4199
4409
  if (first.trim() === '"""') {
4200
4410
  const parts = [];
@@ -4219,7 +4429,7 @@ async function readPossiblyMultiline(opts) {
4219
4429
  }
4220
4430
 
4221
4431
  // src/repl-rendering.ts
4222
- import { color as color8 } from "@wrongstack/core/utils";
4432
+ import { color as color10 } from "@wrongstack/core/utils";
4223
4433
  var FILLED = "\u2588";
4224
4434
  var EMPTY = "\u2591";
4225
4435
  function renderContextChip(used, max) {
@@ -4236,13 +4446,13 @@ function renderProgress(ratio, width) {
4236
4446
  }
4237
4447
  function printBanner(renderer, projectName) {
4238
4448
  const lines = [
4239
- theme.primary(theme.bold("WrongStack")) + color8.dim(` v${CLI_VERSION}`),
4240
- color8.dim("Built on the wrong stack. Shipped anyway.")
4449
+ theme.primary(theme.bold("WrongStack")) + color10.dim(` v${CLI_VERSION}`),
4450
+ color10.dim("Built on the wrong stack. Shipped anyway.")
4241
4451
  ];
4242
4452
  if (projectName && projectName.length > 0) {
4243
- lines.push(color8.dim("Project: ") + theme.bold(projectName));
4453
+ lines.push(color10.dim("Project: ") + theme.bold(projectName));
4244
4454
  }
4245
- lines.push(color8.dim("Type /help for commands, /exit or q to quit."), "");
4455
+ lines.push(color10.dim("Type /help for commands, /exit or q to quit."), "");
4246
4456
  renderer.write(`${lines.join("\n")}
4247
4457
  `);
4248
4458
  }
@@ -4311,144 +4521,21 @@ async function runRepl(opts) {
4311
4521
  try {
4312
4522
  for (; ; ) {
4313
4523
  if (exiting) break;
4314
- if (opts.getAutonomy?.() === "eternal") {
4315
- const engine = opts.getEternalEngine?.();
4316
- if (!engine) {
4317
- opts.renderer.writeWarning("Eternal mode set but no engine wired \u2014 falling back to off.");
4318
- } else {
4319
- const beforeGoal = await loadGoalSafe(opts);
4320
- const beforeIter = beforeGoal?.iterations ?? 0;
4321
- opts.renderer.write(color9.dim(`
4322
- \u21B3 [eternal #${beforeIter + 1}] running iteration\u2026
4323
- `));
4524
+ const autonomy = opts.getAutonomy?.();
4525
+ if (autonomy === "eternal" || autonomy === "eternal-parallel") {
4526
+ const handled = await runReplEternalLoop(opts, () => {
4324
4527
  interrupts = 0;
4325
- try {
4326
- const ok = await engine.runOneIteration();
4327
- const afterGoal = await loadGoalSafe(opts);
4328
- const last = afterGoal?.journal[afterGoal.journal.length - 1];
4329
- if (!ok && !last) {
4330
- opts.renderer.write(color9.dim(" \u21B3 [eternal] iteration produced no progress.\n"));
4331
- } else if (last) {
4332
- const mark = last.status === "success" ? color9.green("\u2713") : last.status === "failure" ? color9.red("\u2717") : color9.amber("\u2298");
4333
- const tail = last.note ? color9.dim(` \u2014 ${last.note.slice(0, 80)}`) : "";
4334
- opts.renderer.write(
4335
- ` ${mark} ${color9.dim(`#${last.iteration}`)} ${color9.dim(`[${last.source}]`)} ${last.task}${tail}
4336
- `
4337
- );
4338
- }
4339
- if (engine.currentState === "stopped") {
4340
- const goal = await loadGoalSafe(opts);
4341
- if (goal?.goalState === "completed") {
4342
- const u = goal.journal.length > 0 ? summarizeUsage(goal) : null;
4343
- const costLine = u && u.iterationsWithUsage > 0 ? color9.dim(
4344
- ` \u2014 ${u.totalCostUsd.toFixed(4)} \xB7 ${u.totalInputTokens} in / ${u.totalOutputTokens} out \xB7 ${goal.iterations} iterations`
4345
- ) : goal.iterations > 0 ? color9.dim(` \u2014 ${goal.iterations} iterations`) : "";
4346
- opts.renderer.write(
4347
- color9.green(`
4348
- \u{1F3AF} Goal completed!${costLine}
4349
-
4350
- `) + color9.dim(" Goal cleared. Use /goal set <mission> to create a new goal.\n")
4351
- );
4352
- if (opts.projectRoot) {
4353
- try {
4354
- const { unlink } = await import("node:fs/promises");
4355
- await unlink(goalFilePath(opts.projectRoot));
4356
- } catch {
4357
- }
4358
- }
4359
- }
4360
- opts.onAutonomy?.("auto");
4361
- continue;
4362
- }
4363
- } catch (err) {
4364
- opts.renderer.writeError(`[eternal] ${toErrorMessage(err)}`);
4365
- }
4366
- await new Promise((resolve3) => setTimeout(resolve3, 250));
4367
- continue;
4368
- }
4369
- } else if (opts.getAutonomy?.() === "eternal-parallel") {
4370
- const engine = opts.getParallelEngine?.();
4371
- if (!engine) {
4372
- opts.renderer.writeWarning(
4373
- "Parallel mode set but no engine wired \u2014 falling back to off."
4374
- );
4375
- } else {
4376
- const beforeGoal = await loadGoalSafe(opts);
4377
- const beforeIter = beforeGoal?.iterations ?? 0;
4378
- const coord = engine.getCoordinator();
4379
- if (coord) {
4380
- const stats = coord.getStats();
4381
- opts.renderer.write(
4382
- color9.dim(
4383
- ` \u250C\u2500 Fleet: ${stats.running} running, ${stats.idle} idle, ${stats.pending} pending, ${stats.completed} done`
4384
- ) + "\n"
4385
- );
4386
- }
4387
- opts.renderer.write(
4388
- color9.magenta(` \u21B3 [parallel #${beforeIter + 1}] launching fan-out\u2026
4389
- `)
4390
- );
4391
- interrupts = 0;
4392
- try {
4393
- await engine.runOneIteration();
4394
- const afterGoal = await loadGoalSafe(opts);
4395
- const last = afterGoal?.journal[afterGoal.journal.length - 1];
4396
- if (coord) {
4397
- const stats = coord.getStats();
4398
- opts.renderer.write(
4399
- color9.dim(
4400
- ` \u2514\u2500 Fleet: ${stats.running} running, ${stats.idle} idle, ${stats.completed} done
4401
- `
4402
- )
4403
- );
4404
- }
4405
- if (last) {
4406
- const mark = last.status === "success" ? color9.green("\u2713") : last.status === "failure" ? color9.red("\u2717") : color9.amber("\u2298");
4407
- const tail = last.note ? color9.dim(` \u2014 ${last.note.slice(0, 80)}`) : "";
4408
- opts.renderer.write(
4409
- ` ${mark} ${color9.dim(`#${last.iteration}`)} ${color9.dim(`[${last.source}]`)} ${last.task}${tail}
4410
- `
4411
- );
4412
- }
4413
- if (engine.currentState === "stopped") {
4414
- const goal = await loadGoalSafe(opts);
4415
- if (goal?.goalState === "completed") {
4416
- const u = goal.journal.length > 0 ? summarizeUsage(goal) : null;
4417
- const costLine = u && u.iterationsWithUsage > 0 ? color9.dim(
4418
- ` \u2014 ${u.totalCostUsd.toFixed(4)} \xB7 ${u.totalInputTokens} in / ${u.totalOutputTokens} out \xB7 ${goal.iterations} iterations`
4419
- ) : goal.iterations > 0 ? color9.dim(` \u2014 ${goal.iterations} iterations`) : "";
4420
- opts.renderer.write(
4421
- color9.green(`
4422
- \u{1F3AF} Goal completed!${costLine}
4423
-
4424
- `) + color9.dim(" Goal cleared. Use /goal set <mission> to create a new goal.\n")
4425
- );
4426
- if (opts.projectRoot) {
4427
- try {
4428
- const { unlink } = await import("node:fs/promises");
4429
- await unlink(goalFilePath(opts.projectRoot));
4430
- } catch {
4431
- }
4432
- }
4433
- }
4434
- opts.onAutonomy?.("auto");
4435
- continue;
4436
- }
4437
- } catch (err) {
4438
- opts.renderer.writeError(`[parallel] ${toErrorMessage(err)}`);
4439
- }
4440
- await new Promise((resolve3) => setTimeout(resolve3, 250));
4441
- continue;
4442
- }
4528
+ });
4529
+ if (handled) continue;
4443
4530
  }
4444
4531
  {
4445
4532
  const mode = opts.getAutonomy?.() ?? "off";
4446
4533
  const suggestions = opts.getSuggestions?.() ?? [];
4447
4534
  if (mode === "suggest" && suggestions.length > 0) {
4448
- const lines = suggestions.map((s, i) => ` ${color9.bold(`${i + 1}.`)} ${color9.dim(s)}`);
4535
+ const lines = suggestions.map((s, i) => ` ${color11.bold(`${i + 1}.`)} ${color11.dim(s)}`);
4449
4536
  opts.renderer.write(
4450
4537
  `
4451
- ${color9.cyan(" \u{1F4A1} Suggested next steps")} ${color9.dim("(use /next 1, /next 2, or /next 1 2 3)")}
4538
+ ${color11.cyan(" \u{1F4A1} Suggested next steps")} ${color11.dim("(use /next 1, /next 2, or /next 1 2 3)")}
4452
4539
  ${lines.join("\n")}
4453
4540
 
4454
4541
  `
@@ -4482,8 +4569,7 @@ ${lines.join("\n")}
4482
4569
  }
4483
4570
  }
4484
4571
  }
4485
- if (!top) {
4486
- } else {
4572
+ if (top) {
4487
4573
  const maxAuto = opts.autoProceedMaxIterations ?? DEFAULT_MAX_CONSECUTIVE_AUTO_PROCEED;
4488
4574
  if (maxAuto > 0 && autoIterCount >= maxAuto) {
4489
4575
  if (!autoCapWarned) {
@@ -4536,7 +4622,7 @@ ${lines.join("\n")}
4536
4622
  autoCapWarned = false;
4537
4623
  autoProceedLoopGuard.reset();
4538
4624
  if (trimmed === "q") {
4539
- opts.renderer.write(color9.dim(" Goodbye!\n"));
4625
+ opts.renderer.write(color11.dim(" Goodbye!\n"));
4540
4626
  break;
4541
4627
  }
4542
4628
  if (trimmed === "wd" || trimmed.startsWith("cd ")) {
@@ -4546,7 +4632,7 @@ ${lines.join("\n")}
4546
4632
  if (res?.message) opts.renderer.write(`${res.message}
4547
4633
  `);
4548
4634
  } catch (err) {
4549
- opts.renderer.writeError(toErrorMessage(err));
4635
+ opts.renderer.writeError(toErrorMessage3(err));
4550
4636
  }
4551
4637
  continue;
4552
4638
  }
@@ -4578,14 +4664,14 @@ ${lines.join("\n")}
4578
4664
  if (specSaved) {
4579
4665
  opts.renderer.write(
4580
4666
  `
4581
- ${color9.cyan(" \u2713 Spec detected and saved! Use /sdd approve to continue.")}
4667
+ ${color11.cyan(" \u2713 Spec detected and saved! Use /sdd approve to continue.")}
4582
4668
  `
4583
4669
  );
4584
4670
  }
4585
4671
  const planSaved = trySaveImplementationPlan(runResult.finalText);
4586
4672
  if (planSaved) {
4587
4673
  opts.renderer.write(`
4588
- ${color9.cyan(" \u2713 Implementation plan saved!")}
4674
+ ${color11.cyan(" \u2713 Implementation plan saved!")}
4589
4675
  `);
4590
4676
  }
4591
4677
  const tasksSaved = await trySaveTasksFromAIOutput(runResult.finalText);
@@ -4594,7 +4680,7 @@ ${color9.cyan(" \u2713 Implementation plan saved!")}
4594
4680
  const count = progress?.total ?? 0;
4595
4681
  opts.renderer.write(
4596
4682
  `
4597
- ${color9.cyan(` \u2713 ${count} tasks detected and saved! Use /sdd approve to execute.`)}
4683
+ ${color11.cyan(` \u2713 ${count} tasks detected and saved! Use /sdd approve to execute.`)}
4598
4684
  `
4599
4685
  );
4600
4686
  }
@@ -4606,13 +4692,13 @@ ${color9.cyan(` \u2713 ${count} tasks detected and saved! Use /sdd approve to e
4606
4692
  if (progress) {
4607
4693
  opts.renderer.write(
4608
4694
  `
4609
- ${color9.cyan(` \u2713 ${autoCompleted} task(s) auto-completed! Progress: ${progress.completed}/${progress.total} (${progress.percentComplete}%)`)}
4695
+ ${color11.cyan(` \u2713 ${autoCompleted} task(s) auto-completed! Progress: ${progress.completed}/${progress.total} (${progress.percentComplete}%)`)}
4610
4696
  `
4611
4697
  );
4612
4698
  const taskList2 = renderTaskListWithProgress();
4613
4699
  if (taskList2) {
4614
4700
  opts.renderer.write(`
4615
- ${color9.dim(taskList2)}
4701
+ ${color11.dim(taskList2)}
4616
4702
  `);
4617
4703
  }
4618
4704
  }
@@ -4620,7 +4706,7 @@ ${color9.dim(taskList2)}
4620
4706
  const taskList2 = renderTaskListWithProgress();
4621
4707
  if (taskList2) {
4622
4708
  opts.renderer.write(`
4623
- ${color9.dim(taskList2)}
4709
+ ${color11.dim(taskList2)}
4624
4710
  `);
4625
4711
  }
4626
4712
  }
@@ -4638,7 +4724,7 @@ ${color9.dim(taskList2)}
4638
4724
  }
4639
4725
  }
4640
4726
  } catch (err) {
4641
- opts.renderer.writeError(toErrorMessage(err));
4727
+ opts.renderer.writeError(toErrorMessage3(err));
4642
4728
  }
4643
4729
  continue;
4644
4730
  }
@@ -4663,22 +4749,22 @@ ${color9.dim(taskList2)}
4663
4749
  }
4664
4750
  if (resolved.source === "open") {
4665
4751
  opts.renderer.write(
4666
- ` ${color9.amber("\u26A0")} ${color9.bold("'continue' has no anchor")} ${color9.dim("\u2014 no pending todo or suggestion.")}
4667
- ` + color9.dim(
4752
+ ` ${color11.amber("\u26A0")} ${color11.bold("'continue' has no anchor")} ${color11.dim("\u2014 no pending todo or suggestion.")}
4753
+ ` + color11.dim(
4668
4754
  " If you proceed, I'll choose the next step from context; that can drift.\n"
4669
4755
  )
4670
4756
  );
4671
- const ans = (await opts.reader.readLine(color9.dim(" Proceed anyway? [Y/n \xB7 e = type your own] "))).trim().toLowerCase();
4757
+ const ans = (await opts.reader.readLine(color11.dim(" Proceed anyway? [Y/n \xB7 e = type your own] "))).trim().toLowerCase();
4672
4758
  if (ans === "n" || ans === "no") {
4673
- opts.renderer.write(color9.dim(" Cancelled \u2014 nothing sent.\n"));
4759
+ opts.renderer.write(color11.dim(" Cancelled \u2014 nothing sent.\n"));
4674
4760
  continue;
4675
4761
  }
4676
4762
  if (ans === "e" || ans === "edit") {
4677
- opts.renderer.write(color9.dim(" Okay \u2014 type what to continue with.\n"));
4763
+ opts.renderer.write(color11.dim(" Okay \u2014 type what to continue with.\n"));
4678
4764
  continue;
4679
4765
  }
4680
4766
  } else {
4681
- opts.renderer.write(color9.dim(` ${resolved.label}
4767
+ opts.renderer.write(color11.dim(` ${resolved.label}
4682
4768
  `));
4683
4769
  }
4684
4770
  builder.appendText(resolved.text);
@@ -4686,7 +4772,7 @@ ${color9.dim(taskList2)}
4686
4772
  const ph = await builder.appendPaste(raw);
4687
4773
  if (ph) {
4688
4774
  const lineCount = raw.split("\n").length;
4689
- opts.renderer.write(color9.dim(` \u21B3 ${ph} (${lineCount} lines)
4775
+ opts.renderer.write(color11.dim(` \u21B3 ${ph} (${lineCount} lines)
4690
4776
  `));
4691
4777
  }
4692
4778
  }
@@ -4739,7 +4825,7 @@ ${taskList}`;
4739
4825
  }) : { blocks: effectiveBlocks, route: "none", convertedImages: 0 };
4740
4826
  if (routed.route === "adapter") {
4741
4827
  opts.renderer.write(
4742
- color9.dim(
4828
+ color11.dim(
4743
4829
  ` \u21B3 image analyzed via ${routed.adapterName ?? "vision adapter"} (${routed.convertedImages} image${routed.convertedImages === 1 ? "" : "s"})
4744
4830
  `
4745
4831
  )
@@ -4773,14 +4859,14 @@ ${taskList}`;
4773
4859
  if (specSaved) {
4774
4860
  opts.renderer.write(
4775
4861
  `
4776
- ${color9.cyan(" \u2713 Spec detected and saved! Use /sdd approve to continue.")}
4862
+ ${color11.cyan(" \u2713 Spec detected and saved! Use /sdd approve to continue.")}
4777
4863
  `
4778
4864
  );
4779
4865
  }
4780
4866
  const planSaved = trySaveImplementationPlan(result.finalText);
4781
4867
  if (planSaved) {
4782
4868
  opts.renderer.write(`
4783
- ${color9.cyan(" \u2713 Implementation plan saved!")}
4869
+ ${color11.cyan(" \u2713 Implementation plan saved!")}
4784
4870
  `);
4785
4871
  }
4786
4872
  const tasksSaved = await trySaveTasksFromAIOutput(result.finalText);
@@ -4789,7 +4875,7 @@ ${color9.cyan(" \u2713 Implementation plan saved!")}
4789
4875
  const count = progress?.total ?? 0;
4790
4876
  opts.renderer.write(
4791
4877
  `
4792
- ${color9.cyan(` \u2713 ${count} tasks detected and saved! Use /sdd approve to execute.`)}
4878
+ ${color11.cyan(` \u2713 ${count} tasks detected and saved! Use /sdd approve to execute.`)}
4793
4879
  `
4794
4880
  );
4795
4881
  }
@@ -4801,13 +4887,13 @@ ${color9.cyan(` \u2713 ${count} tasks detected and saved! Use /sdd approve to e
4801
4887
  if (progress) {
4802
4888
  opts.renderer.write(
4803
4889
  `
4804
- ${color9.cyan(` \u2713 ${autoCompleted} task(s) auto-completed! Progress: ${progress.completed}/${progress.total} (${progress.percentComplete}%)`)}
4890
+ ${color11.cyan(` \u2713 ${autoCompleted} task(s) auto-completed! Progress: ${progress.completed}/${progress.total} (${progress.percentComplete}%)`)}
4805
4891
  `
4806
4892
  );
4807
4893
  if (progress.percentComplete === 100) {
4808
4894
  opts.renderer.write(
4809
4895
  `
4810
- ${color9.green(" \u{1F389} All tasks completed! Use /sdd cancel to end the session.")}
4896
+ ${color11.green(" \u{1F389} All tasks completed! Use /sdd cancel to end the session.")}
4811
4897
  `
4812
4898
  );
4813
4899
  }
@@ -4816,14 +4902,14 @@ ${color9.green(" \u{1F389} All tasks completed! Use /sdd cancel to end the sess
4816
4902
  const taskList2 = renderTaskListWithProgress();
4817
4903
  if (taskList2) {
4818
4904
  opts.renderer.write(`
4819
- ${color9.dim(taskList2)}
4905
+ ${color11.dim(taskList2)}
4820
4906
  `);
4821
4907
  }
4822
4908
  } else {
4823
4909
  const taskList2 = renderTaskListWithProgress();
4824
4910
  if (taskList2) {
4825
4911
  opts.renderer.write(`
4826
- ${color9.dim(taskList2)}
4912
+ ${color11.dim(taskList2)}
4827
4913
  `);
4828
4914
  }
4829
4915
  }
@@ -4840,15 +4926,15 @@ ${color9.dim(taskList2)}
4840
4926
  const ctxChip = effectiveMaxContext && effectiveMaxContext > 0 ? ` ctx: ${renderContextChip(after.input, effectiveMaxContext)}` : "";
4841
4927
  opts.renderer.write(
4842
4928
  `
4843
- ${color9.dim(
4929
+ ${color11.dim(
4844
4930
  `[in: ${fmtTok(after.input - before.input)} out: ${fmtTok(after.output - before.output)} iters: ${result.iterations} cost: ${(costAfter - costBefore).toFixed(4)} ${((Date.now() - startedAt) / 1e3).toFixed(1)}s]${ctxChip}`
4845
4931
  )}
4846
4932
  `
4847
4933
  );
4848
4934
  }
4849
4935
  if (result.status === "done" && opts.getAutonomy) {
4850
- const autonomy = opts.getAutonomy();
4851
- if (autonomy === "suggest" && !hasOpenTodos2(opts.agent.ctx.todos)) {
4936
+ const autonomy2 = opts.getAutonomy();
4937
+ if (autonomy2 === "suggest" && !hasOpenTodos2(opts.agent.ctx.todos)) {
4852
4938
  const suggestPrompt = 'Based on what you just did, suggest 3 exact prompt messages that can be submitted back to you through the TUI or WebUI. Each prompt must ask the agent to perform work; never assign a manual chore to the user. If you include suggestions, wrap them in a balanced <nextsteps>...</nextsteps> block, with one numbered prompt per line and no explanation. If there is nothing meaningful left, say "No further steps needed."';
4853
4939
  const suggestBlocks = [{ type: "text", text: suggestPrompt }];
4854
4940
  const suggestCtrl = new AbortController();
@@ -4867,7 +4953,7 @@ ${color9.dim(
4867
4953
  if (suggestResult.status === "done" && suggestResult.finalText) {
4868
4954
  opts.renderer.write(
4869
4955
  `
4870
- ${color9.cyan(" Suggested next steps:")}
4956
+ ${color11.cyan(" Suggested next steps:")}
4871
4957
  ${suggestResult.finalText}
4872
4958
  `
4873
4959
  );
@@ -4886,8 +4972,8 @@ ${suggestResult.finalText}
4886
4972
  }
4887
4973
  }
4888
4974
  if (result.status === "done" && opts.getNextPredict?.() && !hasOpenTodos2(opts.agent.ctx.todos)) {
4889
- const autonomy = opts.getAutonomy?.() ?? "off";
4890
- if (autonomy === "off") {
4975
+ const autonomy2 = opts.getAutonomy?.() ?? "off";
4976
+ if (autonomy2 === "off") {
4891
4977
  const predictCtrl = new AbortController();
4892
4978
  activeCtrl = predictCtrl;
4893
4979
  try {
@@ -4906,8 +4992,8 @@ ${suggestResult.finalText}
4906
4992
  if (predictions.length > 0) {
4907
4993
  const lines = predictions.map((p, i) => ` ${i + 1}. ${p}`).join("\n");
4908
4994
  opts.renderer.write(`
4909
- ${color9.dim(" \u21B3 likely next:")}
4910
- ${color9.dim(lines)}
4995
+ ${color11.dim(" \u21B3 likely next:")}
4996
+ ${color11.dim(lines)}
4911
4997
  `);
4912
4998
  }
4913
4999
  } catch {
@@ -4917,7 +5003,7 @@ ${color9.dim(lines)}
4917
5003
  }
4918
5004
  }
4919
5005
  } catch (err) {
4920
- opts.renderer.writeError(toErrorMessage(err));
5006
+ opts.renderer.writeError(toErrorMessage3(err));
4921
5007
  } finally {
4922
5008
  activeCtrl = void 0;
4923
5009
  }
@@ -4935,71 +5021,17 @@ async function pasteClipboardImage(builder, opts) {
4935
5021
  try {
4936
5022
  const img = await readClipboardImage();
4937
5023
  if (!img) {
4938
- opts.renderer.write(color9.dim(" no image on clipboard\n"));
5024
+ opts.renderer.write(color11.dim(" no image on clipboard\n"));
4939
5025
  return;
4940
5026
  }
4941
5027
  const placeholder = await builder.appendImage(img.base64, img.mediaType);
4942
5028
  const kb = (img.bytes / 1024).toFixed(0);
4943
- opts.renderer.write(color9.dim(` \u21B3 ${placeholder} (PNG ${kb}KB)
5029
+ opts.renderer.write(color11.dim(` \u21B3 ${placeholder} (PNG ${kb}KB)
4944
5030
  `));
4945
5031
  } catch (err) {
4946
- opts.renderer.writeError(`Clipboard image error: ${toErrorMessage(err)}`);
5032
+ opts.renderer.writeError(`Clipboard image error: ${toErrorMessage3(err)}`);
4947
5033
  }
4948
5034
  }
4949
- async function loadGoalSafe(opts) {
4950
- if (!opts.projectRoot) return null;
4951
- try {
4952
- return await loadGoal(goalFilePath(opts.projectRoot));
4953
- } catch {
4954
- return null;
4955
- }
4956
- }
4957
- async function renderGoalBanner(opts) {
4958
- const goal = await loadGoalSafe(opts);
4959
- if (!goal) return;
4960
- const summary = goal.goal.length > 80 ? `${goal.goal.slice(0, 77)}\u2026` : goal.goal;
4961
- const stateColor = goal.goalState === "active" ? color9.green : goal.goalState === "paused" ? color9.amber : goal.goalState === "completed" ? color9.green : goal.goalState === "abandoned" ? color9.dim : color9.dim;
4962
- opts.renderer.write(
4963
- color9.dim("Goal: ") + stateColor(summary) + color9.dim(` [${goal.goalState}] (iter ${goal.iterations})`) + "\n"
4964
- );
4965
- if (goal.journal.length > 0) {
4966
- const lastEntry = expectDefined(goal.journal[goal.journal.length - 1]);
4967
- const statusIcon = lastEntry.status === "success" ? "\u2713" : lastEntry.status === "failure" ? "\u2717" : lastEntry.status === "aborted" ? "\u2298" : lastEntry.status === "skipped" ? "\u229D" : "\xB7";
4968
- opts.renderer.write(
4969
- color9.dim(` Last: ${statusIcon} ${lastEntry.task} (${lastEntry.status})`) + "\n"
4970
- );
4971
- }
4972
- if (goal.engineState === "running") {
4973
- opts.renderer.write(
4974
- color9.amber(" \u21BA Eternal engine was running when last session ended.") + "\n"
4975
- );
4976
- try {
4977
- const answer = (await opts.reader.readLine(color9.dim(" Resume eternal mode? [y/N] "))).trim().toLowerCase();
4978
- if (answer === "y" || answer === "yes") {
4979
- try {
4980
- await opts.slashRegistry.dispatch("/autonomy eternal", opts.agent.ctx);
4981
- } catch (err) {
4982
- opts.renderer.writeError(`Auto-resume failed: ${toErrorMessage(err)}`);
4983
- }
4984
- } else {
4985
- opts.renderer.write(
4986
- color9.dim(" Not resuming. Use `/autonomy eternal` later to continue.") + "\n"
4987
- );
4988
- }
4989
- } catch {
4990
- opts.renderer.write(color9.dim(" Use `/autonomy eternal` to resume.") + "\n");
4991
- }
4992
- } else if (goal.goalState === "paused") {
4993
- opts.renderer.write(color9.amber(" \u23F8 Goal is paused. Use `/goal resume` to continue.") + "\n");
4994
- } else if (goal.goalState === "completed") {
4995
- opts.renderer.write(
4996
- color9.green(" \u2713 Goal completed! Use `/goal clear` to set a new goal.") + "\n"
4997
- );
4998
- } else if (goal.goalState === "abandoned") {
4999
- opts.renderer.write(color9.dim(" Use `/goal clear` to set a new goal.") + "\n");
5000
- }
5001
- opts.renderer.write("\n");
5002
- }
5003
5035
 
5004
5036
  // src/execution-tui-next-step-callbacks.ts
5005
5037
  function createTuiNextStepCallbacks(input) {
@@ -5998,4 +6030,4 @@ export {
5998
6030
  execute,
5999
6031
  resolveReviewerFallbackModels
6000
6032
  };
6001
- //# sourceMappingURL=execution-4IG5XKOL.js.map
6033
+ //# sourceMappingURL=execution-CGT6J5ZN.js.map