@wrongstack/tools 1.0.8 → 1.0.10

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 (136) hide show
  1. package/dist/_win32-resolve.d.ts +5 -0
  2. package/dist/audit.js +5 -5
  3. package/dist/bash-kill-guard.d.ts +6 -4
  4. package/dist/bash.js +2 -2
  5. package/dist/browser/index.js +1 -1
  6. package/dist/builtin.js +41 -41
  7. package/dist/{chunk-N3OTTQNC.js → chunk-2OCAAFAT.js} +44 -25
  8. package/dist/{chunk-5MP76C72.js → chunk-2UVAIS5O.js} +24 -29
  9. package/dist/{chunk-SIIOHBNY.js → chunk-3RRK33YM.js} +2 -2
  10. package/dist/{chunk-M2W36JT7.js → chunk-4CE3RKEP.js} +6 -3
  11. package/dist/{chunk-QJARSK2G.js → chunk-4SUGLJLO.js} +11 -3
  12. package/dist/{chunk-AH7J5HWL.js → chunk-5RBUYFRV.js} +15 -7
  13. package/dist/{chunk-GNLHBDFO.js → chunk-6I6RXQFG.js} +127 -196
  14. package/dist/{chunk-WKLUOXR4.js → chunk-7GOE2ZTZ.js} +2 -2
  15. package/dist/{chunk-O6AGFJBO.js → chunk-7V33PHT6.js} +49 -77
  16. package/dist/{chunk-CAF4L6KN.js → chunk-C3WP6ZOT.js} +36 -48
  17. package/dist/{chunk-KMXPP32M.js → chunk-C6ZOXNXV.js} +13 -3
  18. package/dist/{chunk-EGT5QLCB.js → chunk-D6RQZMZS.js} +123 -255
  19. package/dist/{chunk-S6CGSFLX.js → chunk-DBG7UQGK.js} +10 -3
  20. package/dist/{chunk-FI6SOIVE.js → chunk-DLZCOEVG.js} +21 -3
  21. package/dist/{chunk-NL45OWEO.js → chunk-DOAHONOS.js} +7 -12
  22. package/dist/{chunk-3LQJXJDM.js → chunk-E7A4SLKR.js} +2 -2
  23. package/dist/{chunk-JB5JLY7V.js → chunk-ENE22I5W.js} +387 -394
  24. package/dist/{chunk-5KRKL3WD.js → chunk-FCSUBTUJ.js} +112 -119
  25. package/dist/{chunk-YUK3WLHJ.js → chunk-FVSMTEO3.js} +2 -2
  26. package/dist/{chunk-SEONDNLN.js → chunk-G7CYW5EP.js} +2 -2
  27. package/dist/{chunk-TU6UVATU.js → chunk-HYHE4VNA.js} +3 -3
  28. package/dist/{chunk-HIRVCXLP.js → chunk-IE4KDAOB.js} +3 -3
  29. package/dist/{chunk-YA2ZYCJY.js → chunk-JPK2HHBK.js} +1 -1
  30. package/dist/{chunk-7E55DAFW.js → chunk-KHUCKLOR.js} +12 -7
  31. package/dist/{chunk-R3HIZVFS.js → chunk-KPDCKSN5.js} +23 -3
  32. package/dist/{chunk-B3MGJBFI.js → chunk-KS2OEZWV.js} +23 -47
  33. package/dist/{chunk-UI3ZJIG3.js → chunk-LKLIQUCW.js} +14 -8
  34. package/dist/{chunk-62OAECEQ.js → chunk-LLSFOUZF.js} +8 -8
  35. package/dist/{chunk-YZQSUL5G.js → chunk-M4ZHHCCW.js} +14 -6
  36. package/dist/{chunk-IXIS7RSG.js → chunk-MRXWOOOR.js} +29 -47
  37. package/dist/{chunk-C4DSQBTT.js → chunk-NEYUPZL6.js} +3 -3
  38. package/dist/{chunk-6XYFYLN7.js → chunk-O2MHULBO.js} +13 -8
  39. package/dist/{chunk-B62LKMWQ.js → chunk-OKZJJDOG.js} +86 -188
  40. package/dist/{chunk-HOFVYIPI.js → chunk-ON6ET5ER.js} +16 -1
  41. package/dist/{chunk-KF7GMVNU.js → chunk-OUERRFEM.js} +32 -11
  42. package/dist/{chunk-GF4JHLCO.js → chunk-PWZUHZP7.js} +2 -2
  43. package/dist/{chunk-OGQMPX3J.js → chunk-QAWI3RSK.js} +37 -81
  44. package/dist/{chunk-ZMCV3XOV.js → chunk-SPNXDTCJ.js} +29 -63
  45. package/dist/{chunk-H2VB7GCR.js → chunk-ULI2J6TX.js} +27 -14
  46. package/dist/{chunk-EMA2XENR.js → chunk-UVYRQKPZ.js} +4 -3
  47. package/dist/{chunk-MF6ZUBI7.js → chunk-V25Q6TQ7.js} +3 -3
  48. package/dist/{chunk-2NTHMZV3.js → chunk-VMJY6FYJ.js} +693 -276
  49. package/dist/{chunk-ZOUG3KKS.js → chunk-XPVYZ2S6.js} +2 -2
  50. package/dist/{chunk-5U5ULQX2.js → chunk-XZLVJD56.js} +5 -1
  51. package/dist/{chunk-HCPSVK7J.js → chunk-YKSOSI2N.js} +47 -31
  52. package/dist/codebase-index/codebase-ast-replace-tool.d.ts +5 -6
  53. package/dist/codebase-index/codebase-context-tool.d.ts +4 -6
  54. package/dist/codebase-index/codebase-impact-analysis-tool.d.ts +1 -2
  55. package/dist/codebase-index/codebase-incoming-calls-tool.d.ts +0 -2
  56. package/dist/codebase-index/codebase-index-tool.d.ts +0 -2
  57. package/dist/codebase-index/codebase-invariant-check-tool.d.ts +1 -2
  58. package/dist/codebase-index/codebase-outgoing-calls-tool.d.ts +0 -2
  59. package/dist/codebase-index/codebase-repo-map-tool.d.ts +1 -2
  60. package/dist/codebase-index/codebase-search-tool.d.ts +1 -1
  61. package/dist/codebase-index/codebase-targeted-test-tool.d.ts +1 -2
  62. package/dist/codebase-index/index.js +8 -8
  63. package/dist/codebase-index/parser-worker-script.js +3 -3
  64. package/dist/codebase-index/project-server.js +5 -5
  65. package/dist/codebase-index/worker.js +4 -4
  66. package/dist/design.js +1 -1
  67. package/dist/diff.js +1 -1
  68. package/dist/edit.js +7 -7
  69. package/dist/exec.d.ts +7 -7
  70. package/dist/exec.js +2 -2
  71. package/dist/format.js +5 -5
  72. package/dist/git.js +1 -1
  73. package/dist/glob.js +1 -1
  74. package/dist/{go-parser-VDPRQEGM.js → go-parser-Z4H6SR3R.js} +6 -3
  75. package/dist/grep.js +1 -1
  76. package/dist/index.js +45 -45
  77. package/dist/install.js +5 -5
  78. package/dist/json.d.ts +0 -1
  79. package/dist/json.js +1 -1
  80. package/dist/kanban-presence.d.ts +6 -0
  81. package/dist/kanban-serializer.d.ts +9 -1
  82. package/dist/kanban-split-task-handler.d.ts +1 -1
  83. package/dist/kanban-tool-results.d.ts +57 -2
  84. package/dist/kanban-tool-types.d.ts +16 -5
  85. package/dist/kanban.d.ts +14 -0
  86. package/dist/kanban.js +9 -1
  87. package/dist/languages/index.js +3 -3
  88. package/dist/{legacy-bridge-4T4OTSQP.js → legacy-bridge-BPT2S2F4.js} +5 -5
  89. package/dist/lint.js +5 -5
  90. package/dist/logs.js +1 -1
  91. package/dist/mode.d.ts +3 -2
  92. package/dist/mode.js +1 -1
  93. package/dist/outdated.js +2 -2
  94. package/dist/pack.js +42 -42
  95. package/dist/{parser-dispatch-4E2SDQUO.js → parser-dispatch-WG4DNBHH.js} +4 -4
  96. package/dist/patch.js +7 -7
  97. package/dist/plan.d.ts +2 -1
  98. package/dist/plan.js +3 -3
  99. package/dist/{py-parser-MAW6DHFE.js → py-parser-4PFZYAJ7.js} +3 -3
  100. package/dist/read.js +7 -7
  101. package/dist/replace.js +7 -7
  102. package/dist/search.d.ts +0 -6
  103. package/dist/search.js +1 -1
  104. package/dist/security-ast-scan-tool.d.ts +1 -2
  105. package/dist/session-shell.js +2 -2
  106. package/dist/task.d.ts +2 -1
  107. package/dist/task.js +3 -3
  108. package/dist/test.d.ts +8 -1
  109. package/dist/test.js +5 -5
  110. package/dist/todo.js +2 -2
  111. package/dist/tool-search.d.ts +2 -0
  112. package/dist/tool-search.js +1 -1
  113. package/dist/tool-tier.js +43 -43
  114. package/dist/tool-use.d.ts +2 -2
  115. package/dist/tool-use.js +1 -1
  116. package/dist/tree.js +1 -1
  117. package/dist/typecheck.js +5 -5
  118. package/dist/wasm/bash/tree-sitter-bash.wasm +0 -0
  119. package/dist/wasm/c/tree-sitter-c.wasm +0 -0
  120. package/dist/wasm/c_sharp/tree-sitter-c_sharp.wasm +0 -0
  121. package/dist/wasm/checksums.json +16 -0
  122. package/dist/wasm/cpp/tree-sitter-cpp.wasm +0 -0
  123. package/dist/wasm/elixir/tree-sitter-elixir.wasm +0 -0
  124. package/dist/wasm/go/tree-sitter-go.wasm +0 -0
  125. package/dist/wasm/java/tree-sitter-java.wasm +0 -0
  126. package/dist/wasm/kotlin/tree-sitter-kotlin.wasm +0 -0
  127. package/dist/wasm/php/tree-sitter-php.wasm +0 -0
  128. package/dist/wasm/python/tree-sitter-python.wasm +0 -0
  129. package/dist/wasm/ruby/tree-sitter-ruby.wasm +0 -0
  130. package/dist/wasm/rust/tree-sitter-rust.wasm +0 -0
  131. package/dist/wasm/swift/tree-sitter-swift.wasm +0 -0
  132. package/dist/wasm/tree-sitter-runtime.wasm +0 -0
  133. package/dist/win32.d.ts +1 -1
  134. package/dist/win32.js +3 -1
  135. package/dist/write.js +7 -7
  136. package/package.json +10 -10
