@wrongstack/cli 1.0.24 → 1.0.26

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 (124) hide show
  1. package/data/providers.json +44 -0
  2. package/dist/{acp-AJWSKWE5.js → acp-LI665LO2.js} +5 -5
  3. package/dist/ascii-mode-SG4PRNLP.js +7 -0
  4. package/dist/{auth-GRBZ7Y3D.js → auth-TE55JF4Z.js} +14 -14
  5. package/dist/{bench-N5K7Z5O3.js → bench-GTLPM22B.js} +2 -2
  6. package/dist/boot/append-system-prompt.d.ts +10 -0
  7. package/dist/boot/ascii-mode.d.ts +12 -0
  8. package/dist/boot/container-wiring.d.ts +4 -2
  9. package/dist/boot/dispatch-singleshot.d.ts +4 -1
  10. package/dist/boot/mcp-config-flag.d.ts +22 -0
  11. package/dist/boot/piped-stdin.d.ts +40 -0
  12. package/dist/boot/restricted-mode.d.ts +15 -0
  13. package/dist/boot/safe-mode.d.ts +30 -0
  14. package/dist/boot/single-shot-budget.d.ts +30 -0
  15. package/dist/boot/stream-json.d.ts +36 -0
  16. package/dist/boot/structured-output.d.ts +16 -0
  17. package/dist/boot/system-prompt-builder.d.ts +2 -0
  18. package/dist/boot/tool-restriction-flags.d.ts +36 -0
  19. package/dist/boot/worktree-sessions.d.ts +21 -0
  20. package/dist/boot-provider-selection.d.ts +67 -0
  21. package/dist/boot.d.ts +1 -38
  22. package/dist/{chunk-LFMVHT3R.js → chunk-2ERX3RPN.js} +11 -13
  23. package/dist/chunk-4TVYGG6G.js +62 -0
  24. package/dist/chunk-5JYDKG5B.js +154 -0
  25. package/dist/{chunk-3VXYY5JC.js → chunk-5UZBUV2H.js} +3 -19
  26. package/dist/chunk-BEHGRNOQ.js +58 -0
  27. package/dist/chunk-CZTXF6HY.js +140 -0
  28. package/dist/{chunk-SKPDE62W.js → chunk-EPR42SWM.js} +36 -6
  29. package/dist/{chunk-YBUCXXYZ.js → chunk-F5DCFAKI.js} +1 -1
  30. package/dist/chunk-HLSHFXTO.js +97 -0
  31. package/dist/{chunk-BLD5DSVA.js → chunk-KJS5543T.js} +2 -2
  32. package/dist/{chunk-QFPQXKCG.js → chunk-KOEO4CJG.js} +21 -6
  33. package/dist/chunk-LBPLTTZ6.js +105 -0
  34. package/dist/{chunk-3OCUS3VN.js → chunk-LDCGZJTC.js} +4 -4
  35. package/dist/chunk-LKPEBZBE.js +143 -0
  36. package/dist/{chunk-DRM7PSW7.js → chunk-OAVBM55Q.js} +3 -3
  37. package/dist/chunk-PZQBGUVZ.js +18 -0
  38. package/dist/{chunk-MHEBWVXL.js → chunk-Q4INH2DG.js} +46 -2
  39. package/dist/{chunk-ZZRSG7VK.js → chunk-RZ4ZDRYA.js} +3 -3
  40. package/dist/{chunk-U46QR4WR.js → chunk-TI7KLHYX.js} +132 -3
  41. package/dist/{chunk-PGKJ2OQP.js → chunk-WQV2NP57.js} +5 -5
  42. package/dist/chunk-X756ZS72.js +329 -0
  43. package/dist/{chunk-JF2MULWF.js → chunk-YHYINL47.js} +47 -15
  44. package/dist/{cli-context-34Q5IJRA.js → cli-context-UVGAN3NO.js} +407 -327
  45. package/dist/{cli-main-AELJDBGU.js → cli-main-TN3KZ2P6.js} +2652 -1978
  46. package/dist/cli-update-notice.d.ts +2 -1
  47. package/dist/config-doctor.d.ts +1 -1
  48. package/dist/{diag-doctor-WIFJH3XH.js → diag-doctor-BIZAFIAT.js} +2 -2
  49. package/dist/{execution-PYC5FCS4.js → execution-7QIP6GRY.js} +1948 -1666
  50. package/dist/fleet/host-types.d.ts +3 -1
  51. package/dist/goal-commands.d.ts +47 -0
  52. package/dist/goal-host.d.ts +1 -14
  53. package/dist/{hq-JTUTFI4L.js → hq-GLZ7QESM.js} +6 -6
  54. package/dist/{hq-server-PC7GZMPT.js → hq-server-YTKDVQPY.js} +2 -2
  55. package/dist/{hq-service-NW56MUP2.js → hq-service-BMMJAHRT.js} +4 -4
  56. package/dist/import-claude-code-32PCSIQI.js +236 -0
  57. package/dist/index.js +12 -8
  58. package/dist/{mailbox-serve-WDOCH6KR.js → mailbox-serve-NW5VZG7R.js} +3 -3
  59. package/dist/{modeldiag-36OGAL5C.js → modeldiag-36VODVIH.js} +8 -8
  60. package/dist/{per-subcommand-help-XE77MTGJ.js → per-subcommand-help-QDAQASPZ.js} +2 -2
  61. package/dist/permission-prompt.d.ts +14 -0
  62. package/dist/permission-rules-view.d.ts +18 -0
  63. package/dist/{permissions-CFDLXETM.js → permissions-PL27UHYD.js} +67 -45
  64. package/dist/{plugin-usage-S5LVGMBW.js → plugin-usage-CIGOOTX3.js} +2 -2
  65. package/dist/{plugins-RHBIVLI7.js → plugins-HQTXUD6A.js} +4 -2
  66. package/dist/preflight.d.ts +1 -1
  67. package/dist/{projects-LMNAGGEU.js → projects-T4CZCA25.js} +3 -6
  68. package/dist/provider-helpers.d.ts +7 -11
  69. package/dist/{providers-models-2CFG46RD.js → providers-models-5Z2PJTEW.js} +5 -5
  70. package/dist/release-asset-download.d.ts +10 -0
  71. package/dist/release-attestation.d.ts +28 -0
  72. package/dist/remote/remote-session.d.ts +64 -0
  73. package/dist/remote/remote-target.d.ts +69 -0
  74. package/dist/remote-O5WXHLWV.js +561 -0
  75. package/dist/{replay-Z3FTJEMM.js → replay-DEI566CW.js} +2 -2
  76. package/dist/services/commit-message.d.ts +2 -1
  77. package/dist/session-move-P2EC2COA.js +44 -0
  78. package/dist/session-move.d.ts +20 -0
  79. package/dist/session-stats.d.ts +10 -0
  80. package/dist/{sessions-config-IQUH2GXT.js → sessions-config-SXTTLNXA.js} +35 -5
  81. package/dist/short-circuit-flags-74Y5N6CF.js +10 -0
  82. package/dist/slash-commands/command-context.d.ts +15 -5
  83. package/dist/slash-commands/goal-refiner.d.ts +4 -49
  84. package/dist/slash-commands/mcp.d.ts +2 -1
  85. package/dist/slash-commands/permissions.d.ts +4 -0
  86. package/dist/slash-commands/settings-context-mutations.d.ts +5 -0
  87. package/dist/slash-commands/settings-limits-mutations.d.ts +12 -0
  88. package/dist/standalone-auto-update-TOTRGCSA.js +249 -0
  89. package/dist/standalone-auto-update.d.ts +65 -0
  90. package/dist/standalone-update-LZO3MNLH.js +24 -0
  91. package/dist/standalone-update.d.ts +37 -1
  92. package/dist/subcommands/handlers/import-claude-code.d.ts +42 -0
  93. package/dist/subcommands/handlers/permissions.d.ts +9 -3
  94. package/dist/subcommands/handlers/remote.d.ts +6 -0
  95. package/dist/subcommands/handlers/version-help.d.ts +5 -0
  96. package/dist/{subcommands-ZTSIN7LG.js → subcommands-Q6ORSB2E.js} +2 -2
  97. package/dist/tui-resume-callback.d.ts +18 -0
  98. package/dist/{typesafe-HVEVPA6R.js → typesafe-U7YB2RRV.js} +5 -5
  99. package/dist/{typesafe-topic-replay-4W73BOLV.js → typesafe-topic-replay-ZILIU3WS.js} +18 -2
  100. package/dist/{update-7XIOEXTD.js → update-TDZX4IL2.js} +4 -4
  101. package/dist/{update-check-2POMBHFB.js → update-check-J5ZVKS73.js} +3 -3
  102. package/dist/version-JB2UAV2A.js +11 -0
  103. package/dist/version-help-XJJQ7YSH.js +10 -0
  104. package/dist/webui-server/route-contexts.d.ts +1 -1
  105. package/dist/webui-server/session-start-payload.d.ts +5 -1
  106. package/dist/{webui-server-L2SICPTB.js → webui-server-YTHLRFD2.js} +509 -366
  107. package/dist/webui-server-lifecycle.d.ts +57 -0
  108. package/dist/webui-server.d.ts +0 -14
  109. package/dist/wiring/brain-and-orchestration.d.ts +3 -1
  110. package/dist/wiring/cli-prompt-and-tools-setup.d.ts +9 -0
  111. package/dist/wiring/cli-slash-commands-setup.d.ts +1 -0
  112. package/dist/wiring/lifecycle-plugins.d.ts +4 -2
  113. package/dist/wiring/metrics.d.ts +9 -1
  114. package/dist/wiring/pipeline.d.ts +2 -7
  115. package/dist/wiring/plugins.d.ts +3 -0
  116. package/dist/wiring/provider-status.d.ts +1 -0
  117. package/dist/wiring/provider-utility-tools.d.ts +3 -1
  118. package/package.json +28 -28
  119. package/dist/chunk-2BKFWIER.js +0 -98
  120. package/dist/chunk-424ORSE7.js +0 -56
  121. package/dist/chunk-QBBF7GIK.js +0 -65
  122. package/dist/short-circuit-flags-SDT53OML.js +0 -10
  123. package/dist/standalone-update-MW47J3AK.js +0 -164
  124. package/dist/version-help-WZ623NWM.js +0 -10
@@ -1,35 +1,43 @@
1
1
  import {
2
+ activateRestrictedMode,
3
+ announceSafeMode,
2
4
  applySimpleUiFullAutoProfile,
3
5
  detectProjectFacts,
4
6
  isSimpleUiFullAuto,
5
- makePromptDelegate,
7
+ makeStdinPromptDelegate,
6
8
  renderAgentsTemplate,
7
- renderDiff
8
- } from "./chunk-U46QR4WR.js";
9
+ renderDiff,
10
+ resolveLaunchAllowedTools,
11
+ resolveToolRestriction
12
+ } from "./chunk-TI7KLHYX.js";
13
+ import {
14
+ parseOutputFormat,
15
+ resolveJsonSchemaFlag
16
+ } from "./chunk-LKPEBZBE.js";
9
17
  import {
10
18
  theme as theme2
11
19
  } from "./chunk-QD544J2B.js";
12
- import {
13
- fmtTok,
14
- patchConfig
15
- } from "./chunk-EWKESL4L.js";
16
20
  import {
17
21
  parseWebuiSessionChildOptions,
18
22
  writeWebuiSessionChildError
19
23
  } from "./chunk-ZMX5HRLI.js";
24
+ import {
25
+ fmtTok,
26
+ patchConfig
27
+ } from "./chunk-EWKESL4L.js";
20
28
  import {
21
29
  subcommands
22
- } from "./chunk-424ORSE7.js";
30
+ } from "./chunk-BEHGRNOQ.js";
23
31
  import {
24
32
  renderDeepHelp,
25
33
  renderFocusedHelp
26
- } from "./chunk-SKPDE62W.js";
34
+ } from "./chunk-EPR42SWM.js";
27
35
  import {
28
36
  handleHelpVersionShortCircuit
29
- } from "./chunk-PGKJ2OQP.js";
37
+ } from "./chunk-WQV2NP57.js";
30
38
  import {
31
39
  DEFAULT_PORT
32
- } from "./chunk-DRM7PSW7.js";
40
+ } from "./chunk-OAVBM55Q.js";
33
41
  import "./chunk-HXJYHAR4.js";
