@wrongstack/core 0.310.1 → 0.313.1

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 (187) hide show
  1. package/dist/chronicle/index.js +84 -6391
  2. package/dist/chronicle/project-server.js +84 -4868
  3. package/dist/chunk-2BUUIMQB.js +225 -0
  4. package/dist/chunk-2FK4WTFF.js +207 -0
  5. package/dist/chunk-2FQL4PDC.js +292 -0
  6. package/dist/chunk-2KKODIQU.js +2256 -0
  7. package/dist/chunk-2YU4WVBW.js +134 -0
  8. package/dist/chunk-3E244UDA.js +356 -0
  9. package/dist/chunk-3XPVB7BA.js +135 -0
  10. package/dist/chunk-4LJJYBAU.js +388 -0
  11. package/dist/chunk-4VWO3ZXL.js +342 -0
  12. package/dist/chunk-4XV6IR37.js +187 -0
  13. package/dist/chunk-4ZHTKJHM.js +183 -0
  14. package/dist/chunk-52RTVH4M.js +361 -0
  15. package/dist/chunk-57GEWK5X.js +26 -0
  16. package/dist/chunk-5DSMEVA4.js +931 -0
  17. package/dist/chunk-5RP3QTRL.js +1223 -0
  18. package/dist/chunk-5S437PRC.js +50 -0
  19. package/dist/chunk-5XDUGTKN.js +511 -0
  20. package/dist/chunk-62V2AFVG.js +422 -0
  21. package/dist/chunk-65RDIOR2.js +2470 -0
  22. package/dist/chunk-6AKOTGLM.js +597 -0
  23. package/dist/chunk-7ZHZE5EO.js +28 -0
  24. package/dist/chunk-A455ATZB.js +140 -0
  25. package/dist/chunk-AD7ZFZCS.js +46 -0
  26. package/dist/chunk-AI4LLQ2U.js +856 -0
  27. package/dist/chunk-ASX6AW36.js +789 -0
  28. package/dist/chunk-AT4V4XGI.js +3522 -0
  29. package/dist/chunk-AWNQ6ED6.js +311 -0
  30. package/dist/chunk-B4AMLZPB.js +9 -0
  31. package/dist/chunk-BAKVJLEV.js +417 -0
  32. package/dist/chunk-BJHVULHO.js +55 -0
  33. package/dist/chunk-CB2HFKTP.js +9 -0
  34. package/dist/chunk-CE4ZOCOI.js +1640 -0
  35. package/dist/chunk-CQQL4ZOQ.js +151 -0
  36. package/dist/chunk-DEIQMBD2.js +65 -0
  37. package/dist/chunk-E6I5RXVK.js +58 -0
  38. package/dist/chunk-EFEHDQGY.js +1589 -0
  39. package/dist/chunk-EODDVJBM.js +82 -0
  40. package/dist/chunk-EPC3GZD4.js +308 -0
  41. package/dist/chunk-FAYRX2AD.js +13 -0
  42. package/dist/chunk-FFSX2QDQ.js +362 -0
  43. package/dist/chunk-FHAMQS7Q.js +5856 -0
  44. package/dist/chunk-FIV4IJL7.js +2263 -0
  45. package/dist/chunk-FNXVT7HF.js +52 -0
  46. package/dist/chunk-FSWCWSTS.js +395 -0
  47. package/dist/chunk-FW5LDDMJ.js +16464 -0
  48. package/dist/chunk-FXQLIX3K.js +211 -0
  49. package/dist/chunk-G5AAKEEZ.js +228 -0
  50. package/dist/chunk-G5S3S5ZN.js +38 -0
  51. package/dist/chunk-GAZEWQEZ.js +231 -0
  52. package/dist/chunk-GFJOMSHG.js +125 -0
  53. package/dist/chunk-GFXZTHNI.js +158 -0
  54. package/dist/chunk-GM54GJBU.js +960 -0
  55. package/dist/chunk-GPQ3NJPR.js +900 -0
  56. package/dist/chunk-GTCU6DZ3.js +1 -0
  57. package/dist/chunk-H5E77KUJ.js +15 -0
  58. package/dist/chunk-H72H4XDU.js +1023 -0
  59. package/dist/chunk-HA4ZYA6T.js +178 -0
  60. package/dist/chunk-I45KAW2N.js +5020 -0
  61. package/dist/chunk-IQ35HMQL.js +1396 -0
  62. package/dist/chunk-IYFBFX34.js +86 -0
  63. package/dist/chunk-JJPMWPB6.js +109 -0
  64. package/dist/chunk-JTHKOYWU.js +663 -0
  65. package/dist/chunk-JVGPR3TS.js +365 -0
  66. package/dist/chunk-JVKB2TBL.js +48 -0
  67. package/dist/chunk-JX7VBZDK.js +31 -0
  68. package/dist/chunk-K3G6JBUC.js +5232 -0
  69. package/dist/chunk-K4YUNKU7.js +589 -0
  70. package/dist/chunk-KBZGE6LN.js +710 -0
  71. package/dist/chunk-KDQJCT2J.js +45 -0
  72. package/dist/chunk-KI4L2DUL.js +560 -0
  73. package/dist/chunk-KJ2ZTQSL.js +47 -0
  74. package/dist/chunk-KSJ5UTP7.js +154 -0
  75. package/dist/chunk-LHOA5DWA.js +28 -0
  76. package/dist/chunk-LX5QWLBL.js +27 -0
  77. package/dist/chunk-LZDDLNCZ.js +279 -0
  78. package/dist/chunk-M2WF6AXG.js +115 -0
  79. package/dist/chunk-M7BS2K6U.js +1 -0
  80. package/dist/chunk-NDBIPFNY.js +102 -0
  81. package/dist/chunk-NEMIWEXC.js +1199 -0
  82. package/dist/chunk-NFAYHPRH.js +323 -0
  83. package/dist/chunk-O37BQ65S.js +21 -0
  84. package/dist/chunk-O74MJHXU.js +187 -0
  85. package/dist/chunk-OJZEX73F.js +112 -0
  86. package/dist/chunk-PAAWLLZX.js +74 -0
  87. package/dist/chunk-PFXFQQRT.js +339 -0
  88. package/dist/chunk-PFZO3C6H.js +14 -0
  89. package/dist/chunk-PHH7LD45.js +113 -0
  90. package/dist/chunk-QRTG4XTI.js +188 -0
  91. package/dist/chunk-QVOVMXJR.js +1351 -0
  92. package/dist/chunk-RCQYT2I4.js +757 -0
  93. package/dist/chunk-RD6DEE36.js +1178 -0
  94. package/dist/chunk-RJIZEJ42.js +30 -0
  95. package/dist/chunk-RPOA7IAE.js +150 -0
  96. package/dist/chunk-SN2DQRL6.js +1172 -0
  97. package/dist/chunk-SQJVFEBV.js +41 -0
  98. package/dist/chunk-SQP64RCS.js +5391 -0
  99. package/dist/chunk-SVT4RNTR.js +49 -0
  100. package/dist/chunk-SWUFN7XM.js +43 -0
  101. package/dist/chunk-SXMVYC5H.js +174 -0
  102. package/dist/chunk-SZ6AYUIZ.js +23 -0
  103. package/dist/chunk-T3KGZBU5.js +3171 -0
  104. package/dist/chunk-TBRL2RCC.js +9 -0
  105. package/dist/chunk-TRT2HRWZ.js +18 -0
  106. package/dist/chunk-TYW2GI5I.js +1077 -0
  107. package/dist/chunk-UIWONWVG.js +4959 -0
  108. package/dist/chunk-VB3H5WWB.js +151 -0
  109. package/dist/chunk-W4A6QA3D.js +258 -0
  110. package/dist/chunk-WBPVKEEE.js +227 -0
  111. package/dist/chunk-WEBMSQP2.js +123 -0
  112. package/dist/chunk-WOEZV3Q4.js +333 -0
  113. package/dist/chunk-WQQON3SV.js +473 -0
  114. package/dist/chunk-WQTOVMGV.js +119 -0
  115. package/dist/chunk-WZO23AWO.js +2779 -0
  116. package/dist/chunk-XBDP4QPW.js +7 -0
  117. package/dist/chunk-XEBHSJLT.js +103 -0
  118. package/dist/chunk-XQ2ECNK3.js +1 -0
  119. package/dist/chunk-XQ2XGIBF.js +2086 -0
  120. package/dist/chunk-Y2GE5TSI.js +355 -0
  121. package/dist/chunk-YBUJCZ57.js +351 -0
  122. package/dist/chunk-YNCVSFGF.js +149 -0
  123. package/dist/chunk-YUPMXOGP.js +282 -0
  124. package/dist/chunk-YY6APYUM.js +49 -0
  125. package/dist/chunk-Z2IJUO45.js +691 -0
  126. package/dist/chunk-ZEHUCJHY.js +129 -0
  127. package/dist/chunk-ZYU2YOJ6.js +1496 -0
  128. package/dist/chunk-ZZ4V3WIZ.js +163 -0
  129. package/dist/coordination/agents/index.js +145 -6260
  130. package/dist/coordination/index.js +365 -34323
  131. package/dist/coordination/mailbox-project-server.js +48 -3220
  132. package/dist/coordination/mailbox-types.d.ts +13 -1
  133. package/dist/coordination/provider-status-tracker.d.ts +4 -0
  134. package/dist/coordination/sqlite-mailbox.d.ts +2 -1
  135. package/dist/core/agent.d.ts +14 -1
  136. package/dist/core/index.js +267 -12479
  137. package/dist/core/model-ref.js +5 -23
  138. package/dist/core/provider-runner.d.ts +36 -1
  139. package/dist/design/index.js +50 -1087
  140. package/dist/execution/index.d.ts +1 -1
  141. package/dist/execution/index.js +1599 -21887
  142. package/dist/execution/prompt-enhancer.js +16 -535
  143. package/dist/execution/retry-policy.d.ts +31 -1
  144. package/dist/extension/index.js +7 -311
  145. package/dist/goal/index.js +33 -3435
  146. package/dist/hooks/index.js +14 -1138
  147. package/dist/hq/index.js +112 -5139
  148. package/dist/hq/protocol.js +21 -668
  149. package/dist/index.js +1410 -92655
  150. package/dist/infrastructure/index.js +64 -4811
  151. package/dist/kernel/events/provider-events.d.ts +15 -0
  152. package/dist/kernel/events/wrongtrace-events.d.ts +26 -0
  153. package/dist/kernel/events.d.ts +16 -7
  154. package/dist/kernel/index.js +14 -992
  155. package/dist/models/index.js +40 -1117
  156. package/dist/notifications/index.js +3 -108
  157. package/dist/observability/index.js +17 -279
  158. package/dist/plugin/index.js +584 -14835
  159. package/dist/prompts/index.js +14 -948
  160. package/dist/registry/index.js +9 -822
  161. package/dist/registry-R23UBE7H.js +14 -0
  162. package/dist/replay/index.js +6 -84
  163. package/dist/review-finding-store-DKAV3AS6.js +21 -0
  164. package/dist/review-report-store-OWY3EC3N.js +19 -0
  165. package/dist/security/index.js +114 -2202
  166. package/dist/session-catalog/index.js +36 -2103
  167. package/dist/session-catalog/project-server.js +42 -1435
  168. package/dist/skills/index.js +35 -1578
  169. package/dist/storage/index.js +182 -15600
  170. package/dist/tasking/index.js +10 -676
  171. package/dist/tools/index.js +52 -9589
  172. package/dist/types/config/autonomy.d.ts +5 -0
  173. package/dist/types/config/tools.d.ts +2 -2
  174. package/dist/types/config/ui.d.ts +1 -1
  175. package/dist/types/errors.d.ts +18 -0
  176. package/dist/types/index.js +121 -1341
  177. package/dist/types/provider-runner.d.ts +8 -0
  178. package/dist/types/session-markers.js +8 -144
  179. package/dist/utils/error.js +3 -4
  180. package/dist/utils/expect-defined.js +3 -9
  181. package/dist/utils/heap-watchdog.js +6 -706
  182. package/dist/utils/index.js +269 -5685
  183. package/dist/utils/sage-output-block.js +5 -42
  184. package/dist/wiring/proxy-rewrite.d.ts +92 -4
  185. package/dist/wiring/proxy-rewrite.js +20 -61
  186. package/dist/worktree/index.js +6 -887
  187. package/package.json +4 -4
