@wrongstack/tools 1.0.7 → 1.0.9

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 (135) hide show
  1. package/dist/_win32-resolve.d.ts +5 -0
  2. package/dist/audit.js +5 -5
  3. package/dist/bash.js +2 -2
  4. package/dist/browser/index.js +1 -1
  5. package/dist/builtin.js +41 -41
  6. package/dist/{chunk-N3OTTQNC.js → chunk-2OCAAFAT.js} +44 -25
  7. package/dist/{chunk-5MP76C72.js → chunk-2UVAIS5O.js} +24 -29
  8. package/dist/{chunk-SIIOHBNY.js → chunk-3RRK33YM.js} +2 -2
  9. package/dist/{chunk-M2W36JT7.js → chunk-4CE3RKEP.js} +6 -3
  10. package/dist/{chunk-QJARSK2G.js → chunk-4SUGLJLO.js} +11 -3
  11. package/dist/{chunk-AH7J5HWL.js → chunk-5RBUYFRV.js} +15 -7
  12. package/dist/{chunk-WKLUOXR4.js → chunk-7GOE2ZTZ.js} +2 -2
  13. package/dist/{chunk-O6AGFJBO.js → chunk-7V33PHT6.js} +49 -77
  14. package/dist/{chunk-CAF4L6KN.js → chunk-C3WP6ZOT.js} +36 -48
  15. package/dist/{chunk-KMXPP32M.js → chunk-C6ZOXNXV.js} +13 -3
  16. package/dist/{chunk-EGT5QLCB.js → chunk-D6RQZMZS.js} +123 -255
  17. package/dist/{chunk-S6CGSFLX.js → chunk-DBG7UQGK.js} +10 -3
  18. package/dist/{chunk-2W4XTULI.js → chunk-DLZCOEVG.js} +50 -8
  19. package/dist/{chunk-NL45OWEO.js → chunk-DOAHONOS.js} +7 -12
  20. package/dist/{chunk-3LQJXJDM.js → chunk-E7A4SLKR.js} +2 -2
  21. package/dist/{chunk-JB5JLY7V.js → chunk-ENE22I5W.js} +387 -394
  22. package/dist/{chunk-SEONDNLN.js → chunk-G7CYW5EP.js} +2 -2
  23. package/dist/{chunk-YPSIG23D.js → chunk-HV7RWDCL.js} +3 -3
  24. package/dist/{chunk-TU6UVATU.js → chunk-HYHE4VNA.js} +3 -3
  25. package/dist/{chunk-HIRVCXLP.js → chunk-IE4KDAOB.js} +3 -3
  26. package/dist/{chunk-YA2ZYCJY.js → chunk-JPK2HHBK.js} +1 -1
  27. package/dist/{chunk-7E55DAFW.js → chunk-KHUCKLOR.js} +12 -7
  28. package/dist/{chunk-R3HIZVFS.js → chunk-KPDCKSN5.js} +23 -3
  29. package/dist/{chunk-B3MGJBFI.js → chunk-KS2OEZWV.js} +23 -47
  30. package/dist/{chunk-UI3ZJIG3.js → chunk-LKLIQUCW.js} +14 -8
  31. package/dist/{chunk-62OAECEQ.js → chunk-LLSFOUZF.js} +8 -8
  32. package/dist/{chunk-YZQSUL5G.js → chunk-M4ZHHCCW.js} +14 -6
  33. package/dist/{chunk-IXIS7RSG.js → chunk-MRXWOOOR.js} +29 -47
  34. package/dist/{chunk-C4DSQBTT.js → chunk-NEYUPZL6.js} +3 -3
  35. package/dist/{chunk-6XYFYLN7.js → chunk-O2MHULBO.js} +13 -8
  36. package/dist/{chunk-B62LKMWQ.js → chunk-OKZJJDOG.js} +86 -188
  37. package/dist/{chunk-JKFIDWQG.js → chunk-ON6ET5ER.js} +52 -9
  38. package/dist/{chunk-KF7GMVNU.js → chunk-OUERRFEM.js} +32 -11
  39. package/dist/{chunk-4DK5WZGR.js → chunk-OXO773CW.js} +127 -196
  40. package/dist/{chunk-GF4JHLCO.js → chunk-PWZUHZP7.js} +2 -2
  41. package/dist/{chunk-CLJXKFVS.js → chunk-QA37PFYL.js} +29 -68
  42. package/dist/{chunk-A3LNNBYO.js → chunk-QAWI3RSK.js} +41 -83
  43. package/dist/{chunk-ZMCV3XOV.js → chunk-SPNXDTCJ.js} +29 -63
  44. package/dist/{chunk-H2VB7GCR.js → chunk-ULI2J6TX.js} +27 -14
  45. package/dist/{chunk-EMA2XENR.js → chunk-UVYRQKPZ.js} +4 -3
  46. package/dist/{chunk-2NTHMZV3.js → chunk-VMJY6FYJ.js} +693 -276
  47. package/dist/{chunk-KPR53VKZ.js → chunk-WEUEU53R.js} +2 -2
  48. package/dist/{chunk-ZOUG3KKS.js → chunk-XPVYZ2S6.js} +2 -2
  49. package/dist/{chunk-5U5ULQX2.js → chunk-XZLVJD56.js} +5 -1
  50. package/dist/{chunk-HCPSVK7J.js → chunk-YKSOSI2N.js} +47 -31
  51. package/dist/codebase-index/codebase-ast-replace-tool.d.ts +5 -6
  52. package/dist/codebase-index/codebase-context-tool.d.ts +4 -6
  53. package/dist/codebase-index/codebase-impact-analysis-tool.d.ts +1 -2
  54. package/dist/codebase-index/codebase-incoming-calls-tool.d.ts +0 -2
  55. package/dist/codebase-index/codebase-index-tool.d.ts +0 -2
  56. package/dist/codebase-index/codebase-invariant-check-tool.d.ts +1 -2
  57. package/dist/codebase-index/codebase-outgoing-calls-tool.d.ts +0 -2
  58. package/dist/codebase-index/codebase-repo-map-tool.d.ts +1 -2
  59. package/dist/codebase-index/codebase-search-tool.d.ts +1 -1
  60. package/dist/codebase-index/codebase-targeted-test-tool.d.ts +1 -2
  61. package/dist/codebase-index/index.js +8 -8
  62. package/dist/codebase-index/parser-worker-script.js +3 -3
  63. package/dist/codebase-index/project-server.js +5 -5
  64. package/dist/codebase-index/worker.js +4 -4
  65. package/dist/design.js +1 -1
  66. package/dist/diff.js +1 -1
  67. package/dist/edit.js +7 -7
  68. package/dist/exec.d.ts +7 -7
  69. package/dist/exec.js +2 -2
  70. package/dist/format.js +5 -5
  71. package/dist/git.js +1 -1
  72. package/dist/glob.js +1 -1
  73. package/dist/{go-parser-VDPRQEGM.js → go-parser-Z4H6SR3R.js} +6 -3
  74. package/dist/grep.js +1 -1
  75. package/dist/index.js +45 -45
  76. package/dist/install.js +5 -5
  77. package/dist/json.d.ts +0 -1
  78. package/dist/json.js +1 -1
  79. package/dist/kanban-presence.d.ts +6 -0
  80. package/dist/kanban-serializer.d.ts +9 -1
  81. package/dist/kanban-split-task-handler.d.ts +1 -1
  82. package/dist/kanban-tool-results.d.ts +57 -2
  83. package/dist/kanban-tool-types.d.ts +16 -5
  84. package/dist/kanban.d.ts +14 -0
  85. package/dist/kanban.js +9 -1
  86. package/dist/languages/index.js +3 -3
  87. package/dist/{legacy-bridge-4T4OTSQP.js → legacy-bridge-BPT2S2F4.js} +5 -5
  88. package/dist/lint.js +5 -5
  89. package/dist/logs.js +1 -1
  90. package/dist/mode.d.ts +3 -2
  91. package/dist/mode.js +1 -1
  92. package/dist/outdated.js +2 -2
  93. package/dist/pack.js +42 -42
  94. package/dist/{parser-dispatch-4E2SDQUO.js → parser-dispatch-WG4DNBHH.js} +4 -4
  95. package/dist/patch.js +7 -7
  96. package/dist/plan.d.ts +2 -1
  97. package/dist/plan.js +3 -3
  98. package/dist/{py-parser-MAW6DHFE.js → py-parser-4PFZYAJ7.js} +3 -3
  99. package/dist/read.js +7 -7
  100. package/dist/replace.js +7 -7
  101. package/dist/search.d.ts +0 -6
  102. package/dist/search.js +1 -1
  103. package/dist/security-ast-scan-tool.d.ts +1 -2
  104. package/dist/session-shell.js +2 -2
  105. package/dist/task.d.ts +2 -1
  106. package/dist/task.js +3 -3
  107. package/dist/test.d.ts +8 -1
  108. package/dist/test.js +5 -5
  109. package/dist/todo.js +2 -2
  110. package/dist/tool-search.d.ts +2 -0
  111. package/dist/tool-search.js +1 -1
  112. package/dist/tool-tier.js +43 -43
  113. package/dist/tool-use.d.ts +2 -2
  114. package/dist/tool-use.js +1 -1
  115. package/dist/tree.js +1 -1
  116. package/dist/typecheck.js +5 -5
  117. package/dist/wasm/bash/tree-sitter-bash.wasm +0 -0
  118. package/dist/wasm/c/tree-sitter-c.wasm +0 -0
  119. package/dist/wasm/c_sharp/tree-sitter-c_sharp.wasm +0 -0
  120. package/dist/wasm/checksums.json +16 -0
  121. package/dist/wasm/cpp/tree-sitter-cpp.wasm +0 -0
  122. package/dist/wasm/elixir/tree-sitter-elixir.wasm +0 -0
  123. package/dist/wasm/go/tree-sitter-go.wasm +0 -0
  124. package/dist/wasm/java/tree-sitter-java.wasm +0 -0
  125. package/dist/wasm/kotlin/tree-sitter-kotlin.wasm +0 -0
  126. package/dist/wasm/php/tree-sitter-php.wasm +0 -0
  127. package/dist/wasm/python/tree-sitter-python.wasm +0 -0
  128. package/dist/wasm/ruby/tree-sitter-ruby.wasm +0 -0
  129. package/dist/wasm/rust/tree-sitter-rust.wasm +0 -0
  130. package/dist/wasm/swift/tree-sitter-swift.wasm +0 -0
  131. package/dist/wasm/tree-sitter-runtime.wasm +0 -0
  132. package/dist/win32.d.ts +1 -1
  133. package/dist/win32.js +3 -1
  134. package/dist/write.js +7 -7
  135. package/package.json +10 -10