34
42
  import {
35
43
  resolveHqPasswordInput
@@ -38,20 +46,34 @@ import {
38
46
  normalizeHqPublicOrigin
39
47
  } from "./chunk-5EA6OTLJ.js";
40
48
  import {
41
- parseHqIpAllowlist
42
- } from "./chunk-Q7E3BPDU.js";
49
+ resolveLaunchMcpServers
50
+ } from "./chunk-HLSHFXTO.js";
43
51
  import {
44
52
  installProviderPersisters
45
- } from "./chunk-3OCUS3VN.js";
53
+ } from "./chunk-LDCGZJTC.js";
54
+ import {
55
+ parseHqIpAllowlist
56
+ } from "./chunk-Q7E3BPDU.js";
46
57
  import {
47
58
  discoverAndMergeProviders
48
59
  } from "./chunk-D5GB5MHA.js";
60
+ import {
61
+ runUpdateCommand
62
+ } from "./chunk-KOEO4CJG.js";
63
+ import "./chunk-U3SS4NRH.js";
49
64
  import {
50
65
  applyNodeEnvDefault,
51
66
  applySessionShellDefault,
52
67
  runPreflight
53
- } from "./chunk-QBBF7GIK.js";
54
- import "./chunk-2BKFWIER.js";
68
+ } from "./chunk-LBPLTTZ6.js";
69
+ import "./chunk-RZ4ZDRYA.js";
70
+ import {
71
+ applyAsciiMode
72
+ } from "./chunk-PZQBGUVZ.js";
73
+ import "./chunk-5JYDKG5B.js";
74
+ import {
75
+ CLI_VERSION
76
+ } from "./chunk-F5DCFAKI.js";
55
77
  import {
56
78
  addFromCatalog,
57
79
  boxBottom,
@@ -63,31 +85,23 @@ import {
63
85
  runPicker,
64
86
  saveToGlobalConfig,
65
87
  theme
66
- } from "./chunk-LFMVHT3R.js";
88
+ } from "./chunk-2ERX3RPN.js";
67
89
  import "./chunk-YTEOAWOJ.js";
68
90
  import {
69
91
  isKeylessLocalProvider,
70
92
  visibleModelIds
71
- } from "./chunk-3VXYY5JC.js";
93
+ } from "./chunk-5UZBUV2H.js";
94
+ import {
95
+ resolveActiveApiKey
96
+ } from "./chunk-LUMETJFO.js";
97
+ import "./chunk-DAKVBMD4.js";
72
98
  import {
73
99
  activeProfileConfigPath
74
100
  } from "./chunk-YMXXOOFN.js";
75
101
  import "./chunk-WSTVGC2C.js";
76
102
  import {
77
103
  parseArgs
78
- } from "./chunk-MHEBWVXL.js";
79
- import "./chunk-DAKVBMD4.js";
80
- import {
81
- resolveActiveApiKey
82
- } from "./chunk-LUMETJFO.js";
83
- import {
84
- runUpdateCommand
85
- } from "./chunk-QFPQXKCG.js";
86
- import "./chunk-U3SS4NRH.js";
87
- import "./chunk-ZZRSG7VK.js";
88
- import {
89
- CLI_VERSION
90
- } from "./chunk-YBUCXXYZ.js";
104
+ } from "./chunk-Q4INH2DG.js";
91
105
 
92
106
  // src/cli-context.ts
93
107
  import { TOKENS as TOKENS3 } from "@wrongstack/core/kernel";
