@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
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  todoTool
3
- } from "./chunk-S6CGSFLX.js";
3
+ } from "./chunk-DBG7UQGK.js";
4
4
  import {
5
5
  projectSessionPlanToKanban
6
6
  } from "./chunk-YZECCW3F.js";
@@ -124,13 +124,9 @@ var planTool = {
124
124
  sessionPlanPath.lastIndexOf("\\")
125
125
  );
126
126
  if (lastSep < 0) {
127
- return {
128
- ok: false,
129
- message: `Cannot derive the project-scoped plan path: session plan path "${sessionPlanPath}" has no directory component.`,
130
- plan: "",
131
- count: 0,
132
- open: 0
133
- };
127
+ throw new Error(
128
+ `plan: cannot derive the project-scoped plan path: session plan path "${sessionPlanPath}" has no directory component.`
129
+ );
134
130
  }
135
131
  planPath = sessionPlanPath.slice(0, lastSep + 1) + "backlog.plan.json";
136
132
  }
@@ -138,13 +134,7 @@ var planTool = {
138
134
  planPath = sessionPlanPath;
139
135
  }
140
136
  if (typeof planPath !== "string" || !planPath) {
141
- return {
142
- ok: false,
143
- message: "Plan storage path is not configured for this session.",
144
- plan: "",
145
- count: 0,
146
- open: 0
147
- };
137
+ throw new Error("plan: Plan storage path is not configured for this session.");
148
138
  }
149
139
  const sessionId = ctx.session?.id ?? "unknown";
150
140
  if (input.action === "show") {
@@ -155,9 +145,13 @@ var planTool = {
155
145
  updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
156
146
  items: []
157
147
  };
158
- return mkResult(plan2, true, "Plan show ok.");
148
+ return mkResult(plan2, "Plan show ok.");
159
149
  }
160
150
  let early = null;
151
+ let failure;
152
+ const refuse = (message, field) => {
153
+ failure = field ? new ToolValidationError({ message: `plan: ${message}`, field }) : new Error(`plan: ${message}`);
154
+ };
161
155
  const taskifyMeta = { title: "", details: "" };
162
156
  let didTaskify = false;
163
157
  let todosToReplace = null;