@@ -0,0 +1,342 @@
1
+ // src/utils/term.ts
2
+ var hasStdout = () => typeof process !== "undefined" && !!process.stdout;
3
+ var hasStdin = () => typeof process !== "undefined" && !!process.stdin;
4
+ function isStdoutTTY() {
5
+ return hasStdout() && Boolean(process.stdout.isTTY);
6
+ }
7
+ function isStdinTTY() {
8
+ return hasStdin() && Boolean(process.stdin.isTTY);
9
+ }
10
+ function isInteractive() {
11
+ return isStdinTTY() && isStdoutTTY();
12
+ }
13
+ function getTermSize() {
14
+ if (!hasStdout()) return { rows: 24, cols: 80 };
15
+ return {
16
+ rows: process.stdout.rows ?? 24,
17
+ cols: process.stdout.columns ?? 80
18
+ };
19
+ }
20
+ function onResize(cb, stream = process.stdout) {
21
+ if (!stream || typeof stream.on !== "function") return () => {
22
+ };
23
+ const handler = () => {
24
+ cb({
25
+ rows: stream.rows ?? 24,
26
+ cols: stream.columns ?? 80
27
+ });
28
+ };
29
+ stream.on("resize", handler);
30
+ return () => {
31
+ stream.off("resize", handler);
32
+ };
33
+ }
34
+ function setRawMode(input, mode) {
35
+ if (input?.isTTY !== true) return false;
36
+ if (typeof input.setRawMode !== "function") return false;
37
+ input.setRawMode(mode);
38
+ return true;
39
+ }
40
+ var activeOutputGuard = null;
41
+ function setOutputLineGuard(guard) {
42
+ activeOutputGuard = guard;
43
+ }
44
+ function writeTo(s, stream) {
45
+ if (!stream || typeof stream.write !== "function") return false;
46
+ const guard = activeOutputGuard;
47
+ if (!guard) {
48
+ stream.write(s);
49
+ return true;
50
+ }
51
+ guard.suspend();
52
+ stream.write(s);
53
+ guard.resume();
54
+ return true;
55
+ }
56
+ function writeOut(s, stream = process.stdout) {
57
+ return writeTo(s, stream);
58
+ }
59
+ function writeErr(s, stream = process.stderr) {
60
+ return writeTo(s, stream);
61
+ }
62
+ function parseColorDepth(env) {
63
+ if (env.FORCE_COLOR === "0") return 0;
64
+ if (env.FORCE_COLOR !== void 0) return 3;
65
+ if (typeof env.NO_COLOR === "string" && env.NO_COLOR !== "") return 0;
66
+ const colorterm = (env.COLORTERM ?? "").toLowerCase();
67
+ if (colorterm === "truecolor" || colorterm === "24bit") return 3;
68
+ const term = (env.TERM ?? "").toLowerCase();
69
+ if (term.includes("truecolor") || term.includes("24bit")) return 3;
70
+ if (term.includes("256color")) return 2;
71
+ if (term === "dumb") return 0;
72
+ return 1;
73
+ }
74
+ function parseMouseProtocol(term) {
75
+ const t = term.toLowerCase();
76
+ if (t.startsWith("xterm") || t.startsWith("tmux") || t.startsWith("screen") || t.includes("rxvt-unicode") || t.includes("urxvt") || t.includes("konsole") || t.includes("gnome") || t.includes("foot") || t.includes("alacritty") || t.includes("wezterm") || t.includes("kitty") || t.includes("vscode") || t.includes("Apple_Terminal")) {
77
+ return "sgr";
78
+ }
79
+ if (t.startsWith("rxvt") || t.startsWith("linux") || t.includes("Eterm")) {
80
+ return "urxvt";
81
+ }
82
+ if (t === "vt100" || t === "dumb") return "none";
83
+ return "sgr";
84
+ }
85
+ function detectTerminal(opts = {}) {
86
+ const stdin = opts.stdin ?? process.stdin;
87
+ const stdout = opts.stdout ?? process.stdout;
88
+ const env = opts.env ?? process.env;
89
+ const isRealTTY = (stdin?.isTTY ?? false) && (stdout?.isTTY ?? false);
90
+ const stdoutWritable = isRealTTY && typeof stdout?.write === "function";
91
+ const term = env.TERM ?? "";
92
+ const isTmux = term.toLowerCase().startsWith("tmux");
93
+ const isWindowsConhost = isRealTTY && process.platform === "win32" && typeof stdout.getColorDepth !== "function";
94
+ return {
95
+ isRealTTY,
96
+ colorDepth: isRealTTY ? parseColorDepth(env) : 0,
97
+ stdoutWritable,
98
+ mouseProtocol: parseMouseProtocol(term),
99
+ canSetTitle: isRealTTY && term !== "dumb",
100
+ isTmux,
101
+ isWindowsConhost
102
+ };
103
+ }
104
+ var TerminalLifecycle = class {
105
+ _active = false;
106
+ /**
107
+ * The stdin stream we took raw mode on. Set by `acquire()`; undefined before
108
+ * first call. Used by `release()` and by the ConPTY race-closer in
109
+ * `acquire()`.
110
+ */
111
+ _stdin;
112
+ /**
113
+ * The `isRaw` snapshot captured before the first `acquire()` call, so
114
+ * `release()` restores to the pre-TUI state rather than blindly disabling
115
+ * raw mode. Null when `acquire()` has never been called.
116
+ */
117
+ _wasRaw = null;
118
+ /**
119
+ * Whether stdin was paused before the TUI took ownership. Readline closes
120
+ * its interface by pausing the shared process stream, so raw mode alone is
121
+ * not enough to make Ink receive bytes during the boot-prompt -> TUI handoff.
122
+ */
123
+ _wasPaused = null;
124
+ /**
125
+ * Request the process to exit. Set the flag, trigger any registered
126
+ * `onRequestExit` callback (typically Ink's `unmount()`), and arm a
127
+ * deadline timer. When the timer fires the process is hard-exited.
128
+ *
129
+ * Safe to call multiple times: subsequent calls no-op after the first.
130
+ */
131
+ requestExit;
132
+ /**
133
+ * Callback invoked when `requestExit` is called. Registered by the Ink
134
+ * mount point so unmount() runs before the deadline timer fires.
135
+ */
136
+ onRequestExit = null;
137
+ constructor() {
138
+ let exitCode = 0;
139
+ let requested = false;
140
+ this.requestExit = (code = 0) => {
141
+ exitCode = code;
142
+ if (requested) return;
143
+ requested = true;
144
+ try {
145
+ this.onRequestExit?.();
146
+ } catch {
147
+ }
148
+ setTimeout(() => process.exit(exitCode), 5e3).unref();
149
+ };
150
+ }
151
+ /** True while raw mode is held. */
152
+ get active() {
153
+ return this._active;
154
+ }
155
+ /**
156
+ * Acquire raw mode on `stdin`. Idempotent — calling twice is safe; only the
157
+ * first call has any effect.
158
+ *
159
+ * On Windows ConPTY, calls `setRawMode` twice: once immediately, then again
160
+ * after the next event-loop tick. This closes the ConPTY race where
161
+ * `readline`'s cleanup (registered before this class is constructed) can
162
+ * restore the original cooked mode after we set raw mode but before Ink's
163
+ * render loop takes over the stdin fd. The double-call ensures the last
164
+ * writer wins.
165
+ *
166
+ * @param stdin - The stdin stream (defaults to `process.stdin`).
167
+ * @returns `true` if raw mode was acquired; `false` if stdin is not a TTY
168
+ * or already shut down.
169
+ */
170
+ acquire(stdin = process.stdin) {
171
+ if (this._active) return false;
172
+ if (stdin?.isTTY !== true) return false;
173
+ if (typeof stdin.setRawMode !== "function") return false;
174
+ this._wasRaw = stdin.isRaw ?? false;
175
+ this._wasPaused = stdin.isPaused();
176
+ this._stdin = stdin;
177
+ stdin.setRawMode(true);
178
+ stdin.resume();
179
+ this._active = true;
180
+ if (process.platform === "win32") {
181
+ setImmediate(() => {
182
+ if (this._active && this._stdin?.isTTY) {
183
+ this._stdin.setRawMode?.(true);
184
+ }
185
+ });
186
+ }
187
+ return true;
188
+ }
189
+ /**
190
+ * Release raw mode and restore the terminal to the state it was in before
191
+ * `acquire()` was called. Idempotent — subsequent calls are no-ops.
192
+ *
193
+ * Call this on: SIGINT, SIGTERM, SIGHUP, SIGBREAK, and `process.exit`.
194
+ *
195
+ * ⚠ **Windows caveat**: `setRawMode(false)` on ConPTY restores the original
196
+ * console mode captured when the process started — not the mode captured by
197
+ * `acquire()`. On ConPTY, the original mode was already raw (ConPTY starts
198
+ * raw), so this call is typically a no-op on Windows Terminal. On conhost.exe
199
+ * it may restore cooked mode, which is correct for that backend.
200
+ */
201
+ release() {
202
+ if (!this._active) return;
203
+ this._active = false;
204
+ const stdin = this._stdin;
205
+ if (stdin?.isTTY === true) {
206
+ stdin.setRawMode?.(this._wasRaw ?? false);
207
+ if (this._wasPaused) stdin.pause();
208
+ }
209
+ this._stdin = void 0;
210
+ this._wasRaw = null;
211
+ this._wasPaused = null;
212
+ }
213
+ /**
214
+ * Synchronously reset all terminal state written by the TUI layer:
215
+ * raw mode, SGR attributes, cursor visibility, and mouse tracking.
216
+ *
217
+ * Intended for the final `process.on('exit')` handler where async is
218
+ * impossible. Uses `\x1b[0m` (SGR reset), `\x1b[?25h` (cursor show),
219
+ * and `\x1b[?9l` (mouse off) — all safe to emit even if the terminal does
220
+ * not understand them (unknown CSI sequences are silently ignored).
221
+ *
222
+ * Safe to call multiple times from multiple exit paths because each write
223
+ * is a constant-time synchronous stream write.
224
+ *
225
+ * @param stdout - Stream to reset (defaults to `process.stdout`).
226
+ */
227
+ reset(stdout = process.stdout) {
228
+ if (typeof stdout?.write !== "function") return;
229
+ stdout.write("\x1B[0m");
230
+ stdout.write("\x1B[?25h");
231
+ stdout.write("\x1B[?1003l\x1B[?1002l\x1B[?1000l");
232
+ }
233
+ };
234
+ var ESCAPE_TERMINATOR = Object.freeze({
235
+ BEL: "\x07",
236
+ // OSC 0 / OSC 2 (title)
237
+ ST: "\x1B\\"
238
+ // DCS / strict OSC
239
+ });
240
+ function safeEmit(sequence, stdout = process.stdout) {
241
+ const raw = typeof sequence === "string" ? sequence : sequence.raw;
242
+ const term = typeof sequence === "string" ? void 0 : sequence.terminator;
243
+ if (!raw) {
244
+ return { ok: false, reason: "empty" };
245
+ }
246
+ if (stdout?.isTTY !== true) {
247
+ return { ok: false, reason: "not_a_tty" };
248
+ }
249
+ if (raw.startsWith("\x1B]") || raw.startsWith("\x1BP")) {
250
+ if (!term) {
251
+ void term;
252
+ const safe = `${raw}\x07`;
253
+ try {
254
+ stdout.write(safe);
255
+ } catch {
256
+ return { ok: false, reason: "unwritable" };
257
+ }
258
+ return { ok: true, reason: "empty" };
259
+ }
260
+ try {
261
+ stdout.write(`${raw}${term}`);
262
+ } catch {
263
+ return { ok: false, reason: "unwritable" };
264
+ }
265
+ return { ok: true, reason: "empty" };
266
+ }
267
+ try {
268
+ stdout.write(raw);
269
+ } catch {
270
+ return { ok: false, reason: "unwritable" };
271
+ }
272
+ return { ok: true, reason: "empty" };
273
+ }
274
+ function buildTitleSequence(title, terminator = ESCAPE_TERMINATOR.BEL) {
275
+ return {
276
+ raw: `\x1B]0;${title.replace(/\x07/g, "")}`,
277
+ terminator
278
+ };
279
+ }
280
+ function buildSgrSequence(...codes) {
281
+ return { raw: `\x1B[${codes.join(";")}m` };
282
+ }
283
+ function setTitle(title, stdout = process.stdout) {
284
+ return safeEmit(buildTitleSequence(title), stdout).ok;
285
+ }
286
+
287
+ // src/utils/color.ts
288
+ var isColorTty = () => {
289
+ if (envFlag(process.env.NO_COLOR)) return false;
290
+ if (envFlag(process.env.FORCE_COLOR)) return true;
291
+ return isStdoutTTY();
292
+ };
293
+ function envFlag(value) {
294
+ if (value === void 0) return false;
295
+ if (value.trim() === "") return false;
296
+ return !/^(0|false|no|off)$/i.test(value.trim());
297
+ }
298
+ var COLOR = isColorTty();
299
+ var wrap = (open, close) => (s) => COLOR ? `\x1B[${open}m${s}\x1B[${close}m` : s;
300
+ var color = {
301
+ reset: wrap("0", "0"),
302
+ bold: wrap("1", "22"),
303
+ dim: wrap("2", "22"),
304
+ italic: wrap("3", "23"),
305
+ underline: wrap("4", "24"),
306
+ red: wrap("31", "39"),
307
+ green: wrap("32", "39"),
308
+ yellow: wrap("33", "39"),
309
+ blue: wrap("34", "39"),
310
+ magenta: wrap("35", "39"),
311
+ cyan: wrap("36", "39"),
312
+ gray: wrap("90", "39"),
313
+ amber: wrap("38;5;214", "39"),
314
+ pink: wrap("38;5;205", "39"),
315
+ bgRed: wrap("41", "49"),
316
+ bgGreen: wrap("42", "49")
317
+ };
318
+ function stripAnsi(s) {
319
+ return s.replace(/\x1b\[[0-9;]*[A-Za-z]/g, "");
320
+ }
321
+
322
+ export {
323
+ isStdoutTTY,
324
+ isStdinTTY,
325
+ isInteractive,
326
+ getTermSize,
327
+ onResize,
328
+ setRawMode,
329
+ setOutputLineGuard,
330
+ writeOut,
331
+ writeErr,
332
+ detectTerminal,
333
+ TerminalLifecycle,
334
+ ESCAPE_TERMINATOR,
335
+ safeEmit,
336
+ buildTitleSequence,
337
+ buildSgrSequence,
338
+ setTitle,
339
+ color,
340
+ stripAnsi
341
+ };
342
+ //# sourceMappingURL=chunk-4VWO3ZXL.js.map
@@ -0,0 +1,187 @@
1
+ import {
2
+ atomicWrite
3
+ } from "./chunk-7ZHZE5EO.js";
4
+
5
+ // src/utils/ulid.ts
6
+ import { randomBytes } from "node:crypto";
7
+ var ENCODING = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
8
+ var ENCODING_LEN = ENCODING.length;
9
+ var TIME_LEN = 10;
10
+ var RANDOM_LEN = 16;
11
+ function encodeTime(now, len) {
12
+ let mod;
13
+ let str = "";
14
+ for (let i = len - 1; i >= 0; i--) {
15
+ mod = now % ENCODING_LEN;
16
+ str = ENCODING[mod] + str;
17
+ now = (now - mod) / ENCODING_LEN;
18
+ }
19
+ return str;
20
+ }
21
+ function encodeRandom(len) {
22
+ const bytes = randomBytes(len);
23
+ let str = "";
24
+ for (let i = 0; i < len; i++) {
25
+ str += ENCODING[bytes[i] % ENCODING_LEN];
26
+ }
27
+ return str;
28
+ }
29
+ function ulid(seedTime = Date.now()) {
30
+ return encodeTime(seedTime, TIME_LEN) + encodeRandom(RANDOM_LEN);
31
+ }
32
+ function isUlid(value) {
33
+ if (value.length !== TIME_LEN + RANDOM_LEN) return false;
34
+ for (const ch of value) {
35
+ if (!ENCODING.includes(ch)) return false;
36
+ }
37
+ return true;
38
+ }
39
+
40
+ // src/utils/project-identity.ts
41
+ import * as fs from "node:fs";
42
+ import * as fsPromises from "node:fs/promises";
43
+ import * as path from "node:path";
44
+ var PROJECT_IDENTITY_VERSION = 1;
45
+ var PROJECT_ID_PREFIX = "proj_";
46
+ var PROJECT_IDENTITY_RELATIVE_PATH = path.join(".wrongstack", "project.json");
47
+ var PROJECT_GITIGNORE_RULES = [
48
+ ".wrongstack/",
49
+ "!/.wrongstack/",
50
+ "/.wrongstack/*",
51
+ "!/.wrongstack/project.json"
52
+ ];
53
+ function projectIdentityPath(projectRoot) {
54
+ return path.join(projectRoot, PROJECT_IDENTITY_RELATIVE_PATH);
55
+ }
56
+ function createProjectId(seedTime = Date.now()) {
57
+ return `${PROJECT_ID_PREFIX}${ulid(seedTime)}`;
58
+ }
59
+ function isProjectId(value) {
60
+ return value.startsWith(PROJECT_ID_PREFIX) && isUlid(value.slice(PROJECT_ID_PREFIX.length));
61
+ }
62
+ function readProjectIdentitySync(projectRoot) {
63
+ const filePath = projectIdentityPath(projectRoot);
64
+ try {
65
+ return parseProjectIdentity(fs.readFileSync(filePath, "utf8"), filePath);
66
+ } catch (error) {
67
+ if (isMissingFileError(error)) return void 0;
68
+ throw error;
69
+ }
70
+ }
71
+ async function readProjectIdentity(projectRoot) {
72
+ const filePath = projectIdentityPath(projectRoot);
73
+ try {
74
+ return parseProjectIdentity(await fsPromises.readFile(filePath, "utf8"), filePath);
75
+ } catch (error) {
76
+ if (isMissingFileError(error)) return void 0;
77
+ throw error;
78
+ }
79
+ }
80
+ async function ensureProjectIdentity(projectRoot, idFactory = createProjectId) {
81
+ const existing = await readProjectIdentity(projectRoot);
82
+ if (existing) return { identity: existing, created: false };
83
+ const filePath = projectIdentityPath(projectRoot);
84
+ const identity = makeIdentity(idFactory());
85
+ await fsPromises.mkdir(path.dirname(filePath), { recursive: true });
86
+ try {
87
+ await fsPromises.writeFile(filePath, serializeProjectIdentity(identity), {
88
+ encoding: "utf8",
89
+ flag: "wx"
90
+ });
91
+ return { identity, created: true };
92
+ } catch (error) {
93
+ if (!isAlreadyExistsError(error)) throw error;
94
+ const winner = await readProjectIdentity(projectRoot);
95
+ if (!winner) throw error;
96
+ return { identity: winner, created: false };
97
+ }
98
+ }
99
+ async function rekeyProjectIdentity(projectRoot, idFactory = createProjectId) {
100
+ const previous = await readProjectIdentity(projectRoot);
101
+ const identity = makeIdentity(idFactory());
102
+ const filePath = projectIdentityPath(projectRoot);
103
+ await fsPromises.mkdir(path.dirname(filePath), { recursive: true });
104
+ await atomicWrite(filePath, serializeProjectIdentity(identity));
105
+ return { previous, identity };
106
+ }
107
+ async function ensureProjectGitignore(projectRoot) {
108
+ const filePath = path.join(projectRoot, ".gitignore");
109
+ let content = "";
110
+ try {
111
+ content = await fsPromises.readFile(filePath, "utf8");
112
+ } catch (error) {
113
+ if (!isMissingFileError(error)) throw error;
114
+ }
115
+ const hadTrailingNewline = content.endsWith("\n");
116
+ const lines = content.length === 0 ? [] : content.split(/\r?\n/);
117
+ if (hadTrailingNewline) lines.pop();
118
+ let changed = false;
119
+ for (let index = 0; index < lines.length; index++) {
120
+ if (lines[index]?.trim() === ".wrongstack/*") {
121
+ lines[index] = ".wrongstack/";
122
+ changed = true;
123
+ }
124
+ }
125
+ for (const entry of PROJECT_GITIGNORE_RULES) {
126
+ if (!lines.some((line) => line.trim() === entry)) {
127
+ if (entry === ".wrongstack/" && lines.length > 0 && lines.at(-1) !== "") lines.push("");
128
+ lines.push(entry);
129
+ changed = true;
130
+ }
131
+ }
132
+ if (!changed) return;
133
+ await fsPromises.writeFile(filePath, `${lines.join("\n")}
134
+ `, "utf8");
135
+ }
136
+ function makeIdentity(projectId) {
137
+ if (!isProjectId(projectId)) {
138
+ throw new Error(`Invalid WrongStack project id: ${projectId}`);
139
+ }
140
+ return { version: PROJECT_IDENTITY_VERSION, projectId };
141
+ }
142
+ function parseProjectIdentity(raw, filePath) {
143
+ let value;
144
+ try {
145
+ value = JSON.parse(raw);
146
+ } catch {
147
+ throw new Error(`Invalid JSON in WrongStack project identity file: ${filePath}`);
148
+ }
149
+ if (typeof value !== "object" || value === null) {
150
+ throw new Error(`Invalid WrongStack project identity file: ${filePath}`);
151
+ }
152
+ const record = value;
153
+ if (record["version"] !== PROJECT_IDENTITY_VERSION) {
154
+ throw new Error(`Unsupported WrongStack project identity version in ${filePath}`);
155
+ }
156
+ if (typeof record["projectId"] !== "string" || !isProjectId(record["projectId"])) {
157
+ throw new Error(`Invalid projectId in WrongStack project identity file: ${filePath}`);
158
+ }
159
+ return { version: PROJECT_IDENTITY_VERSION, projectId: record["projectId"] };
160
+ }
161
+ function serializeProjectIdentity(identity) {
162
+ return `${JSON.stringify(identity, null, 2)}
163
+ `;
164
+ }
165
+ function isMissingFileError(error) {
166
+ return error?.code === "ENOENT";
167
+ }
168
+ function isAlreadyExistsError(error) {
169
+ return error?.code === "EEXIST";
170
+ }
171
+
172
+ export {
173
+ ulid,
174
+ isUlid,
175
+ PROJECT_IDENTITY_VERSION,
176
+ PROJECT_ID_PREFIX,
177
+ PROJECT_IDENTITY_RELATIVE_PATH,
178
+ projectIdentityPath,
179
+ createProjectId,
180
+ isProjectId,
181
+ readProjectIdentitySync,
182
+ readProjectIdentity,
183
+ ensureProjectIdentity,
184
+ rekeyProjectIdentity,
185
+ ensureProjectGitignore
186
+ };
187
+ //# sourceMappingURL=chunk-4XV6IR37.js.map
@@ -0,0 +1,183 @@
1
+ // src/wiring/proxy-rewrite.ts
2
+ var PROXY_PATH_PREFIX = "/proxy/";
3
+ var PROXY_EXCLUDED_PROVIDERS = /* @__PURE__ */ new Set(["openai-codex"]);
4
+ function isProxyEligible(providerId) {
5
+ if (!providerId) return false;
6
+ if (PROXY_EXCLUDED_PROVIDERS.has(providerId)) return false;
7
+ return true;
8
+ }
9
+ function rewriteBaseUrl(originalBaseUrl, proxyUrl) {
10
+ if (!originalBaseUrl) return void 0;
11
+ if (!proxyUrl) return originalBaseUrl;
12
+ if (!isProxyEligibleForRewrite(originalBaseUrl, proxyUrl)) return originalBaseUrl;
13
+ return composeRewrittenUrl(originalBaseUrl, proxyUrl);
14
+ }
15
+ function isProxyEligibleForRewrite(originalBaseUrl, proxyUrl) {
16
+ if (!originalBaseUrl.includes("://")) return false;
17
+ if (!proxyUrl.includes("://")) return false;
18
+ const normalizedProxy = proxyUrl.replace(/\/+$/, "");
19
+ if (originalBaseUrl.startsWith(`${normalizedProxy}${PROXY_PATH_PREFIX}`)) {
20
+ return false;
21
+ }
22
+ try {
23
+ const parsed = new URL(originalBaseUrl);
24
+ const isLoopback = parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1" || // WHATWG URL serializes IPv6 hosts with brackets — `[::1]`, not `::1`.
25
+ parsed.hostname === "[::1]";
26
+ if (isLoopback && parsed.port !== "") return false;
27
+ } catch {
28
+ }
29
+ return true;
30
+ }
31
+ function composeRewrittenUrl(originalBaseUrl, proxyUrl) {
32
+ const parsedOriginal = new URL(originalBaseUrl);
33
+ const hostAndPath = `${parsedOriginal.host}${parsedOriginal.pathname}`;
34
+ const trailingQuery = parsedOriginal.search || "";
35
+ const trailingHash = parsedOriginal.hash || "";
36
+ const proxyRoot = proxyUrl.replace(/\/+$/, "");
37
+ return `${proxyRoot}${PROXY_PATH_PREFIX}${hostAndPath}${trailingQuery}${trailingHash}`;
38
+ }
39
+ var DEFAULT_PROXY_CONFIG = { enabled: false, url: "", active: false };
40
+ var currentConfig = { ...DEFAULT_PROXY_CONFIG };
41
+ function getProxyConfig() {
42
+ return currentConfig;
43
+ }
44
+ var listeners = /* @__PURE__ */ new Set();
45
+ function subscribeToProxyConfig(listener) {
46
+ listeners.add(listener);
47
+ return () => {
48
+ listeners.delete(listener);
49
+ };
50
+ }
51
+ function applyProxyConfig(next) {
52
+ const previous = currentConfig;
53
+ currentConfig = {
54
+ enabled: next.enabled ?? previous.enabled,
55
+ url: next.url ?? previous.url,
56
+ active: next.active ?? previous.active
57
+ };
58
+ const materialChange = currentConfig.enabled !== previous.enabled || currentConfig.url !== previous.url || currentConfig.active !== previous.active;
59
+ if (materialChange) {
60
+ for (const listener of listeners) {
61
+ try {
62
+ listener(currentConfig, previous);
63
+ } catch {
64
+ }
65
+ }
66
+ }
67
+ return previous;
68
+ }
69
+ function shouldRewriteFor(providerId) {
70
+ const cfg = currentConfig;
71
+ if (!cfg.enabled || !cfg.active || !cfg.url) return false;
72
+ return isProxyEligible(providerId);
73
+ }
74
+ function deactivateProxyOnConnectionFailure(err) {
75
+ const cfg = currentConfig;
76
+ if (!cfg.enabled || !cfg.active) return false;
77
+ const msg = (err instanceof Error ? `${err.name} ${err.message} ${err.code ?? ""}` : String(err)).toLowerCase();
78
+ let isProxyFail = false;
79
+ if (cfg.url) {
80
+ try {
81
+ const parsed = new URL(cfg.url);
82
+ if (msg.includes(parsed.host.toLowerCase())) isProxyFail = true;
83
+ } catch {
84
+ }
85
+ }
86
+ if (!isProxyFail && (msg.includes("econnrefused") || msg.includes("ehostunreach") || msg.includes("enetunreach") || msg.includes("fetch failed") || msg.includes("failed to fetch") || msg.includes("connect error") || msg.includes("proxy error") || msg.includes("502") || msg.includes("503") || msg.includes("504"))) {
87
+ isProxyFail = true;
88
+ }
89
+ if (isProxyFail) {
90
+ applyProxyConfig({ active: false });
91
+ return true;
92
+ }
93
+ return false;
94
+ }
95
+ function __resetProxyConfigForTests() {
96
+ currentConfig = { ...DEFAULT_PROXY_CONFIG };
97
+ listeners.clear();
98
+ instantApplyChains.clear();
99
+ }
100
+ var PROXY_ROUTING_SETTLE_CAP_MS = 2e3;
101
+ var instantApplyChains = /* @__PURE__ */ new Set();
102
+ async function waitForProxyRoutingSettle(timeoutMs = PROXY_ROUTING_SETTLE_CAP_MS, signal) {
103
+ if (signal?.aborted) return;
104
+ const chains = [...instantApplyChains].map((get) => get());
105
+ if (chains.length === 0) return;
106
+ let timer;
107
+ let onAbort;
108
+ try {
109
+ await Promise.race([
110
+ Promise.allSettled(chains),
111
+ new Promise((resolve) => {
112
+ onAbort = () => resolve();
113
+ timer = setTimeout(resolve, Math.max(0, timeoutMs));
114
+ signal?.addEventListener("abort", onAbort, { once: true });
115
+ })
116
+ ]);
117
+ } finally {
118
+ if (timer !== void 0) clearTimeout(timer);
119
+ if (onAbort !== void 0) signal?.removeEventListener("abort", onAbort);
120
+ }
121
+ }
122
+ function effectiveBaseUrlFor(cfg, providerId, rawBaseUrl) {
123
+ if (!rawBaseUrl) return void 0;
124
+ const active = cfg.enabled && cfg.active && !!cfg.url && isProxyEligible(providerId);
125
+ return active ? rewriteBaseUrl(rawBaseUrl, cfg.url) : rawBaseUrl;
126
+ }
127
+ function effectiveBaseUrl(providerId, rawBaseUrl) {
128
+ return effectiveBaseUrlFor(currentConfig, providerId, rawBaseUrl);
129
+ }
130
+ function createProxyInstantApply(deps) {
131
+ const { getActiveProviderId, getRawBaseUrl, rebuildProvider, logger } = deps;
132
+ let lastProviderId = getActiveProviderId();
133
+ let lastEffectiveUrl = effectiveBaseUrl(lastProviderId, getRawBaseUrl(lastProviderId));
134
+ let disposed = false;
135
+ let rebuildChain = Promise.resolve();
136
+ const chainGetter = () => rebuildChain;
137
+ instantApplyChains.add(chainGetter);
138
+ const unsubscribe = subscribeToProxyConfig((next, previous) => {
139
+ if (disposed) return;
140
+ const providerId = getActiveProviderId();
141
+ const raw = getRawBaseUrl(providerId);
142
+ const nextUrl = effectiveBaseUrlFor(next, providerId, raw);
143
+ const baselineUrl = providerId === lastProviderId ? lastEffectiveUrl : effectiveBaseUrlFor(previous, providerId, raw);
144
+ lastProviderId = providerId;
145
+ lastEffectiveUrl = nextUrl;
146
+ if (nextUrl === baselineUrl) return;
147
+ rebuildChain = rebuildChain.then(() => rebuildProvider(providerId)).then(() => {
148
+ if (!disposed) {
149
+ logger.info(`WrongProxy routing changed \u2014 live provider rebuilt (${providerId})`);
150
+ }
151
+ }).catch((err) => {
152
+ if (!disposed) {
153
+ logger.warn(
154
+ `WrongProxy instant-apply: provider rebuild failed for ${providerId}: ${err instanceof Error ? err.message : String(err)}`
155
+ );
156
+ }
157
+ });
158
+ });
159
+ return {
160
+ dispose() {
161
+ if (disposed) return;
162
+ disposed = true;
163
+ instantApplyChains.delete(chainGetter);
164
+ unsubscribe();
165
+ }
166
+ };
167
+ }
168
+
169
+ export {
170
+ PROXY_EXCLUDED_PROVIDERS,
171
+ isProxyEligible,
172
+ rewriteBaseUrl,
173
+ getProxyConfig,
174
+ subscribeToProxyConfig,
175
+ applyProxyConfig,
176
+ shouldRewriteFor,
177
+ deactivateProxyOnConnectionFailure,
178
+ __resetProxyConfigForTests,
179
+ PROXY_ROUTING_SETTLE_CAP_MS,
180
+ waitForProxyRoutingSettle,
181
+ createProxyInstantApply
182
+ };
183
+ //# sourceMappingURL=chunk-4ZHTKJHM.js.map