@wrongstack/tools 0.317.0 → 0.317.2

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 (109) hide show
  1. package/dist/_spawn-stream.d.ts +1 -1
  2. package/dist/audit.d.ts +37 -2
  3. package/dist/audit.js +4 -4
  4. package/dist/bash.js +1 -1
  5. package/dist/batch-tool-use.js +1 -1
  6. package/dist/browser/index.js +1 -1
  7. package/dist/browser/tools.d.ts +16 -1
  8. package/dist/builtin.js +43 -43
  9. package/dist/{chunk-SDLVH5RZ.js → chunk-3QQSBUXR.js} +6 -5
  10. package/dist/{chunk-K3WNSHUF.js → chunk-45JPRMC2.js} +62 -36
  11. package/dist/{chunk-EJWSCQ6D.js → chunk-4AEZIFOW.js} +6 -5
  12. package/dist/{chunk-PQKK5JH7.js → chunk-4E42D7UF.js} +2 -2
  13. package/dist/{chunk-JRJJX3L5.js → chunk-5WNDJHT6.js} +3 -2
  14. package/dist/{chunk-7EY5DCRO.js → chunk-5ZYEGP2P.js} +4 -4
  15. package/dist/{chunk-HPEO4EA7.js → chunk-6RR5VX6U.js} +35 -17
  16. package/dist/{chunk-QDQY7NQ2.js → chunk-A2PX7M7A.js} +5 -5
  17. package/dist/{chunk-JQRIR762.js → chunk-AK2K4KHR.js} +27 -19
  18. package/dist/{chunk-P7FYFZ6M.js → chunk-BANPF4LY.js} +11 -7
  19. package/dist/{chunk-RGISBZBD.js → chunk-CPSAF2AU.js} +3 -2
  20. package/dist/{chunk-BSLVR56S.js → chunk-CPVLVQYT.js} +6 -5
  21. package/dist/{chunk-VJNHFZ7J.js → chunk-CVALEVGA.js} +6 -5
  22. package/dist/{chunk-PY2IOS7C.js → chunk-CWALNI6K.js} +5 -5
  23. package/dist/{chunk-LIJQMYYX.js → chunk-ELFFQ4RU.js} +7 -3
  24. package/dist/{chunk-JNNVRHMV.js → chunk-FJEQZHZN.js} +8 -8
  25. package/dist/{chunk-S5CCLZL3.js → chunk-FRN7TIAA.js} +2 -2
  26. package/dist/{chunk-PCHQ6YRR.js → chunk-FYDKHXN7.js} +2 -2
  27. package/dist/{chunk-NKJW5GFO.js → chunk-H6AWAZ2Y.js} +3 -3
  28. package/dist/{chunk-IVWV2UM6.js → chunk-HTYEO67J.js} +6 -5
  29. package/dist/{chunk-UNSKG6DC.js → chunk-ICAXDRP6.js} +10 -15
  30. package/dist/{chunk-IYK7XGDZ.js → chunk-JJQB6R7Y.js} +7 -7
  31. package/dist/{chunk-LWKUTMD5.js → chunk-MRZOVQ5D.js} +6 -5
  32. package/dist/{chunk-YGG6X57C.js → chunk-NKX4SJ5R.js} +12 -9
  33. package/dist/{chunk-U4D5S3VQ.js → chunk-NWZ6XGBJ.js} +2 -1
  34. package/dist/{chunk-UKU2ZX4C.js → chunk-P7ZQ2FAJ.js} +27 -17
  35. package/dist/{chunk-4I4LWFOO.js → chunk-PQTONQ4P.js} +16 -11
  36. package/dist/{chunk-XGHMUZ77.js → chunk-RMB76PDS.js} +3 -3
  37. package/dist/{chunk-5OAOKALG.js → chunk-RUOMW2I6.js} +4 -3
  38. package/dist/{chunk-553IQUMO.js → chunk-S2JRYDYG.js} +7 -6
  39. package/dist/{chunk-OUBDL3WH.js → chunk-SOG7XIRF.js} +11 -8
  40. package/dist/{chunk-U6DZWHBA.js → chunk-TDLZIDCY.js} +9 -7
  41. package/dist/{chunk-TRDX25UH.js → chunk-TFEGJDH5.js} +293 -86
  42. package/dist/{chunk-AHHDWNXC.js → chunk-TKA4VEX2.js} +2 -2
  43. package/dist/{chunk-5H4GSJAI.js → chunk-UE3UBMCP.js} +7 -6
  44. package/dist/{chunk-IXMNTNW5.js → chunk-UKGMDCXT.js} +4 -3
  45. package/dist/{chunk-VGBUDLW4.js → chunk-UOXX4SQZ.js} +7 -6
  46. package/dist/{chunk-T2F4S7U4.js → chunk-WI3VDXHD.js} +18 -8
  47. package/dist/{chunk-O4MBV4AX.js → chunk-WJYXMB2R.js} +6 -5
  48. package/dist/{chunk-U4VAATKP.js → chunk-WXJY3BKV.js} +16 -6
  49. package/dist/{chunk-DR7JOQTC.js → chunk-X5K3U6GI.js} +3 -3
  50. package/dist/{chunk-DSEANA2W.js → chunk-XVGB6KYU.js} +37 -36
  51. package/dist/{chunk-TEBQ4VPZ.js → chunk-YOHO4DVT.js} +6 -5
  52. package/dist/{chunk-RXISBFR5.js → chunk-ZE6KLBUO.js} +5 -4
  53. package/dist/{chunk-22B7GE5T.js → chunk-ZHH3BEWU.js} +13 -12
  54. package/dist/codebase-index/bm25.d.ts +14 -1
  55. package/dist/codebase-index/index.js +8 -8
  56. package/dist/codebase-index/json-parser.d.ts +4 -0
  57. package/dist/codebase-index/parser-worker-script.js +2 -2
  58. package/dist/codebase-index/project-server.js +48 -9
  59. package/dist/codebase-index/worker.js +4 -4
  60. package/dist/codebase-index/writer-bulk-insert.d.ts +0 -1
  61. package/dist/codebase-index/writer-schema.d.ts +1 -1
  62. package/dist/codebase-index/writer.d.ts +38 -0
  63. package/dist/diff.js +1 -1
  64. package/dist/e2e.d.ts +40 -1
  65. package/dist/e2e.js +1 -1
  66. package/dist/edit.js +7 -7
  67. package/dist/exec.js +1 -1
  68. package/dist/fetch.js +1 -1
  69. package/dist/format.d.ts +42 -2
  70. package/dist/format.js +4 -4
  71. package/dist/git.d.ts +70 -1
  72. package/dist/git.js +1 -1
  73. package/dist/glob.js +3 -3
  74. package/dist/{go-parser-JXYKJHRC.js → go-parser-IKHW67WE.js} +2 -2
  75. package/dist/grep.js +3 -3
  76. package/dist/index.js +45 -45
  77. package/dist/install.d.ts +51 -2
  78. package/dist/install.js +4 -4
  79. package/dist/{json-parser-IBHZ4BZC.js → json-parser-2EOVP5MR.js} +81 -15
  80. package/dist/kanban.d.ts +19 -1
  81. package/dist/kanban.js +2 -2
  82. package/dist/languages/index.js +2 -2
  83. package/dist/{legacy-bridge-7M6QLUQN.js → legacy-bridge-SFNXIRAP.js} +4 -4
  84. package/dist/lint.js +4 -4
  85. package/dist/logs.js +1 -1
  86. package/dist/outdated.d.ts +25 -1
  87. package/dist/outdated.js +1 -1
  88. package/dist/pack.js +44 -44
  89. package/dist/{parser-dispatch-QH4XPGG6.js → parser-dispatch-X62UWXJS.js} +3 -3
  90. package/dist/patch.js +7 -7
  91. package/dist/plan.js +4 -4
  92. package/dist/{py-parser-IS4HKYMF.js → py-parser-TDXSQZBC.js} +2 -2
  93. package/dist/read.js +7 -7
  94. package/dist/replace.js +7 -7
  95. package/dist/{rs-parser-XHUUO2KZ.js → rs-parser-GIWPUA3T.js} +2 -2
  96. package/dist/scaffold.js +1 -1
  97. package/dist/search.js +1 -1
  98. package/dist/session-kanban.js +1 -1
  99. package/dist/task.js +4 -4
  100. package/dist/test.js +4 -4
  101. package/dist/todo.js +3 -3
  102. package/dist/tool-diff.js +1 -1
  103. package/dist/tool-tier.js +45 -45
  104. package/dist/tool-use.js +1 -1
  105. package/dist/{ts-parser-RCTYKSVI.js → ts-parser-7W26YB26.js} +2 -2
  106. package/dist/typecheck.js +4 -4
  107. package/dist/write.js +7 -7
  108. package/dist/{yaml-parser-4SAXV3PL.js → yaml-parser-RGBXEZE4.js} +2 -2
  109. package/package.json +5 -5