@@ -170,7 +164,7 @@ var planTool = {
170
164
  case "add": {
171
165
  const title = input.title?.trim();
172
166
  if (!title) {
173
- early = mkResult(p, false, "add requires `title`.");
167
+ refuse("add requires `title`.", "title");
174
168
  return p;
175
169
  }
176
170
  const { plan: updated } = addPlanItem(p, title, input.details?.trim() || void 0);
@@ -179,11 +173,7 @@ var planTool = {
179
173
  case "start":
180
174
  case "done": {
181
175
  if (!input.target) {
182
- early = mkResult(
183
- p,
184
- false,
185
- `${input.action} requires \`target\` (id|index|substring).`
186
- );
176
+ refuse(`${input.action} requires \`target\` (id|index|substring).`, "target");
187
177
  return p;
188
178
  }
189
179
  const next = setPlanItemStatus(
@@ -192,52 +182,52 @@ var planTool = {
192
182
  input.action === "start" ? "in_progress" : "done"
193
183
  );
194
184
  if (next === p) {
195
- early = mkResult(p, false, `No plan item matched "${input.target}".`);
185
+ refuse(`No plan item matched "${input.target}".`, "target");
196
186
  return p;
197
187
  }
198
188
  return next;
199
189
  }
200
190
  case "status": {
201
- const VALID_PLAN_STATUSES = /* @__PURE__ */ new Set(["open", "in_progress", "done"]);
191
+ const VALID_PLAN_STATUSES = /* @__PURE__ */ new Set([
192
+ "open",
193
+ "in_progress",
194
+ "done"
195
+ ]);
202
196
  if (!input.target || !input.status) {
203
- early = mkResult(
204
- p,
205
- false,
206
- "status requires `target` (id|index|substring) and `status`."
197
+ refuse(
198
+ "status requires `target` (id|index|substring) and `status`.",
199
+ input.target ? "status" : "target"
207
200
  );
208
201
  return p;
209
202
  }
210
203
  if (!VALID_PLAN_STATUSES.has(input.status)) {
211
- early = mkResult(
212
- p,
213
- false,
214
- `status requires valid status ('open' | 'in_progress' | 'done'), got "${input.status}".`
204
+ refuse(
205
+ `status requires valid status ('open' | 'in_progress' | 'done'), got "${input.status}".`,
206
+ "status"
215
207
  );
216
208
  return p;
217
209
  }
218
210
  const next = setPlanItemStatus(p, input.target, input.status);
219
211
  if (next === p) {
220
- early = mkResult(p, false, `No plan item matched "${input.target}".`);
212
+ refuse(`No plan item matched "${input.target}".`, "target");
221
213
  return p;
222
214
  }
223
215
  return next;
224
216
  }
225
217
  case "remove": {
226
218
  if (!input.target) {
227
- early = mkResult(p, false, "remove requires `target` (id|index|substring).");
219
+ refuse("remove requires `target` (id|index|substring).", "target");
228
220
  return p;
229
221
  }
230
222
  const next = removePlanItem(p, input.target);
231
223
  if (next === p) {
232
- early = mkResult(p, false, `No plan item matched "${input.target}".`);
224
+ refuse(`No plan item matched "${input.target}".`, "target");
233
225
  return p;
234
226
  }
235
227
  const nextIds = new Set(next.items.map((item) => item.id));
236
228
  const removed = p.items.find((item) => !nextIds.has(item.id));
237
229
  if (removed?.status !== "done") {
238
- early = mkResult(
239
- p,
240
- false,
230
+ refuse(
241
231
  `Plan item "${removed?.title ?? input.target}" is not done and cannot be removed. Complete it first.`
242
232
  );
243
233
  return p;
@@ -246,22 +236,17 @@ var planTool = {
246
236
  }
247
237
  case "promote": {
248
238
  if (!input.target) {
249
- early = mkResult(
250
- p,
251
- false,
252
- `${input.action} requires \`target\` (id|index|substring).`
253
- );
239
+ refuse(`${input.action} requires \`target\` (id|index|substring).`, "target");
254
240
  return p;
255
241
  }
256
242
  const derived = deriveTodosFromPlanItem(p, input.target, input.subtasks);
257
243
  if (!derived) {
258
- early = mkResult(p, false, `No plan item matched "${input.target}".`);
244
+ refuse(`No plan item matched "${input.target}".`, "target");
259
245
  return p;
260
246
  }
261
247
  todosToReplace = derived.todos;
262
248
  early = mkResult(
263
249
  derived.plan,
264
- true,
265
250
  `${input.action} ok \u2014 ${derived.todos.length} todo(s) created.`,
266
251
  derived.todos
267
252
  );
@@ -270,12 +255,12 @@ var planTool = {
270
255
  case "template_use": {
271
256
  const templateName = input.template?.trim();
272
257
  if (!templateName) {
273
- early = mkResult(p, false, "template_use requires `template` name.");
258
+ refuse("template_use requires `template` name.", "template");
274
259
  return p;
275
260
  }
276
261
  const template = getPlanTemplate(templateName);
277
262
  if (!template) {
278
- early = mkResult(p, false, `Unknown template "${templateName}".`);
263
+ refuse(`Unknown template "${templateName}".`, "template");
279
264
  return p;
280
265
  }
281
266
  let updated = p;
@@ -284,28 +269,19 @@ var planTool = {
284
269
  }
285
270
  early = mkResult(
286
271
  updated,
287
- true,
288
272
  `Applied template "${template.name}" \u2014 ${template.items.length} items added.`
289
273
  );
290
274
  return updated;
291
275
  }
292
276
  case "clear":
293
277
  if (p.items.some((item) => item.status !== "done")) {
294
- early = mkResult(
295
- p,
296
- false,
297
- "Plan contains unfinished items and cannot be cleared. Complete them first."
298
- );
278
+ refuse("Plan contains unfinished items and cannot be cleared. Complete them first.");
299
279
  return p;
300
280
  }
301
281
  return clearPlan(p);
302
282
  case "taskify": {
303
283
  if (!input.target) {
304
- early = mkResult(
305
- p,
306
- false,
307
- "taskify requires `target` (plan item id|index|substring)."
308
- );
284
+ refuse("taskify requires `target` (plan item id|index|substring).", "target");
309
285
  return p;
310
286
  }
311
287
  let itemIdx = p.items.findIndex((it) => it.id === input.target);
@@ -320,7 +296,7 @@ var planTool = {
320
296
  itemIdx = p.items.findIndex((it) => it.title.toLowerCase().includes(lower));
321
297
  }
322
298
  if (itemIdx === -1 || !p.items[itemIdx]) {
323
- early = mkResult(p, false, `No plan item matched "${input.target}".`);
299
+ refuse(`No plan item matched "${input.target}".`, "target");
324
300
  return p;
325
301
  }
326
302
  const item = p.items[itemIdx];
@@ -330,20 +306,18 @@ var planTool = {
330
306
  break;
331
307
  }
332
308
  default:
333
- early = mkResult(p, false, `Unknown action "${input.action}".`);
309
+ refuse(`Unknown action "${input.action}".`, "action");
334
310
  return p;
335
311
  }
336
312
  return p;
337
313
  });
338
314
  } catch (err) {
339
- return {
340
- ok: false,
341
- message: `Plan change not saved \u2014 ${err instanceof Error ? err.message : String(err)}`,
342
- plan: "",
343
- count: 0,
344
- open: 0
345
- };
315
+ throw new Error(
316
+ `plan: change not saved \u2014 ${err instanceof Error ? err.message : String(err)}`,
317
+ { cause: err }
318
+ );
346
319
  }
320
+ if (failure) throw failure;
347
321
  ctx.meta["plan.path.resolved"] = planPath;
348
322
  await projectSessionPlanToKanban(ctx.projectRoot, plan.items, sessionId);
349
323
  if (todosToReplace) {
@@ -355,7 +329,7 @@ var planTool = {
355
329
  if (didTaskify) {
356
330
  const taskPathRaw = ctx.meta["task.path"];
357
331
  if (typeof taskPathRaw !== "string" || !taskPathRaw) {
358
- return mkResult(plan, false, "Task storage path not configured \u2014 cannot taskify.");
332
+ throw new Error("plan: Task storage path not configured \u2014 cannot taskify.");
359
333
  }
360
334
  let taskPath = taskPathRaw;
361
335
  if (input.scope === "project") {
@@ -380,28 +354,26 @@ var planTool = {
380
354
  ctx.meta["task.path.resolved"] = taskPath;
381
355
  return mkResult(
382
356
  plan,
383
- true,
384
357
  `taskify ok \u2014 added "${taskifyMeta.title}" to tasks.
385
358
  ${formatTaskList(taskFile.tasks)}`
386
359
  );
387
360
  } catch (err) {
388
- return mkResult(
389
- plan,
390
- false,
391
- `taskify: task not saved \u2014 ${err instanceof Error ? err.message : String(err)}`
361
+ throw new Error(
362
+ `plan: taskify: task not saved \u2014 ${err instanceof Error ? err.message : String(err)}`,
363
+ { cause: err }
392
364
  );
393
365
  }
394
366
  }
395
- return mkResult(plan, true, `Plan ${input.action} ok.`);
367
+ return mkResult(plan, `Plan ${input.action} ok.`);
396
368
  }
397
369
  };
398
- function mkResult(plan, ok, message, todos) {
370
+ function mkResult(plan, message, todos) {
399
371
  let open = 0;
400
372
  for (let i = 0; i < plan.items.length; i++) {
401
373
  if (plan.items[i].status !== "done") open++;
402
374
  }
403
375
  const result = {
404
- ok,
376
+ ok: true,
405
377
  message,
406
378
  plan: formatPlan(plan),
407
379
  count: plan.items.length,
@@ -414,4 +386,4 @@ function mkResult(plan, ok, message, todos) {
414
386
  export {
415
387
  planTool
416
388
  };
417
- //# sourceMappingURL=chunk-O6AGFJBO.js.map
389
+ //# sourceMappingURL=chunk-7V33PHT6.js.map
@@ -54,15 +54,7 @@ var logsTool = {
54
54
  async execute(input, ctx, opts) {
55
55
  const cwd = input.cwd ? await safeResolveReal(input.cwd, ctx) : ctx.cwd;
56
56
  const signal = opts?.signal ?? ctx.signal ?? new AbortController().signal;
57
- if (signal.aborted) {
58
- return {
59
- source: "none",
60
- entries: [],
61
- total: 0,
62
- truncated: false,
63
- stream_mode: false
64
- };
65
- }
57
+ signal.throwIfAborted();
66
58
  const VALID_SINCE = /* @__PURE__ */ new Set(["1h", "6h", "24h", "all"]);
67
59
  if (input.since !== void 0 && !VALID_SINCE.has(input.since)) {
68
60
  throw new ToolValidationError({
@@ -119,61 +111,42 @@ var logsTool = {
119
111
  }
120
112
  return await fileLogs(resolved, lines, filterRe);
121
113
  }
122
- return {
123
- source: "none",
124
- entries: [],
125
- total: 0,
126
- truncated: false,
127
- stream_mode: false
128
- };
114
+ throw new ToolValidationError({
115
+ message: "logs: provide `service` (Docker container) or `path` (log file)",
116
+ field: "path"
117
+ });
129
118
  }
130
119
  };
131
120
  async function dockerLogs(service, lines, filterRe, cwd, signal, since) {
121
+ if (!/^[a-zA-Z0-9][a-zA-Z0-9._:-]+$/.test(service)) {
122
+ throw new ToolValidationError({
123
+ message: `logs: invalid Docker container name "${service}"`,
124
+ field: "service"
125
+ });
126
+ }
132
127
  const args = ["logs"];
133
128
  if (lines > 0) args.push("--tail", String(lines));
134
129
  if (since && since !== "all") {
135
130
  const sinceMap = { "1h": "1h", "6h": "6h", "24h": "24h" };
136
131
  args.push("--since", sinceMap[since] ?? "1h");
137
132
  }
138
- if (!/^[a-zA-Z0-9][a-zA-Z0-9._:-]+$/.test(service)) {
139
- return {
140
- source: `docker:${service}`,
141
- entries: [],
142
- total: 0,
143
- truncated: false,
144
- stream_mode: false
145
- };
146
- }
147
133
  args.push("--timestamps", service);
148
- if (signal.aborted) {
149
- return Promise.resolve({
150
- source: `docker:${service}`,
151
- entries: [],
152
- total: 0,
153
- truncated: false,
154
- stream_mode: false
155
- });
156
- }
157
- return new Promise((resolve) => {
134
+ signal.throwIfAborted();
135
+ return new Promise((resolve, reject) => {
158
136
  let stdout = "";
159
137
  let stderr = "";
160
138
  const MAX = 2e5;
161
139
  const stdoutDecoder = new StringDecoder("utf8");
162
140
  const stderrDecoder = new StringDecoder("utf8");
163
141
  let settled = false;
164
- const empty = () => ({
165
- source: `docker:${service}`,
166
- entries: [],
167
- total: 0,
168
- truncated: false,
169
- stream_mode: false
170
- });
171
- const finish = (result) => {
142
+ const settle = (fn) => {
172
143
  if (settled) return;
173
144
  settled = true;
174
145
  clearTimeout(timer);
175
- resolve(result);
146
+ fn();
176
147
  };
148
+ const finish = (result) => settle(() => resolve(result));
149
+ const fail = (err) => settle(() => reject(err));
177
150
  const child = spawn("docker", args, {
178
151
  cwd,
179
152
  signal,
@@ -183,7 +156,11 @@ async function dockerLogs(service, lines, filterRe, cwd, signal, since) {
183
156
  });
184
157
  const timer = setTimeout(() => {
185
158
  child.kill("SIGTERM");
186
- finish(empty());
159
+ fail(
160
+ new Error(
161
+ `logs: docker logs did not finish within ${DOCKER_LOGS_TIMEOUT_MS}ms (is the Docker daemon running?)`
162
+ )
163
+ );
187
164
  }, DOCKER_LOGS_TIMEOUT_MS);
188
165
  child.stdout?.on("data", (c) => {
189
166
  if (stdout.length < MAX) {
@@ -207,7 +184,15 @@ async function dockerLogs(service, lines, filterRe, cwd, signal, since) {
207
184
  JSON.stringify({ level: "debug", event: "pipe_error", stream: "stderr", error: e.message })
208
185
  );
209
186
  });
210
- child.on("close", () => {
187
+ child.on("close", (code) => {
188
+ if (code !== 0) {
189
+ fail(
190
+ new Error(
191
+ `logs: docker logs exited with code ${code ?? "null"}: ${stderr.trim() || "no output"}`
192
+ )
193
+ );
194
+ return;
195
+ }
211
196
  const output = stdout + stderr;
212
197
  const entries = parseLogLines(output, filterRe);
213
198
  finish({
@@ -218,7 +203,10 @@ async function dockerLogs(service, lines, filterRe, cwd, signal, since) {
218
203
  stream_mode: false
219
204
  });
220
205
  });
221
- child.on("error", () => finish(empty()));
206
+ child.on(
207
+ "error",
208
+ (err) => fail(new Error(`logs: could not run docker: ${err.message}`, { cause: err }))
209
+ );
222
210
  });
223
211
  }
224
212
  var DOCKER_LOGS_TIMEOUT_MS = 3e3;
@@ -299,4 +287,4 @@ function parseLine(line) {
299
287
  export {
300
288
  logsTool
301
289
  };
302
- //# sourceMappingURL=chunk-CAF4L6KN.js.map
290
+ //# sourceMappingURL=chunk-C3WP6ZOT.js.map
@@ -6,7 +6,7 @@ import {
6
6
  } from "./chunk-ZBMANLYH.js";
7
7
  import {
8
8
  enqueueReindex
9
- } from "./chunk-TU6UVATU.js";
9
+ } from "./chunk-HYHE4VNA.js";
10
10
  import {
11
11
  isBinaryBuffer,
12
12
  safeResolveReal,
@@ -18,6 +18,7 @@ import {
18
18
  import { spawn } from "node:child_process";
19
19
  import * as fs from "node:fs/promises";
20
20
  import * as path from "node:path";
21
+ import { StringDecoder } from "node:string_decoder";
21
22
  import { ToolValidationError } from "@wrongstack/core/types";
22
23
  import {
23
24
  atomicWrite,
@@ -287,6 +288,13 @@ async function resolveFiles(filesInput, ctx, extraGlob) {
287
288
  const stat2 = await fs.stat(absPath).catch(() => null);
288
289
  if (stat2?.isFile()) {
289
290
  resolved.push(absPath);
291
+ continue;
292
+ }
293
+ if (!stat2 && !await fs.lstat(absPath).catch(() => null)) {
294
+ throw new ToolValidationError({
295
+ message: `replace: file not found "${p}"`,
296
+ field: "files"
297
+ });
290
298
  }
291
299
  }
292
300
  return [...new Set(resolved)];
@@ -343,9 +351,10 @@ function spawnRgFind(pattern, base) {
343
351
  const MAX_BUF_CHARS = 8 * 1024 * 1024;
344
352
  let buf = "";
345
353
  let truncated = false;
354
+ const stdoutDecoder = new StringDecoder("utf8");
346
355
  child.stdout?.on("data", (chunk) => {
347
356
  if (truncated) return;
348
- buf += chunk.toString();
357
+ buf += stdoutDecoder.write(chunk);
349
358
  if (buf.length > MAX_BUF_CHARS) {
350
359
  truncated = true;
351
360
  buf = buf.slice(0, buf.lastIndexOf("\n") + 1);
@@ -360,6 +369,7 @@ function spawnRgFind(pattern, base) {
360
369
  reject(new Error(`rg exited with code ${code}`));
361
370
  return;
362
371
  }
372
+ if (!truncated) buf += stdoutDecoder.end();
363
373
  resolve(
364
374
  buf.split(/\r?\n/).map((s) => s.trim()).filter(Boolean)
365
375
  );
@@ -413,4 +423,4 @@ export {
413
423
  replaceTool,
414
424
  __resetRgDetectionForTests
415
425
  };
416
- //# sourceMappingURL=chunk-KMXPP32M.js.map
426
+ //# sourceMappingURL=chunk-C6ZOXNXV.js.map