@@ -8,7 +8,8 @@ import {
8
8
 
9
9
  // src/json.ts
10
10
  import * as fs from "node:fs/promises";
11
- import { deepMerge as deepMergeCore } from "@wrongstack/core/utils";
11
+ import { deepMerge as deepMergeCore, toErrorMessage } from "@wrongstack/core/utils";
12
+ import { ToolValidationError } from "@wrongstack/core/types";
12
13
  var MAX_JSON_FILE_BYTES = 16 * 1024 * 1024;
13
14
  var MAX_JSON_FILE_BYTES_HUMAN = "16 MiB";
14
15
  var JsonFileTooLargeError = class extends Error {
@@ -39,8 +40,8 @@ async function readJsonFileBounded(filePath, ctx) {
39
40
  var jsonTool = {
40
41
  name: "json",
41
42
  category: "Data",
42
- description: "Parse, pretty-print, query, validate, transform, and merge JSON/JSON5/YAML (read-only \u2014 does not write files). Use `action` to select the operation: parse (default), query, validate, transform, or merge.",
43
- usageHint: 'VERY USEFUL FOR DATA INSPECTION:\n\n- `action: "parse"` (default): read/pretty-print/convert JSON, JSON5, or YAML from `file` or `data`.\n- `action: "query"`: JMESPath-like query (`a.b[0].c`, `items[*].name`, filters, functions).\n- `action: "validate"`: validate data against a JSON Schema (`schema` param).\n- `action: "transform"`: chain multiple JMESPath transforms (`transforms` param).\n- `action: "merge"`: deep merge `base` and `patch` objects (`conflictResolution` param).\nPrefer this over raw `read` + manual parsing when dealing with configuration or data files.',
43
+ description: "Parse, pretty-print, query, validate, transform, and merge JSON (read-only \u2014 does not write files). Input must be strict JSON; results can be rendered as JSON, JSON5-style, or YAML via `format`. Use `action` to select the operation: parse (default), query, validate, transform, or merge.",
44
+ usageHint: 'VERY USEFUL FOR DATA INSPECTION:\n\n- `action: "parse"` (default): read/pretty-print JSON from `file` or `data` (output as JSON, JSON5-style, or YAML via `format`).\n- `action: "query"`: JMESPath-like query (`a.b[0].c`, `items[*].name`, filters, functions).\n- `action: "validate"`: validate data against a JSON Schema (`schema` param).\n- `action: "transform"`: chain multiple JMESPath transforms (`transforms` param).\n- `action: "merge"`: deep merge `base` and `patch` objects (`conflictResolution` param).\nPrefer this over raw `read` + manual parsing when dealing with configuration or data files.',
44
45
  permission: "auto",
45
46
  mutating: false,
46
47
  maxOutputBytes: 262144,
@@ -55,10 +56,10 @@ var jsonTool = {
55
56
  enum: ["parse", "query", "validate", "transform", "merge"],
56
57
  description: "Operation (default: parse). parse=read/pretty-print, query=JMESPath, validate=schema, transform=chained queries, merge=deep merge."
57
58
  },
58
- file: { type: "string", description: "Path to JSON/JSON5/YAML file (parse/query/validate)" },
59
+ file: { type: "string", description: "Path to a JSON file (parse/query/validate/transform)" },
59
60
  data: {
60
61
  type: "string",
61
- description: "JSON/JSON5/YAML string (parse/query/validate, alternative to file)"
62
+ description: "JSON string (parse/query/validate/transform, alternative to file)"
62
63
  },
63
64
  format: {
64
65
  type: "string",
@@ -103,13 +104,10 @@ var jsonTool = {
103
104
  "merge"
104
105
  ]);
105
106
  if (input.action !== void 0 && !ALLOWED_ACTIONS.has(input.action)) {
106
- return {
107
- data: null,
108
- formatted: "",
109
- type: "unknown",
110
- action: String(input.action),
111
- error: `Unknown action "${input.action}". Allowed actions: parse, query, validate, transform, merge`
112
- };
107
+ throw new ToolValidationError({
108
+ message: `json: unknown action "${input.action}". Allowed actions: parse, query, validate, transform, merge`,
109
+ field: "action"
110
+ });
113
111
  }
114
112
  switch (action) {
115
113
  case "query":
@@ -125,54 +123,61 @@ var jsonTool = {
125
123
  }
126
124
  }
127
125
  };
126
+ async function readSource(input, ctx, action) {
127
+ if (input.file) {
128
+ try {
129
+ return await readJsonFileBounded(input.file, ctx);
130
+ } catch (error) {
131
+ if (error instanceof JsonFileTooLargeError || error instanceof JsonFileIsDirectoryError) {
132
+ throw error;
133
+ }
134
+ throw new Error(`json: could not read file "${input.file}": ${toErrorMessage(error)}`, {
135
+ cause: error
136
+ });
137
+ }
138
+ }
139
+ if (input.data) return input.data;
140
+ throw new ToolValidationError({
141
+ message: `json: provide \`file\` or \`data\` for action: ${action}`,
142
+ field: "file"
143
+ });
144
+ }
145
+ function parseSource(raw, input) {
146
+ try {
147
+ return JSON.parse(raw);
148
+ } catch (error) {
149
+ const message = `json: parse failed${input.file ? ` for "${input.file}"` : ""}: ${toErrorMessage(error)}`;
150
+ if (input.file) throw new Error(message, { cause: error });
151
+ throw new ToolValidationError({ message, field: "data", cause: error });
152
+ }
153
+ }
128
154
  async function executeParse(input, ctx) {
129
155
  const format = input.format ?? "json";
130
- let parsed;
131
- let raw;
132
- if (input.file) {
156
+ const raw = await readSource(input, ctx, "parse");
157
+ if (input.validate) {
158
+ let checked;
133
159
  try {
134
- raw = await readJsonFileBounded(input.file, ctx);
160
+ checked = JSON.parse(raw);
135
161
  } catch (error) {
136
162
  return {
137
163
  data: null,
138
- formatted: "",
164
+ formatted: "invalid",
139
165
  type: "unknown",
140
166
  action: "parse",
141
- error: error instanceof JsonFileTooLargeError || error instanceof JsonFileIsDirectoryError ? error.message : "Could not read file"
167
+ valid: false,
168
+ errors: [`Parse failed: ${toErrorMessage(error)}`]
142
169
  };
143
170
  }
144
- } else if (input.data) {
145
- raw = input.data;
146
- } else {
147
171
  return {
148
- data: null,
149
- formatted: "",
150
- type: "unknown",
151
- action: "parse",
152
- error: "Provide file or data"
153
- };
154
- }
155
- try {
156
- parsed = JSON.parse(raw);
157
- } catch (e) {
158
- return {
159
- data: null,
160
- formatted: "",
161
- type: "unknown",
162
- action: "parse",
163
- /* v8 ignore next -- JSON.parse only throws SyntaxError (an Error); the String(e) side is defensive. */
164
- error: `Parse failed: ${e instanceof Error ? e.message : String(e)}`
165
- };
166
- }
167
- if (input.validate) {
168
- return {
169
- data: parsed,
172
+ data: checked,
170
173
  formatted: "valid",
171
- type: Array.isArray(parsed) ? "array" : typeof parsed,
174
+ type: Array.isArray(checked) ? "array" : typeof checked,
172
175
  action: "parse",
173
- keys: typeof parsed === "object" && parsed !== null ? Object.keys(parsed) : void 0
176
+ valid: true,
177
+ keys: typeof checked === "object" && checked !== null ? Object.keys(checked) : void 0
174
178
  };
175
179
  }
180
+ const parsed = parseSource(raw, input);
176
181
  if (input.query) {
177
182
  const queryResult = simpleQuery(parsed, input.query);
178
183
  const formatted2 = formatOutput(queryResult, format);
@@ -196,239 +201,102 @@ async function executeParse(input, ctx) {
196
201
  }
197
202
  async function executeQuery(input, ctx) {
198
203
  if (!input.query) {
199
- return {
200
- data: null,
201
- formatted: "",
202
- type: "unknown",
203
- action: "query",
204
- error: "query is required for action: query"
205
- };
206
- }
207
- let parsed;
208
- if (input.file) {
209
- try {
210
- const raw = await readJsonFileBounded(input.file, ctx);
211
- parsed = JSON.parse(raw);
212
- } catch (error) {
213
- return {
214
- data: null,
215
- formatted: "",
216
- type: "unknown",
217
- action: "query",
218
- error: error instanceof JsonFileTooLargeError || error instanceof JsonFileIsDirectoryError ? error.message : "Could not read/parse file"
219
- };
220
- }
221
- } else if (input.data) {
222
- try {
223
- parsed = JSON.parse(input.data);
224
- } catch {
225
- return {
226
- data: null,
227
- formatted: "",
228
- type: "unknown",
229
- action: "query",
230
- error: "Could not parse data string"
231
- };
232
- }
233
- } else {
234
- return {
235
- data: null,
236
- formatted: "",
237
- type: "unknown",
238
- action: "query",
239
- error: "Provide file or data"
240
- };
204
+ throw new ToolValidationError({
205
+ message: "json: query is required for action: query",
206
+ field: "query"
207
+ });
241
208
  }
209
+ const parsed = parseSource(await readSource(input, ctx, "query"), input);
210
+ let result;
242
211
  try {
243
- const result = jmespathSearch(parsed, input.query);
244
- const format = input.format ?? "json";
245
- return {
246
- data: parsed,
247
- formatted: formatOutput(result, format),
248
- type: result === null ? "null" : Array.isArray(result) ? "array" : typeof result,
249
- action: "query",
250
- query_result: result
251
- };
252
- } catch (e) {
253
- return {
254
- data: null,
255
- formatted: "",
256
- type: "unknown",
257
- action: "query",
258
- /* v8 ignore next -- defensive String(e) */
259
- error: `Query failed: ${e instanceof Error ? e.message : String(e)}`
260
- };
212
+ result = jmespathSearch(parsed, input.query);
213
+ } catch (error) {
214
+ throw new Error(`json: query failed: ${toErrorMessage(error)}`, { cause: error });
261
215
  }
216
+ const format = input.format ?? "json";
217
+ return {
218
+ data: parsed,
219
+ formatted: formatOutput(result, format),
220
+ type: result === null ? "null" : Array.isArray(result) ? "array" : typeof result,
221
+ action: "query",
222
+ query_result: result
223
+ };
262
224
  }
263
225
  async function executeValidate(input, ctx) {
264
226
  if (!input.schema) {
265
- return {
266
- data: null,
267
- formatted: "",
268
- type: "unknown",
269
- action: "validate",
270
- error: "schema is required for action: validate"
271
- };
272
- }
273
- let parsed;
274
- if (input.file) {
275
- try {
276
- const raw = await readJsonFileBounded(input.file, ctx);
277
- parsed = JSON.parse(raw);
278
- } catch (error) {
279
- return {
280
- data: null,
281
- formatted: "",
282
- type: "unknown",
283
- action: "validate",
284
- error: error instanceof JsonFileTooLargeError || error instanceof JsonFileIsDirectoryError ? error.message : "Could not read/parse file"
285
- };
286
- }
287
- } else if (input.data) {
288
- try {
289
- parsed = JSON.parse(input.data);
290
- } catch {
291
- return {
292
- data: null,
293
- formatted: "",
294
- type: "unknown",
295
- action: "validate",
296
- error: "Could not parse data string"
297
- };
298
- }
299
- } else {
300
- return {
301
- data: null,
302
- formatted: "",
303
- type: "unknown",
304
- action: "validate",
305
- error: "Provide file or data"
306
- };
227
+ throw new ToolValidationError({
228
+ message: "json: schema is required for action: validate",
229
+ field: "schema"
230
+ });
307
231
  }
232
+ const parsed = parseSource(await readSource(input, ctx, "validate"), input);
233
+ let outcome;
308
234
  try {
309
- const { valid, errors } = validateJsonSchema(parsed, input.schema);
310
- return {
311
- data: parsed,
312
- formatted: valid ? "valid" : "invalid",
313
- type: Array.isArray(parsed) ? "array" : typeof parsed,
314
- action: "validate",
315
- valid,
316
- errors
317
- };
318
- } catch (e) {
319
- return {
320
- data: null,
321
- formatted: "",
322
- type: "unknown",
323
- action: "validate",
324
- /* v8 ignore next -- defensive String(e) */
325
- error: `Validation failed: ${e instanceof Error ? e.message : String(e)}`
326
- };
235
+ outcome = validateJsonSchema(parsed, input.schema);
236
+ } catch (error) {
237
+ throw new Error(`json: schema validation failed to run: ${toErrorMessage(error)}`, {
238
+ cause: error
239
+ });
327
240
  }
241
+ return {
242
+ data: parsed,
243
+ formatted: outcome.valid ? "valid" : "invalid",
244
+ type: Array.isArray(parsed) ? "array" : typeof parsed,
245
+ action: "validate",
246
+ valid: outcome.valid,
247
+ errors: outcome.errors
248
+ };
328
249
  }
329
250
  async function executeTransform(input, ctx) {
330
251
  if (!input.transforms || input.transforms.length === 0) {
331
- return {
332
- data: null,
333
- formatted: "",
334
- type: "unknown",
335
- action: "transform",
336
- error: "transforms array is required for action: transform"
337
- };
252
+ throw new ToolValidationError({
253
+ message: "json: transforms array is required for action: transform",
254
+ field: "transforms"
255
+ });
338
256
  }
339
- let parsed;
340
- if (input.file) {
341
- try {
342
- const raw = await readJsonFileBounded(input.file, ctx);
343
- parsed = JSON.parse(raw);
344
- } catch (error) {
345
- return {
346
- data: null,
347
- formatted: "",
348
- type: "unknown",
349
- action: "transform",
350
- error: error instanceof JsonFileTooLargeError || error instanceof JsonFileIsDirectoryError ? error.message : "Could not read/parse file"
351
- };
352
- }
353
- } else if (input.data) {
257
+ const parsed = parseSource(await readSource(input, ctx, "transform"), input);
258
+ let current = parsed;
259
+ const steps = [];
260
+ for (const t of input.transforms) {
354
261
  try {
355
- parsed = JSON.parse(input.data);
356
- } catch {
357
- return {
358
- data: null,
359
- formatted: "",
360
- type: "unknown",
361
- action: "transform",
362
- error: "Could not parse data string"
363
- };
364
- }
365
- } else {
366
- return {
367
- data: null,
368
- formatted: "",
369
- type: "unknown",
370
- action: "transform",
371
- error: "Provide file or data"
372
- };
373
- }
374
- try {
375
- let current = parsed;
376
- const steps = [];
377
- for (const t of input.transforms) {
378
262
  current = jmespathSearch(current, t);
379
- steps.push({ transform: t, result: current });
263
+ } catch (error) {
264
+ throw new Error(`json: transform "${t}" failed: ${toErrorMessage(error)}`, { cause: error });
380
265
  }
381
- const format = input.format ?? "json";
382
- return {
383
- data: parsed,
384
- formatted: formatOutput(current, format),
385
- type: current === null ? "null" : Array.isArray(current) ? "array" : typeof current,
386
- action: "transform",
387
- result: current,
388
- steps
389
- };
390
- } catch (e) {
391
- return {
392
- data: null,
393
- formatted: "",
394
- type: "unknown",
395
- action: "transform",
396
- /* v8 ignore next -- defensive String(e) */
397
- error: `Transform failed: ${e instanceof Error ? e.message : String(e)}`
398
- };
266
+ steps.push({ transform: t, result: current });
399
267
  }
268
+ const format = input.format ?? "json";
269
+ return {
270
+ data: parsed,
271
+ formatted: formatOutput(current, format),
272
+ type: current === null ? "null" : Array.isArray(current) ? "array" : typeof current,
273
+ action: "transform",
274
+ result: current,
275
+ steps
276
+ };
400
277
  }
401
278
  async function executeMerge(input) {
402
279
  if (input.base === void 0 || input.patch === void 0) {
403
- return {
404
- data: null,
405
- formatted: "",
406
- type: "unknown",
407
- action: "merge",
408
- error: "base and patch are required for action: merge"
409
- };
280
+ throw new ToolValidationError({
281
+ message: "json: base and patch are required for action: merge",
282
+ field: input.base === void 0 ? "base" : "patch"
283
+ });
410
284
  }
411
285
  const conflictResolution = input.conflictResolution ?? "prefer-patch";
286
+ let result;
412
287
  try {
413
- const result = deepMergeCore(input.base, input.patch, { conflictResolution });
414
- const format = input.format ?? "json";
415
- return {
416
- data: result,
417
- formatted: formatOutput(result, format),
418
- type: result === null ? "null" : Array.isArray(result) ? "array" : typeof result,
419
- action: "merge",
420
- result
421
- };
422
- } catch (e) {
423
- return {
424
- data: null,
425
- formatted: "",
426
- type: "unknown",
427
- action: "merge",
428
- /* v8 ignore next -- defensive String(e) */
429
- error: `Merge failed: ${e instanceof Error ? e.message : String(e)}`
430
- };
288
+ result = deepMergeCore(input.base, input.patch, { conflictResolution });
289
+ } catch (error) {
290
+ throw new Error(`json: merge failed: ${toErrorMessage(error)}`, { cause: error });
431
291
  }
292
+ const format = input.format ?? "json";
293
+ return {
294
+ data: result,
295
+ formatted: formatOutput(result, format),
296
+ type: result === null ? "null" : Array.isArray(result) ? "array" : typeof result,
297
+ action: "merge",
298
+ result
299
+ };
432
300
  }
433
301
  function jmespathSearch(data, query) {
434
302
  if (!query || query === "@") return data;
@@ -704,4 +572,4 @@ ${toYaml(v, indent + 1)}`;
704
572
  export {
705
573
  jsonTool
706
574
  };
707
- //# sourceMappingURL=chunk-EGT5QLCB.js.map
575
+ //# sourceMappingURL=chunk-D6RQZMZS.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  kanbanTool
3
- } from "./chunk-2NTHMZV3.js";
3
+ } from "./chunk-VMJY6FYJ.js";
4
4
  import {
5
5
  applyManagedKanbanBoardToTodos,
6
6
  blockingTitles,
@@ -118,7 +118,14 @@ async function synchronizeManagedKanban(items, board, ctx, signal) {
118
118
  const warnings = [];
119
119
  const actor = ctx.agentId?.trim() || ctx.agentName?.trim() || "kanban-agent";
120
120
  const execute = async (input) => {
121
- const result = await kanbanTool.execute(input, ctx, { signal });
121
+ let result;
122
+ try {
123
+ result = await kanbanTool.execute(input, ctx, { signal });
124
+ } catch (err) {
125
+ const message = err instanceof Error ? err.message : String(err);
126
+ warnings.push(message);
127
+ return { ok: false, message };
128
+ }
122
129
  if (!result.ok) warnings.push(result.message);
123
130
  else {
124
131
  synced++;
@@ -487,4 +494,4 @@ var todoTool = {
487
494
  export {
488
495
  todoTool
489
496
  };
490
- //# sourceMappingURL=chunk-S6CGSFLX.js.map
497
+ //# sourceMappingURL=chunk-DBG7UQGK.js.map
@@ -107,6 +107,12 @@ var grepTool = {
107
107
  });
108
108
  }
109
109
  const base = input.path ? await safeResolveReal(input.path, ctx) : ctx.cwd;
110
+ if (input.path && !await fs.stat(base).catch(() => null)) {
111
+ throw new ToolValidationError({
112
+ message: `grep: path "${input.path}" does not exist`,
113
+ field: "path"
114
+ });
115
+ }
110
116
  const ignoreRoot = await fs.realpath(ctx.projectRoot ?? ctx.cwd).catch(() => path.resolve(ctx.projectRoot ?? ctx.cwd));
111
117
  const ignoreTarget = await fs.realpath(base).catch(() => path.resolve(base));
112
118
  const mode = input.output_mode ?? "content";
@@ -228,6 +234,7 @@ async function* runRgStream(input, base, mode, limit, signal, relativize) {
228
234
  windowsHide: true
229
235
  });
230
236
  const queue = [];
237
+ const stdoutDecoder = new StringDecoder("utf8");
231
238
  let queuedChars = 0;
232
239
  let waiter;
233
240
  let paused = false;
@@ -249,7 +256,8 @@ async function* runRgStream(input, base, mode, limit, signal, relativize) {
249
256
  child.stdout?.resume();
250
257
  };
251
258
  const onStdoutData = (c) => {
252
- const data = c.toString();
259
+ const data = stdoutDecoder.write(c);
260
+ if (data.length === 0) return;
253
261
  queue.push({ kind: "out", data });
254
262
  queuedChars += data.length;
255
263
  wake();
@@ -259,7 +267,14 @@ async function* runRgStream(input, base, mode, limit, signal, relativize) {
259
267
  queue.push({ kind: "error", data: e.message });
260
268
  wake();
261
269
  };
262
- const onClose = () => {
270
+ let rgExitCode = null;
271
+ const onClose = (code) => {
272
+ rgExitCode = code;
273
+ const tail = stdoutDecoder.end();
274
+ if (tail.length > 0) {
275
+ queue.push({ kind: "out", data: tail });
276
+ queuedChars += tail.length;
277
+ }
263
278
  queue.push({ kind: "close", data: "" });
264
279
  wake();
265
280
  };
@@ -341,6 +356,9 @@ async function* runRgStream(input, base, mode, limit, signal, relativize) {
341
356
  };
342
357
  }
343
358
  if (errored) throw new Error("rg: spawn error");
359
+ if (rgExitCode === 2 && totalLines === 0 && !bufOverflow) {
360
+ throw new Error("rg: exited with an error and produced no matches");
361
+ }
344
362
  yield {
345
363
  type: "final",
346
364
  output: {
@@ -550,4 +568,4 @@ export {
550
568
  __resetRgDetectionForTests,
551
569
  __setRgAvailableForTests
552
570
  };
553
- //# sourceMappingURL=chunk-FI6SOIVE.js.map
571
+ //# sourceMappingURL=chunk-DLZCOEVG.js.map
@@ -4,8 +4,9 @@ import {
4
4
  } from "./chunk-HDYUBRMF.js";
5
5
  import {
6
6
  buildWin32CmdShimInvocation,
7
+ isWinCmdShim,
7
8
  resolveWin32Command
8
- } from "./chunk-5U5ULQX2.js";
9
+ } from "./chunk-XZLVJD56.js";
9
10
  import {
10
11
  COMMAND_OUTPUT_MAX_BYTES,
11
12
  detectPackageManager,
@@ -66,7 +67,7 @@ var outdatedTool = {
66
67
  const manager = await detectPackageManager(cwd, ctx.projectRoot);
67
68
  if (manager === "npm") {
68
69
  try {
69
- const { detectNonJsEcosystem } = await import("./legacy-bridge-4T4OTSQP.js");
70
+ const { detectNonJsEcosystem } = await import("./legacy-bridge-BPT2S2F4.js");
70
71
  const nonJs = await detectNonJsEcosystem(cwd, ctx.projectRoot);
71
72
  if (nonJs) {
72
73
  const { planLanguageOperation, executePackagePlan } = await import("./languages/index.js");
@@ -129,7 +130,7 @@ function runOutdated(manager, args, cwd, signal) {
129
130
  truncated: false
130
131
  });
131
132
  }
132
- return new Promise((resolve) => {
133
+ return new Promise((resolve, reject) => {
133
134
  let stdout = "";
134
135
  let stderr = "";
135
136
  let stdoutBytes = 0;
@@ -138,7 +139,7 @@ function runOutdated(manager, args, cwd, signal) {
138
139
  const stdoutDecoder = new StringDecoder("utf8");
139
140
  const stderrDecoder = new StringDecoder("utf8");
140
141
  const resolved = resolveWin32Command(manager);
141
- const needsShell = process.platform === "win32" && (resolved.endsWith(".cmd") || resolved.endsWith(".bat"));
142
+ const needsShell = process.platform === "win32" && isWinCmdShim(resolved);
142
143
  const shim = needsShell ? buildWin32CmdShimInvocation(resolved, args) : null;
143
144
  const spawnCmd = shim?.command ?? resolved;
144
145
  const spawnArgs = shim?.args ?? args;
@@ -222,13 +223,7 @@ function runOutdated(manager, args, cwd, signal) {
222
223
  });
223
224
  return;
224
225
  }
225
- resolve({
226
- exit_code: 1,
227
- packages: [],
228
- total: 0,
229
- output: e.message,
230
- truncated: false
231
- });
226
+ reject(new Error(`outdated: failed to run ${manager}: ${e.message}`, { cause: e }));
232
227
  });
233
228
  });
234
229
  }
@@ -282,4 +277,4 @@ Note: exit code 1 from \`outdated\` means outdated packages were found (expected
282
277
  export {
283
278
  outdatedTool
284
279
  };
285
- //# sourceMappingURL=chunk-NL45OWEO.js.map
280
+ //# sourceMappingURL=chunk-DOAHONOS.js.map
@@ -2,7 +2,7 @@ import {
2
2
  executeLanguagePlan,
3
3
  executePackagePlan,
4
4
  planLanguageOperation
5
- } from "./chunk-SEONDNLN.js";
5
+ } from "./chunk-G7CYW5EP.js";
6
6
 
7
7
  // src/languages/legacy-bridge.ts
8
8
  import * as fs from "node:fs/promises";
@@ -104,4 +104,4 @@ export {
104
104
  tryLegacyCodeOperation,
105
105
  tryLegacyPackageOperation
106
106
  };
107
- //# sourceMappingURL=chunk-3LQJXJDM.js.map
107
+ //# sourceMappingURL=chunk-E7A4SLKR.js.map