@@ -604,6 +604,7 @@ var bashTool = {
604
604
  const args = [...plan.argv, plan.commandArg];
605
605
  const env = buildChildEnv(ctx.session?.id);
606
606
  const spawnCwd = ctx.workingDir ?? ctx.projectRoot;
607
+ const callerSignal = opts?.signal ?? ctx.signal ?? new AbortController().signal;
607
608
  const detached = !isWin2;
608
609
  const startedAt = Date.now();
609
610
  if (input.background) {
@@ -691,7 +692,7 @@ var bashTool = {
691
692
  stdio: ["ignore", "pipe", "pipe"],
692
693
  detached,
693
694
  windowsHide: true,
694
- ...isWin2 ? {} : { signal: opts.signal }
695
+ ...isWin2 ? {} : { signal: callerSignal }
695
696
  });
696
697
  const pid = child.pid;
697
698
  let stdoutBytes = 0;
@@ -779,8 +780,8 @@ var bashTool = {
779
780
  timer.unref?.();
780
781
  const onAbort = () => killWithTimeout(child, 2e3);
781
782
  if (isWin2) {
782
- if (opts.signal.aborted) onAbort();
783
- else opts.signal.addEventListener("abort", onAbort, { once: true });
783
+ if (callerSignal.aborted) onAbort();
784
+ else callerSignal.addEventListener("abort", onAbort, { once: true });
784
785
  }
785
786
  const queue = [];
786
787
  let resolveNext = null;
@@ -900,7 +901,7 @@ ${hint}` : "") + pipeToShellNote,
900
901
  } finally {
901
902
  for (const t of timers) clearTimeout(t);
902
903
  spool.finalize();
903
- if (isWin2) opts.signal.removeEventListener("abort", onAbort);
904
+ if (isWin2) callerSignal.removeEventListener("abort", onAbort);
904
905
  child.stdout?.off("data", onStdoutData);
905
906
  child.stderr?.off("data", onStderrData);
906
907
  child.stdout?.destroy();
@@ -952,4 +953,4 @@ export {
952
953
  checkAndBlockKillCommand,
953
954
  bashTool
954
955
  };
955
- //# sourceMappingURL=chunk-IVWV2UM6.js.map
956
+ //# sourceMappingURL=chunk-HTYEO67J.js.map
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  mapWithConcurrency
3
- } from "./chunk-U4D5S3VQ.js";
3
+ } from "./chunk-NWZ6XGBJ.js";
4
4
  import {
5
5
  loadGitignoreMatcher
6
- } from "./chunk-LIJQMYYX.js";
6
+ } from "./chunk-ELFFQ4RU.js";
7
7
  import {
8
8
  assertRealInsideRoot,
9
9
  safeResolveReal
@@ -58,7 +58,10 @@ var globTool = {
58
58
  field: "pattern"
59
59
  });
60
60
  }
61
- const signal = opts?.signal;
61
+ const signal = opts?.signal ?? ctx?.signal;
62
+ if (signal?.aborted) {
63
+ return { files: [], truncated: true };
64
+ }
62
65
  const base = input.path ? await safeResolveReal(input.path, ctx) : ctx.cwd;
63
66
  const limit = Math.max(1, Math.min(input.limit ?? 1e3, 5e3));
64
67
  const isGitIgnored = await loadGitignoreMatcher(base);
@@ -66,7 +69,7 @@ var globTool = {
66
69
  const results = [];
67
70
  let truncated = false;
68
71
  const pushResult = async (full) => {
69
- if (truncated || results.length >= limit) {
72
+ if (signal?.aborted || truncated || results.length >= limit) {
70
73
  truncated = true;
71
74
  return;
72
75
  }
@@ -108,11 +111,7 @@ var globTool = {
108
111
  subdirs.push({ full, rel });
109
112
  } else if (e.isFile()) {
110
113
  if (isGitIgnored(rel, false)) continue;
111
- re.lastIndex = 0;
112
- const relMatch = re.test(rel);
113
- re.lastIndex = 0;
114
- const nameMatch = re.test(name);
115
- if (relMatch || nameMatch) {
114
+ if (re.test(rel) || re.test(name)) {
116
115
  matchedFiles.push(full);
117
116
  }
118
117
  } else if (e.isSymbolicLink()) {
@@ -127,11 +126,7 @@ var globTool = {
127
126
  if (isGitIgnored(rel, false)) continue;
128
127
  const real = await fs.realpath(full);
129
128
  await assertRealInsideRoot(real, ctx);
130
- re.lastIndex = 0;
131
- const relMatch = re.test(rel);
132
- re.lastIndex = 0;
133
- const nameMatch = re.test(name);
134
- if (relMatch || nameMatch) matchedFiles.push(full);
129
+ if (re.test(rel) || re.test(name)) matchedFiles.push(full);
135
130
  }
136
131
  } catch {
137
132
  }
@@ -156,4 +151,4 @@ var globTool = {
156
151
  export {
157
152
  globTool
158
153
  };
159
- //# sourceMappingURL=chunk-UNSKG6DC.js.map
154
+ //# sourceMappingURL=chunk-ICAXDRP6.js.map
@@ -824,27 +824,27 @@ async function dispatch(file, content, lang) {
824
824
  case "tsx":
825
825
  case "js":
826
826
  case "jsx": {
827
- const { parseSymbols } = await import("./ts-parser-RCTYKSVI.js");
827
+ const { parseSymbols } = await import("./ts-parser-7W26YB26.js");
828
828
  return parseSymbols({ file, content, lang });
829
829
  }
830
830
  case "go": {
831
- const { parseSymbols } = await import("./go-parser-JXYKJHRC.js");
831
+ const { parseSymbols } = await import("./go-parser-IKHW67WE.js");
832
832
  return parseSymbols({ file, content, lang: "go" });
833
833
  }
834
834
  case "py": {
835
- const { parseSymbols } = await import("./py-parser-IS4HKYMF.js");
835
+ const { parseSymbols } = await import("./py-parser-TDXSQZBC.js");
836
836
  return parseSymbols({ file, content, lang: "py" });
837
837
  }
838
838
  case "rs": {
839
- const { parseSymbols } = await import("./rs-parser-XHUUO2KZ.js");
839
+ const { parseSymbols } = await import("./rs-parser-GIWPUA3T.js");
840
840
  return parseSymbols({ file, content, lang: "rs" });
841
841
  }
842
842
  case "json": {
843
- const { parseSymbols } = await import("./json-parser-IBHZ4BZC.js");
843
+ const { parseSymbols } = await import("./json-parser-2EOVP5MR.js");
844
844
  return parseSymbols({ file, content, lang: "json" });
845
845
  }
846
846
  case "yaml": {
847
- const { parseSymbols } = await import("./yaml-parser-4SAXV3PL.js");
847
+ const { parseSymbols } = await import("./yaml-parser-RGBXEZE4.js");
848
848
  return parseSymbols({ file, content, lang: "yaml" });
849
849
  }
850
850
  // Phase 1: ten languages now route through the Tree-Sitter WASM
@@ -889,4 +889,4 @@ export {
889
889
  parseFileContent,
890
890
  parseFilesContent
891
891
  };
892
- //# sourceMappingURL=chunk-IYK7XGDZ.js.map
892
+ //# sourceMappingURL=chunk-JJQB6R7Y.js.map
@@ -49,10 +49,11 @@ var outdatedTool = {
49
49
  },
50
50
  async execute(input, ctx, opts) {
51
51
  const cwd = input.cwd ? await safeResolveReal(input.cwd, ctx) : ctx.cwd;
52
+ const signal = opts?.signal ?? ctx.signal ?? new AbortController().signal;
52
53
  const manager = await detectPackageManager(cwd, ctx.projectRoot);
53
54
  if (manager === "npm") {
54
55
  try {
55
- const { detectNonJsEcosystem } = await import("./legacy-bridge-7M6QLUQN.js");
56
+ const { detectNonJsEcosystem } = await import("./legacy-bridge-SFNXIRAP.js");
56
57
  const nonJs = await detectNonJsEcosystem(cwd, ctx.projectRoot);
57
58
  if (nonJs) {
58
59
  const { planLanguageOperation, executePackagePlan } = await import("./languages/index.js");
@@ -61,7 +62,7 @@ var outdatedTool = {
61
62
  cwd,
62
63
  operation: "package-outdated",
63
64
  language: nonJs,
64
- signal: opts.signal
65
+ signal
65
66
  });
66
67
  if (planResult.status === "planned") {
67
68
  const runner = executePackagePlan({
@@ -69,7 +70,7 @@ var outdatedTool = {
69
70
  workspace: planResult.workspace,
70
71
  plan: planResult.plan,
71
72
  packages: [],
72
- signal: opts.signal
73
+ signal
73
74
  });
74
75
  let outcome = null;
75
76
  for (; ; ) {
@@ -102,7 +103,7 @@ var outdatedTool = {
102
103
  }
103
104
  }
104
105
  const args = ["outdated", "--json"];
105
- return runOutdated(manager, args, cwd, opts.signal);
106
+ return runOutdated(manager, args, cwd, signal);
106
107
  }
107
108
  };
108
109
  function runOutdated(manager, args, cwd, signal) {
@@ -194,4 +195,4 @@ Note: exit code 1 from \`outdated\` means outdated packages were found (expected
194
195
  export {
195
196
  outdatedTool
196
197
  };
197
- //# sourceMappingURL=chunk-LWKUTMD5.js.map
198
+ //# sourceMappingURL=chunk-MRZOVQ5D.js.map
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  getIndexState,
3
3
  searchCodebaseIndex
4
- } from "./chunk-QDQY7NQ2.js";
4
+ } from "./chunk-A2PX7M7A.js";
5
5
  import {
6
6
  codebaseIndexDirOverride
7
- } from "./chunk-TRDX25UH.js";
7
+ } from "./chunk-TFEGJDH5.js";
8
8
  import {
9
9
  isBinaryBuffer,
10
10
  safeResolveReal,
@@ -68,6 +68,8 @@ var readTool = {
68
68
  field: "path"
69
69
  });
70
70
  }
71
+ const signal = execOpts?.signal ?? ctx?.signal;
72
+ signal?.throwIfAborted();
71
73
  const absPath = await safeResolveReal(input.path, ctx);
72
74
  const shouldIncludeSymbols = input.includeSymbols === true || input.includeSymbols !== false && ctx.meta[ADVANCED_MODE_META_KEY] === true;
73
75
  let stat2;
@@ -113,7 +115,7 @@ var readTool = {
113
115
  const requestedEnd = prior ? Math.min(offset + limit - 1, prior.totalLines) : offset + limit - 1;
114
116
  if (input.mode !== "summary" && limit > 0 && prior && coversRange(prior, stat2.mtimeMs, offset, requestedEnd)) {
115
117
  ctx.recordRead(absPath, stat2.mtimeMs);
116
- const symResult2 = shouldIncludeSymbols ? await fetchSymbolsForFile(absPath, ctx, execOpts?.signal) : void 0;
118
+ const symResult2 = shouldIncludeSymbols ? await fetchSymbolsForFile(absPath, ctx, signal) : void 0;
117
119
  return {
118
120
  text: `[unchanged since previous read: "${input.path}" mtime=${Math.round(stat2.mtimeMs)}; requested lines ${offset}-${requestedEnd} were already shown. Use offset/limit for a new range if needed.]`,
119
121
  total_lines: prior.totalLines,
@@ -124,6 +126,7 @@ var readTool = {
124
126
  ...symResult2?.symbols ? { symbols: symResult2.symbols } : {}
125
127
  };
126
128
  }
129
+ signal?.throwIfAborted();
127
130
  const buf = await fs.readFile(absPath);
128
131
  if (isBinaryBuffer(buf)) {
129
132
  throw new FsError({
@@ -135,12 +138,12 @@ var readTool = {
135
138
  }
136
139
  const text = buf.toString("utf8");
137
140
  const contentHash = sha256hex(text);
138
- const allLines = text.split(/\r\n|\r|\n/);
141
+ const allLines = text.split(/\r?\n/);
139
142
  const total = allLines.length;
140
143
  if (input.mode === "summary") {
141
144
  ctx.recordRead(absPath, stat2.mtimeMs, "user", contentHash);
142
145
  rememberReadRange(ctx, absPath, stat2.mtimeMs, total, 1, Math.min(total, 200));
143
- const symResult2 = shouldIncludeSymbols ? await fetchSymbolsForFile(absPath, ctx, execOpts?.signal) : void 0;
146
+ const symResult2 = shouldIncludeSymbols ? await fetchSymbolsForFile(absPath, ctx, signal) : void 0;
144
147
  return {
145
148
  text: summarizeFile(input.path, stat2.size, allLines),
146
149
  total_lines: total,
@@ -156,7 +159,7 @@ var readTool = {
156
159
  if (limit === 0) {
157
160
  ctx.recordRead(absPath, stat2.mtimeMs, "user", contentHash);
158
161
  rememberReadRange(ctx, absPath, stat2.mtimeMs, total, 1, 0);
159
- const symResult2 = shouldIncludeSymbols ? await fetchSymbolsForFile(absPath, ctx, execOpts?.signal) : void 0;
162
+ const symResult2 = shouldIncludeSymbols ? await fetchSymbolsForFile(absPath, ctx, signal) : void 0;
160
163
  return {
161
164
  text: "",
162
165
  total_lines: total,
@@ -169,7 +172,7 @@ var readTool = {
169
172
  if (offset > total) {
170
173
  ctx.recordRead(absPath, stat2.mtimeMs, "user", contentHash);
171
174
  rememberReadRange(ctx, absPath, stat2.mtimeMs, total, total + 1, total + 1);
172
- const symResult2 = shouldIncludeSymbols ? await fetchSymbolsForFile(absPath, ctx, execOpts?.signal) : void 0;
175
+ const symResult2 = shouldIncludeSymbols ? await fetchSymbolsForFile(absPath, ctx, signal) : void 0;
173
176
  return {
174
177
  text: `[offset ${offset} is past end of file "${input.path}" \u2014 file has ${total} line(s). Do not retry this offset.]`,
175
178
  total_lines: total,
@@ -185,7 +188,7 @@ var readTool = {
185
188
  const numbered = slice.map((line, i) => `${String(offset + i).padStart(width, " ")}\u2192${line}`).join("\n");
186
189
  ctx.recordRead(absPath, stat2.mtimeMs, "user", contentHash);
187
190
  rememberReadRange(ctx, absPath, stat2.mtimeMs, total, offset, offset + slice.length - 1);
188
- const symResult = shouldIncludeSymbols ? await fetchSymbolsForFile(absPath, ctx, execOpts?.signal) : void 0;
191
+ const symResult = shouldIncludeSymbols ? await fetchSymbolsForFile(absPath, ctx, signal) : void 0;
189
192
  return {
190
193
  text: numbered,
191
194
  total_lines: total,
@@ -292,4 +295,4 @@ ${interesting.join("\n")}` : "symbols/imports: (none detected)"
292
295
  export {
293
296
  readTool
294
297
  };
295
- //# sourceMappingURL=chunk-YGG6X57C.js.map
298
+ //# sourceMappingURL=chunk-NKX4SJ5R.js.map
@@ -1,6 +1,7 @@
1
1
  // src/_concurrency.ts
2
2
  async function mapWithConcurrency(items, limit, fn) {
3
3
  if (items.length === 0) return [];
4
+ if (items.length === 1) return [await fn(items[0])];
4
5
  const effectiveLimit = Math.max(1, Math.min(limit | 0, items.length));
5
6
  const results = new Array(items.length);
6
7
  let nextIndex = 0;
@@ -18,4 +19,4 @@ async function mapWithConcurrency(items, limit, fn) {
18
19
  export {
19
20
  mapWithConcurrency
20
21
  };
21
- //# sourceMappingURL=chunk-U4D5S3VQ.js.map
22
+ //# sourceMappingURL=chunk-NWZ6XGBJ.js.map
@@ -58,10 +58,11 @@ var diffTool = {
58
58
  }
59
59
  },
60
60
  async execute(input, ctx, opts) {
61
+ const signal = opts?.signal ?? ctx.signal ?? new AbortController().signal;
61
62
  if (input.a !== void 0 || input.b !== void 0) {
62
- return await gitDiff(input, ctx, opts.signal);
63
+ return await gitDiff(input, ctx, signal);
63
64
  }
64
- return await fileDiff(input, ctx, opts.signal);
65
+ return await fileDiff(input, ctx, signal);
65
66
  }
66
67
  };
67
68
  async function gitDiff(input, ctx, signal) {
@@ -163,22 +164,31 @@ async function fileDiff(input, ctx, _signal) {
163
164
  mode: "dump"
164
165
  };
165
166
  }
167
+ const fileEntries = await Promise.all(
168
+ files.map(async (file) => {
169
+ const absPath = await safeResolveReal(file, ctx);
170
+ const stat2 = await fs.stat(absPath).catch(() => null);
171
+ if (!stat2?.isFile()) return null;
172
+ if (stat2.size > MAX_FILE_DUMP_BYTES) {
173
+ return {
174
+ truncated: true,
175
+ output: `--- ${file} (skipped: ${stat2.size} bytes exceeds the ${MAX_FILE_DUMP_BYTES} limit; use the read tool with offset/limit) ---`
176
+ };
177
+ }
178
+ const content = await fs.readFile(absPath, "utf8");
179
+ const lines = content.split(/\r?\n/);
180
+ return {
181
+ truncated: false,
182
+ output: formatWithLineNumbers(file, lines)
183
+ };
184
+ })
185
+ );
166
186
  const results = [];
167
187
  let truncated = false;
168
- for (const file of files) {
169
- const absPath = await safeResolveReal(file, ctx);
170
- const stat2 = await fs.stat(absPath).catch(() => null);
171
- if (!stat2?.isFile()) continue;
172
- if (stat2.size > MAX_FILE_DUMP_BYTES) {
173
- truncated = true;
174
- results.push(
175
- `--- ${file} (skipped: ${stat2.size} bytes exceeds the ${MAX_FILE_DUMP_BYTES} limit; use the read tool with offset/limit) ---`
176
- );
177
- continue;
178
- }
179
- const content = await fs.readFile(absPath, "utf8");
180
- const lines = content.split(/\r?\n/);
181
- results.push(formatWithLineNumbers(file, lines));
188
+ for (const entry of fileEntries) {
189
+ if (!entry) continue;
190
+ if (entry.truncated) truncated = true;
191
+ results.push(entry.output);
182
192
  }
183
193
  return {
184
194
  diff: results.join("\n\n"),
@@ -200,4 +210,4 @@ ${numbered}`;
200
210
  export {
201
211
  diffTool
202
212
  };
203
- //# sourceMappingURL=chunk-UKU2ZX4C.js.map
213
+ //# sourceMappingURL=chunk-P7ZQ2FAJ.js.map
@@ -55,13 +55,14 @@ var searchTool = {
55
55
  if (!final) throw new Error("search: stream ended without final event");
56
56
  return final;
57
57
  },
58
- async *executeStream(input, _ctx, opts) {
58
+ async *executeStream(input, ctx, opts) {
59
59
  if (!input?.query || input.query.trim() === "") {
60
60
  throw new ToolValidationError({
61
61
  message: "search: query is required and must be a non-empty string",
62
62
  field: "query"
63
63
  });
64
64
  }
65
+ const signal = opts?.signal ?? ctx?.signal ?? new AbortController().signal;
65
66
  const num = Math.max(1, Math.min(input.num_results ?? DEFAULT_NUM, MAX_RESULTS));
66
67
  const source = input.source ?? "duckduckgo";
67
68
  const skipCache = input.skip_cache ?? false;
@@ -106,13 +107,13 @@ var searchTool = {
106
107
  let effectiveSource = source;
107
108
  switch (source) {
108
109
  case "duckduckgo":
109
- engine = await duckduckgoSearch(input.query, opts.signal);
110
+ engine = await duckduckgoSearch(input.query, signal);
110
111
  break;
111
112
  case "google":
112
- engine = await googleSearch(input.query, opts.signal);
113
+ engine = await googleSearch(input.query, signal);
113
114
  break;
114
115
  case "bing":
115
- engine = await bingSearch(input.query, opts.signal);
116
+ engine = await bingSearch(input.query, signal);
116
117
  break;
117
118
  default:
118
119
  throw new ToolValidationError({
@@ -128,7 +129,7 @@ var searchTool = {
128
129
  text: `${source} returned no relevant static results; falling back to duckduckgo`,
129
130
  data: { source, fallback: "duckduckgo", query: input.query }
130
131
  };
131
- const fallback = await duckduckgoSearch(input.query, opts.signal);
132
+ const fallback = await duckduckgoSearch(input.query, signal);
132
133
  ranked = rankSearchResults(fallback.results, input.query);
133
134
  engineError = fallback.error;
134
135
  effectiveSource = "duckduckgo";
@@ -161,14 +162,18 @@ var searchTool = {
161
162
  }
162
163
  };
163
164
  function pruneCacheEntries() {
165
+ if (cache.size <= CACHE_MAX_ENTRIES) return;
164
166
  const cutoff = Date.now() - CACHE_TTL_MS * 2;
165
167
  for (const [key, entry] of cache.entries()) {
166
- if (entry.timestamp < cutoff) cache.delete(key);
168
+ if (entry.timestamp < cutoff) {
169
+ cache.delete(key);
170
+ }
167
171
  }
168
- while (cache.size > CACHE_MAX_ENTRIES) {
169
- const oldestKey = cache.keys().next().value;
170
- if (oldestKey === void 0) break;
171
- cache.delete(oldestKey);
172
+ if (cache.size > CACHE_MAX_ENTRIES) {
173
+ for (const key of cache.keys()) {
174
+ cache.delete(key);
175
+ if (cache.size <= CACHE_MAX_ENTRIES) break;
176
+ }
172
177
  }
173
178
  }
174
179
  function __clearSearchCache() {
@@ -428,4 +433,4 @@ export {
428
433
  searchTool,
429
434
  __clearSearchCache
430
435
  };
431
- //# sourceMappingURL=chunk-4I4LWFOO.js.map
436
+ //# sourceMappingURL=chunk-PQTONQ4P.js.map
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  builtinToolsPack
3
- } from "./chunk-PCHQ6YRR.js";
3
+ } from "./chunk-FYDKHXN7.js";
4
4
  import {
5
5
  TIER1_TOOLS,
6
6
  TIER2_TOOLS
7
- } from "./chunk-DSEANA2W.js";
7
+ } from "./chunk-XVGB6KYU.js";
8
8
 
9
9
  // src/tool-tier.ts
10
10
  function toolNameSet(tools) {
@@ -51,4 +51,4 @@ export {
51
51
  selectBuiltinToolsForTier,
52
52
  registerBuiltinToolTier
53
53
  };
54
- //# sourceMappingURL=chunk-XGHMUZ77.js.map
54
+ //# sourceMappingURL=chunk-RMB76PDS.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  enqueueReindex
3
- } from "./chunk-QDQY7NQ2.js";
3
+ } from "./chunk-A2PX7M7A.js";
4
4
  import {
5
5
  resolveRealInsideRoot,
6
6
  safeResolveReal,
@@ -43,6 +43,7 @@ var patchTool = {
43
43
  },
44
44
  async execute(input, ctx, opts) {
45
45
  if (!input?.patch) throw new Error("patch: patch content is required");
46
+ const signal = opts?.signal ?? ctx.signal ?? new AbortController().signal;
46
47
  const strip = Math.max(1, input.strip ?? 1);
47
48
  const dryRun = input.dry_run ?? false;
48
49
  const refuse = (message) => ({
@@ -96,7 +97,7 @@ var patchTool = {
96
97
  const patchFile = path.join(tmpDir, "in.diff");
97
98
  await fs.writeFile(patchFile, input.patch, { mode: 384 });
98
99
  const args = [`-p${strip}`, "--merge", ...dryRun ? ["--dry-run"] : [], "-i", patchFile];
99
- const result = await runPatch(args, dir, opts.signal, {
100
+ const result = await runPatch(args, dir, signal, {
100
101
  patchFile,
101
102
  strip,
102
103
  dryRun
@@ -312,4 +313,4 @@ function extractPatchedFiles(output) {
312
313
  export {
313
314
  patchTool
314
315
  };
315
- //# sourceMappingURL=chunk-5OAOKALG.js.map
316
+ //# sourceMappingURL=chunk-RUOMW2I6.js.map
@@ -4,10 +4,10 @@ import {
4
4
  } from "./chunk-Q5JPPCZC.js";
5
5
  import {
6
6
  mapWithConcurrency
7
- } from "./chunk-U4D5S3VQ.js";
7
+ } from "./chunk-NWZ6XGBJ.js";
8
8
  import {
9
9
  loadGitignoreMatcher
10
- } from "./chunk-LIJQMYYX.js";
10
+ } from "./chunk-ELFFQ4RU.js";
11
11
  import {
12
12
  isBinaryBuffer,
13
13
  safeResolveReal
@@ -107,16 +107,17 @@ var grepTool = {
107
107
  field: "pattern"
108
108
  });
109
109
  }
110
+ const signal = opts?.signal ?? ctx.signal ?? new AbortController().signal;
110
111
  const rgAvailable = await detectRg();
111
112
  if (rgAvailable) {
112
113
  try {
113
- yield* runRgStream(input, base, mode, limit, opts.signal);
114
+ yield* runRgStream(input, base, mode, limit, signal);
114
115
  return;
115
116
  } catch {
116
117
  }
117
118
  }
118
119
  yield { type: "log", text: "Falling back to native grep\u2026" };
119
- const out = await runNative(input, base, mode, limit, opts.signal);
120
+ const out = await runNative(input, base, mode, limit, signal);
120
121
  yield { type: "final", output: out };
121
122
  }
122
123
  };
@@ -151,7 +152,7 @@ async function* runRgStream(input, base, mode, limit, signal) {
151
152
  if (input.context_lines) args.push("-C", String(input.context_lines));
152
153
  }
153
154
  for (const ignored of DEFAULT_IGNORE) {
154
- args.push("--glob", `!${ignored}/**`, "--glob", `!**/${ignored}/**`);
155
+ args.push("--glob", `!**/${ignored}/**`);
155
156
  }
156
157
  const gitignorePath = path.join(base, ".gitignore");
157
158
  if (await fs.access(gitignorePath).then(
@@ -475,4 +476,4 @@ export {
475
476
  grepTool,
476
477
  __resetRgDetectionForTests
477
478
  };
478
- //# sourceMappingURL=chunk-553IQUMO.js.map
479
+ //# sourceMappingURL=chunk-S2JRYDYG.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  spawnStream
3
- } from "./chunk-22B7GE5T.js";
3
+ } from "./chunk-ZHH3BEWU.js";
4
4
  import {
5
5
  normalizeCommandOutput,
6
6
  safeResolveReal
@@ -2929,11 +2929,12 @@ var languageTool = {
2929
2929
  },
2930
2930
  async *executeStream(input, ctx, opts) {
2931
2931
  const cwd = input.cwd ? await safeResolveReal(input.cwd, ctx) : ctx.workingDir ?? ctx.cwd;
2932
+ const signal = opts?.signal ?? ctx.signal ?? new AbortController().signal;
2932
2933
  const operations = operationsFor(input);
2933
2934
  const runs = [];
2934
2935
  const unavailableReasons = [];
2935
2936
  for (const operation of operations) {
2936
- opts.signal.throwIfAborted();
2937
+ signal.throwIfAborted();
2937
2938
  const planResult = await planLanguageOperation({
2938
2939
  projectRoot: ctx.projectRoot,
2939
2940
  cwd,
@@ -2943,7 +2944,7 @@ var languageTool = {
2943
2944
  ...input.workspace ? { workspace: input.workspace } : {},
2944
2945
  ...input.mode ? { mode: input.mode } : {},
2945
2946
  operationOptions: operationOptions(input),
2946
- signal: opts.signal
2947
+ signal
2947
2948
  });
2948
2949
  if (planResult.status !== "planned") {
2949
2950
  const reason = planResult.status === "unavailable" ? planResult.unavailable.reason : planResult.reason;
@@ -2961,7 +2962,7 @@ var languageTool = {
2961
2962
  projectRoot: ctx.projectRoot,
2962
2963
  workspace: planResult.workspace,
2963
2964
  plan: planResult.plan,
2964
- signal: opts.signal
2965
+ signal
2965
2966
  });
2966
2967
  for (; ; ) {
2967
2968
  const next = await runner.next();
@@ -3196,6 +3197,7 @@ var languagePackageTool = {
3196
3197
  },
3197
3198
  async *executeStream(input, ctx, opts) {
3198
3199
  const cwd = input.cwd ? await safeResolveReal(input.cwd, ctx) : ctx.workingDir ?? ctx.cwd;
3200
+ const signal = opts?.signal ?? ctx.signal ?? new AbortController().signal;
3199
3201
  const planOperation = OPERATION_TO_PLAN[input.operation];
3200
3202
  const operationOptions2 = {
3201
3203
  ...input.names ? { packages: input.names } : {},
@@ -3209,7 +3211,7 @@ var languagePackageTool = {
3209
3211
  ...input.language ? { language: input.language } : {},
3210
3212
  ...input.workspace ? { workspace: input.workspace } : {},
3211
3213
  operationOptions: operationOptions2,
3212
- signal: opts.signal
3214
+ signal
3213
3215
  });
3214
3216
  if (planResult.status !== "planned") {
3215
3217
  const reason = planResult.status === "unavailable" ? planResult.unavailable.reason : planResult.reason;
@@ -3251,7 +3253,7 @@ var languagePackageTool = {
3251
3253
  workspace: planResult.workspace,
3252
3254
  plan: planResult.plan,
3253
3255
  packages: input.names ?? [],
3254
- signal: opts.signal
3256
+ signal
3255
3257
  });
3256
3258
  let outcome;
3257
3259
  for (; ; ) {
@@ -3473,12 +3475,13 @@ var languageInfoTool = {
3473
3475
  };
3474
3476
  }
3475
3477
  const cwd = input.cwd ? await safeResolveReal(input.cwd, ctx) : ctx.workingDir ?? ctx.cwd;
3478
+ const signal = opts?.signal ?? ctx.signal ?? new AbortController().signal;
3476
3479
  const common = {
3477
3480
  projectRoot: ctx.projectRoot,
3478
3481
  cwd,
3479
3482
  ...input.target ? { target: input.target } : {},
3480
3483
  ...input.language ? { language: input.language } : {},
3481
- signal: opts.signal
3484
+ signal
3482
3485
  };
3483
3486
  if (input.action === "detect") {
3484
3487
  return { action: "detect", ...await detectLanguageWorkspaces(common) };
@@ -3512,4 +3515,4 @@ export {
3512
3515
  languagePackageTool,
3513
3516
  languageInfoTool
3514
3517
  };
3515
- //# sourceMappingURL=chunk-OUBDL3WH.js.map
3518
+ //# sourceMappingURL=chunk-SOG7XIRF.js.map
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-FQZOHLG3.js";
4
4
  import {
5
5
  enqueueReindex
6
- } from "./chunk-QDQY7NQ2.js";
6
+ } from "./chunk-A2PX7M7A.js";
7
7
  import {
8
8
  safeResolveReal,
9
9
  sha256hex,
@@ -280,6 +280,8 @@ var editTool = {
280
280
  if (!input?.path) {
281
281
  throw new ToolValidationError({ message: "edit: path is required", field: "path" });
282
282
  }
283
+ const signal = opts?.signal ?? ctx?.signal;
284
+ signal?.throwIfAborted();
283
285
  if (input.old_string === void 0) {
284
286
  throw new ToolValidationError({
285
287
  message: "edit: old_string is required",
@@ -364,10 +366,10 @@ var editTool = {
364
366
  note: autoReadNote
365
367
  };
366
368
  }
367
- opts?.signal?.throwIfAborted();
369
+ signal?.throwIfAborted();
368
370
  const ladder = findLadderMatches(fileLf, oldLf);
369
371
  if (!ladder) {
370
- opts?.signal?.throwIfAborted();
372
+ signal?.throwIfAborted();
371
373
  throw noMatchError(input.path, fileLf, oldLf);
372
374
  }
373
375
  const { tier, matches } = ladder;
@@ -398,7 +400,7 @@ var editTool = {
398
400
  let newFileLf;
399
401
  let tierNote;
400
402
  if (tier === "exact") {
401
- newFileLf = input.replace_all ? fileLf.split(oldLf).join(newLf) : fileLf.replace(oldLf, newLf);
403
+ newFileLf = input.replace_all ? fileLf.split(oldLf).join(newLf) : fileLf.replace(oldLf, () => newLf);
402
404
  } else {
403
405
  let replacement = newLf;
404
406
  let indentSuffix = "";
@@ -419,7 +421,7 @@ var editTool = {
419
421
  tierNote = `old_string did not match exactly; applied via ${TIER_LABEL[tier]} at line ${matches[0].startLine} (confidence: ${TIER_CONFIDENCE[tier]}${scoreSuffix}${indentSuffix}). Review the diff to confirm the intended target was edited.`;
420
422
  }
421
423
  const newFile = toStyle(newFileLf, style);
422
- opts?.signal?.throwIfAborted();
424
+ signal?.throwIfAborted();
423
425
  await atomicWrite(absPath, newFile, { mode: updated.mode & 511 });
424
426
  try {
425
427
  enqueueReindex({ projectRoot: ctx.projectRoot, files: [absPath] });
@@ -433,7 +435,7 @@ var editTool = {
433
435
  before: original,
434
436
  after: newFile
435
437
  });
436
- opts?.signal?.throwIfAborted();
438
+ signal?.throwIfAborted();
437
439
  const { text: diff, truncated: diffTruncated } = truncateDiffPayload(
438
440
  unifiedDiff(original, newFile, {
439
441
  fromFile: input.path,
@@ -471,4 +473,4 @@ Compare this against your old_string and retry with the file's actual text.` : "
471
473
  export {
472
474
  editTool
473
475
  };
474
- //# sourceMappingURL=chunk-U6DZWHBA.js.map
476
+ //# sourceMappingURL=chunk-TDLZIDCY.js.map