@@ -1,4 +1,9 @@
1
1
  export { buildWin32CmdShimInvocation, type Win32CmdShimInvocation, } from '@wrongstack/core/utils';
2
+ /**
3
+ * Check whether a file path or command names a Windows batch / cmd shim
4
+ * (`.cmd` or `.bat`), case-insensitively.
5
+ */
6
+ export declare function isWinCmdShim(filePath: string): boolean;
2
7
  /**
3
8
  * On Windows, Node.js `spawn()` without a shell does NOT resolve .cmd/.bat
4
9
  * extensions through PATHEXT — it only auto-resolves .exe. Most Node.js CLI
package/dist/audit.js CHANGED
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  auditTool
3
- } from "./chunk-HCPSVK7J.js";
4
- import "./chunk-3LQJXJDM.js";
5
- import "./chunk-SEONDNLN.js";
6
- import "./chunk-EMA2XENR.js";
3
+ } from "./chunk-YKSOSI2N.js";
4
+ import "./chunk-E7A4SLKR.js";
5
+ import "./chunk-G7CYW5EP.js";
6
+ import "./chunk-UVYRQKPZ.js";
7
7
  import "./chunk-SCMRM6NL.js";
8
8
  import "./chunk-HDYUBRMF.js";
9
9
  import "./chunk-7JJFC6CT.js";
10
- import "./chunk-5U5ULQX2.js";
10
+ import "./chunk-XZLVJD56.js";
11
11
  import "./chunk-2IAEJRLT.js";
12
12
  export {
13
13
  auditTool
package/dist/bash.js CHANGED
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  bashTool
3
- } from "./chunk-CLJXKFVS.js";
3
+ } from "./chunk-QA37PFYL.js";
4
4
  import "./chunk-BTSFTGIL.js";
5
5
  import "./chunk-PVCB7RUZ.js";
6
6
  import "./chunk-SCMRM6NL.js";
7
7
  import "./chunk-HDYUBRMF.js";
8
8
  import "./chunk-7JJFC6CT.js";
9
- import "./chunk-5U5ULQX2.js";
9
+ import "./chunk-XZLVJD56.js";
10
10
  import "./chunk-2IAEJRLT.js";
11
11
  export {
12
12
  bashTool
@@ -31,7 +31,7 @@ import {
31
31
  resolvePinnedBrowserTarget,
32
32
  safeBrowserUrl,
33
33
  shutdownBrowserTools
34
- } from "../chunk-6XYFYLN7.js";
34
+ } from "../chunk-O2MHULBO.js";
35
35
  export {
36
36
  BROWSER_TOOL_NAMES,
37
37
  BrowserArtifactStore,
package/dist/builtin.js CHANGED
@@ -6,64 +6,64 @@ import {
6
6
  TIER2_TOOLS,
7
7
  TIER3_TOOLS,
8
8
  builtinTools
9
- } from "./chunk-4DK5WZGR.js";
9
+ } from "./chunk-OXO773CW.js";
10
10
  import "./chunk-BVHKBBGA.js";
11
- import "./chunk-JB5JLY7V.js";
11
+ import "./chunk-ENE22I5W.js";
12
12
  import "./chunk-XRNN44QY.js";
13
- import "./chunk-IXIS7RSG.js";
14
- import "./chunk-O6AGFJBO.js";
15
- import "./chunk-B62LKMWQ.js";
16
- import "./chunk-KF7GMVNU.js";
17
- import "./chunk-H2VB7GCR.js";
18
- import "./chunk-HCPSVK7J.js";
19
- import "./chunk-NL45OWEO.js";
20
- import "./chunk-CAF4L6KN.js";
21
- import "./chunk-YA2ZYCJY.js";
22
- import "./chunk-B3MGJBFI.js";
23
- import "./chunk-ZMCV3XOV.js";
24
- import "./chunk-5MP76C72.js";
25
- import "./chunk-EGT5QLCB.js";
26
- import "./chunk-N3OTTQNC.js";
27
- import "./chunk-YZQSUL5G.js";
28
- import "./chunk-R3HIZVFS.js";
29
- import "./chunk-QJARSK2G.js";
30
- import "./chunk-AH7J5HWL.js";
31
- import "./chunk-3LQJXJDM.js";
32
- import "./chunk-SEONDNLN.js";
33
- import "./chunk-EMA2XENR.js";
34
- import "./chunk-KMXPP32M.js";
35
- import "./chunk-JKFIDWQG.js";
36
- import "./chunk-2W4XTULI.js";
13
+ import "./chunk-MRXWOOOR.js";
14
+ import "./chunk-7V33PHT6.js";
15
+ import "./chunk-OKZJJDOG.js";
16
+ import "./chunk-OUERRFEM.js";
17
+ import "./chunk-ULI2J6TX.js";
18
+ import "./chunk-YKSOSI2N.js";
19
+ import "./chunk-DOAHONOS.js";
20
+ import "./chunk-C3WP6ZOT.js";
21
+ import "./chunk-JPK2HHBK.js";
22
+ import "./chunk-KS2OEZWV.js";
23
+ import "./chunk-SPNXDTCJ.js";
24
+ import "./chunk-2UVAIS5O.js";
25
+ import "./chunk-D6RQZMZS.js";
26
+ import "./chunk-2OCAAFAT.js";
27
+ import "./chunk-M4ZHHCCW.js";
28
+ import "./chunk-KPDCKSN5.js";
29
+ import "./chunk-4SUGLJLO.js";
30
+ import "./chunk-5RBUYFRV.js";
31
+ import "./chunk-E7A4SLKR.js";
32
+ import "./chunk-G7CYW5EP.js";
33
+ import "./chunk-UVYRQKPZ.js";
34
+ import "./chunk-C6ZOXNXV.js";
35
+ import "./chunk-ON6ET5ER.js";
36
+ import "./chunk-DLZCOEVG.js";
37
37
  import "./chunk-YJTXRH5Y.js";
38
38
  import "./chunk-ZBMANLYH.js";
39
- import "./chunk-CLJXKFVS.js";
40
- import "./chunk-A3LNNBYO.js";
39
+ import "./chunk-QA37PFYL.js";
40
+ import "./chunk-QAWI3RSK.js";
41
41
  import "./chunk-BTSFTGIL.js";
42
42
  import "./chunk-PVCB7RUZ.js";
43
43
  import "./chunk-SCMRM6NL.js";
44
44
  import "./chunk-HDYUBRMF.js";
45
45
  import "./chunk-7JJFC6CT.js";
46
46
  import "./chunk-4SW6BXUR.js";
47
- import "./chunk-62OAECEQ.js";
47
+ import "./chunk-LLSFOUZF.js";
48
48
  import "./chunk-NBDZMMG2.js";
49
- import "./chunk-S6CGSFLX.js";
50
- import "./chunk-2NTHMZV3.js";
49
+ import "./chunk-DBG7UQGK.js";
50
+ import "./chunk-VMJY6FYJ.js";
51
51
  import "./chunk-YZECCW3F.js";
52
- import "./chunk-6XYFYLN7.js";
53
- import "./chunk-HIRVCXLP.js";
54
- import "./chunk-GF4JHLCO.js";
55
- import "./chunk-WKLUOXR4.js";
52
+ import "./chunk-O2MHULBO.js";
53
+ import "./chunk-IE4KDAOB.js";
54
+ import "./chunk-PWZUHZP7.js";
55
+ import "./chunk-7GOE2ZTZ.js";
56
56
  import "./chunk-MSOAX3GC.js";
57
- import "./chunk-TU6UVATU.js";
58
- import "./chunk-ZOUG3KKS.js";
59
- import "./chunk-C4DSQBTT.js";
60
- import "./chunk-7E55DAFW.js";
61
- import "./chunk-M2W36JT7.js";
57
+ import "./chunk-HYHE4VNA.js";
58
+ import "./chunk-XPVYZ2S6.js";
59
+ import "./chunk-NEYUPZL6.js";
60
+ import "./chunk-KHUCKLOR.js";
61
+ import "./chunk-4CE3RKEP.js";
62
62
  import "./chunk-SKRMUHTU.js";
63
63
  import "./chunk-ZKC5UNGD.js";
64
64
  import "./chunk-YOHO4DVT.js";
65
65
  import "./chunk-XHSHNOAF.js";
66
- import "./chunk-5U5ULQX2.js";
66
+ import "./chunk-XZLVJD56.js";
67
67
  import "./chunk-2IAEJRLT.js";
68
68
  export {
69
69
  BUILTIN_TOOL_DESCRIPTIONS,
@@ -10,6 +10,7 @@ import { spawn } from "node:child_process";
10
10
  import { statSync } from "node:fs";
11
11
  import * as fs from "node:fs/promises";
12
12
  import * as path from "node:path";
13
+ import { StringDecoder } from "node:string_decoder";
13
14
  import { buildChildEnv } from "@wrongstack/core/utils";
14
15
  import { ToolValidationError } from "@wrongstack/core/types";
15
16
  var MAX_FILE_DUMP_BYTES = 5 * 1024 * 1024;
@@ -131,13 +132,7 @@ async function gitDiff(input, ctx, signal) {
131
132
  }
132
133
  const gitDir = findGitDir(basePath);
133
134
  if (!gitDir) {
134
- return {
135
- diff: "",
136
- files: [],
137
- truncated: false,
138
- mode: effectiveMode,
139
- note: "Not a git repository (or any parent up to root)."
140
- };
135
+ throw new Error(`diff: not a git repository (or any parent up to root): ${basePath}`);
141
136
  }
142
137
  const args = ["diff", "--no-color"];
143
138
  if (statMode) args.push("--stat");
@@ -162,6 +157,11 @@ async function gitDiff(input, ctx, signal) {
162
157
  }
163
158
  }
164
159
  const result = await runGit(args, gitDir, signal);
160
+ if (result.exitCode !== 0) {
161
+ throw new Error(
162
+ `diff: git diff exited with code ${result.exitCode}: ${result.stderr.trim() || "command failed"}`
163
+ );
164
+ }
165
165
  let diff = result.stdout;
166
166
  let truncated = false;
167
167
  if (diff.length > MAX_GIT_DIFF_CHARS) {
@@ -172,14 +172,12 @@ async function gitDiff(input, ctx, signal) {
172
172
  \u2026[git diff truncated: ${result.stdout.length - clipped.length} of ${result.stdout.length} characters omitted]`;
173
173
  truncated = true;
174
174
  }
175
- const exitNote = result.exitCode !== 0 ? `git diff exited with code ${result.exitCode}: ${result.stderr.trim() || "command failed"}` : void 0;
176
- const combinedNote = [sideBySideNote, exitNote].filter(Boolean).join("\n") || void 0;
177
175
  return {
178
176
  diff,
179
177
  files: effectiveFiles,
180
178
  truncated,
181
179
  mode: effectiveMode,
182
- note: combinedNote
180
+ note: sideBySideNote
183
181
  };
184
182
  }
185
183
  function findGitDir(cwd) {
@@ -203,6 +201,8 @@ function runGit(args, cwd, signal) {
203
201
  return new Promise((resolve2) => {
204
202
  let stdout = "";
205
203
  let stderr = "";
204
+ const stdoutDecoder = new StringDecoder("utf8");
205
+ const stderrDecoder = new StringDecoder("utf8");
206
206
  const child = spawn("git", args, {
207
207
  cwd,
208
208
  signal,
@@ -211,12 +211,16 @@ function runGit(args, cwd, signal) {
211
211
  windowsHide: true
212
212
  });
213
213
  child.stdout?.on("data", (c) => {
214
- stdout += c.toString();
214
+ stdout += stdoutDecoder.write(c);
215
215
  });
216
216
  child.stderr?.on("data", (c) => {
217
- stderr += c.toString();
217
+ stderr += stderrDecoder.write(c);
218
+ });
219
+ child.on("close", (code) => {
220
+ stdout += stdoutDecoder.end();
221
+ stderr += stderrDecoder.end();
222
+ resolve2({ stdout, stderr, exitCode: code ?? 0 });
218
223
  });
219
- child.on("close", (code) => resolve2({ stdout, stderr, exitCode: code ?? 0 }));
220
224
  child.on("error", (e) => resolve2({ stdout: "", stderr: e.message, exitCode: 1 }));
221
225
  });
222
226
  }
@@ -230,12 +234,10 @@ async function fileDiff(input, ctx, signal) {
230
234
  )
231
235
  ];
232
236
  if (files.length === 0) {
233
- return {
234
- diff: "No files specified",
235
- files: [],
236
- truncated: false,
237
- mode: "dump"
238
- };
237
+ throw new ToolValidationError({
238
+ message: "diff: no files specified \u2014 pass `files`, or `a`/`b`/`staged` for a git diff",
239
+ field: "files"
240
+ });
239
241
  }
240
242
  let basePath;
241
243
  try {
@@ -252,11 +254,15 @@ async function fileDiff(input, ctx, signal) {
252
254
  let absPath;
253
255
  try {
254
256
  absPath = await safeResolveReal(fileToResolve, ctx);
255
- } catch {
256
- return null;
257
+ } catch (err) {
258
+ throw new ToolValidationError({
259
+ message: `diff: file "${file}": ${err.message}`,
260
+ field: "files",
261
+ cause: err
262
+ });
257
263
  }
258
264
  const stat2 = await fs.stat(absPath).catch(() => null);
259
- if (!stat2?.isFile()) return null;
265
+ if (!stat2?.isFile()) return { missing: file };
260
266
  if (stat2.size > MAX_FILE_DUMP_BYTES) {
261
267
  return {
262
268
  truncated: true,
@@ -271,12 +277,25 @@ async function fileDiff(input, ctx, signal) {
271
277
  };
272
278
  });
273
279
  const results = [];
280
+ const missing = [];
274
281
  let truncated = false;
275
282
  for (const entry of fileEntries) {
276
- if (!entry) continue;
283
+ if ("missing" in entry) {
284
+ missing.push(entry.missing);
285
+ continue;
286
+ }
277
287
  if (entry.truncated) truncated = true;
278
288
  results.push(entry.output);
279
289
  }
290
+ if (results.length === 0) {
291
+ throw new Error(
292
+ `diff: none of the requested files exist or are regular files: ${missing.join(", ")}`
293
+ );
294
+ }
295
+ const notes = [
296
+ input.mode !== void 0 ? "The `files`-only path is a line-numbered dump; `mode` only affects the git-diff path (`a`/`b`)." : void 0,
297
+ missing.length > 0 ? `Skipped (not found or not a regular file): ${missing.join(", ")}` : void 0
298
+ ].filter(Boolean);
280
299
  return {
281
300
  diff: results.join("\n\n"),
282
301
  files,
@@ -284,7 +303,7 @@ async function fileDiff(input, ctx, signal) {
284
303
  // Honest mode: this path always produces a line-numbered dump — it never
285
304
  // honors `mode`, so it must not echo the requested value back.
286
305
  mode: "dump",
287
- note: input.mode !== void 0 ? "The `files`-only path is a line-numbered dump; `mode` only affects the git-diff path (`a`/`b`)." : void 0
306
+ note: notes.length > 0 ? notes.join("\n") : void 0
288
307
  };
289
308
  }
290
309
  function formatWithLineNumbers(file, lines) {
@@ -302,4 +321,4 @@ ${parts.join("\n")}`;
302
321
  export {
303
322
  diffTool
304
323
  };
305
- //# sourceMappingURL=chunk-N3OTTQNC.js.map
324
+ //# sourceMappingURL=chunk-2OCAAFAT.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  enqueueReindex
3
- } from "./chunk-TU6UVATU.js";
3
+ } from "./chunk-HYHE4VNA.js";
4
4
  import {
5
5
  resolveRealInsideRoot,
6
6
  safeResolveReal,
@@ -12,13 +12,14 @@ import { spawn } from "node:child_process";
12
12
  import * as fs from "node:fs/promises";
13
13
  import * as os from "node:os";
14
14
  import * as path from "node:path";
15
+ import { StringDecoder } from "node:string_decoder";
15
16
  import { ToolValidationError } from "@wrongstack/core/types";
16
17
  import { buildChildEnv, toErrorMessage } from "@wrongstack/core/utils";
17
18
  var patchTool = {
18
19
  name: "patch",
19
20
  category: "Filesystem",
20
21
  description: "Apply a unified diff (patch) to the project. This is the correct tool when you have a diff that needs to be applied precisely, including handling of rejects.",
21
- usageHint: "Best used when you already have a diff (from generation, external source, or previous step).\n- Use `dry_run: true` to see what would happen without modifying files.\n- Applied with `--merge`: a conflicting hunk writes git-style conflict\n markers (<<<<<<< / ======= / >>>>>>>) INTO the file and reports failure.\n It does NOT create .rej/.orig files. `files` lists what changed on disk\n even when the patch failed, so read those back before retrying.\nOften cleaner than many small `edit` operations for larger changes.",
22
+ usageHint: "Best used when you already have a diff (from generation, external source, or previous step).\n- Use `dry_run: true` to see what would happen without modifying files.\n- Applied with `--merge`: a conflicting hunk writes git-style conflict\n markers (<<<<<<< / ======= / >>>>>>>) INTO the file and the call fails.\n It does NOT create .rej/.orig files. The failure message lists every file\n changed on disk anyway, so read those back before retrying.\n- A dry run that would conflict is reported (not thrown) with `rejected: 1`.\nOften cleaner than many small `edit` operations for larger changes.",
22
23
  selection: {
23
24
  doNotUseWhen: "you do not already have a unified diff or only need one precise replacement.",
24
25
  useInstead: ["edit"]
@@ -74,18 +75,14 @@ var patchTool = {
74
75
  }
75
76
  const strip = typeof input.strip === "number" && Number.isFinite(input.strip) && input.strip >= 0 ? Math.floor(input.strip) : 1;
76
77
  const dryRun = input.dry_run ?? false;
77
- const refuse = (message) => ({
78
- applied: 0,
79
- rejected: 1,
80
- files: [],
81
- dry_run: dryRun,
82
- message
83
- });
78
+ const refuse = (message, field = "patch") => {
79
+ throw new ToolValidationError({ message, field });
80
+ };
84
81
  let dir;
85
82
  try {
86
83
  dir = input.directory ? await safeResolveReal(input.directory, ctx) : ctx.cwd;
87
84
  } catch (err) {
88
- return refuse(`patch refused: ${toErrorMessage(err)}`);
85
+ return refuse(`patch refused: ${toErrorMessage(err)}`, "directory");
89
86
  }
90
87
  const realRoot = await fs.realpath(ctx.projectRoot).catch(() => path.resolve(ctx.projectRoot));
91
88
  const targets = extractDiffTargets(input.patch);
@@ -140,6 +137,11 @@ var patchTool = {
140
137
  strip,
141
138
  dryRun
142
139
  });
140
+ if (result.unavailable) {
141
+ throw new Error(
142
+ `patch: no patch engine could be started (GNU patch and git both unavailable): ${result.stderr}`
143
+ );
144
+ }
143
145
  const touched = [];
144
146
  if (!dryRun) {
145
147
  for (const target of resolvedTargets) {
@@ -178,18 +180,8 @@ var patchTool = {
178
180
  }
179
181
  if (result.exitCode !== 0) {
180
182
  if (!dryRun) {
181
- const partial = touched.length > 0 ? ` ${touched.length} file(s) were still modified on disk and have been recorded for rewind: ${touched.map((p) => path.relative(realRoot, p) || p).join(", ")}.` : "";
182
- return {
183
- applied: touched.length,
184
- rejected: 1,
185
- // Normalize to relative-to-realRoot for API consistency with the
186
- // success path (which returns GNU patch's dir-relative names).
187
- // `touched` entries are realpaths from resolveRealInsideRoot, and
188
- // realRoot is also a realpath, so path.relative is like-for-like.
189
- files: touched.map((p) => path.relative(realRoot, p) || p),
190
- dry_run: dryRun,
191
- message: `patch failed: ${result.stderr || result.stdout}${partial}`
192
- };
183
+ const partial = touched.length > 0 ? ` ${touched.length} file(s) were still modified on disk and have been recorded for rewind: ${touched.map((p) => path.relative(realRoot, p) || p).join(", ")}. Read them back before retrying.` : "";
184
+ throw new Error(`patch failed: ${result.stderr || result.stdout}${partial}`);
193
185
  }
194
186
  const wouldPatch = result.engine === "git" ? [
195
187
  ...new Set(
@@ -350,6 +342,8 @@ function runPatchProcess(command, args, cwd, signal) {
350
342
  return new Promise((resolve2) => {
351
343
  let stdout = "";
352
344
  let stderr = "";
345
+ const stdoutDecoder = new StringDecoder("utf8");
346
+ const stderrDecoder = new StringDecoder("utf8");
353
347
  const env = { ...buildChildEnv(), LANG: "C", LC_ALL: "C" };
354
348
  const child = spawn(command, args, {
355
349
  cwd,
@@ -360,15 +354,16 @@ function runPatchProcess(command, args, cwd, signal) {
360
354
  });
361
355
  child.stdin?.end();
362
356
  child.stdout?.on("data", (c) => {
363
- stdout += c.toString();
357
+ stdout += stdoutDecoder.write(c);
364
358
  });
365
359
  child.stderr?.on("data", (c) => {
366
- stderr += c.toString();
360
+ stderr += stderrDecoder.write(c);
361
+ });
362
+ child.on("close", (code) => {
363
+ stdout += stdoutDecoder.end();
364
+ stderr += stderrDecoder.end();
365
+ resolve2({ exitCode: code ?? 1, stdout, stderr, unavailable: false });
367
366
  });
368
- child.on(
369
- "close",
370
- (code) => resolve2({ exitCode: code ?? 1, stdout, stderr, unavailable: false })
371
- );
372
367
  child.on(
373
368
  "error",
374
369
  (e) => resolve2({
@@ -395,4 +390,4 @@ function extractPatchedFiles(output) {
395
390
  export {
396
391
  patchTool
397
392
  };
398
- //# sourceMappingURL=chunk-5MP76C72.js.map
393
+ //# sourceMappingURL=chunk-2UVAIS5O.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  resolveWin32Command
3
- } from "./chunk-5U5ULQX2.js";
3
+ } from "./chunk-XZLVJD56.js";
4
4
 
5
5
  // src/_session-shell.ts
6
6
  function normalizeShell(value) {
@@ -35,4 +35,4 @@ export {
35
35
  resolveSessionShell,
36
36
  ensureSessionShell
37
37
  };
38
- //# sourceMappingURL=chunk-SIIOHBNY.js.map
38
+ //# sourceMappingURL=chunk-3RRK33YM.js.map
@@ -8,13 +8,14 @@ import {
8
8
  } from "./chunk-ZKC5UNGD.js";
9
9
  import {
10
10
  resolveWin32Command
11
- } from "./chunk-5U5ULQX2.js";
11
+ } from "./chunk-XZLVJD56.js";
12
12
 
13
13
  // src/codebase-index/py-parser.ts
14
14
  import { spawn } from "node:child_process";
15
15
  import * as fs from "node:fs/promises";
16
16
  import * as os from "node:os";
17
17
  import * as path from "node:path";
18
+ import { StringDecoder } from "node:string_decoder";
18
19
  async function parseSymbols(opts) {
19
20
  const { file, content, lang } = opts;
20
21
  try {
@@ -320,8 +321,9 @@ function spawnPyParser(pyBinary, scriptPath, filePath, content) {
320
321
  proc.stdin?.write(content);
321
322
  proc.stdin?.end();
322
323
  let stdout = "";
324
+ const stdoutDecoder = new StringDecoder("utf8");
323
325
  proc.stdout?.on("data", (chunk) => {
324
- stdout += chunk.toString();
326
+ stdout += stdoutDecoder.write(chunk);
325
327
  });
326
328
  proc.stderr?.resume();
327
329
  const timer = setTimeout(() => {
@@ -335,6 +337,7 @@ function spawnPyParser(pyBinary, scriptPath, filePath, content) {
335
337
  if (settled) return;
336
338
  settled = true;
337
339
  clearTimeout(timer);
340
+ stdout += stdoutDecoder.end();
338
341
  resolve({ code, stdout });
339
342
  });
340
343
  });
@@ -384,4 +387,4 @@ export {
384
387
  parseSymbols,
385
388
  resolvePythonBinary
386
389
  };
387
- //# sourceMappingURL=chunk-M2W36JT7.js.map
390
+ //# sourceMappingURL=chunk-4CE3RKEP.js.map
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  tryLegacyCodeOperation
3
- } from "./chunk-3LQJXJDM.js";
3
+ } from "./chunk-E7A4SLKR.js";
4
4
  import {
5
5
  spawnStream
6
- } from "./chunk-EMA2XENR.js";
6
+ } from "./chunk-UVYRQKPZ.js";
7
7
  import {
8
8
  ensureInsideRoot,
9
9
  normalizeCommandOutput,
@@ -101,6 +101,11 @@ var formatTool = {
101
101
  });
102
102
  if (bridge?.run) {
103
103
  const run = bridge.run;
104
+ if (run.status === "unavailable" || run.status === "cancelled" || run.status === "timed_out") {
105
+ throw new Error(
106
+ `format: ${bridge.language} formatter did not run (${run.status})${run.error ? `: ${run.error}` : ""}`
107
+ );
108
+ }
104
109
  yield {
105
110
  type: "final",
106
111
  output: {
@@ -172,6 +177,9 @@ var formatTool = {
172
177
  signal,
173
178
  maxBytes: 1e5
174
179
  });
180
+ if (result.error) {
181
+ throw new Error(`format: could not run ${detected}: ${result.error}`);
182
+ }
175
183
  const combinedOut = `${result.stdout}
176
184
  ${result.stderr}`;
177
185
  const counts = parseFormatterCounts(detected, combinedOut, !!input.check);
@@ -251,4 +259,4 @@ export {
251
259
  parseFormatterCounts,
252
260
  detectFixer
253
261
  };
254
- //# sourceMappingURL=chunk-QJARSK2G.js.map
262
+ //# sourceMappingURL=chunk-4SUGLJLO.js.map
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  tryLegacyCodeOperation
3
- } from "./chunk-3LQJXJDM.js";
3
+ } from "./chunk-E7A4SLKR.js";
4
4
  import {
5
5
  spawnStream
6
- } from "./chunk-EMA2XENR.js";
6
+ } from "./chunk-UVYRQKPZ.js";
7
7
  import {
8
8
  detectPackageManager,
9
9
  normalizeCommandOutput,
@@ -73,6 +73,11 @@ var typecheckTool = {
73
73
  });
74
74
  if (bridge?.run) {
75
75
  const run = bridge.run;
76
+ if (run.status === "unavailable") {
77
+ throw new Error(
78
+ `typecheck: ${bridge.language} checker unavailable: ${run.error || run.output || "no detail"}`
79
+ );
80
+ }
76
81
  yield {
77
82
  type: "final",
78
83
  output: {
@@ -118,14 +123,17 @@ var typecheckTool = {
118
123
  signal,
119
124
  maxBytes: 2e5
120
125
  });
121
- const combined = [result.stdout, result.stderr, result.error].filter(Boolean).join("\n");
122
- let errors = [...combined.matchAll(/^.*\berror TS\d+:/gmi)].length;
123
- const warnings = [...combined.matchAll(/^.*\bwarning TS\d+:/gmi)].length;
126
+ if (result.error) {
127
+ throw new Error(`typecheck: failed to start ${cmd}: ${result.error}`);
128
+ }
129
+ const combined = [result.stdout, result.stderr].filter(Boolean).join("\n");
130
+ let errors = [...combined.matchAll(/^.*\berror TS\d+:/gim)].length;
131
+ const warnings = [...combined.matchAll(/^.*\bwarning TS\d+:/gim)].length;
124
132
  if (errors === 0 && result.exitCode !== 0) {
125
133
  errors = 1;
126
134
  }
127
135
  const rawOutput = result.stdout && result.stderr ? `${result.stdout}
128
- ${result.stderr}` : result.stdout || result.stderr || result.error || "";
136
+ ${result.stderr}` : result.stdout || result.stderr || "";
129
137
  yield {
130
138
  type: "final",
131
139
  output: {
@@ -162,4 +170,4 @@ async function findTsConfig(cwd) {
162
170
  export {
163
171
  typecheckTool
164
172
  };
165
- //# sourceMappingURL=chunk-AH7J5HWL.js.map
173
+ //# sourceMappingURL=chunk-5RBUYFRV.js.map
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-MSOAX3GC.js";
4
4
  import {
5
5
  enqueueReindex
6
- } from "./chunk-TU6UVATU.js";
6
+ } from "./chunk-HYHE4VNA.js";
7
7
  import {
8
8
  safeResolveReal,
9
9
  sha256hex,
@@ -518,4 +518,4 @@ Compare this against your old_string and retry with the file's actual text.` : "
518
518
  export {
519
519
  editTool
520
520
  };
521
- //# sourceMappingURL=chunk-WKLUOXR4.js.map
521
+ //# sourceMappingURL=chunk-7GOE2ZTZ.js.map