@wrongstack/core 0.313.0 → 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 (182) 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 -34324
  131. package/dist/coordination/mailbox-project-server.js +48 -3276
  132. package/dist/coordination/provider-status-tracker.d.ts +4 -0
  133. package/dist/core/agent.d.ts +14 -1
  134. package/dist/core/index.js +267 -12480
  135. package/dist/core/model-ref.js +5 -23
  136. package/dist/core/provider-runner.d.ts +36 -1
  137. package/dist/design/index.js +50 -1087
  138. package/dist/execution/index.d.ts +1 -1
  139. package/dist/execution/index.js +1599 -21888
  140. package/dist/execution/prompt-enhancer.js +16 -535
  141. package/dist/execution/retry-policy.d.ts +31 -1
  142. package/dist/extension/index.js +7 -311
  143. package/dist/goal/index.js +33 -3435
  144. package/dist/hooks/index.js +14 -1138
  145. package/dist/hq/index.js +112 -5139
  146. package/dist/hq/protocol.js +21 -668
  147. package/dist/index.js +1410 -92656
  148. package/dist/infrastructure/index.js +64 -4811
  149. package/dist/kernel/events/provider-events.d.ts +15 -0
  150. package/dist/kernel/index.js +14 -992
  151. package/dist/models/index.js +40 -1117
  152. package/dist/notifications/index.js +3 -108
  153. package/dist/observability/index.js +17 -279
  154. package/dist/plugin/index.js +584 -14835
  155. package/dist/prompts/index.js +14 -948
  156. package/dist/registry/index.js +9 -822
  157. package/dist/registry-R23UBE7H.js +14 -0
  158. package/dist/replay/index.js +6 -84
  159. package/dist/review-finding-store-DKAV3AS6.js +21 -0
  160. package/dist/review-report-store-OWY3EC3N.js +19 -0
  161. package/dist/security/index.js +114 -2202
  162. package/dist/session-catalog/index.js +36 -2103
  163. package/dist/session-catalog/project-server.js +42 -1435
  164. package/dist/skills/index.js +35 -1578
  165. package/dist/storage/index.js +182 -15600
  166. package/dist/tasking/index.js +10 -676
  167. package/dist/tools/index.js +52 -9590
  168. package/dist/types/config/autonomy.d.ts +5 -0
  169. package/dist/types/config/ui.d.ts +1 -1
  170. package/dist/types/errors.d.ts +18 -0
  171. package/dist/types/index.js +121 -1342
  172. package/dist/types/provider-runner.d.ts +8 -0
  173. package/dist/types/session-markers.js +8 -144
  174. package/dist/utils/error.js +3 -4
  175. package/dist/utils/expect-defined.js +3 -9
  176. package/dist/utils/heap-watchdog.js +6 -706
  177. package/dist/utils/index.js +269 -5685
  178. package/dist/utils/sage-output-block.js +5 -42
  179. package/dist/wiring/proxy-rewrite.d.ts +18 -0
  180. package/dist/wiring/proxy-rewrite.js +18 -121
  181. package/dist/worktree/index.js +6 -887
  182. package/package.json +4 -4
