@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,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