@@ -192,12 +206,13 @@ function wireContainer(deps) {
192
206
  events,
193
207
  permission: {
194
208
  yolo: deps.config.yolo,
209
+ launchAllowedTools: deps.launchAllowedTools,
195
210
  // Wrapped so the REPL's terminal prompt also appears on the HQ
196
211
  // dashboard and can be answered from there. The wrapper is a no-op
197
212
  // until `approvalMirror.current` is populated (HQ telemetry boot), and
198
213
  // the terminal prompt itself behaves exactly as it always has.
199
214
  promptDelegate: makeMirroredPromptDelegate({
200
- inner: makePromptDelegate(deps.reader),
215
+ inner: makeStdinPromptDelegate(deps.reader),
201
216
  getRegistry: () => approvalMirror.current,
202
217
  getSessionId: () => approvalMirror.sessionId?.()
203
218
  })
@@ -475,7 +490,7 @@ async function promptModeArrow(deps) {
475
490
  const { renderer } = deps;
476
491
  const stdin = process.stdin;
477
492
  const out = (s) => renderer.write(s);
478
- return await new Promise((resolve2) => {
493
+ return await new Promise((resolve3) => {
479
494
  let index = 0;
480
495
  let drawn = 0;
481
496
  let remaining = Math.round(MENU_TIMEOUT_MS / 1e3);
@@ -530,7 +545,7 @@ async function promptModeArrow(deps) {
530
545
  out("\x1B[0J");
531
546
  out(finalLine);
532
547
  out("\x1B[?25h");
533
- resolve2(result);
548
+ resolve3(result);
534
549
  };
535
550
  const pick = () => {
536
551
  const opt = MODE_OPTIONS[index];
@@ -589,7 +604,7 @@ async function promptModeArrow(deps) {
589
604
  setRawMode(stdin, true);
590
605
  stdin.resume();
591
606
  } catch {
592
- resolve2(null);
607
+ resolve3(null);
593
608
  return;
594
609
  }
595
610
  out("\x1B[?25l");
@@ -854,7 +869,7 @@ async function launchDesktop(args) {
854
869
  );
855
870
  return 1;
856
871
  }
857
- return await new Promise((resolve2) => {
872
+ return await new Promise((resolve3) => {
858
873
  const env = { ...process.env };
859
874
  if (native) delete env["ELECTRON_RUN_AS_NODE"];
860
875
  const child = spawn(executable, launchArgs, {
@@ -867,11 +882,11 @@ async function launchDesktop(args) {
867
882
  `${color2.red("\u2717 Failed to start WrongStack Desktop:")} ${err.message}
868
883
  `
869
884
  );
870
- resolve2(1);
885
+ resolve3(1);
871
886
  });
872
887
  child.once("exit", (code, signal) => {
873
- if (typeof code === "number") resolve2(code);
874
- else resolve2(signal ? 1 : 0);
888
+ if (typeof code === "number") resolve3(code);
889
+ else resolve3(signal ? 1 : 0);
875
890
  });
876
891
  });
877
892
  }
@@ -896,24 +911,24 @@ async function isHqAlreadyRunning(dataDir) {
896
911
  return null;
897
912
  }
898
913
  async function isPortInUse(host, port) {
899
- return new Promise((resolve2) => {
914
+ return new Promise((resolve3) => {
900
915
  const server = net.createServer();
901
916
  server.once("error", (err) => {
902
917
  if (err.code === "EADDRINUSE") {
903
- resolve2(true);
918
+ resolve3(true);
904
919
  } else {
905
- resolve2(false);
920
+ resolve3(false);
906
921
  }
907
922
  });
908
923
  server.once("listening", () => {
909
- server.close(() => resolve2(false));
924
+ server.close(() => resolve3(false));
910
925
  });
911
926
  server.listen(port, host);
912
927
  });
913
928
  }
914
929
  async function handleHqShortCircuit(flags) {
915
930
  if (flags["hq"] !== true) return null;
916
- const { startHqServer } = await import("./hq-server-PC7GZMPT.js");
931
+ const { startHqServer } = await import("./hq-server-YTKDVQPY.js");
917
932
  const tunnelRequested = flags["tunnel"] === true;
918
933
  const rawPublicUrl = typeof flags["hq-public-url"] === "string" ? flags["hq-public-url"] : process.env.WRONGSTACK_HQ_PUBLIC_URL;
919
934
  let publicOrigin;
@@ -1127,7 +1142,7 @@ ${color3.green("Cloudflare Quick Tunnel ready:")} ${browserUrl}
1127
1142
  } catch {
1128
1143
  }
1129
1144
  }
1130
- await new Promise((resolve2) => {
1145
+ await new Promise((resolve3) => {
1131
1146
  const shutdown = async () => {
1132
1147
  const results = await Promise.allSettled([
1133
1148
  ...tunnel ? [tunnel.close()] : [],
@@ -1146,7 +1161,7 @@ ${color3.green("Cloudflare Quick Tunnel ready:")} ${browserUrl}
1146
1161
  })
1147
1162
  );
1148
1163
  }
1149
- resolve2();
1164
+ resolve3();
1150
1165
  };
1151
1166
  process.on("SIGINT", shutdown);
1152
1167
  process.on("SIGTERM", shutdown);
@@ -1155,26 +1170,195 @@ ${color3.green("Cloudflare Quick Tunnel ready:")} ${browserUrl}
1155
1170
  }
1156
1171
 
1157
1172
  // src/boot.ts
1158
- import * as fs6 from "node:fs/promises";
1159
- import { createRequire as createRequire4 } from "node:module";
1160
1173
  import * as os from "node:os";
1161
- import * as path7 from "node:path";
1174
+ import * as path9 from "node:path";
1175
+ import { toErrorMessage as toErrorMessage5 } from "@wrongstack/core/utils";
1176
+
1177
+ // src/boot-provider-selection.ts
1178
+ import * as fs2 from "node:fs/promises";
1179
+ import { createRequire as createRequire4 } from "node:module";
1180
+ import * as path4 from "node:path";
1162
1181
  import { fileURLToPath } from "node:url";
1163
- import { moduleUrlFor, toErrorMessage as toErrorMessage4, wrongstackPackageJsonPath as wrongstackPackageJsonPath3 } from "@wrongstack/core/utils";
1182
+ import {
1183
+ color as color4,
1184
+ moduleUrlFor,
1185
+ toErrorMessage,
1186
+ wrongstackPackageJsonPath as wrongstackPackageJsonPath3
1187
+ } from "@wrongstack/core/utils";
1188
+ import { isSetupProvider } from "@wrongstack/providers";
1189
+ function resolveBundledOverlayFile() {
1190
+ try {
1191
+ return fileURLToPath(
1192
+ new URL("../data/providers.json", moduleUrlFor(import.meta.url, "@wrongstack/cli"))
1193
+ );
1194
+ } catch {
1195
+ return void 0;
1196
+ }
1197
+ }
1198
+ async function validateSavedProviderModel(config, modelsRegistry) {
1199
+ const providerId = config.provider;
1200
+ const modelId = config.model;
1201
+ if (!providerId || !modelId) return { ok: false, reason: "missing provider/model" };
1202
+ if (isSetupProvider(providerId)) return { ok: true };
1203
+ const saved = config.providers?.[providerId];
1204
+ const lookupId = saved?.type && saved.type !== providerId ? saved.type : providerId;
1205
+ const catalogProvider = await modelsRegistry.getProvider(lookupId).catch(() => void 0);
1206
+ if (!catalogProvider && !saved?.family)
1207
+ return { ok: false, reason: `provider "${providerId}" is no longer available` };
1208
+ const hasCredential = (catalogProvider?.envVars ?? saved?.envVars ?? []).some(
1209
+ (envVar) => Boolean(process.env[envVar])
1210
+ ) || saved !== void 0 && resolveActiveApiKey(saved) !== void 0 || isKeylessLocalProvider({
1211
+ apiBase: saved?.baseUrl ?? catalogProvider?.apiBase,
1212
+ envVars: saved?.envVars ?? catalogProvider?.envVars
1213
+ });
1214
+ if (!hasCredential) return { ok: false, reason: `provider "${providerId}" has no usable key` };
1215
+ const visible = visibleModelIds(
1216
+ providerId,
1217
+ config,
1218
+ (catalogProvider?.models ?? []).map((m) => m.id),
1219
+ saved
1220
+ );
1221
+ if (visible.length > 0 && !visible.includes(modelId)) {
1222
+ return {
1223
+ ok: false,
1224
+ reason: `model "${modelId}" is no longer available for provider "${providerId}"`
1225
+ };
1226
+ }
1227
+ return { ok: true };
1228
+ }
1229
+ async function autoSelectSavedProvider(config, modelsRegistry) {
1230
+ const providers = config.providers ?? {};
1231
+ const entries = config.provider && providers[config.provider] ? [[config.provider, providers[config.provider]]] : Object.entries(providers);
1232
+ for (const [id, cfg] of entries) {
1233
+ if (!cfg) continue;
1234
+ let model = cfg.models?.[0];
1235
+ if (!model) {
1236
+ const catalogId = cfg.type && cfg.type !== id ? cfg.type : id;
1237
+ const catalog = await modelsRegistry.getProvider(catalogId).catch(() => void 0);
1238
+ model = catalog?.models?.[0]?.id;
1239
+ }
1240
+ if (model) return { provider: id, model };
1241
+ }
1242
+ return void 0;
1243
+ }
1244
+ function resolveBundledSkillsDir2() {
1245
+ try {
1246
+ const req = createRequire4(import.meta.url);
1247
+ const corePkg = wrongstackPackageJsonPath3("@wrongstack/core", (id) => req.resolve(id));
1248
+ return path4.join(path4.dirname(corePkg), "skills");
1249
+ } catch {
1250
+ return void 0;
1251
+ }
1252
+ }
1253
+ function resolveBundledPromptsDir2() {
1254
+ try {
1255
+ const req = createRequire4(import.meta.url);
1256
+ const corePkg = wrongstackPackageJsonPath3("@wrongstack/core", (id) => req.resolve(id));
1257
+ return path4.join(path4.dirname(corePkg), "data", "prompts");
1258
+ } catch {
1259
+ return void 0;
1260
+ }
1261
+ }
1262
+ function isHomeDirectory(cwd, userHome) {
1263
+ if (!cwd || !userHome) return false;
1264
+ return path4.resolve(cwd) === path4.resolve(userHome);
1265
+ }
1266
+ function shouldPrintYoloNotice(lastChoices, yoloPinned, yolo) {
1267
+ return !lastChoices && yoloPinned === void 0 && yolo;
1268
+ }
1269
+ async function checkGitInCwd(opts) {
1270
+ const { cwd, renderer, reader } = opts;
1271
+ const cwdGit = path4.join(cwd, ".git");
1272
+ let hasCwdGit = false;
1273
+ try {
1274
+ await fs2.access(cwdGit);
1275
+ hasCwdGit = true;
1276
+ } catch {
1277
+ }
1278
+ if (!hasCwdGit) {
1279
+ renderer.write(
1280
+ `
1281
+ ${color4.amber("\u25CB")} This folder has no ${color4.bold(".git")} repository.
1282
+ `
1283
+ );
1284
+ const answer = (await reader.readLine(` ${color4.amber("?")} Initialize one here? ${color4.dim("[y/N]")} `)).trim().toLowerCase();
1285
+ if (answer === "y" || answer === "yes") {
1286
+ try {
1287
+ const { spawn: spawn2 } = await import("node:child_process");
1288
+ await new Promise((resolve3, reject) => {
1289
+ const child = spawn2("git", ["init"], {
1290
+ cwd,
1291
+ signal: AbortSignal.timeout(1e4),
1292
+ windowsHide: true
1293
+ });
1294
+ child.on("error", reject);
1295
+ child.on(
1296
+ "close",
1297
+ (code) => code === 0 ? resolve3() : reject(new Error(`git init failed with ${code}`))
1298
+ );
1299
+ });
1300
+ renderer.write(` ${color4.green("\u2713")} Git repository initialized
1301
+ `);
1302
+ hasCwdGit = true;
1303
+ } catch (err) {
1304
+ renderer.writeError(`git init failed: ${toErrorMessage(err)}
1305
+ `);
1306
+ }
1307
+ }
1308
+ }
1309
+ const parentDir = path4.dirname(cwd);
1310
+ if (parentDir !== cwd) {
1311
+ try {
1312
+ await fs2.access(path4.join(parentDir, ".git"));
1313
+ renderer.write(
1314
+ ` ${color4.dim("\u2139")} A ${color4.bold(".git")} repo exists in the parent directory: ${color4.dim(parentDir)}
1315
+ `
1316
+ );
1317
+ } catch {
1318
+ }
1319
+ }
1320
+ }
1321
+
1322
+ // src/boot.ts
1164
1323
  import { DefaultLogger } from "@wrongstack/core/infrastructure";
1165
1324
  import { TOKENS as TOKENS2 } from "@wrongstack/core/kernel";
1166
- import { DefaultModelsRegistry } from "@wrongstack/core/models";
1325
+ import { DefaultModelsRegistry, startCatalog } from "@wrongstack/core/models";
1167
1326
  import { ToolRegistry } from "@wrongstack/core/registry";
1168
1327
  import { normalizeTokenSavingTier } from "@wrongstack/core/types";
1169
- import { color as color10, isStdinTTY as isStdinTTY2, writeErr } from "@wrongstack/core/utils";
1170
- import { isSetupProvider, SETUP_MODEL_ID, SETUP_PROVIDER_ID } from "@wrongstack/providers";
1328
+ import { color as color11, isStdinTTY as isStdinTTY2, writeErr } from "@wrongstack/core/utils";
1329
+ import { isSetupProvider as isSetupProvider2, SETUP_MODEL_ID, SETUP_PROVIDER_ID } from "@wrongstack/providers";
1171
1330
  import { createDefaultContainer as createDefaultContainer2 } from "@wrongstack/runtime";
1172
1331
  import { registerBuiltinToolTier } from "@wrongstack/tools/tool-tier";
1173
1332
 
1333
+ // src/boot/append-system-prompt.ts
1334
+ import * as fs3 from "node:fs/promises";
1335
+ import * as path5 from "node:path";
1336
+ async function resolveAppendedSystemPrompt(flags, cwd) {
1337
+ const parts = [];
1338
+ const inline = flags["append-system-prompt"];
1339
+ if (typeof inline === "string" && inline.trim()) parts.push(inline.trim());
1340
+ const file = flags["append-system-prompt-file"];
1341
+ if (file === true) {
1342
+ throw new Error("--append-system-prompt-file needs a path");
1343
+ }
1344
+ if (typeof file === "string" && file.trim()) {
1345
+ const resolved = path5.resolve(cwd, file.trim());
1346
+ let text;
1347
+ try {
1348
+ text = await fs3.readFile(resolved, "utf8");
1349
+ } catch (err) {
1350
+ const reason = err.code ?? String(err);
1351
+ throw new Error(`--append-system-prompt-file: cannot read ${resolved} (${reason})`);
1352
+ }
1353
+ if (text.trim()) parts.push(text.trim());
1354
+ }
1355
+ return parts.length > 0 ? parts.join("\n\n") : void 0;
1356
+ }
1357
+
1174
1358
  // src/boot/config-backup-recovery.ts
1175
- import * as fs2 from "node:fs/promises";
1176
- import * as path4 from "node:path";
1177
- import { atomicWrite as atomicWrite2, backupConfigFile, color as color4, toErrorMessage } from "@wrongstack/core/utils";
1359
+ import * as fs4 from "node:fs/promises";
1360
+ import * as path6 from "node:path";
1361
+ import { atomicWrite as atomicWrite2, backupConfigFile, color as color5, toErrorMessage as toErrorMessage2 } from "@wrongstack/core/utils";
1178
1362
  function isRecord(value) {
1179
1363
  return value !== null && typeof value === "object" && !Array.isArray(value);
1180
1364
  }
@@ -1185,7 +1369,7 @@ function providerIds(value) {
1185
1369
  }
1186
1370
  async function defaultProfileProvidersAreEmpty(profilePath) {
1187
1371
  try {
1188
- const parsed = JSON.parse(await fs2.readFile(profilePath, "utf8"));
1372
+ const parsed = JSON.parse(await fs4.readFile(profilePath, "utf8"));
1189
1373
  return providerIds(parsed).length === 0;
1190
1374
  } catch {
1191
1375
  return false;
@@ -1208,7 +1392,7 @@ function profileSnapshotTimestamp(fileName, fallback) {
1208
1392
  );
1209
1393
  }
1210
1394
  async function findLatestProviderBackup(globalRoot, profileName = "default") {
1211
- const directory = path4.join(globalRoot, "config-history");
1395
+ const directory = path6.join(globalRoot, "config-history");
1212
1396
  const escapedProfile = profileName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1213
1397
  const filePattern = new RegExp(
1214
1398
  `^profiles-${escapedProfile}-config-\\d{4}-\\d{2}-\\d{2}T\\d{2}-\\d{2}-\\d{2}-\\d{3}\\.json$`,
@@ -1217,7 +1401,7 @@ async function findLatestProviderBackup(globalRoot, profileName = "default") {
1217
1401
  const candidates = [];
1218
1402
  let entries;
1219
1403
  try {
1220
- entries = await fs2.readdir(directory, { withFileTypes: true });
1404
+ entries = await fs4.readdir(directory, { withFileTypes: true });
1221
1405
  } catch {
1222
1406
  return void 0;
1223
1407
  }
@@ -1225,9 +1409,9 @@ async function findLatestProviderBackup(globalRoot, profileName = "default") {
1225
1409
  if (!entry.isFile() || !filePattern.test(entry.name)) {
1226
1410
  continue;
1227
1411
  }
1228
- const filePath = path4.join(directory, entry.name);
1412
+ const filePath = path6.join(directory, entry.name);
1229
1413
  try {
1230
- const stat2 = await fs2.stat(filePath);
1414
+ const stat2 = await fs4.stat(filePath);
1231
1415
  candidates.push({
1232
1416
  filePath,
1233
1417
  fileName: entry.name,
@@ -1239,7 +1423,7 @@ async function findLatestProviderBackup(globalRoot, profileName = "default") {
1239
1423
  candidates.sort((a, b) => b.modifiedAtMs - a.modifiedAtMs);
1240
1424
  for (const candidate of candidates) {
1241
1425
  try {
1242
- const raw = await fs2.readFile(candidate.filePath, "utf8");
1426
+ const raw = await fs4.readFile(candidate.filePath, "utf8");
1243
1427
  const parsed = JSON.parse(raw);
1244
1428
  const ids = providerIds(parsed);
1245
1429
  if (ids.length === 0) continue;
@@ -1251,7 +1435,7 @@ async function findLatestProviderBackup(globalRoot, profileName = "default") {
1251
1435
  }
1252
1436
  async function restoreDefaultProfileBackup(opts) {
1253
1437
  await backupConfigFile(opts.profilePath, { globalRoot: opts.globalRoot });
1254
- await fs2.mkdir(path4.dirname(opts.profilePath), { recursive: true });
1438
+ await fs4.mkdir(path6.dirname(opts.profilePath), { recursive: true });
1255
1439
  await atomicWrite2(opts.profilePath, opts.backup.raw, { mode: 384 });
1256
1440
  }
1257
1441
  async function maybeRestoreDefaultProfileFromBackup(opts) {
@@ -1264,12 +1448,12 @@ async function maybeRestoreDefaultProfileFromBackup(opts) {
1264
1448
  const providerSummary = remainder > 0 ? `${shownProviders} +${remainder}` : shownProviders;
1265
1449
  opts.renderer.write(
1266
1450
  `
1267
- ${color4.amber("\u25CB")} ${color4.bold(profileName)} profile has no saved providers.
1268
- ${color4.dim("Latest usable backup:")} ${color4.bold(backup.fileName)} ${color4.dim(`(${backup.providerIds.length} provider: ${providerSummary})`)}
1451
+ ${color5.amber("\u25CB")} ${color5.bold(profileName)} profile has no saved providers.
1452
+ ${color5.dim("Latest usable backup:")} ${color5.bold(backup.fileName)} ${color5.dim(`(${backup.providerIds.length} provider: ${providerSummary})`)}
1269
1453
  `
1270
1454
  );
1271
1455
  const answer = (await opts.reader.readLine(
1272
- ` ${color4.amber("?")} Restore all settings from this backup? ${color4.dim("[Y/n]")} `
1456
+ ` ${color5.amber("?")} Restore all settings from this backup? ${color5.dim("[Y/n]")} `
1273
1457
  )).trim().toLowerCase();
1274
1458
  if (answer === "n" || answer === "no") return false;
1275
1459
  try {
@@ -1279,12 +1463,12 @@ async function maybeRestoreDefaultProfileFromBackup(opts) {
1279
1463
  profilePath: opts.profilePath
1280
1464
  });
1281
1465
  opts.renderer.write(
1282
- ` ${color4.green("\u2713")} Restored all settings from ${color4.dim(backup.fileName)}
1466
+ ` ${color5.green("\u2713")} Restored all settings from ${color5.dim(backup.fileName)}
1283
1467
  `
1284
1468
  );
1285
1469
  return true;
1286
1470
  } catch (err) {
1287
- opts.renderer.writeWarning(`Could not restore config backup: ${toErrorMessage(err)}
1471
+ opts.renderer.writeWarning(`Could not restore config backup: ${toErrorMessage2(err)}
1288
1472
  `);
1289
1473
  return false;
1290
1474
  }
@@ -1298,11 +1482,11 @@ import {
1298
1482
  SYSTEM_PROMPT_VARIANT_OPTIONS,
1299
1483
  SYSTEM_PROMPT_VARIANTS
1300
1484
  } from "@wrongstack/core/agent";
1301
- import { color as color8 } from "@wrongstack/core/utils";
1485
+ import { color as color9 } from "@wrongstack/core/utils";
1302
1486
 
1303
1487
  // src/pre-launch/first-run.ts
1304
1488
  import { hasProviderCredential } from "@wrongstack/core/models";
1305
- import { color as color5, toErrorMessage as toErrorMessage2 } from "@wrongstack/core/utils";
1489
+ import { color as color6, toErrorMessage as toErrorMessage3 } from "@wrongstack/core/utils";
1306
1490
  import { PROVIDER_DEFINITIONS } from "@wrongstack/providers/definitions";
1307
1491
  async function hasAnyCredential(config, modelsRegistry, env = process.env) {
1308
1492
  for (const cfg of Object.values(config.providers ?? {})) {
@@ -1328,39 +1512,39 @@ function renderWelcome(renderer) {
1328
1512
  renderer.write(`${boxTop("Welcome to WrongStack")}
1329
1513
  `);
1330
1514
  renderer.write(
1331
- `${boxRow(color5.dim("No model is connected yet. Pick how you want to connect one:"))}
1515
+ `${boxRow(color6.dim("No model is connected yet. Pick how you want to connect one:"))}
1332
1516
  `
1333
1517
  );
1334
1518
  renderer.write(`${boxDivider()}
1335
1519
  `);
1336
1520
  renderer.write(
1337
1521
  `${boxRow(
1338
- `${theme.accent("1")} ${color5.bold("Sign in with a subscription")} ${color5.dim("ChatGPT \xB7 Claude \xB7 GitHub Copilot")}`
1522
+ `${theme.accent("1")} ${color6.bold("Sign in with a subscription")} ${color6.dim("ChatGPT \xB7 Claude \xB7 GitHub Copilot")}`
1339
1523
  )}
1340
1524
  `
1341
1525
  );
1342
1526
  renderer.write(
1343
1527
  `${boxRow(
1344
- `${theme.accent("2")} ${color5.bold("Add an API key")} ${color5.dim("Anthropic \xB7 OpenAI \xB7 Google \xB7 OpenRouter \xB7 \u2026")}`
1528
+ `${theme.accent("2")} ${color6.bold("Add an API key")} ${color6.dim("Anthropic \xB7 OpenAI \xB7 Google \xB7 OpenRouter \xB7 \u2026")}`
1345
1529
  )}
1346
1530
  `
1347
1531
  );
1348
1532
  renderer.write(
1349
1533
  `${boxRow(
1350
- `${theme.accent("3")} ${color5.bold("Use a local server")} ${color5.dim("Ollama \xB7 LM Studio \xB7 vLLM \xB7 OmniRoute")}`
1534
+ `${theme.accent("3")} ${color6.bold("Use a local server")} ${color6.dim("Ollama \xB7 LM Studio \xB7 vLLM \xB7 OmniRoute")}`
1351
1535
  )}
1352
1536
  `
1353
1537
  );
1354
1538
  renderer.write(
1355
1539
  `${boxRow(
1356
- `${theme.accent("4")} ${color5.bold("Continue without a key")} ${color5.dim("setup mode \u2014 explore the app, no model")}`
1540
+ `${theme.accent("4")} ${color6.bold("Continue without a key")} ${color6.dim("setup mode \u2014 explore the app, no model")}`
1357
1541
  )}
1358
1542
  `
1359
1543
  );
1360
1544
  renderer.write(`${boxDivider()}
1361
1545
  `);
1362
1546
  renderer.write(
1363
- `${boxRow(color5.dim("You can change this any time with /auth inside the app, or `wstack auth`."))}
1547
+ `${boxRow(color6.dim("You can change this any time with /auth inside the app, or `wstack auth`."))}
1364
1548
  `
1365
1549
  );
1366
1550
  renderer.write(`${boxBottom()}
@@ -1379,12 +1563,12 @@ async function runFirstRunSetup(deps) {
1379
1563
  renderWelcome(renderer);
1380
1564
  const answer = (await reader.readLine(
1381
1565
  `
1382
- ${color5.amber("?")} Choose ${color5.dim("(1-4)")} ${color5.dim("[q to quit]")}: `
1566
+ ${color6.amber("?")} Choose ${color6.dim("(1-4)")} ${color6.dim("[q to quit]")}: `
1383
1567
  )).trim().toLowerCase();
1384
1568
  if (!answer || answer === "q" || answer === "quit" || answer === "exit") {
1385
1569
  renderer.write(
1386
1570
  `
1387
- ${color5.dim("No provider configured. Run")} ${color5.bold("wstack auth")} ${color5.dim("when you are ready.")}
1571
+ ${color6.dim("No provider configured. Run")} ${color6.bold("wstack auth")} ${color6.dim("when you are ready.")}
1388
1572
 
1389
1573
  `
1390
1574
  );
@@ -1401,14 +1585,14 @@ ${color5.amber("?")} Choose ${color5.dim("(1-4)")} ${color5.dim("[q to quit]")}:
1401
1585
  try {
1402
1586
  await flow();
1403
1587
  } catch (err) {
1404
- renderer.writeWarning(`Setup step did not complete: ${toErrorMessage2(err)}
1588
+ renderer.writeWarning(`Setup step did not complete: ${toErrorMessage3(err)}
1405
1589
  `);
1406
1590
  }
1407
1591
  let updated;
1408
1592
  try {
1409
1593
  updated = await deps.reloadConfig();
1410
1594
  } catch (err) {
1411
- renderer.writeWarning(`Could not re-read config: ${toErrorMessage2(err)}
1595
+ renderer.writeWarning(`Could not re-read config: ${toErrorMessage3(err)}
1412
1596
  `);
1413
1597
  continue;
1414
1598
  }
@@ -1420,8 +1604,8 @@ ${color5.amber("?")} Choose ${color5.dim("(1-4)")} ${color5.dim("[q to quit]")}:
1420
1604
  }
1421
1605
 
1422
1606
  // src/pre-launch/launch-prompts.ts
1423
- import * as fs3 from "node:fs/promises";
1424
- import { atomicWrite as atomicWrite3, color as color6 } from "@wrongstack/core/utils";
1607
+ import * as fs5 from "node:fs/promises";
1608
+ import { atomicWrite as atomicWrite3, color as color7 } from "@wrongstack/core/utils";
1425
1609
  var LaunchAbortedError = class extends Error {
1426
1610
  exitCode = 0;
1427
1611
  constructor() {
@@ -1452,19 +1636,19 @@ async function runLaunchPrompts(opts) {
1452
1636
  yolo: yoloPinned ?? lastChoices.yolo,
1453
1637
  autonomy: autonomyPinned ?? lastChoices.autonomy
1454
1638
  };
1455
- const onOff = (v) => v ? color6.green("on") : color6.dim("off");
1639
+ const onOff = (v) => v ? color7.green("on") : color7.dim("off");
1456
1640
  const modeLabel = effective.mode.toUpperCase();
1457
1641
  renderer.write(
1458
1642
  `
1459
- ${color6.dim("Last settings:")} ${color6.bold(modeLabel)} \xB7 YOLO ${onOff(effective.yolo)} \xB7 Autonomy ${effective.autonomy === "auto" ? color6.green("auto") : color6.dim("off")}
1643
+ ${color7.dim("Last settings:")} ${color7.bold(modeLabel)} \xB7 YOLO ${onOff(effective.yolo)} \xB7 Autonomy ${effective.autonomy === "auto" ? color7.green("auto") : color7.dim("off")}
1460
1644
  `
1461
1645
  );
1462
1646
  const answer = (await reader.readLine(
1463
- ` ${color6.amber("?")} Continue with these? ${color6.dim("[Y/n/q]")} ${color6.dim("(auto Y in 5s)")} `,
1647
+ ` ${color7.amber("?")} Continue with these? ${color7.dim("[Y/n/q]")} ${color7.dim("(auto Y in 5s)")} `,
1464
1648
  { timeoutMs: 5e3, defaultAnswer: "y" }
1465
1649
  )).trim().toLowerCase();
1466
1650
  if (answer === "q") {
1467
- renderer.write(color6.dim(" Goodbye!\n"));
1651
+ renderer.write(color7.dim(" Goodbye!\n"));
1468
1652
  throw new LaunchAbortedError();
1469
1653
  }
1470
1654
  if (answer !== "n" && answer !== "no") {
@@ -1472,7 +1656,7 @@ async function runLaunchPrompts(opts) {
1472
1656
  const badgeStr2 = badges2.length > 0 ? ` (${badges2.join(" \xB7 ")})` : "";
1473
1657
  renderer.write(
1474
1658
  `
1475
- ${color6.green("\u25B6")} Launching in ${color6.bold(modeLabel)} mode${badgeStr2}
1659
+ ${color7.green("\u25B6")} Launching in ${color7.bold(modeLabel)} mode${badgeStr2}
1476
1660
 
1477
1661
  `
1478
1662
  );
@@ -1485,10 +1669,10 @@ async function runLaunchPrompts(opts) {
1485
1669
  } else {
1486
1670
  const answer = (await reader.readLine(
1487
1671
  `
1488
- ${color6.amber("?")} Interactive mode: ${color6.bold("T")}UI / ${color6.bold("R")}EPL ${color6.dim("[T/r/q]")} `
1672
+ ${color7.amber("?")} Interactive mode: ${color7.bold("T")}UI / ${color7.bold("R")}EPL ${color7.dim("[T/r/q]")} `
1489
1673
  )).trim().toLowerCase();
1490
1674
  if (answer === "q") {
1491
- renderer.write(color6.dim(" Goodbye!\n"));
1675
+ renderer.write(color7.dim(" Goodbye!\n"));
1492
1676
  throw new LaunchAbortedError();
1493
1677
  }
1494
1678
  mode = answer === "r" || answer === "repl" ? "repl" : "tui";
@@ -1498,10 +1682,10 @@ async function runLaunchPrompts(opts) {
1498
1682
  yolo = yoloPinned;
1499
1683
  } else {
1500
1684
  const answer = (await reader.readLine(
1501
- ` ${color6.amber("?")} YOLO mode ${color6.dim("(auto-approve tool calls)")} ${color6.dim("[Y/n/q]")} `
1685
+ ` ${color7.amber("?")} YOLO mode ${color7.dim("(auto-approve tool calls)")} ${color7.dim("[Y/n/q]")} `
1502
1686
  )).trim().toLowerCase();
1503
1687
  if (answer === "q") {
1504
- renderer.write(color6.dim(" Goodbye!\n"));
1688
+ renderer.write(color7.dim(" Goodbye!\n"));
1505
1689
  throw new LaunchAbortedError();
1506
1690
  }
1507
1691
  yolo = answer !== "n" && answer !== "no";
@@ -1511,10 +1695,10 @@ async function runLaunchPrompts(opts) {
1511
1695
  autonomy = autonomyPinned;
1512
1696
  } else {
1513
1697
  const answer = (await reader.readLine(
1514
- ` ${color6.amber("?")} Autonomy mode ${color6.dim("(auto-continue \u2014 agent picks next step)")} ${color6.dim("[Y/n/q]")} `
1698
+ ` ${color7.amber("?")} Autonomy mode ${color7.dim("(auto-continue \u2014 agent picks next step)")} ${color7.dim("[Y/n/q]")} `
1515
1699
  )).trim().toLowerCase();
1516
1700
  if (answer === "q") {
1517
- renderer.write(color6.dim(" Goodbye!\n"));
1701
+ renderer.write(color7.dim(" Goodbye!\n"));
1518
1702
  throw new LaunchAbortedError();
1519
1703
  }
1520
1704
  autonomy = answer !== "n" && answer !== "no" ? "auto" : "off";
@@ -1523,7 +1707,7 @@ async function runLaunchPrompts(opts) {
1523
1707
  const badgeStr = badges.length > 0 ? ` (${badges.join(" \xB7 ")})` : "";
1524
1708
  renderer.write(
1525
1709
  `
1526
- ${color6.green("\u25B6")} Launching in ${color6.bold(mode.toUpperCase())} mode${badgeStr}
1710
+ ${color7.green("\u25B6")} Launching in ${color7.bold(mode.toUpperCase())} mode${badgeStr}
1527
1711
 
1528
1712
  `
1529
1713
  );
@@ -1531,21 +1715,21 @@ async function runLaunchPrompts(opts) {
1531
1715
  }
1532
1716
  function buildBadges(chosen) {
1533
1717
  const badges = [];
1534
- if (chosen.yolo) badges.push(color6.yellow("YOLO"));
1718
+ if (chosen.yolo) badges.push(color7.yellow("YOLO"));
1535
1719
  if (chosen.autonomy !== "off")
1536
- badges.push(color6.magenta(`AUTONOMY:${chosen.autonomy.toUpperCase()}`));
1720
+ badges.push(color7.magenta(`AUTONOMY:${chosen.autonomy.toUpperCase()}`));
1537
1721
  return badges;
1538
1722
  }
1539
1723
  async function persistLaunchChoices(configPath, choices) {
1540
1724
  let fileExists = false;
1541
1725
  try {
1542
- await fs3.access(configPath);
1726
+ await fs5.access(configPath);
1543
1727
  fileExists = true;
1544
1728
  } catch {
1545
1729
  }
1546
1730
  let existing = {};
1547
1731
  try {
1548
- const raw = await fs3.readFile(configPath, "utf8");
1732
+ const raw = await fs5.readFile(configPath, "utf8");
1549
1733
  existing = JSON.parse(raw);
1550
1734
  } catch (err) {
1551
1735
  if (fileExists) {
@@ -1565,9 +1749,9 @@ async function persistLaunchChoices(configPath, choices) {
1565
1749
  }
1566
1750
 
1567
1751
  // src/pre-launch/project-check.ts
1568
- import * as fs4 from "node:fs/promises";
1569
- import * as path5 from "node:path";
1570
- import { color as color7, toErrorMessage as toErrorMessage3 } from "@wrongstack/core/utils";
1752
+ import * as fs6 from "node:fs/promises";
1753
+ import * as path7 from "node:path";
1754
+ import { color as color8, toErrorMessage as toErrorMessage4 } from "@wrongstack/core/utils";
1571
1755
  var MANIFESTS = [
1572
1756
  "package.json",
1573
1757
  "pyproject.toml",
@@ -1582,13 +1766,13 @@ var MANIFESTS = [
1582
1766
  ];
1583
1767
  async function detectProjectKind(projectRoot) {
1584
1768
  try {
1585
- await fs4.access(path5.join(projectRoot, ".wrongstack", "AGENTS.md"));
1769
+ await fs6.access(path7.join(projectRoot, ".wrongstack", "AGENTS.md"));
1586
1770
  return "initialized";
1587
1771
  } catch {
1588
1772
  }
1589
1773
  for (const m of MANIFESTS) {
1590
1774
  try {
1591
- await fs4.access(path5.join(projectRoot, m));
1775
+ await fs6.access(path7.join(projectRoot, m));
1592
1776
  return "project";
1593
1777
  } catch {
1594
1778
  }
@@ -1596,12 +1780,12 @@ async function detectProjectKind(projectRoot) {
1596
1780
  return "empty";
1597
1781
  }
1598
1782
  async function scaffoldAgentsMd(projectRoot) {
1599
- const dir = path5.join(projectRoot, ".wrongstack");
1600
- const file = path5.join(dir, "AGENTS.md");
1783
+ const dir = path7.join(projectRoot, ".wrongstack");
1784
+ const file = path7.join(dir, "AGENTS.md");
1601
1785
  const facts = await detectProjectFacts(projectRoot);
1602
1786
  const body = renderAgentsTemplate(facts);
1603
- await fs4.mkdir(dir, { recursive: true });
1604
- await fs4.writeFile(file, body, "utf8");
1787
+ await fs6.mkdir(dir, { recursive: true });
1788
+ await fs6.writeFile(file, body, "utf8");
1605
1789
  return file;
1606
1790
  }
1607
1791
  async function runProjectCheck(opts) {
@@ -1610,7 +1794,7 @@ async function runProjectCheck(opts) {
1610
1794
  if (kind === "initialized") {
1611
1795
  renderer.write(
1612
1796
  `
1613
- ${color7.green("\u2713")} Project initialized ${color7.dim(`(${path5.join(projectRoot, ".wrongstack", "AGENTS.md")})`)}
1797
+ ${color8.green("\u2713")} Project initialized ${color8.dim(`(${path7.join(projectRoot, ".wrongstack", "AGENTS.md")})`)}
1614
1798
  `
1615
1799
  );
1616
1800
  return true;
@@ -1618,51 +1802,51 @@ async function runProjectCheck(opts) {
1618
1802
  if (kind === "project") {
1619
1803
  renderer.write(
1620
1804
  `
1621
- ${color7.amber("\u25CF")} Project detected ${color7.dim(`(${projectRoot})`)} but ${color7.bold(".wrongstack/AGENTS.md")} is missing.
1805
+ ${color8.amber("\u25CF")} Project detected ${color8.dim(`(${projectRoot})`)} but ${color8.bold(".wrongstack/AGENTS.md")} is missing.
1622
1806
  `
1623
1807
  );
1624
1808
  const answer2 = (await reader.readLine(
1625
- ` ${color7.amber("?")} Scaffold ${color7.bold("AGENTS.md")} now? ${color7.dim("[y/N/q]")} `
1809
+ ` ${color8.amber("?")} Scaffold ${color8.bold("AGENTS.md")} now? ${color8.dim("[y/N/q]")} `
1626
1810
  )).trim().toLowerCase();
1627
1811
  if (answer2 === "q") {
1628
- renderer.write(color7.dim(" Cancelled.\n"));
1812
+ renderer.write(color8.dim(" Cancelled.\n"));
1629
1813
  return false;
1630
1814
  }
1631
1815
  if (answer2 === "y" || answer2 === "yes") {
1632
1816
  try {
1633
1817
  const file = await scaffoldAgentsMd(projectRoot);
1634
- renderer.write(` ${color7.green("\u2713")} Wrote ${color7.dim(file)}
1818
+ renderer.write(` ${color8.green("\u2713")} Wrote ${color8.dim(file)}
1635
1819
  `);
1636
1820
  } catch (err) {
1637
- renderer.writeError(`Failed to scaffold AGENTS.md: ${toErrorMessage3(err)}`);
1821
+ renderer.writeError(`Failed to scaffold AGENTS.md: ${toErrorMessage4(err)}`);
1638
1822
  }
1639
1823
  }
1640
1824
  return true;
1641
1825
  }
1642
- const gitDir = path5.join(projectRoot, ".git");
1826
+ const gitDir = path7.join(projectRoot, ".git");
1643
1827
  let hasGit = false;
1644
1828
  try {
1645
- await fs4.access(gitDir);
1829
+ await fs6.access(gitDir);
1646
1830
  hasGit = true;
1647
1831
  } catch {
1648
1832
  }
1649
1833
  if (!hasGit) {
1650
1834
  renderer.write(
1651
1835
  `
1652
- ${color7.dim("\u25CB")} ${color7.dim(`No project manifest in ${projectRoot} \u2014 running in a scratch directory.`)}
1836
+ ${color8.dim("\u25CB")} ${color8.dim(`No project manifest in ${projectRoot} \u2014 running in a scratch directory.`)}
1653
1837
  `
1654
1838
  );
1655
1839
  const answer2 = (await reader.readLine(
1656
- ` ${color7.amber("?")} No git repo found. ${color7.bold("Initialize git?")} ${color7.dim("[y/N/q]")} `
1840
+ ` ${color8.amber("?")} No git repo found. ${color8.bold("Initialize git?")} ${color8.dim("[y/N/q]")} `
1657
1841
  )).trim().toLowerCase();
1658
1842
  if (answer2 === "q") {
1659
- renderer.write(color7.dim(" Cancelled.\n"));
1843
+ renderer.write(color8.dim(" Cancelled.\n"));
1660
1844
  return false;
1661
1845
  }
1662
1846
  if (answer2 === "y" || answer2 === "yes") {
1663
1847
  try {
1664
1848
  const { spawn: spawn2 } = await import("node:child_process");
1665
- await new Promise((resolve2, reject) => {
1849
+ await new Promise((resolve3, reject) => {
1666
1850
  const child = spawn2("git", ["init"], {
1667
1851
  cwd,
1668
1852
  signal: AbortSignal.timeout(1e4),
@@ -1671,26 +1855,26 @@ async function runProjectCheck(opts) {
1671
1855
  child.on("error", reject);
1672
1856
  child.on(
1673
1857
  "close",
1674
- (code) => code === 0 ? resolve2() : reject(new Error(`git init failed with ${code}`))
1858
+ (code) => code === 0 ? resolve3() : reject(new Error(`git init failed with ${code}`))
1675
1859
  );
1676
1860
  });
1677
- renderer.write(` ${color7.green("\u2713")} Git repository initialized
1861
+ renderer.write(` ${color8.green("\u2713")} Git repository initialized
1678
1862
  `);
1679
1863
  } catch (err) {
1680
- renderer.writeError(`git init failed: ${toErrorMessage3(err)}
1864
+ renderer.writeError(`git init failed: ${toErrorMessage4(err)}
1681
1865
  `);
1682
1866
  }
1683
1867
  }
1684
1868
  } else {
1685
1869
  renderer.write(
1686
1870
  `
1687
- ${color7.dim("\u25CB")} ${color7.dim(`No project manifest in ${projectRoot} \u2014 running in a scratch directory.`)}
1871
+ ${color8.dim("\u25CB")} ${color8.dim(`No project manifest in ${projectRoot} \u2014 running in a scratch directory.`)}
1688
1872
  `
1689
1873
  );
1690
1874
  }
1691
- const answer = (await reader.readLine(` ${color7.amber("?")} Continue anyway? ${color7.dim("[Y/n/q]")} `)).trim().toLowerCase();
1875
+ const answer = (await reader.readLine(` ${color8.amber("?")} Continue anyway? ${color8.dim("[Y/n/q]")} `)).trim().toLowerCase();
1692
1876
  if (answer === "q" || answer === "n" || answer === "no") {
1693
- renderer.write(color7.dim(" Cancelled.\n"));
1877
+ renderer.write(color8.dim(" Cancelled.\n"));
1694
1878
  return false;
1695
1879
  }
1696
1880
  return true;
@@ -1725,28 +1909,28 @@ async function runSystemPromptMenu(deps) {
1725
1909
  const defaultVariant = lastVariant ?? "default";
1726
1910
  if (lastVariant) {
1727
1911
  const answer2 = (await reader.readLine(
1728
- ` ${color8.amber("?")} Continue with ${color8.bold(labelFor(lastVariant))} system prompt ${color8.dim(`(~${fmtTok(tokens[lastVariant])} tokens)`)}? ${color8.dim("[Y/n/q]")} ${color8.dim("(auto Y in 5s)")} `,
1912
+ ` ${color9.amber("?")} Continue with ${color9.bold(labelFor(lastVariant))} system prompt ${color9.dim(`(~${fmtTok(tokens[lastVariant])} tokens)`)}? ${color9.dim("[Y/n/q]")} ${color9.dim("(auto Y in 5s)")} `,
1729
1913
  { timeoutMs: SUMMARY_TIMEOUT_MS2, defaultAnswer: "y" }
1730
1914
  )).trim().toLowerCase();
1731
1915
  if (answer2 === "q" || answer2 === "quit") throw new LaunchAbortedError();
1732
1916
  if (answer2 !== "n" && answer2 !== "no") return lastVariant;
1733
1917
  }
1734
1918
  renderer.write(`
1735
- ${color8.amber("?")} System prompt:
1919
+ ${color9.amber("?")} System prompt:
1736
1920
  `);
1737
1921
  for (const [index, opt] of SYSTEM_PROMPT_OPTIONS.entries()) {
1738
1922
  const num2 = index + 1;
1739
1923
  const isDefault = opt.variant === defaultVariant;
1740
- const marker = isDefault ? color8.cyan("\u25CF") : color8.dim("\u25CB");
1741
- const label = isDefault ? color8.bold(opt.label) : opt.label;
1924
+ const marker = isDefault ? color9.cyan("\u25CF") : color9.dim("\u25CB");
1925
+ const label = isDefault ? color9.bold(opt.label) : opt.label;
1742
1926
  renderer.write(
1743
- ` ${color8.dim(`${num2}.`)} ${marker} ${label.padEnd(9)} ${color8.dim(`~${fmtTok(tokens[opt.variant])} tokens`)} ${color8.dim(opt.hint)}
1927
+ ` ${color9.dim(`${num2}.`)} ${marker} ${label.padEnd(9)} ${color9.dim(`~${fmtTok(tokens[opt.variant])} tokens`)} ${color9.dim(opt.hint)}
1744
1928
  `
1745
1929
  );
1746
1930
  }
1747
1931
  const answer = (await reader.readLine(
1748
1932
  `
1749
- ${color8.amber("?")} Select system prompt ${color8.dim(`[1-${SYSTEM_PROMPT_OPTIONS.length}, Enter = ${labelFor(defaultVariant)}, q to quit]`)}: `
1933
+ ${color9.amber("?")} Select system prompt ${color9.dim(`[1-${SYSTEM_PROMPT_OPTIONS.length}, Enter = ${labelFor(defaultVariant)}, q to quit]`)}: `
1750
1934
  )).trim().toLowerCase();
1751
1935
  if (answer === "q" || answer === "quit") throw new LaunchAbortedError();
1752
1936
  if (!answer) return defaultVariant;
@@ -1803,8 +1987,8 @@ async function bootConfig(flags) {
1803
1987
  }
1804
1988
 
1805
1989
  // src/input-reader.ts
1806
- import * as fs5 from "node:fs/promises";
1807
- import * as path6 from "node:path";
1990
+ import * as fs7 from "node:fs/promises";
1991
+ import * as path8 from "node:path";
1808
1992
  import * as readline from "node:readline";
1809
1993
  import {
1810
1994
  resolveWstackPaths,
@@ -1823,7 +2007,7 @@ var ReadlineInputReader = class {
1823
2007
  }
1824
2008
  async loadHistory() {
1825
2009
  try {
1826
- const raw = await fs5.readFile(this.historyFile, "utf8");
2010
+ const raw = await fs7.readFile(this.historyFile, "utf8");
1827
2011
  this.history = raw.split("\n").filter(Boolean).slice(-1e3);
1828
2012
  } catch {
1829
2013
  this.history = [];
@@ -1831,8 +2015,8 @@ var ReadlineInputReader = class {
1831
2015
  }
1832
2016
  async saveHistory() {
1833
2017
  try {
1834
- await fs5.mkdir(path6.dirname(this.historyFile), { recursive: true });
1835
- await fs5.writeFile(this.historyFile, this.history.slice(-1e3).join("\n"));
2018
+ await fs7.mkdir(path8.dirname(this.historyFile), { recursive: true });
2019
+ await fs7.writeFile(this.historyFile, this.history.slice(-1e3).join("\n"));
1836
2020
  } catch {
1837
2021
  }
1838
2022
  }
@@ -1853,25 +2037,25 @@ var ReadlineInputReader = class {
1853
2037
  async readLine(prompt, timeoutOpts) {
1854
2038
  if (this.history.length === 0) await this.loadHistory();
1855
2039
  while (this.pending) {
1856
- await new Promise((resolve2) => setTimeout(resolve2, 50));
2040
+ await new Promise((resolve3) => setTimeout(resolve3, 50));
1857
2041
  }
1858
2042
  this.pending = true;
1859
2043
  try {
1860
2044
  if (this.rl) {
1861
2045
  const old = this.rl;
1862
2046
  this.rl = void 0;
1863
- await new Promise((resolve2) => {
2047
+ await new Promise((resolve3) => {
1864
2048
  if (old.closed) {
1865
- resolve2();
2049
+ resolve3();
1866
2050
  } else {
1867
- old.once("close", resolve2);
2051
+ old.once("close", resolve3);
1868
2052
  old.close();
1869
2053
  }
1870
2054
  });
1871
2055
  }
1872
2056
  const fresh = this.ensure();
1873
2057
  this.installPromptGuard(fresh);
1874
- const line = await new Promise((resolve2) => {
2058
+ const line = await new Promise((resolve3) => {
1875
2059
  let settled = false;
1876
2060
  let timeoutHandle;
1877
2061
  const settle = (line2) => {
@@ -1879,7 +2063,7 @@ var ReadlineInputReader = class {
1879
2063
  settled = true;
1880
2064
  if (timeoutHandle) clearTimeout(timeoutHandle);
1881
2065
  setOutputLineGuard(null);
1882
- resolve2(line2);
2066
+ resolve3(line2);
1883
2067
  };
1884
2068
  if (timeoutOpts) {
1885
2069
  timeoutHandle = setTimeout(() => {
@@ -1946,7 +2130,7 @@ var ReadlineInputReader = class {
1946
2130
  const signal = opts.signal;
1947
2131
  if (signal?.aborted) return "";
1948
2132
  writeOut(prompt);
1949
- return new Promise((resolve2) => {
2133
+ return new Promise((resolve3) => {
1950
2134
  const stdin = process.stdin;
1951
2135
  const wasRaw = stdin.isRaw;
1952
2136
  const wasPaused = stdin.isPaused();
@@ -1957,7 +2141,7 @@ var ReadlineInputReader = class {
1957
2141
  if (key === "") {
1958
2142
  cleanup();
1959
2143
  writeOut("\n");
1960
- resolve2("");
2144
+ resolve3("");
1961
2145
  return;
1962
2146
  }
1963
2147
  const opt = options.find(
@@ -1967,17 +2151,17 @@ var ReadlineInputReader = class {
1967
2151
  cleanup();
1968
2152
  writeOut(`${opt.key}
1969
2153
  `);
1970
- resolve2(opt.value);
2154
+ resolve3(opt.value);
1971
2155
  }
1972
2156
  };
1973
2157
  const onClose = () => {
1974
2158
  cleanup();
1975
- resolve2("");
2159
+ resolve3("");
1976
2160
  };
1977
2161
  const onAbort = () => {
1978
2162
  cleanup();
1979
2163
  writeOut("\n");
1980
- resolve2("");
2164
+ resolve3("");
1981
2165
  };
1982
2166
  const cleanup = () => {
1983
2167
  stdin.off("data", onData);
@@ -2011,7 +2195,7 @@ var ReadlineInputReader = class {
2011
2195
  this.rl?.close();
2012
2196
  this.rl = void 0;
2013
2197
  writeOut(prompt);
2014
- return new Promise((resolve2) => {
2198
+ return new Promise((resolve3) => {
2015
2199
  let buf = "";
2016
2200
  const wasRaw = stdin.isRaw;
2017
2201
  const cleanup = () => {
@@ -2040,13 +2224,13 @@ var ReadlineInputReader = class {
2040
2224
  cleanup();
2041
2225
  writeOut(` ${dim(`[${buf.length} chars]`)}
2042
2226
  `);
2043
- resolve2(buf);
2227
+ resolve3(buf);
2044
2228
  return;
2045
2229
  }
2046
2230
  if (ch === "") {
2047
2231
  cleanup();
2048
2232
  writeOut("\n");
2049
- resolve2("");
2233
+ resolve3("");
2050
2234
  return;
2051
2235
  }
2052
2236
  if (ch === "") {
@@ -2089,7 +2273,7 @@ function dim(s) {
2089
2273
  }
2090
2274
 
2091
2275
  // src/renderer.ts
2092
- import { color as color9 } from "@wrongstack/core/utils";
2276
+ import { color as color10 } from "@wrongstack/core/utils";
2093
2277
  var TerminalRenderer = class _TerminalRenderer {
2094
2278
  out;
2095
2279
  err;
@@ -2202,7 +2386,7 @@ var TerminalRenderer = class _TerminalRenderer {
2202
2386
  if (!this.lineStart) this.out.write("\n");
2203
2387
  const arrow = theme2.primary("\u2192");
2204
2388
  const display = formatInputSummary(input);
2205
- this.out.write(`${arrow} ${theme2.bold(name)}${display ? color9.dim(` ${display}`) : ""}
2389
+ this.out.write(`${arrow} ${theme2.bold(name)}${display ? color10.dim(` ${display}`) : ""}
2206
2390
  `);
2207
2391
  this.lineStart = true;
2208
2392
  }
@@ -2219,7 +2403,7 @@ var TerminalRenderer = class _TerminalRenderer {
2219
2403
  if (isError) {
2220
2404
  const firstLine = txt.split("\n")[0] ?? "";
2221
2405
  const truncated = firstLine.length > 200 ? `${firstLine.slice(0, 197)}\u2026` : firstLine;
2222
- this.out.write(` ${prefix} ${color9.dim(truncated)}
2406
+ this.out.write(` ${prefix} ${color10.dim(truncated)}
2223
2407
  `);
2224
2408
  this.lineStart = true;
2225
2409
  return;
@@ -2227,7 +2411,7 @@ var TerminalRenderer = class _TerminalRenderer {
2227
2411
  const isEditLike = name === "edit" || name === "write";
2228
2412
  const diff = extractDiff(content);
2229
2413
  if (isEditLike && diff) {
2230
- this.out.write(` ${prefix} ${color9.dim(summarize(content, name))}
2414
+ this.out.write(` ${prefix} ${color10.dim(summarize(content, name))}
2231
2415
  `);
2232
2416
  const rendered = renderDiff(diff).split("\n").map((l) => ` ${l}`).join("\n");
2233
2417
  this.out.write(`${rendered}
@@ -2238,7 +2422,7 @@ var TerminalRenderer = class _TerminalRenderer {
2238
2422
  const summary = summarize(content, name);
2239
2423
  const isReadLike = name === "read" || name === "grep" || name === "glob" || name === "bash" || name === "exec";
2240
2424
  if (renderMode === "simple") {
2241
- this.out.write(` ${prefix} ${color9.dim(summary || compactSingleLine(bodyText))}
2425
+ this.out.write(` ${prefix} ${color10.dim(summary || compactSingleLine(bodyText))}
2242
2426
  `);
2243
2427
  this.lineStart = true;
2244
2428
  return;
@@ -2247,16 +2431,16 @@ var TerminalRenderer = class _TerminalRenderer {
2247
2431
  const lines = bodyText.split("\n");
2248
2432
  const head = lines.slice(0, previewLines).map((l) => l.replace(/\s+$/, ""));
2249
2433
  const moreCount = Math.max(0, lines.length - head.length);
2250
- this.out.write(` ${prefix} ${color9.dim(summary)}
2434
+ this.out.write(` ${prefix} ${color10.dim(summary)}
2251
2435
  `);
2252
2436
  for (const l of head) {
2253
2437
  const capped = l.length > 200 ? `${l.slice(0, 197)}\u2026` : l;
2254
- this.out.write(` ${color9.dim(capped)}
2438
+ this.out.write(` ${color10.dim(capped)}
2255
2439
  `);
2256
2440
  }
2257
2441
  if (moreCount > 0) {
2258
2442
  this.out.write(
2259
- ` ${color9.dim(`+${moreCount} more line${moreCount === 1 ? "" : "s"}`)}
2443
+ ` ${color10.dim(`+${moreCount} more line${moreCount === 1 ? "" : "s"}`)}
2260
2444
  `
2261
2445
  );
2262
2446
  }
@@ -2395,7 +2579,7 @@ function renderMarkdown(s) {
2395
2579
  return theme2.primary(theme2.bold(`${hashes} ${text}`));
2396
2580
  });
2397
2581
  out = out.replace(/```([a-zA-Z0-9_+-]*)\n([\s\S]*?)```/g, (_m, _lang, code) => {
2398
- return color9.gray(`
2582
+ return color10.gray(`
2399
2583
  \u250C\u2500
2400
2584
  ${code.replace(/^/gm, "\u2502 ")}\u2514\u2500`);
2401
2585
  });
@@ -2403,7 +2587,7 @@ ${code.replace(/^/gm, "\u2502 ")}\u2514\u2500`);
2403
2587
  out = out.replace(/\*\*([^*]+)\*\*/g, (_m, text) => theme2.bold(text));
2404
2588
  out = out.replace(
2405
2589
  /(^|[^*])\*([^*\n]+)\*([^*]|$)/g,
2406
- (_m, l, t, r) => `${l}${color9.italic(t)}${r}`
2590
+ (_m, l, t, r) => `${l}${color10.italic(t)}${r}`
2407
2591
  );
2408
2592
  return out;
2409
2593
  }
@@ -2496,14 +2680,14 @@ function summarize(value, name) {
2496
2680
  if (typeof v === "object" && v !== null) {
2497
2681
  const o = v;
2498
2682
  if (name === "edit") {
2499
- const path8 = typeof o["path"] === "string" ? o["path"] : "";
2683
+ const path10 = typeof o["path"] === "string" ? o["path"] : "";
2500
2684
  const reps = typeof o["replacements"] === "number" ? o["replacements"] : 0;
2501
- return `${path8} ${reps} replacement${reps === 1 ? "" : "s"}`.trim();
2685
+ return `${path10} ${reps} replacement${reps === 1 ? "" : "s"}`.trim();
2502
2686
  }
2503
2687
  if (name === "write") {
2504
- const path8 = typeof o["path"] === "string" ? o["path"] : "";
2688
+ const path10 = typeof o["path"] === "string" ? o["path"] : "";
2505
2689
  const bytes = typeof o["bytes"] === "number" ? o["bytes"] : void 0;
2506
- return bytes !== void 0 ? `${path8} ${bytes}B` : path8;
2690
+ return bytes !== void 0 ? `${path10} ${bytes}B` : path10;
2507
2691
  }
2508
2692
  if (name === "read") {
2509
2693
  return summarizeRead(o);
@@ -2521,13 +2705,13 @@ function summarize(value, name) {
2521
2705
  return "";
2522
2706
  }
2523
2707
  function summarizeRead(o) {
2524
- const path8 = typeof o["path"] === "string" ? o["path"] : "";
2708
+ const path10 = typeof o["path"] === "string" ? o["path"] : "";
2525
2709
  const total = typeof o["total_lines"] === "number" ? o["total_lines"] : void 0;
2526
2710
  const truncated = o["truncated"] === true;
2527
2711
  const cached = o["cached"] === true;
2528
2712
  const note = typeof o["note"] === "string" ? o["note"] : void 0;
2529
2713
  const parts = [];
2530
- if (path8) parts.push(path8);
2714
+ if (path10) parts.push(path10);
2531
2715
  if (total !== void 0) parts.push(`${total} line${total === 1 ? "" : "s"}`);
2532
2716
  const flags = [];
2533
2717
  if (truncated) flags.push("truncated");
@@ -2575,86 +2759,6 @@ function compactSingleLine(text) {
2575
2759
 
2576
2760
  // src/boot.ts
2577
2761
  var GITHUB_PROVIDERS_OVERLAY_URL = "https://raw.githubusercontent.com/WrongStack/WrongStack/main/packages/cli/data/providers.json";
2578
- function resolveBundledOverlayFile() {
2579
- try {
2580
- return fileURLToPath(
2581
- new URL("../data/providers.json", moduleUrlFor(import.meta.url, "@wrongstack/cli"))
2582
- );
2583
- } catch {
2584
- return void 0;
2585
- }
2586
- }
2587
- async function validateSavedProviderModel(config, modelsRegistry) {
2588
- const providerId = config.provider;
2589
- const modelId = config.model;
2590
- if (!providerId || !modelId) return { ok: false, reason: "missing provider/model" };
2591
- if (isSetupProvider(providerId)) return { ok: true };
2592
- const saved = config.providers?.[providerId];
2593
- const lookupId = saved?.type && saved.type !== providerId ? saved.type : providerId;
2594
- const catalogProvider = await modelsRegistry.getProvider(lookupId).catch(() => void 0);
2595
- if (!catalogProvider && !saved?.family)
2596
- return { ok: false, reason: `provider "${providerId}" is no longer available` };
2597
- const hasCredential = (catalogProvider?.envVars ?? saved?.envVars ?? []).some(
2598
- (envVar) => Boolean(process.env[envVar])
2599
- ) || saved !== void 0 && resolveActiveApiKey(saved) !== void 0 || isKeylessLocalProvider({
2600
- apiBase: saved?.baseUrl ?? catalogProvider?.apiBase,
2601
- envVars: saved?.envVars ?? catalogProvider?.envVars
2602
- });
2603
- if (!hasCredential) return { ok: false, reason: `provider "${providerId}" has no usable key` };
2604
- const visible = visibleModelIds(
2605
- providerId,
2606
- config,
2607
- (catalogProvider?.models ?? []).map((m) => m.id),
2608
- saved
2609
- );
2610
- if (visible.length > 0 && !visible.includes(modelId)) {
2611
- return {
2612
- ok: false,
2613
- reason: `model "${modelId}" is no longer available for provider "${providerId}"`
2614
- };
2615
- }
2616
- return { ok: true };
2617
- }
2618
- async function autoSelectSavedProvider(config, modelsRegistry) {
2619
- const providers = config.providers ?? {};
2620
- const entries = config.provider && providers[config.provider] ? [[config.provider, providers[config.provider]]] : Object.entries(providers);
2621
- for (const [id, cfg] of entries) {
2622
- if (!cfg) continue;
2623
- let model = cfg.models?.[0];
2624
- if (!model) {
2625
- const catalogId = cfg.type && cfg.type !== id ? cfg.type : id;
2626
- const catalog = await modelsRegistry.getProvider(catalogId).catch(() => void 0);
2627
- model = catalog?.models?.[0]?.id;
2628
- }
2629
- if (model) return { provider: id, model };
2630
- }
2631
- return void 0;
2632
- }
2633
- function resolveBundledSkillsDir2() {
2634
- try {
2635
- const req = createRequire4(import.meta.url);
2636
- const corePkg = wrongstackPackageJsonPath3("@wrongstack/core", (id) => req.resolve(id));
2637
- return path7.join(path7.dirname(corePkg), "skills");
2638
- } catch {
2639
- return void 0;
2640
- }
2641
- }
2642
- function resolveBundledPromptsDir2() {
2643
- try {
2644
- const req = createRequire4(import.meta.url);
2645
- const corePkg = wrongstackPackageJsonPath3("@wrongstack/core", (id) => req.resolve(id));
2646
- return path7.join(path7.dirname(corePkg), "data", "prompts");
2647
- } catch {
2648
- return void 0;
2649
- }
2650
- }
2651
- function isHomeDirectory(cwd, userHome) {
2652
- if (!cwd || !userHome) return false;
2653
- return path7.resolve(cwd) === path7.resolve(userHome);
2654
- }
2655
- function shouldPrintYoloNotice(lastChoices, yoloPinned, yolo) {
2656
- return !lastChoices && yoloPinned === void 0 && yolo;
2657
- }
2658
2762
  async function boot(argv) {
2659
2763
  const { flags, positional } = parseArgs(argv);
2660
2764
  if (positional[0] === "update") {
@@ -2666,6 +2770,14 @@ async function boot(argv) {
2666
2770
  flags
2667
2771
  });
2668
2772
  }
2773
+ if (positional[0] === "remote" || typeof flags["remote"] === "string") {
2774
+ const { runRemoteCommand } = await import("./remote-O5WXHLWV.js");
2775
+ return runRemoteCommand(
2776
+ positional[0] === "remote" ? positional.slice(1) : positional,
2777
+ flags,
2778
+ new TerminalRenderer()
2779
+ );
2780
+ }
2669
2781
  if (positional[0] === "resume" && positional[1] && !subcommands["__noop_resume_marker"]) {
2670
2782
  flags["resume"] = positional[1];
2671
2783
  positional.splice(0, 2);
@@ -2674,14 +2786,34 @@ async function boot(argv) {
2674
2786
  try {
2675
2787
  bootResult = await bootConfig(flags);
2676
2788
  } catch (err) {
2677
- writeErr(`Config error: ${toErrorMessage4(err)}
2789
+ writeErr(`Config error: ${toErrorMessage5(err)}
2678
2790
  `);
2679
2791
  return 2;
2680
2792
  }
2681
2793
  let { paths, config, vault } = bootResult;
2794
+ try {
2795
+ resolveToolRestriction(flags);
2796
+ resolveLaunchAllowedTools(flags);
2797
+ parseOutputFormat(flags["output-format"]);
2798
+ announceSafeMode(flags, writeErr);
2799
+ activateRestrictedMode(flags, writeErr);
2800
+ const launchMcp = await resolveLaunchMcpServers(flags, paths.cwd);
2801
+ if (launchMcp) flags["mcp-config"] = JSON.stringify({ mcpServers: launchMcp });
2802
+ const schema = await resolveJsonSchemaFlag(flags["json-schema"], paths.cwd);
2803
+ if (schema) flags["json-schema"] = JSON.stringify(schema);
2804
+ const appended = await resolveAppendedSystemPrompt(flags, paths.cwd);
2805
+ delete flags["append-system-prompt-file"];
2806
+ if (appended) flags["append-system-prompt"] = appended;
2807
+ else delete flags["append-system-prompt"];
2808
+ } catch (err) {
2809
+ writeErr(`wstack: ${toErrorMessage5(err)}
2810
+ `);
2811
+ return 2;
2812
+ }
2682
2813
  let first = positional[0];
2683
2814
  const mayOfferConfigRecovery = isStdinTTY2() && (positional.length === 0 || first === "quick") && typeof flags["prompt"] !== "string" && !flags["webui"] && !flags["no-interactive"] && !flags["skip"];
2684
- const renderer = new TerminalRenderer();
2815
+ const machineOutput = flags["output-json"] === true || flags["output-format"] === "json" || flags["output-format"] === "stream-json";
2816
+ const renderer = new TerminalRenderer(machineOutput ? { out: process.stderr } : void 0);
2685
2817
  const reader = new ReadlineInputReader({ historyFile: paths.wpaths.historyFile });
2686
2818
  if (mayOfferConfigRecovery) {
2687
2819
  const recoveryProfile = config.activeProfile ?? "default";
@@ -2697,7 +2829,7 @@ async function boot(argv) {
2697
2829
  bootResult = await bootConfig(flags);
2698
2830
  ({ paths, config, vault } = bootResult);
2699
2831
  } catch (err) {
2700
- writeErr(`Config error after backup restore: ${toErrorMessage4(err)}
2832
+ writeErr(`Config error after backup restore: ${toErrorMessage5(err)}
2701
2833
  `);
2702
2834
  await reader.close();
2703
2835
  return 2;
@@ -2798,8 +2930,8 @@ async function boot(argv) {
2798
2930
  if (isHomeDirectory(cwd, userHome)) {
2799
2931
  writeErr(
2800
2932
  `
2801
- ${color10.red(color10.bold("\u26A0 This is not a working directory."))}
2802
- ${color10.red("Please open wstack in a project folder.")}
2933
+ ${color11.red(color11.bold("\u26A0 This is not a working directory."))}
2934
+ ${color11.red("Please open wstack in a project folder.")}
2803
2935
 
2804
2936
  `
2805
2937
  );
@@ -2807,23 +2939,21 @@ async function boot(argv) {
2807
2939
  return 1;
2808
2940
  }
2809
2941
  if (!flags["no-models-refresh"]) {
2810
- try {
2811
- await modelsRegistry.refresh();
2812
- logger.info("models.dev catalog refreshed");
2813
- } catch (err) {
2814
- const msg = toErrorMessage4(err);
2815
- logger.warn(`models.dev refresh failed (${msg}); using cached catalog`);
2816
- }
2942
+ await startCatalog({
2943
+ registry: modelsRegistry,
2944
+ logger,
2945
+ shortLived: positional.length > 0 || typeof flags["prompt"] === "string"
2946
+ });
2817
2947
  }
2818
2948
  try {
2819
2949
  await discoverAndMergeProviders({
2820
2950
  config,
2821
2951
  registry: modelsRegistry,
2822
- cacheDir: path7.dirname(wpaths.modelsCache),
2952
+ cacheDir: path9.dirname(wpaths.modelsCache),
2823
2953
  logger
2824
2954
  });
2825
2955
  } catch (err) {
2826
- logger.debug(`provider auto-discovery skipped: ${toErrorMessage4(err)}`);
2956
+ logger.debug(`provider auto-discovery skipped: ${toErrorMessage5(err)}`);
2827
2957
  }
2828
2958
  const isSingleShot = positional.length > 0 || typeof flags["prompt"] === "string";
2829
2959
  const isInteractiveTTY = isStdinTTY2() && !isSingleShot && !flags["webui"] && !flags["no-interactive"] && !flags["skip"];
@@ -2858,11 +2988,11 @@ async function boot(argv) {
2858
2988
  if (isStdinTTY2() && !noInteractiveMode) {
2859
2989
  let picked;
2860
2990
  let skipPicker = false;
2861
- if (isSetupProvider(config.provider)) {
2991
+ if (isSetupProvider2(config.provider)) {
2862
2992
  skipPicker = true;
2863
2993
  renderer.write(
2864
2994
  `
2865
- ${color10.amber("\u25B6")} ${color10.bold("Setup mode")} ${color10.dim("\u2014 no model connected. Run")} ${color10.bold("/auth")} ${color10.dim("to connect one.")}
2995
+ ${color11.amber("\u25B6")} ${color11.bold("Setup mode")} ${color11.dim("\u2014 no model connected. Run")} ${color11.bold("/auth")} ${color11.dim("to connect one.")}
2866
2996
 
2867
2997
  `
2868
2998
  );
@@ -2889,7 +3019,7 @@ async function boot(argv) {
2889
3019
  config = reloaded.config;
2890
3020
  vault = reloaded.vault;
2891
3021
  } catch (err) {
2892
- writeErr(`Config error after setup: ${toErrorMessage4(err)}
3022
+ writeErr(`Config error after setup: ${toErrorMessage5(err)}
2893
3023
  `);
2894
3024
  await reader.close();
2895
3025
  return 2;
@@ -2902,7 +3032,7 @@ async function boot(argv) {
2902
3032
  const savedStatus = await validateSavedProviderModel(config, modelsRegistry);
2903
3033
  renderer.write(
2904
3034
  `
2905
- ${color10.dim("Last settings:")} ${color10.bold(savedProvider)} / ${color10.bold(savedModel)}
3035
+ ${color11.dim("Last settings:")} ${color11.bold(savedProvider)} / ${color11.bold(savedModel)}
2906
3036
  `
2907
3037
  );
2908
3038
  if (!savedStatus.ok) {
@@ -2912,11 +3042,11 @@ async function boot(argv) {
2912
3042
  );
2913
3043
  } else {
2914
3044
  const answer = (await reader.readLine(
2915
- ` ${color10.amber("?")} Continue with these? ${color10.dim("[Y/n/q]")} ${color10.dim("(auto Y in 5s)")} `,
3045
+ ` ${color11.amber("?")} Continue with these? ${color11.dim("[Y/n/q]")} ${color11.dim("(auto Y in 5s)")} `,
2916
3046
  { timeoutMs: 5e3, defaultAnswer: "y" }
2917
3047
  )).trim().toLowerCase();
2918
3048
  if (answer === "q") {
2919
- renderer.write(color10.dim(" Goodbye!\n"));
3049
+ renderer.write(color11.dim(" Goodbye!\n"));
2920
3050
  await reader.close();
2921
3051
  return 0;
2922
3052
  }
@@ -2924,7 +3054,7 @@ async function boot(argv) {
2924
3054
  skipPicker = true;
2925
3055
  renderer.write(
2926
3056
  `
2927
- ${color10.green("\u25B6")} ${color10.bold(savedProvider)} / ${color10.bold(savedModel)}
3057
+ ${color11.green("\u25B6")} ${color11.bold(savedProvider)} / ${color11.bold(savedModel)}
2928
3058
 
2929
3059
  `
2930
3060
  );
@@ -2945,9 +3075,9 @@ async function boot(argv) {
2945
3075
  if (!config.provider || !config.model) {
2946
3076
  renderer.write(
2947
3077
  `
2948
- ${color10.dim("No provider selected.")}
2949
- ${color10.dim("Run")} ${color10.bold("wstack auth")} ${color10.dim("to add a key or sign in, or start with no model:")}
2950
- ${color10.bold(`wstack --provider ${SETUP_PROVIDER_ID} --model ${SETUP_MODEL_ID}`)}
3078
+ ${color11.dim("No provider selected.")}
3079
+ ${color11.dim("Run")} ${color11.bold("wstack auth")} ${color11.dim("to add a key or sign in, or start with no model:")}
3080
+ ${color11.bold(`wstack --provider ${SETUP_PROVIDER_ID} --model ${SETUP_MODEL_ID}`)}
2951
3081
 
2952
3082
  `
2953
3083
  );
@@ -3017,7 +3147,7 @@ To start the app with no model connected, pass --provider ${SETUP_PROVIDER_ID} -
3017
3147
  }
3018
3148
  if (promptMenu.persistError) {
3019
3149
  renderer.writeWarning(
3020
- `Could not save system prompt variant to config: ${toErrorMessage4(promptMenu.persistError)}
3150
+ `Could not save system prompt variant to config: ${toErrorMessage5(promptMenu.persistError)}
3021
3151
  `
3022
3152
  );
3023
3153
  }
@@ -3069,8 +3199,8 @@ To start the app with no model connected, pass --provider ${SETUP_PROVIDER_ID} -
3069
3199
  if (shouldPrintYoloNotice(lastChoices, yoloPinned, choices.yolo)) {
3070
3200
  writeErr(
3071
3201
  `
3072
- ${color10.yellow("YOLO is on")}: non-denied tool calls, including shell and file writes, run without confirmation.
3073
- ${color10.dim("Explicit deny rules still apply. Use")} --no-yolo ${color10.dim("or")} /yolo off ${color10.dim("to require prompts.")}
3202
+ ${color11.yellow("YOLO is on")}: non-denied tool calls, including shell and file writes, run without confirmation.
3203
+ ${color11.dim("Explicit deny rules still apply. Use")} --no-yolo ${color11.dim("or")} /yolo off ${color11.dim("to require prompts.")}
3074
3204
 
3075
3205
  `
3076
3206
  );
@@ -3121,64 +3251,13 @@ To start the app with no model connected, pass --provider ${SETUP_PROVIDER_ID} -
3121
3251
  needsSetup: !noInteractiveMode ? false : !config.provider || !config.model
3122
3252
  };
3123
3253
  }
3124
- async function checkGitInCwd(opts) {
3125
- const { cwd, renderer, reader } = opts;
3126
- const cwdGit = path7.join(cwd, ".git");
3127
- let hasCwdGit = false;
3128
- try {
3129
- await fs6.access(cwdGit);
3130
- hasCwdGit = true;
3131
- } catch {
3132
- }
3133
- if (!hasCwdGit) {
3134
- renderer.write(
3135
- `
3136
- ${color10.amber("\u25CB")} This folder has no ${color10.bold(".git")} repository.
3137
- `
3138
- );
3139
- const answer = (await reader.readLine(` ${color10.amber("?")} Initialize one here? ${color10.dim("[y/N]")} `)).trim().toLowerCase();
3140
- if (answer === "y" || answer === "yes") {
3141
- try {
3142
- const { spawn: spawn2 } = await import("node:child_process");
3143
- await new Promise((resolve2, reject) => {
3144
- const child = spawn2("git", ["init"], {
3145
- cwd,
3146
- signal: AbortSignal.timeout(1e4),
3147
- windowsHide: true
3148
- });
3149
- child.on("error", reject);
3150
- child.on(
3151
- "close",
3152
- (code) => code === 0 ? resolve2() : reject(new Error(`git init failed with ${code}`))
3153
- );
3154
- });
3155
- renderer.write(` ${color10.green("\u2713")} Git repository initialized
3156
- `);
3157
- hasCwdGit = true;
3158
- } catch (err) {
3159
- renderer.writeError(`git init failed: ${toErrorMessage4(err)}
3160
- `);
3161
- }
3162
- }
3163
- }
3164
- const parentDir = path7.dirname(cwd);
3165
- if (parentDir !== cwd) {
3166
- try {
3167
- await fs6.access(path7.join(parentDir, ".git"));
3168
- renderer.write(
3169
- ` ${color10.dim("\u2139")} A ${color10.bold(".git")} repo exists in the parent directory: ${color10.dim(parentDir)}
3170
- `
3171
- );
3172
- } catch {
3173
- }
3174
- }
3175
- }
3176
3254
 
3177
3255
  // src/cli-context.ts
3178
3256
  async function initializeCli(argv) {
3179
3257
  applyNodeEnvDefault();
3180
3258
  applySessionShellDefault();
3181
3259
  const earlyFlags = parseArgs(argv).flags;
3260
+ applyAsciiMode(earlyFlags);
3182
3261
  const earlyExit = await handleHelpVersionShortCircuit(argv);
3183
3262
  if (earlyExit !== null) return earlyExit;
3184
3263
  const desktopExit = await handleDesktopShortCircuit(earlyFlags, argv);
@@ -3319,7 +3398,8 @@ async function initializeCli(argv) {
3319
3398
  logger,
3320
3399
  reader,
3321
3400
  renderer,
3322
- modelsRegistry
3401
+ modelsRegistry,
3402
+ launchAllowedTools: resolveLaunchAllowedTools(ctx.flags)
3323
3403
  });
3324
3404
  const configStore = container.resolve(TOKENS3.ConfigStore);
3325
3405
  return {
@@ -3335,4 +3415,4 @@ async function initializeCli(argv) {
3335
3415
  export {
3336
3416
  initializeCli
3337
3417
  };
3338
- //# sourceMappingURL=cli-context-34Q5IJRA.js.map
3418
+ //# sourceMappingURL=cli-context-UVGAN3NO.js.map