@@ -0,0 +1,1077 @@
1
+ import {
2
+ SYSTEM_BLOCK_SOURCE,
3
+ buildLiveNextStepsGateBlock
4
+ } from "./chunk-WZO23AWO.js";
5
+ import {
6
+ color,
7
+ writeErr
8
+ } from "./chunk-4VWO3ZXL.js";
9
+ import {
10
+ buildCompletedWorkLedgerBlock
11
+ } from "./chunk-EFEHDQGY.js";
12
+ import {
13
+ estimateTextTokens,
14
+ estimateToolDefTokens,
15
+ estimateToolInputTokens,
16
+ estimateToolResultTokens
17
+ } from "./chunk-FSWCWSTS.js";
18
+ import {
19
+ expectDefined
20
+ } from "./chunk-PFZO3C6H.js";
21
+
22
+ // src/utils/assert-never.ts
23
+ function assertNever(x, message) {
24
+ const err = new Error(
25
+ message ?? `Unhandled case: ${JSON.stringify(x)}`
26
+ );
27
+ err.name = "AssertNeverError";
28
+ throw err;
29
+ }
30
+
31
+ // src/utils/connectivity.ts
32
+ var DEFAULT_PROBE_URL = "https://1.1.1.1";
33
+ var DEFAULT_TIMEOUT_MS = 5e3;
34
+ var DEFAULT_TTL_MS = 3e4;
35
+ var cached;
36
+ async function checkConnectivity(opts) {
37
+ const url = opts?.probeUrl ?? DEFAULT_PROBE_URL;
38
+ const timeout = opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
39
+ const ttl = opts?.ttlMs ?? DEFAULT_TTL_MS;
40
+ if (cached && ttl > 0 && Date.now() - cached.at < ttl) {
41
+ return cached.ok;
42
+ }
43
+ cached = { ok: await probe(url, timeout), at: Date.now() };
44
+ return cached.ok;
45
+ }
46
+ async function probe(url, timeoutMs) {
47
+ const controller = new AbortController();
48
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
49
+ try {
50
+ await fetch(url, { method: "HEAD", signal: controller.signal });
51
+ return true;
52
+ } catch {
53
+ return false;
54
+ } finally {
55
+ clearTimeout(timer);
56
+ }
57
+ }
58
+ function resetConnectivityCache() {
59
+ cached = void 0;
60
+ }
61
+
62
+ // src/utils/context-breakdown.ts
63
+ var SYSTEM_BLOCK_SOURCES = [
64
+ "identity",
65
+ "tool-usage",
66
+ "environment",
67
+ "skills",
68
+ "mode",
69
+ "plan",
70
+ "leader-after-task",
71
+ "contributor",
72
+ "ledger",
73
+ "glossary",
74
+ "peers",
75
+ "nextsteps",
76
+ "other"
77
+ ];
78
+ function emptyBySource() {
79
+ const out = {};
80
+ for (const key of SYSTEM_BLOCK_SOURCES) out[key] = 0;
81
+ return out;
82
+ }
83
+ function isMcpTool(tool) {
84
+ return (tool.capabilities?.includes("mcp.proxy") ?? false) || tool.name.startsWith("mcp__");
85
+ }
86
+ function mcpServerOf(tool) {
87
+ const parts = tool.name.split("__");
88
+ return parts.length >= 3 && parts[0] === "mcp" ? parts[1] ?? "mcp" : "mcp";
89
+ }
90
+ function safeBuild(fn, warn = () => {
91
+ }) {
92
+ try {
93
+ return fn();
94
+ } catch (e) {
95
+ warn(e);
96
+ return void 0;
97
+ }
98
+ }
99
+ function resolveEffectiveMaxContext(ctx) {
100
+ const metaLimit = ctx.meta?.["effectiveMaxContext"];
101
+ const providerMax = ctx.provider.capabilities.maxContext;
102
+ return typeof metaLimit === "number" && metaLimit > 0 ? metaLimit : typeof providerMax === "number" && providerMax > 0 ? providerMax : 2e5;
103
+ }
104
+ function getContextBreakdown(ctx) {
105
+ const bySource = emptyBySource();
106
+ let systemTotal = 0;
107
+ for (const block of ctx.systemPrompt) {
108
+ const tokens = estimateTextTokens(block.text);
109
+ systemTotal += tokens;
110
+ bySource[SYSTEM_BLOCK_SOURCE.get(block) ?? "other"] += tokens;
111
+ }
112
+ let toolsBuiltin = 0;
113
+ let toolsMcp = 0;
114
+ const mcpByServer = {};
115
+ for (const tool of ctx.tools) {
116
+ const tokens = estimateToolDefTokens(tool);
117
+ if (isMcpTool(tool)) {
118
+ toolsMcp += tokens;
119
+ const server = mcpServerOf(tool);
120
+ mcpByServer[server] = (mcpByServer[server] ?? 0) + tokens;
121
+ } else {
122
+ toolsBuiltin += tokens;
123
+ }
124
+ }
125
+ let histText = 0;
126
+ let histToolInputs = 0;
127
+ let histToolResults = 0;
128
+ let histThinking = 0;
129
+ let histOther = 0;
130
+ for (const msg of ctx.messages) {
131
+ if (typeof msg.content === "string") {
132
+ histText += estimateTextTokens(msg.content);
133
+ continue;
134
+ }
135
+ for (const b of msg.content) {
136
+ switch (b.type) {
137
+ case "text":
138
+ histText += estimateTextTokens(b.text);
139
+ break;
140
+ case "tool_use":
141
+ histToolInputs += estimateToolInputTokens(b.input);
142
+ break;
143
+ case "tool_result":
144
+ histToolResults += estimateToolResultTokens(b.content);
145
+ break;
146
+ case "thinking":
147
+ histThinking += estimateTextTokens(JSON.stringify(b));
148
+ break;
149
+ default:
150
+ histOther += estimateTextTokens(JSON.stringify(b));
151
+ }
152
+ }
153
+ }
154
+ const warnings = [];
155
+ const warn = (e) => {
156
+ const msg = e instanceof Error ? e.message : String(e);
157
+ warnings.push(msg);
158
+ };
159
+ const ledgerBlock = safeBuild(() => buildCompletedWorkLedgerBlock(ctx), warn);
160
+ const nextstepsBlock = safeBuild(() => buildLiveNextStepsGateBlock(ctx), warn);
161
+ const ledger = ledgerBlock ? estimateTextTokens(ledgerBlock.text) : 0;
162
+ const nextsteps = nextstepsBlock ? estimateTextTokens(nextstepsBlock.text) : 0;
163
+ const toolsTotal = toolsBuiltin + toolsMcp;
164
+ const historyTotal = histText + histToolInputs + histToolResults + histThinking + histOther;
165
+ const volatileTotal = ledger + nextsteps;
166
+ const total = systemTotal + toolsTotal + historyTotal + volatileTotal;
167
+ const effectiveMaxContext = resolveEffectiveMaxContext(ctx);
168
+ return {
169
+ system: { total: systemTotal, bySource },
170
+ tools: {
171
+ total: toolsTotal,
172
+ builtin: toolsBuiltin,
173
+ mcp: toolsMcp,
174
+ count: ctx.tools.length,
175
+ mcpByServer
176
+ },
177
+ history: {
178
+ total: historyTotal,
179
+ text: histText,
180
+ toolInputs: histToolInputs,
181
+ toolResults: histToolResults,
182
+ thinking: histThinking,
183
+ other: histOther,
184
+ messageCount: ctx.messages.length
185
+ },
186
+ volatile: { ledger, nextsteps, total: volatileTotal },
187
+ total,
188
+ effectiveMaxContext,
189
+ usedPct: effectiveMaxContext > 0 ? total / effectiveMaxContext : 0,
190
+ warnings
191
+ };
192
+ }
193
+
194
+ // src/utils/crash-shield.ts
195
+ var CRASH_STORM_WINDOW_MS = 6e4;
196
+ var CRASH_STORM_LIMIT = 20;
197
+ var fatalSalvageHooks = [];
198
+ function addFatalSalvageHook(hook) {
199
+ fatalSalvageHooks.push(hook);
200
+ return () => {
201
+ const idx = fatalSalvageHooks.indexOf(hook);
202
+ if (idx >= 0) fatalSalvageHooks.splice(idx, 1);
203
+ };
204
+ }
205
+ function runFatalSalvageSync() {
206
+ for (const hook of [...fatalSalvageHooks]) {
207
+ try {
208
+ hook();
209
+ } catch {
210
+ }
211
+ }
212
+ }
213
+ function isBrokenOutputConsumer(error) {
214
+ if (typeof error !== "object" || error === null || !("code" in error)) return false;
215
+ return error.code === "EPIPE" || error.code === "ECONNRESET" || error.code === "ECONNABORTED";
216
+ }
217
+ function installCrashShield(options = {}) {
218
+ const target = options.target ?? process;
219
+ const exit = options.exit ?? ((code) => process.exit(code));
220
+ const write = options.write ?? ((s) => void writeErr(s));
221
+ const recent = [];
222
+ const isStorming = () => {
223
+ const now = Date.now();
224
+ recent.push(now);
225
+ while (recent.length > 0 && now - recent[0] > CRASH_STORM_WINDOW_MS) {
226
+ recent.shift();
227
+ }
228
+ return recent.length > CRASH_STORM_LIMIT;
229
+ };
230
+ const report = (kind, reason) => {
231
+ try {
232
+ const detail = reason instanceof Error ? reason.stack ?? reason.message : String(reason);
233
+ write(`[wrongstack] ${kind} (recovered \u2014 please report): ${detail}
234
+ `);
235
+ } catch {
236
+ }
237
+ };
238
+ const guard = (kind) => (reason) => {
239
+ if (isBrokenOutputConsumer(reason)) return;
240
+ report(kind, reason);
241
+ if (isStorming()) {
242
+ report(
243
+ kind,
244
+ new Error(
245
+ `error storm: >${CRASH_STORM_LIMIT} in ${CRASH_STORM_WINDOW_MS / 1e3}s \u2014 exiting`
246
+ )
247
+ );
248
+ runFatalSalvageSync();
249
+ exit(1);
250
+ }
251
+ };
252
+ const onRejection = guard("unhandled promise rejection");
253
+ const onException = guard("uncaught exception");
254
+ target.on("unhandledRejection", onRejection);
255
+ target.on("uncaughtException", onException);
256
+ return () => {
257
+ target.off("unhandledRejection", onRejection);
258
+ target.off("uncaughtException", onException);
259
+ };
260
+ }
261
+
262
+ // src/utils/diff.ts
263
+ function myersDiff(a, b) {
264
+ const N = a.length;
265
+ const M = b.length;
266
+ const max = N + M;
267
+ if (max === 0) return [];
268
+ const v = /* @__PURE__ */ new Map();
269
+ v.set(1, 0);
270
+ const trace = [];
271
+ for (let d = 0; d <= max; d++) {
272
+ const snapshot = new Map(v);
273
+ trace.push(snapshot);
274
+ for (let k = -d; k <= d; k += 2) {
275
+ const left = v.get(k - 1) ?? -1;
276
+ const right = v.get(k + 1) ?? -1;
277
+ let x;
278
+ if (k === -d || k !== d && left < right) {
279
+ x = right;
280
+ } else {
281
+ x = left + 1;
282
+ }
283
+ let y = x - k;
284
+ while (x < N && y < M && a[x] === b[y]) {
285
+ x++;
286
+ y++;
287
+ }
288
+ v.set(k, x);
289
+ if (x >= N && y >= M) {
290
+ return backtrack(trace, a, b, N, M, d);
291
+ }
292
+ }
293
+ }
294
+ return [];
295
+ }
296
+ function backtrack(trace, a, b, N, M, finalD) {
297
+ const edits = [];
298
+ let x = N;
299
+ let y = M;
300
+ for (let d = finalD; d > 0; d--) {
301
+ const v = trace[d];
302
+ if (!v) break;
303
+ const k = x - y;
304
+ const left = v.get(k - 1) ?? -1;
305
+ const right = v.get(k + 1) ?? -1;
306
+ let prevK;
307
+ if (k === -d || k !== d && left < right) {
308
+ prevK = k + 1;
309
+ } else {
310
+ prevK = k - 1;
311
+ }
312
+ const prevX = v.get(prevK) ?? 0;
313
+ const prevY = prevX - prevK;
314
+ while (x > prevX && y > prevY) {
315
+ edits.push({ op: "equal", a: x - 1, b: y - 1, line: a[x - 1] ?? "" });
316
+ x--;
317
+ y--;
318
+ }
319
+ if (d > 0) {
320
+ if (x === prevX) {
321
+ edits.push({ op: "insert", a: x, b: y - 1, line: b[y - 1] ?? "" });
322
+ } else {
323
+ edits.push({ op: "delete", a: x - 1, b: y, line: a[x - 1] ?? "" });
324
+ }
325
+ x = prevX;
326
+ y = prevY;
327
+ }
328
+ }
329
+ while (x > 0 && y > 0) {
330
+ edits.push({ op: "equal", a: x - 1, b: y - 1, line: a[x - 1] ?? "" });
331
+ x--;
332
+ y--;
333
+ }
334
+ return edits.reverse();
335
+ }
336
+ function unifiedDiff(oldText, newText, opts = {}) {
337
+ const context = opts.context ?? 3;
338
+ const a = oldText.split("\n");
339
+ const b = newText.split("\n");
340
+ if (a[a.length - 1] === "") a.pop();
341
+ if (b[b.length - 1] === "") b.pop();
342
+ const edits = myersDiff(a, b);
343
+ if (edits.every((e) => e.op === "equal")) return "";
344
+ const hunks = [];
345
+ let i = 0;
346
+ while (i < edits.length) {
347
+ while (i < edits.length && edits[i]?.op === "equal") i++;
348
+ if (i >= edits.length) break;
349
+ const hunkStart = Math.max(0, i - context);
350
+ const lines = [];
351
+ let aStart = (edits[hunkStart]?.a ?? 0) + 1;
352
+ let bStart = (edits[hunkStart]?.b ?? 0) + 1;
353
+ let aCount = 0;
354
+ let bCount = 0;
355
+ let cursor = hunkStart;
356
+ let trailing = 0;
357
+ while (cursor < edits.length) {
358
+ const e = edits[cursor];
359
+ if (!e) break;
360
+ if (e.op === "equal") {
361
+ trailing++;
362
+ if (trailing > context * 2) break;
363
+ } else {
364
+ trailing = 0;
365
+ }
366
+ if (e.op === "equal") {
367
+ lines.push(` ${e.line}`);
368
+ aCount++;
369
+ bCount++;
370
+ } else if (e.op === "delete") {
371
+ lines.push(`-${e.line}`);
372
+ aCount++;
373
+ } else {
374
+ lines.push(`+${e.line}`);
375
+ bCount++;
376
+ }
377
+ cursor++;
378
+ }
379
+ while (lines.length > 0 && lines[lines.length - 1]?.startsWith(" ") && trailing > context) {
380
+ lines.pop();
381
+ aCount--;
382
+ bCount--;
383
+ trailing--;
384
+ }
385
+ if (aCount === 0) aStart = 0;
386
+ if (bCount === 0) bStart = 0;
387
+ hunks.push({ aStart, bStart, lines });
388
+ i = cursor;
389
+ }
390
+ if (hunks.length === 0) return "";
391
+ let out = "";
392
+ out += `--- ${opts.fromFile ?? "a"}
393
+ `;
394
+ out += `+++ ${opts.toFile ?? "b"}
395
+ `;
396
+ for (const h of hunks) {
397
+ let aCount = 0;
398
+ let bCount = 0;
399
+ for (const l of h.lines) {
400
+ if (l.startsWith(" ")) {
401
+ aCount++;
402
+ bCount++;
403
+ } else if (l.startsWith("-")) aCount++;
404
+ else if (l.startsWith("+")) bCount++;
405
+ }
406
+ out += `@@ -${h.aStart},${aCount} +${h.bStart},${bCount} @@
407
+ `;
408
+ out += `${h.lines.join("\n")}
409
+ `;
410
+ }
411
+ return out;
412
+ }
413
+
414
+ // src/utils/env-typed.ts
415
+ function envBool(key, env = process.env) {
416
+ const raw = env[key];
417
+ if (raw === void 0 || raw === "") return false;
418
+ return !/^(0|false|no|off)$/i.test(raw.trim());
419
+ }
420
+ function envBoolOptional(key, env = process.env) {
421
+ const raw = env[key];
422
+ if (raw === void 0 || raw === "") return void 0;
423
+ return !/^(0|false|no|off)$/i.test(raw.trim());
424
+ }
425
+ function envInt(key, options = { default: 0 }, env = process.env) {
426
+ const raw = env[key];
427
+ if (raw === void 0 || raw === "") return options.default;
428
+ const parsed = Number.parseInt(raw, 10);
429
+ if (!Number.isFinite(parsed)) return options.default;
430
+ if (options.min !== void 0 && parsed < options.min) return options.default;
431
+ if (options.max !== void 0 && parsed > options.max) return options.default;
432
+ return parsed;
433
+ }
434
+ function envFloat(key, options = { default: 0 }, env = process.env) {
435
+ const raw = env[key];
436
+ if (raw === void 0 || raw === "") return options.default;
437
+ const parsed = Number.parseFloat(raw);
438
+ if (!Number.isFinite(parsed)) return options.default;
439
+ if (options.min !== void 0 && parsed < options.min) return options.default;
440
+ if (options.max !== void 0 && parsed > options.max) return options.default;
441
+ return parsed;
442
+ }
443
+ function envString(key, env = process.env) {
444
+ const raw = env[key];
445
+ if (raw === void 0) return void 0;
446
+ const trimmed = raw.trim();
447
+ return trimmed === "" ? void 0 : trimmed;
448
+ }
449
+ function envEnum(key, allowed, options, env = process.env) {
450
+ const raw = envString(key, env);
451
+ if (raw === void 0) return options.default;
452
+ return allowed.includes(raw) ? raw : options.default;
453
+ }
454
+
455
+ // src/utils/glob-expand.ts
456
+ import * as fsp from "node:fs/promises";
457
+ import { isAbsolute, resolve } from "node:path";
458
+ var GLOB_CHARS = /* @__PURE__ */ new Set(["*", "?", "["]);
459
+ var IS_WINDOWS = typeof process !== "undefined" && process.platform === "win32";
460
+ var SEP = IS_WINDOWS ? "\\" : "/";
461
+ function isGlob(p) {
462
+ for (const c of p) {
463
+ if (GLOB_CHARS.has(c)) return true;
464
+ }
465
+ return false;
466
+ }
467
+ function globToRegex(pat) {
468
+ let i = 0;
469
+ let re = "^";
470
+ while (i < pat.length) {
471
+ const c = expectDefined(pat[i]);
472
+ if (c === "*") {
473
+ if (pat[i + 1] === "*") {
474
+ re += ".*";
475
+ i += 2;
476
+ if (pat[i] === "/") i++;
477
+ } else {
478
+ re += "[^/\\\\]*";
479
+ i++;
480
+ }
481
+ } else if (c === "?") {
482
+ re += "[^/\\\\]";
483
+ i++;
484
+ } else if (c === "[") {
485
+ let cls = "[";
486
+ i++;
487
+ if (pat[i] === "!" || pat[i] === "^") {
488
+ cls += "^";
489
+ i++;
490
+ }
491
+ while (i < pat.length && pat[i] !== "]") {
492
+ const ch = pat[i] ?? "";
493
+ if (ch === "\\") cls += "\\\\";
494
+ else if (ch === "]" || ch === "^") cls += `\\${ch}`;
495
+ else cls += ch;
496
+ i++;
497
+ }
498
+ cls += "]";
499
+ re += cls;
500
+ i++;
501
+ } else {
502
+ re += c.replace(/[.+^${}()|\\]/g, "\\$&");
503
+ i++;
504
+ }
505
+ }
506
+ return new RegExp(re + "$");
507
+ }
508
+ function baseDir(pat) {
509
+ let firstGlob = pat.length;
510
+ for (let i = 0; i < pat.length; i++) {
511
+ if (GLOB_CHARS.has(expectDefined(pat[i]))) {
512
+ firstGlob = i;
513
+ break;
514
+ }
515
+ }
516
+ const cut = Math.max(
517
+ pat.lastIndexOf(SEP, firstGlob - 1),
518
+ pat.lastIndexOf("/", firstGlob - 1)
519
+ );
520
+ return cut < 0 ? "." : pat.slice(0, cut);
521
+ }
522
+ async function expandGlob(pattern) {
523
+ if (!isGlob(pattern)) return [pattern];
524
+ const results = /* @__PURE__ */ new Set();
525
+ const abs = isAbsolute(pattern);
526
+ const base = abs ? baseDir(pattern) : baseDir(pattern);
527
+ const relPat = base === "." ? pattern : pattern.slice(base.length + 1);
528
+ async function walk(dir, pat) {
529
+ let entries;
530
+ try {
531
+ entries = await fsp.readdir(dir, { withFileTypes: true });
532
+ } catch {
533
+ return;
534
+ }
535
+ if (pat.startsWith("**/")) {
536
+ const rest = pat.slice(3);
537
+ await walk(dir, rest);
538
+ for (const e of entries) {
539
+ if (e.isDirectory()) {
540
+ const subDir = `${dir}${SEP}${e.name}`;
541
+ await walk(subDir, pat);
542
+ }
543
+ }
544
+ return;
545
+ }
546
+ if (pat === "**") {
547
+ for (const e of entries) {
548
+ const full = `${dir}${SEP}${e.name}`;
549
+ results.add(abs ? resolve(full) : full);
550
+ if (e.isDirectory()) {
551
+ await walk(full, "**");
552
+ }
553
+ }
554
+ return;
555
+ }
556
+ const firstSlash = pat.indexOf("/");
557
+ if (firstSlash < 0) {
558
+ const re = globToRegex(pat);
559
+ for (const e of entries) {
560
+ if (re.test(e.name)) {
561
+ const full = `${dir}${SEP}${e.name}`;
562
+ results.add(abs ? resolve(full) : full);
563
+ }
564
+ }
565
+ return;
566
+ }
567
+ const currentSeg = pat.slice(0, firstSlash);
568
+ const remainingPat = pat.slice(firstSlash + 1);
569
+ if (isGlob(currentSeg)) {
570
+ const re = globToRegex(currentSeg);
571
+ for (const e of entries) {
572
+ if (e.isDirectory() && re.test(e.name)) {
573
+ const subDir = `${dir}${SEP}${e.name}`;
574
+ await walk(subDir, remainingPat);
575
+ }
576
+ }
577
+ } else {
578
+ for (const e of entries) {
579
+ if (e.isDirectory() && e.name === currentSeg) {
580
+ const subDir = `${dir}${SEP}${e.name}`;
581
+ await walk(subDir, remainingPat);
582
+ }
583
+ }
584
+ }
585
+ }
586
+ await walk(base === "." ? "." : base, relPat);
587
+ return [...results];
588
+ }
589
+
590
+ // src/utils/incoming-images.ts
591
+ var MAX_INCOMING_IMAGES = 8;
592
+ var MAX_INCOMING_IMAGE_BYTES = 8 * 1024 * 1024;
593
+ var ALLOWED_IMAGE_MEDIA_TYPES = /* @__PURE__ */ new Set([
594
+ "image/png",
595
+ "image/jpeg",
596
+ "image/webp",
597
+ "image/gif"
598
+ ]);
599
+ function isAllowedImageMediaType(mediaType) {
600
+ return ALLOWED_IMAGE_MEDIA_TYPES.has(mediaType.toLowerCase());
601
+ }
602
+ function isValidImageBase64(base64) {
603
+ return /^[A-Za-z0-9+/]+={0,2}$/.test(base64);
604
+ }
605
+ function base64DecodedBytes(base64) {
606
+ return Math.floor(base64.length * 3 / 4);
607
+ }
608
+ var IncomingImageError = class extends Error {
609
+ constructor(message) {
610
+ super(message);
611
+ this.name = "IncomingImageError";
612
+ }
613
+ };
614
+ var DATA_URL_RE = /^data:([a-z0-9.+-]+\/[a-z0-9.+-]+)?(?:;[a-z0-9-]+=[^;,]*)*(;base64)?,/i;
615
+ function splitDataUrl(data) {
616
+ const match = DATA_URL_RE.exec(data);
617
+ if (!match) return { base64: data.trim() };
618
+ return {
619
+ base64: data.slice(match[0].length).trim(),
620
+ mediaType: match[1]?.toLowerCase()
621
+ };
622
+ }
623
+ function parseIncomingImages(images, legacyImageBase64) {
624
+ const raw = [...images ?? []];
625
+ if (legacyImageBase64) raw.push({ data: legacyImageBase64 });
626
+ if (raw.length === 0) return [];
627
+ if (raw.length > MAX_INCOMING_IMAGES) {
628
+ throw new IncomingImageError(
629
+ `Too many images: ${raw.length} (max ${MAX_INCOMING_IMAGES} per message).`
630
+ );
631
+ }
632
+ return raw.map((img, i) => {
633
+ const { base64, mediaType: fromUrl } = splitDataUrl(img.data ?? "");
634
+ const mediaType = (img.mediaType ?? fromUrl ?? "image/png").toLowerCase();
635
+ if (!isAllowedImageMediaType(mediaType)) {
636
+ throw new IncomingImageError(
637
+ `Image ${i + 1}: unsupported media type "${mediaType}" (allowed: ${[...ALLOWED_IMAGE_MEDIA_TYPES].join(", ")}).`
638
+ );
639
+ }
640
+ if (!base64) {
641
+ throw new IncomingImageError(`Image ${i + 1}: empty image data.`);
642
+ }
643
+ if (!isValidImageBase64(base64)) {
644
+ throw new IncomingImageError(`Image ${i + 1}: data is not valid base64.`);
645
+ }
646
+ const bytes = base64DecodedBytes(base64);
647
+ if (bytes > MAX_INCOMING_IMAGE_BYTES) {
648
+ throw new IncomingImageError(
649
+ `Image ${i + 1}: ${(bytes / (1024 * 1024)).toFixed(1)} MB exceeds the ${MAX_INCOMING_IMAGE_BYTES / (1024 * 1024)} MB limit.`
650
+ );
651
+ }
652
+ return {
653
+ type: "image",
654
+ source: { type: "base64", media_type: mediaType, data: base64 }
655
+ };
656
+ });
657
+ }
658
+ function buildUserContentBlocks(text, images) {
659
+ const blocks = [...images];
660
+ if (text) blocks.push({ type: "text", text });
661
+ return blocks;
662
+ }
663
+
664
+ // src/utils/merge-custom-models.ts
665
+ function mergeCustomModelDefs(providerCustomModels, configModels) {
666
+ const out = {};
667
+ if (providerCustomModels) {
668
+ for (const [id, def] of Object.entries(providerCustomModels)) {
669
+ out[id] = { ...def };
670
+ }
671
+ }
672
+ if (configModels) {
673
+ for (const [id, def] of Object.entries(configModels)) {
674
+ out[id] = { ...def };
675
+ }
676
+ }
677
+ if (Object.keys(out).length === 0) return void 0;
678
+ return out;
679
+ }
680
+
681
+ // src/utils/newline-normalize.ts
682
+ function detectNewlineStyle(text) {
683
+ let lf = 0;
684
+ let crlf = 0;
685
+ let cr = 0;
686
+ for (let i = 0; i < text.length; i++) {
687
+ const c = text.charCodeAt(i);
688
+ if (c === 13) {
689
+ if (text.charCodeAt(i + 1) === 10) {
690
+ crlf++;
691
+ i++;
692
+ } else {
693
+ cr++;
694
+ }
695
+ } else if (c === 10) {
696
+ lf++;
697
+ }
698
+ }
699
+ if (crlf > lf && crlf > cr) return "crlf";
700
+ if (cr > lf && cr > crlf) return "cr";
701
+ return "lf";
702
+ }
703
+ function toStyle(text, style) {
704
+ const normalized = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
705
+ if (style === "lf") return normalized;
706
+ if (style === "crlf") return normalized.replace(/\n/g, "\r\n");
707
+ return normalized.replace(/\n/g, "\r");
708
+ }
709
+ function normalizeToLf(text) {
710
+ return text.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
711
+ }
712
+
713
+ // src/utils/path-segment.ts
714
+ import * as path from "node:path";
715
+ var MAX_PATH_SEGMENT_LENGTH = 256;
716
+ function isSafePathSegment(value) {
717
+ if (value.length === 0 || value.length > MAX_PATH_SEGMENT_LENGTH) return false;
718
+ if (value === "." || value === "..") return false;
719
+ if (value.includes("/") || value.includes("\\")) return false;
720
+ if (value.includes("\0")) return false;
721
+ if (value.includes(":")) return false;
722
+ return true;
723
+ }
724
+ function resolveContainedPath(root, ...segments) {
725
+ if (segments.length === 0) return null;
726
+ for (const segment of segments) {
727
+ if (!isSafePathSegment(segment)) return null;
728
+ }
729
+ const resolvedRoot = path.resolve(root);
730
+ const candidate = path.resolve(resolvedRoot, ...segments);
731
+ if (candidate === resolvedRoot) return null;
732
+ if (!candidate.startsWith(resolvedRoot + path.sep)) return null;
733
+ return candidate;
734
+ }
735
+
736
+ // src/utils/project-watch.ts
737
+ import * as fs from "node:fs";
738
+ import * as path2 from "node:path";
739
+ var REGISTRY_KEY = /* @__PURE__ */ Symbol.for("wrongstack.projectWatchRegistry");
740
+ var globalScope = globalThis;
741
+ if (!globalScope[REGISTRY_KEY]) globalScope[REGISTRY_KEY] = /* @__PURE__ */ new Map();
742
+ var registry = globalScope[REGISTRY_KEY];
743
+ function registryKey(root) {
744
+ const resolved = path2.resolve(root);
745
+ return process.platform === "win32" ? resolved.toLowerCase() : resolved;
746
+ }
747
+ function watchProjectTree(root, listener, opts) {
748
+ const key = registryKey(root);
749
+ let entry = registry.get(key);
750
+ if (!entry || entry.dead) {
751
+ const subscribers = /* @__PURE__ */ new Set();
752
+ const watcher = fs.watch(
753
+ path2.resolve(root),
754
+ { recursive: true, persistent: false },
755
+ (eventType, filename) => {
756
+ const event = {
757
+ eventType: eventType === "rename" ? "rename" : "change",
758
+ filename: filename === null ? null : String(filename)
759
+ };
760
+ for (const sub of subscribers) {
761
+ try {
762
+ sub.listener(event);
763
+ } catch (error) {
764
+ sub.onError?.(error);
765
+ }
766
+ }
767
+ }
768
+ );
769
+ const created = { watcher, subscribers, dead: false };
770
+ const retire = () => {
771
+ created.dead = true;
772
+ if (registry.get(key) === created) registry.delete(key);
773
+ };
774
+ watcher.on("error", (error) => {
775
+ retire();
776
+ for (const sub of subscribers) sub.onError?.(error);
777
+ });
778
+ watcher.on("close", retire);
779
+ registry.set(key, created);
780
+ entry = created;
781
+ }
782
+ const active = entry;
783
+ const subscriber = { listener, onError: opts?.onError };
784
+ active.subscribers.add(subscriber);
785
+ let closed = false;
786
+ return {
787
+ close() {
788
+ if (closed) return;
789
+ closed = true;
790
+ active.subscribers.delete(subscriber);
791
+ if (active.subscribers.size === 0 && !active.dead) {
792
+ active.dead = true;
793
+ if (registry.get(key) === active) registry.delete(key);
794
+ try {
795
+ active.watcher.close();
796
+ } catch {
797
+ }
798
+ }
799
+ }
800
+ };
801
+ }
802
+
803
+ // src/utils/regex-guard.ts
804
+ import {
805
+ capSubject,
806
+ compileUserRegex,
807
+ MAX_SUBJECT_LEN
808
+ } from "@wrongstack/primitives";
809
+
810
+ // src/utils/sleep.ts
811
+ function sleep(ms) {
812
+ return new Promise((resolve4) => setTimeout(resolve4, ms));
813
+ }
814
+
815
+ // src/utils/slug.ts
816
+ function slugify(name, fallback = "prompt", maxLen = 64) {
817
+ return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, maxLen).replace(/-+$/g, "") || fallback;
818
+ }
819
+
820
+ // src/utils/task-format.ts
821
+ function computeTaskItemProgress(tasks) {
822
+ let completed = 0;
823
+ let pending = 0;
824
+ let inProgress = 0;
825
+ let blocked = 0;
826
+ let failed = 0;
827
+ let review = 0;
828
+ let estimatedHours = 0;
829
+ const actualHours = 0;
830
+ for (const t of tasks) {
831
+ switch (t.status) {
832
+ case "completed":
833
+ completed++;
834
+ break;
835
+ case "pending":
836
+ pending++;
837
+ break;
838
+ case "in_progress":
839
+ inProgress++;
840
+ break;
841
+ case "blocked":
842
+ blocked++;
843
+ break;
844
+ case "failed":
845
+ failed++;
846
+ break;
847
+ case "review":
848
+ review++;
849
+ break;
850
+ }
851
+ estimatedHours += t.estimateHours ?? 0;
852
+ }
853
+ return {
854
+ total: tasks.length,
855
+ pending,
856
+ inProgress,
857
+ blocked,
858
+ failed,
859
+ review,
860
+ completed,
861
+ percentComplete: tasks.length > 0 ? Math.round(completed / tasks.length * 100) : 0,
862
+ estimatedHours,
863
+ actualHours
864
+ };
865
+ }
866
+ var STATUS_ICON = {
867
+ pending: "\u25CB",
868
+ in_progress: "\u25D0",
869
+ blocked: "\u2298",
870
+ failed: "\u2717",
871
+ review: "\u25D1",
872
+ completed: "\u25CF"
873
+ };
874
+ var PRIORITY_ICON = {
875
+ critical: "\u{1F534}",
876
+ high: "\u{1F7E0}",
877
+ medium: "\u{1F7E1}",
878
+ low: "\u{1F7E2}"
879
+ };
880
+ var TYPE_ICON = {
881
+ feature: "\u26A1",
882
+ bugfix: "\u{1F41B}",
883
+ refactor: "\u267B\uFE0F",
884
+ docs: "\u{1F4DD}",
885
+ test: "\u{1F9EA}",
886
+ chore: "\u{1F527}"
887
+ };
888
+ function formatTaskProgress(tasks) {
889
+ const p = computeTaskItemProgress(tasks);
890
+ if (p.total === 0) return "No tasks.";
891
+ const barWidth = 24;
892
+ const filled = Math.round(p.percentComplete / 100 * barWidth);
893
+ const empty = barWidth - filled;
894
+ const bar = "\u2588".repeat(filled) + "\u2591".repeat(empty);
895
+ return [
896
+ `${color.bold("Tasks")} [${bar}] ${p.percentComplete}%`,
897
+ ` ${color.green("\u25CF")} ${p.completed} done \u2502 ${color.yellow("\u25D0")} ${p.inProgress} active \u2502 ${color.dim("\u25CB")} ${p.pending} pending \u2502 \u2298 ${p.blocked} blocked \u2502 \u2717 ${p.failed} failed`,
898
+ p.estimatedHours > 0 ? ` ${color.dim(`est. ${p.estimatedHours}h`)}` : ""
899
+ ].filter(Boolean).join("\n");
900
+ }
901
+ function formatTaskList(tasks) {
902
+ if (tasks.length === 0) return "No tasks.";
903
+ const order = ["in_progress", "blocked", "review", "pending", "failed", "completed"];
904
+ const groups = /* @__PURE__ */ new Map();
905
+ for (const t of tasks) {
906
+ const list = groups.get(t.status) ?? [];
907
+ list.push(t);
908
+ groups.set(t.status, list);
909
+ }
910
+ const lines = [];
911
+ lines.push(color.dim(`Tasks (${tasks.length} total):`));
912
+ for (const status of order) {
913
+ const group = groups.get(status);
914
+ if (!group || group.length === 0) continue;
915
+ const icon = STATUS_ICON[status];
916
+ lines.push(` ${icon} ${status.toUpperCase()} (${group.length})`);
917
+ for (const t of group) {
918
+ const prio = PRIORITY_ICON[t.priority];
919
+ const type = TYPE_ICON[t.type];
920
+ const deps = t.dependsOn && t.dependsOn.length > 0 ? ` ${color.dim("\u2190")} ${color.dim(t.dependsOn.map((d) => d.slice(0, 8)).join(", "))}` : "";
921
+ const who = t.assignee ? ` ${color.dim(`@${t.assignee}`)}` : "";
922
+ const hrs = t.estimateHours ? ` ${color.dim(`${t.estimateHours}h`)}` : "";
923
+ lines.push(` ${type} ${prio} ${t.title}${deps}${who}${hrs}`);
924
+ }
925
+ }
926
+ return lines.join("\n");
927
+ }
928
+
929
+ // src/utils/terminal-sanitize.ts
930
+ var ANSI_RE = /\x1b\[[0-?]*[ -/]*[@-~]/g;
931
+ var ANSI_OSC_RE = /\x1b\][\s\S]*?(?:\x07|\x1b\\)/g;
932
+ var ANSI_CONTROL_STRING_RE = /\x1b[P^_X][\s\S]*?\x1b\\/g;
933
+ var ANSI_ESCAPE_RE = /\x1b[ -/]*[@-~]/g;
934
+ var BIDI_AND_ZERO_WIDTH_RE = /[​-‏‪-‮⁦-⁩]/g;
935
+ function sanitizeTerminalText(value, tabWidth = 2) {
936
+ const tab = " ".repeat(Math.max(1, Math.min(8, Math.floor(tabWidth))));
937
+ const withoutEscapes = value.replace(ANSI_OSC_RE, "").replace(ANSI_CONTROL_STRING_RE, "").replace(ANSI_RE, "").replace(ANSI_ESCAPE_RE, "").replace(BIDI_AND_ZERO_WIDTH_RE, "").replace(/\t/g, tab).replace(/\r/g, "");
938
+ let safe = "";
939
+ for (const char of withoutEscapes) {
940
+ const code = char.codePointAt(0) ?? 0;
941
+ if (char === "\n" || code >= 32 && code !== 127 && !(code >= 128 && code <= 159)) {
942
+ safe += char;
943
+ }
944
+ }
945
+ return safe;
946
+ }
947
+ function sanitizeTerminalPreview(value, opts = {}) {
948
+ const maxLines = opts.maxLines ?? 40;
949
+ const maxChars = opts.maxChars ?? 8e3;
950
+ const safe = sanitizeTerminalText(value, opts.tabWidth);
951
+ let truncated = false;
952
+ let clipped = safe;
953
+ if (clipped.length > maxChars) {
954
+ clipped = clipped.slice(0, maxChars);
955
+ truncated = true;
956
+ }
957
+ const lines = clipped.split("\n");
958
+ if (lines.length > maxLines) {
959
+ clipped = lines.slice(0, maxLines).join("\n");
960
+ truncated = true;
961
+ }
962
+ return { text: clipped, truncated };
963
+ }
964
+
965
+ // src/utils/tool-result-render-mode.ts
966
+ var DEFAULT_TOOL_RESULT_RENDER_MODE = "extend";
967
+ function normalizeToolResultRenderMode(value) {
968
+ if (typeof value !== "string") return void 0;
969
+ const raw = value.trim().toLowerCase();
970
+ if (raw === "extend" || raw === "extended" || raw === "full") return "extend";
971
+ if (raw === "simple" || raw === "short" || raw === "brief") return "simple";
972
+ return void 0;
973
+ }
974
+ function resolveToolResultRenderMode(modes, toolName) {
975
+ return normalizeToolResultRenderMode(modes?.[toolName]) ?? DEFAULT_TOOL_RESULT_RENDER_MODE;
976
+ }
977
+ function setToolResultRenderMode(registry2, name, mode) {
978
+ if (typeof registry2.setResultRenderMode === "function") {
979
+ return registry2.setResultRenderMode(name, mode);
980
+ }
981
+ return false;
982
+ }
983
+ function getToolResultRenderMode(registry2, name) {
984
+ return registry2.getResultRenderMode?.(name) ?? DEFAULT_TOOL_RESULT_RENDER_MODE;
985
+ }
986
+ function applyToolResultRenderModes(registry2, modes) {
987
+ if (typeof registry2.applyResultRenderModes === "function") {
988
+ return registry2.applyResultRenderModes(modes);
989
+ }
990
+ const entries = Object.entries(modes ?? {});
991
+ const missing = [];
992
+ let applied = 0;
993
+ for (const [name, rawMode] of entries) {
994
+ const mode = normalizeToolResultRenderMode(rawMode);
995
+ if (!mode) continue;
996
+ if (setToolResultRenderMode(registry2, name, mode)) applied++;
997
+ else missing.push(name);
998
+ }
999
+ return { applied, missing };
1000
+ }
1001
+
1002
+ // src/utils/walk-ignore.ts
1003
+ var DEFAULT_WALK_IGNORE_DIRS = Object.freeze([
1004
+ "node_modules",
1005
+ ".git",
1006
+ "dist",
1007
+ "build",
1008
+ ".next",
1009
+ ".nuxt",
1010
+ ".turbo",
1011
+ "coverage",
1012
+ ".nyc_output",
1013
+ "__snapshots__",
1014
+ "__pycache__",
1015
+ ".venv",
1016
+ "venv",
1017
+ "target",
1018
+ ".cache",
1019
+ ".parcel-cache",
1020
+ ".pnpm-store",
1021
+ ".gradle"
1022
+ ]);
1023
+ var DEFAULT_WALK_IGNORE_SET = new Set(DEFAULT_WALK_IGNORE_DIRS);
1024
+
1025
+ export {
1026
+ watchProjectTree,
1027
+ DEFAULT_WALK_IGNORE_DIRS,
1028
+ DEFAULT_WALK_IGNORE_SET,
1029
+ assertNever,
1030
+ checkConnectivity,
1031
+ resetConnectivityCache,
1032
+ getContextBreakdown,
1033
+ addFatalSalvageHook,
1034
+ runFatalSalvageSync,
1035
+ installCrashShield,
1036
+ unifiedDiff,
1037
+ envBool,
1038
+ envBoolOptional,
1039
+ envInt,
1040
+ envFloat,
1041
+ envString,
1042
+ envEnum,
1043
+ expandGlob,
1044
+ MAX_INCOMING_IMAGES,
1045
+ MAX_INCOMING_IMAGE_BYTES,
1046
+ ALLOWED_IMAGE_MEDIA_TYPES,
1047
+ isAllowedImageMediaType,
1048
+ isValidImageBase64,
1049
+ base64DecodedBytes,
1050
+ IncomingImageError,
1051
+ parseIncomingImages,
1052
+ buildUserContentBlocks,
1053
+ mergeCustomModelDefs,
1054
+ detectNewlineStyle,
1055
+ toStyle,
1056
+ normalizeToLf,
1057
+ MAX_PATH_SEGMENT_LENGTH,
1058
+ isSafePathSegment,
1059
+ resolveContainedPath,
1060
+ capSubject,
1061
+ compileUserRegex,
1062
+ MAX_SUBJECT_LEN,
1063
+ sleep,
1064
+ slugify,
1065
+ computeTaskItemProgress,
1066
+ formatTaskProgress,
1067
+ formatTaskList,
1068
+ sanitizeTerminalText,
1069
+ sanitizeTerminalPreview,
1070
+ DEFAULT_TOOL_RESULT_RENDER_MODE,
1071
+ normalizeToolResultRenderMode,
1072
+ resolveToolResultRenderMode,
1073
+ setToolResultRenderMode,
1074
+ getToolResultRenderMode,
1075
+ applyToolResultRenderModes
1076
+ };
1077
+ //# sourceMappingURL=chunk-TYW2GI5I.js.map