@wrongstack/tools 0.319.0 → 0.320.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/dist/_edit-match.d.ts +1 -3
  2. package/dist/_util.d.ts +7 -0
  3. package/dist/audit.js +8 -8
  4. package/dist/bash.js +6 -6
  5. package/dist/browser/index.js +1 -1
  6. package/dist/builtin.d.ts +10 -0
  7. package/dist/builtin.js +54 -52
  8. package/dist/{chunk-65EMYN5G.js → chunk-23EX5WDO.js} +6 -3
  9. package/dist/{chunk-2472NT76.js → chunk-2OXHS3KZ.js} +17 -5
  10. package/dist/{chunk-7WV3D4S3.js → chunk-34VLZ35Z.js} +75 -36
  11. package/dist/{chunk-MYRMD6PZ.js → chunk-3GIKYHLA.js} +32 -8
  12. package/dist/{chunk-X5K3U6GI.js → chunk-3M7LLN7W.js} +71 -7
  13. package/dist/{chunk-VALQFAY2.js → chunk-4BABEJC2.js} +158 -45
  14. package/dist/{chunk-42BHI7TN.js → chunk-4CQWNZ62.js} +2 -2
  15. package/dist/{chunk-WNUJR3H4.js → chunk-5UFVCIUB.js} +40 -16
  16. package/dist/{chunk-UMXVT7ST.js → chunk-6AAOT4PW.js} +58 -10
  17. package/dist/{chunk-H6AWAZ2Y.js → chunk-B4HTSV6Z.js} +57 -6
  18. package/dist/{chunk-5ZYEGP2P.js → chunk-BK732J7I.js} +72 -27
  19. package/dist/{chunk-KD5EHYA2.js → chunk-C2DQKVLO.js} +61 -28
  20. package/dist/{chunk-Z4VBTVUM.js → chunk-DFQDJT22.js} +99 -12
  21. package/dist/{chunk-6RNIFLG4.js → chunk-ELRRTWNP.js} +38 -6
  22. package/dist/{chunk-3PVYQFRQ.js → chunk-ESLPBT5A.js} +2 -1
  23. package/dist/{chunk-YZHK4TLF.js → chunk-FQNXYA6W.js} +45 -6
  24. package/dist/{chunk-OYVPBPCL.js → chunk-HR67OWEP.js} +72 -33
  25. package/dist/{chunk-ZDUGI5BC.js → chunk-I7FBZOEP.js} +2 -2
  26. package/dist/{chunk-HBM4QNXU.js → chunk-IU4DV2PA.js} +18 -8
  27. package/dist/{chunk-TFMVHYJI.js → chunk-J43O3BOX.js} +9 -15
  28. package/dist/{chunk-ODFVG54U.js → chunk-J74TMK4M.js} +37 -13
  29. package/dist/{chunk-COUNXG4X.js → chunk-JLYA4X7K.js} +75 -8
  30. package/dist/{chunk-FQZOHLG3.js → chunk-JSNSMG5R.js} +3 -2
  31. package/dist/{chunk-SYXW3Y5Z.js → chunk-JVRLTEO7.js} +2 -2
  32. package/dist/{chunk-V43EQ6VR.js → chunk-KE7A76VC.js} +3 -2
  33. package/dist/{chunk-ZKSBHXVB.js → chunk-KWXIKGE3.js} +64 -15
  34. package/dist/{chunk-RK47IWO3.js → chunk-LRDIRJJL.js} +62 -30
  35. package/dist/{chunk-UC3RKRIV.js → chunk-NDIT3SBZ.js} +3 -3
  36. package/dist/{chunk-C3W3V54D.js → chunk-NSPNFOJ7.js} +57 -27
  37. package/dist/{chunk-TX3R5NVV.js → chunk-NU2IZ72J.js} +7 -7
  38. package/dist/{chunk-WHIIIREL.js → chunk-NYRLWDT5.js} +7 -3
  39. package/dist/{chunk-PMHVSHMU.js → chunk-OTPTQBYE.js} +80 -19
  40. package/dist/{chunk-ZHH3BEWU.js → chunk-OYP27E3I.js} +4 -4
  41. package/dist/{chunk-W4GAAI3M.js → chunk-PV6HIZQD.js} +2 -2
  42. package/dist/{chunk-NKNOBUBU.js → chunk-QGF2C7TF.js} +2 -2
  43. package/dist/{chunk-PQTONQ4P.js → chunk-QPNYDH5B.js} +19 -5
  44. package/dist/{chunk-VFF3Q5Z3.js → chunk-QSNVDHOZ.js} +37 -9
  45. package/dist/{chunk-45JPRMC2.js → chunk-QWKSKFKZ.js} +7 -3
  46. package/dist/{chunk-2VSZC6QM.js → chunk-SCMRM6NL.js} +6 -4
  47. package/dist/{chunk-RJZQWEMS.js → chunk-T77XOX7E.js} +3 -2
  48. package/dist/{chunk-QZDOQRF7.js → chunk-UZFY3CKD.js} +35 -14
  49. package/dist/{chunk-D4CXUZIF.js → chunk-VD2LV5WO.js} +82 -13
  50. package/dist/{chunk-DPKTXJQS.js → chunk-VPALDFYM.js} +2 -2
  51. package/dist/{chunk-IIF5HIVF.js → chunk-VVZPQPTY.js} +2 -2
  52. package/dist/{chunk-HWDB2G7J.js → chunk-W232EFEM.js} +49 -36
  53. package/dist/{chunk-FJEQZHZN.js → chunk-W2CECGTG.js} +24 -14
  54. package/dist/{chunk-4Q7LFU4T.js → chunk-WAQASTXB.js} +20 -9
  55. package/dist/{chunk-CWALNI6K.js → chunk-X6KXNHUO.js} +1 -1
  56. package/dist/{chunk-OCUXN6Y3.js → chunk-XRNN44QY.js} +1 -1
  57. package/dist/{chunk-N5O3FK5Q.js → chunk-XSSFBS5I.js} +70 -29
  58. package/dist/{chunk-Y7QXSE7N.js → chunk-YTKSNTT4.js} +44 -10
  59. package/dist/{chunk-MRKWZCHZ.js → chunk-Z5Q3TXRY.js} +3 -3
  60. package/dist/{chunk-PRXZOIEW.js → chunk-Z6IHMJMC.js} +104 -59
  61. package/dist/{chunk-NWZ6XGBJ.js → chunk-ZBMANLYH.js} +5 -3
  62. package/dist/{chunk-OJ4FIBAN.js → chunk-ZMW6WJFT.js} +30 -23
  63. package/dist/{chunk-QLF74MSV.js → chunk-ZUFHAHTE.js} +12 -6
  64. package/dist/codebase-index/index.js +12 -12
  65. package/dist/codebase-index/parser-worker-script.js +3 -3
  66. package/dist/codebase-index/project-server.js +5 -5
  67. package/dist/codebase-index/worker.js +4 -4
  68. package/dist/design.d.ts +1 -1
  69. package/dist/design.js +1 -1
  70. package/dist/diff.js +3 -2
  71. package/dist/document.js +2 -2
  72. package/dist/e2e.js +2 -2
  73. package/dist/edit.js +9 -9
  74. package/dist/exec.js +6 -6
  75. package/dist/fetch.js +2 -2
  76. package/dist/format.js +8 -8
  77. package/dist/git.js +2 -2
  78. package/dist/glob.js +3 -3
  79. package/dist/{go-parser-IKHW67WE.js → go-parser-D7ELWQ7F.js} +2 -2
  80. package/dist/grep.d.ts +2 -0
  81. package/dist/grep.js +5 -3
  82. package/dist/index.js +56 -56
  83. package/dist/install.js +8 -8
  84. package/dist/{json-parser-2EOVP5MR.js → json-parser-34DHYCPW.js} +1 -18
  85. package/dist/json.js +2 -2
  86. package/dist/kanban-tool-types.d.ts +2 -0
  87. package/dist/kanban.js +2 -2
  88. package/dist/languages/index.js +6 -6
  89. package/dist/legacy-bridge-FOV5ODDI.js +18 -0
  90. package/dist/lint.js +8 -8
  91. package/dist/logs.js +2 -2
  92. package/dist/memory.js +1 -1
  93. package/dist/next-steps.d.ts +7 -0
  94. package/dist/next-steps.js +82 -38
  95. package/dist/outdated.js +5 -3
  96. package/dist/pack.js +53 -53
  97. package/dist/{parser-dispatch-3PDBKIQ7.js → parser-dispatch-BDVCJXTV.js} +4 -4
  98. package/dist/patch.js +8 -8
  99. package/dist/plan.js +4 -4
  100. package/dist/process-registry.js +1 -1
  101. package/dist/ps-slash.js +3 -3
  102. package/dist/{py-parser-RFWG2HYI.js → py-parser-QC6MR4GB.js} +3 -3
  103. package/dist/read.js +8 -8
  104. package/dist/replace.js +9 -8
  105. package/dist/scaffold.js +2 -2
  106. package/dist/search.js +1 -1
  107. package/dist/session-kanban.js +1 -1
  108. package/dist/task.js +4 -4
  109. package/dist/test.js +8 -8
  110. package/dist/todo.js +3 -3
  111. package/dist/tool-search.js +1 -1
  112. package/dist/tool-tier.js +54 -54
  113. package/dist/{tree-sitter-parser-FGKHJGSX.js → tree-sitter-parser-GILYQLS4.js} +2 -2
  114. package/dist/tree.js +2 -2
  115. package/dist/typecheck.js +8 -8
  116. package/dist/win32.js +1 -1
  117. package/dist/write.js +9 -9
  118. package/package.json +5 -5
  119. package/dist/legacy-bridge-EC7GM2IW.js +0 -18
@@ -1,13 +1,20 @@
1
1
  import {
2
2
  todoTool
3
- } from "./chunk-5ZYEGP2P.js";
3
+ } from "./chunk-BK732J7I.js";
4
4
  import {
5
5
  mirrorSessionTasksToKanban
6
- } from "./chunk-CWALNI6K.js";
6
+ } from "./chunk-X6KXNHUO.js";
7
7
 
8
8
  // src/task.ts
9
9
  import { randomUUID } from "node:crypto";
10
- import { addPlanItem, formatPlan, mutatePlan, mutateTasks } from "@wrongstack/core/storage";
10
+ import {
11
+ addPlanItem,
12
+ formatPlan,
13
+ loadTasks,
14
+ mutatePlan,
15
+ mutateTasks
16
+ } from "@wrongstack/core/storage";
17
+ import { ToolValidationError } from "@wrongstack/core/types";
11
18
  import { computeTaskItemProgress, formatTaskList } from "@wrongstack/core/utils";
12
19
  function findTaskIndex(tasks, query) {
13
20
  const asNum = Number.parseInt(query, 10);
@@ -119,8 +126,34 @@ var taskTool = {
119
126
  },
120
127
  required: ["action"]
121
128
  },
122
- async execute(input, ctx) {
123
- const sessionTaskPath = ctx.meta["task.path"];
129
+ async execute(input, ctx, _opts) {
130
+ const signal = _opts?.signal ?? ctx?.signal;
131
+ signal?.throwIfAborted();
132
+ const VALID_ACTIONS = /* @__PURE__ */ new Set([
133
+ "replace",
134
+ "add",
135
+ "status",
136
+ "show",
137
+ "promote",
138
+ "planify"
139
+ ]);
140
+ if (!input?.action || !VALID_ACTIONS.has(input.action)) {
141
+ return {
142
+ ok: false,
143
+ message: `Unknown action "${input?.action}". Use replace | add | status | show | promote | planify.`,
144
+ count: 0,
145
+ completed: 0,
146
+ inProgress: 0
147
+ };
148
+ }
149
+ if (input.scope !== void 0 && input.scope !== "session" && input.scope !== "project") {
150
+ throw new ToolValidationError({
151
+ message: `task: invalid scope "${input.scope}". Allowed: session, project`,
152
+ field: "scope"
153
+ });
154
+ }
155
+ const meta = ctx.meta ??= {};
156
+ const sessionTaskPath = meta["task.path"];
124
157
  let taskPath;
125
158
  if (input.scope === "project") {
126
159
  if (typeof sessionTaskPath === "string") {
@@ -143,6 +176,19 @@ var taskTool = {
143
176
  };
144
177
  }
145
178
  const sessionId = ctx.session?.id ?? "unknown";
179
+ if (input.action === "show") {
180
+ meta["task.path.resolved"] = taskPath;
181
+ const file2 = await loadTasks(taskPath) ?? { version: 1, tasks: [] };
182
+ const p2 = computeTaskItemProgress(file2.tasks);
183
+ const summary2 = file2.tasks.length > 0 ? formatTaskList(file2.tasks) : "No tasks.";
184
+ return {
185
+ ok: true,
186
+ message: summary2,
187
+ count: file2.tasks.length,
188
+ completed: p2.completed,
189
+ inProgress: p2.inProgress
190
+ };
191
+ }
146
192
  let early = null;
147
193
  const promoteMeta = { count: 0, title: "" };
148
194
  const planifyMeta = { title: "", details: "" };
@@ -198,6 +244,7 @@ var taskTool = {
198
244
  };
199
245
  return f;
200
246
  }
247
+ const taskStatusById = new Map(input.tasks.map((t) => [t.id, t.status]));
201
248
  for (const t of input.tasks) {
202
249
  if (t.dependsOn && t.dependsOn.length > 0) {
203
250
  const missing = t.dependsOn.filter((d) => !newIds.has(d));
@@ -214,7 +261,7 @@ var taskTool = {
214
261
  }
215
262
  if (t.status === "in_progress" || t.status === "completed") {
216
263
  const unmet = (t.dependsOn ?? []).filter(
217
- (dependencyId) => input.tasks?.find((candidate) => candidate.id === dependencyId)?.status !== "completed"
264
+ (dependencyId) => taskStatusById.get(dependencyId) !== "completed"
218
265
  );
219
266
  if (unmet.length > 0) {
220
267
  early = {
@@ -280,6 +327,14 @@ var taskTool = {
280
327
  break;
281
328
  }
282
329
  case "status": {
330
+ const VALID_TASK_STATUSES = /* @__PURE__ */ new Set([
331
+ "pending",
332
+ "in_progress",
333
+ "blocked",
334
+ "failed",
335
+ "review",
336
+ "completed"
337
+ ]);
283
338
  if (!input.id || !input.status) {
284
339
  early = {
285
340
  ok: false,
@@ -290,6 +345,15 @@ var taskTool = {
290
345
  };
291
346
  return f;
292
347
  }
348
+ if (!VALID_TASK_STATUSES.has(input.status)) {
349
+ early = {
350
+ ok: false,
351
+ message: `action=status requires valid status ('pending' | 'in_progress' | 'blocked' | 'failed' | 'review' | 'completed'), got "${input.status}".`,
352
+ count: f.tasks.length,
353
+ ...computeTaskItemProgress(f.tasks)
354
+ };
355
+ return f;
356
+ }
293
357
  const task = f.tasks.find((t) => t.id === input.id);
294
358
  if (!task) {
295
359
  early = {
@@ -517,4 +581,4 @@ ${formatTaskList(file.tasks)}` : file.tasks.length > 0 ? formatTaskList(file.tas
517
581
  export {
518
582
  taskTool
519
583
  };
520
- //# sourceMappingURL=chunk-X5K3U6GI.js.map
584
+ //# sourceMappingURL=chunk-3M7LLN7W.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  e2ePlanTool
3
- } from "./chunk-DPKTXJQS.js";
3
+ } from "./chunk-VPALDFYM.js";
4
4
  import {
5
5
  codebaseAstReplaceTool,
6
6
  codebaseImpactAnalysisTool,
@@ -14,16 +14,16 @@ import {
14
14
  codebaseStatsTool,
15
15
  codebaseTargetedTestTool,
16
16
  deadCodeScanTool
17
- } from "./chunk-RK47IWO3.js";
17
+ } from "./chunk-LRDIRJJL.js";
18
18
  import {
19
19
  planTool
20
- } from "./chunk-H6AWAZ2Y.js";
20
+ } from "./chunk-B4HTSV6Z.js";
21
21
  import {
22
22
  taskTool
23
- } from "./chunk-X5K3U6GI.js";
23
+ } from "./chunk-3M7LLN7W.js";
24
24
  import {
25
25
  toolSearchTool
26
- } from "./chunk-RJZQWEMS.js";
26
+ } from "./chunk-T77XOX7E.js";
27
27
  import {
28
28
  toolUseTool
29
29
  } from "./chunk-FRN7TIAA.js";
@@ -35,119 +35,119 @@ import {
35
35
  } from "./chunk-QBV725YG.js";
36
36
  import {
37
37
  designTool
38
- } from "./chunk-6RNIFLG4.js";
38
+ } from "./chunk-ELRRTWNP.js";
39
39
  import {
40
40
  testTool
41
- } from "./chunk-Y7QXSE7N.js";
41
+ } from "./chunk-YTKSNTT4.js";
42
42
  import {
43
43
  installTool
44
- } from "./chunk-4Q7LFU4T.js";
44
+ } from "./chunk-WAQASTXB.js";
45
45
  import {
46
46
  auditTool
47
- } from "./chunk-QZDOQRF7.js";
47
+ } from "./chunk-UZFY3CKD.js";
48
48
  import {
49
49
  outdatedTool
50
- } from "./chunk-Z4VBTVUM.js";
50
+ } from "./chunk-DFQDJT22.js";
51
51
  import {
52
52
  logsTool
53
- } from "./chunk-YZHK4TLF.js";
53
+ } from "./chunk-FQNXYA6W.js";
54
54
  import {
55
55
  documentTool
56
- } from "./chunk-HBM4QNXU.js";
56
+ } from "./chunk-IU4DV2PA.js";
57
57
  import {
58
58
  scaffoldTool
59
- } from "./chunk-2472NT76.js";
59
+ } from "./chunk-2OXHS3KZ.js";
60
60
  import {
61
61
  gitTool
62
- } from "./chunk-UMXVT7ST.js";
62
+ } from "./chunk-6AAOT4PW.js";
63
63
  import {
64
64
  patchTool
65
- } from "./chunk-COUNXG4X.js";
65
+ } from "./chunk-JLYA4X7K.js";
66
66
  import {
67
67
  jsonTool
68
- } from "./chunk-D4CXUZIF.js";
68
+ } from "./chunk-VD2LV5WO.js";
69
69
  import {
70
70
  diffTool
71
- } from "./chunk-7WV3D4S3.js";
71
+ } from "./chunk-34VLZ35Z.js";
72
72
  import {
73
73
  treeTool
74
- } from "./chunk-HWDB2G7J.js";
74
+ } from "./chunk-W232EFEM.js";
75
75
  import {
76
76
  lintTool
77
- } from "./chunk-ZKSBHXVB.js";
77
+ } from "./chunk-KWXIKGE3.js";
78
78
  import {
79
79
  formatTool
80
- } from "./chunk-ODFVG54U.js";
80
+ } from "./chunk-J74TMK4M.js";
81
81
  import {
82
82
  typecheckTool
83
- } from "./chunk-VFF3Q5Z3.js";
83
+ } from "./chunk-QSNVDHOZ.js";
84
84
  import {
85
85
  languageInfoTool,
86
86
  languagePackageTool,
87
87
  languageTool
88
- } from "./chunk-UC3RKRIV.js";
88
+ } from "./chunk-NDIT3SBZ.js";
89
89
  import {
90
90
  replaceTool
91
- } from "./chunk-OYVPBPCL.js";
91
+ } from "./chunk-HR67OWEP.js";
92
92
  import {
93
93
  globTool
94
- } from "./chunk-OJ4FIBAN.js";
94
+ } from "./chunk-ZMW6WJFT.js";
95
95
  import {
96
96
  grepTool
97
- } from "./chunk-N5O3FK5Q.js";
97
+ } from "./chunk-XSSFBS5I.js";
98
98
  import {
99
99
  bashTool,
100
100
  checkAndBlockKillCommand,
101
101
  diagnoseBashism,
102
102
  shellArgs
103
- } from "./chunk-WNUJR3H4.js";
103
+ } from "./chunk-5UFVCIUB.js";
104
104
  import {
105
105
  detectDanger,
106
106
  execTool
107
- } from "./chunk-PMHVSHMU.js";
107
+ } from "./chunk-OTPTQBYE.js";
108
108
  import {
109
109
  buildChildEnv
110
110
  } from "./chunk-BTSFTGIL.js";
111
111
  import {
112
112
  createOutputSpool,
113
113
  spoolNote
114
- } from "./chunk-2VSZC6QM.js";
114
+ } from "./chunk-SCMRM6NL.js";
115
115
  import {
116
116
  getProcessRegistry,
117
117
  redactCommand
118
- } from "./chunk-3PVYQFRQ.js";
118
+ } from "./chunk-ESLPBT5A.js";
119
119
  import {
120
120
  fetchTool
121
- } from "./chunk-KD5EHYA2.js";
121
+ } from "./chunk-C2DQKVLO.js";
122
122
  import {
123
123
  searchTool
124
- } from "./chunk-PQTONQ4P.js";
124
+ } from "./chunk-QPNYDH5B.js";
125
125
  import {
126
126
  todoTool
127
- } from "./chunk-5ZYEGP2P.js";
127
+ } from "./chunk-BK732J7I.js";
128
128
  import {
129
129
  kanbanTool
130
- } from "./chunk-FJEQZHZN.js";
130
+ } from "./chunk-W2CECGTG.js";
131
131
  import {
132
132
  browserTools
133
- } from "./chunk-45JPRMC2.js";
133
+ } from "./chunk-QWKSKFKZ.js";
134
134
  import {
135
135
  readTool
136
- } from "./chunk-C3W3V54D.js";
136
+ } from "./chunk-NSPNFOJ7.js";
137
137
  import {
138
138
  writeTool
139
- } from "./chunk-MYRMD6PZ.js";
139
+ } from "./chunk-3GIKYHLA.js";
140
140
  import {
141
141
  editTool
142
- } from "./chunk-PRXZOIEW.js";
142
+ } from "./chunk-Z6IHMJMC.js";
143
143
  import {
144
144
  resolvePowerShell
145
- } from "./chunk-V43EQ6VR.js";
145
+ } from "./chunk-KE7A76VC.js";
146
146
  import {
147
147
  normalizeCommandOutput,
148
148
  safeResolveProjectPath,
149
149
  safeResolveReal
150
- } from "./chunk-QLF74MSV.js";
150
+ } from "./chunk-ZUFHAHTE.js";
151
151
 
152
152
  // src/clarify.ts
153
153
  import { toErrorMessage } from "@wrongstack/core/utils";
@@ -193,8 +193,10 @@ var clarifyTool = {
193
193
  required: ["question", "options"],
194
194
  additionalProperties: false
195
195
  },
196
- async execute(input, ctx) {
196
+ async execute(input, ctx, opts) {
197
197
  try {
198
+ const signal = opts?.signal ?? ctx?.signal;
199
+ signal?.throwIfAborted();
198
200
  const options = input.options;
199
201
  if (!options || options.length < 2) {
200
202
  throw new Error("clarify requires at least 2 distinct options.");
@@ -238,6 +240,7 @@ import {
238
240
  emitProcessOutput,
239
241
  emitProcessStarted
240
242
  } from "@wrongstack/core/observability";
243
+ import { ToolValidationError } from "@wrongstack/core/types";
241
244
  var MAX_OUTPUT = 32768;
242
245
  var DEFAULT_TIMEOUT_MS = 3e5;
243
246
  var STREAM_FLUSH_INTERVAL_MS = 200;
@@ -383,8 +386,38 @@ var pwshTool = {
383
386
  if (!final) throw new Error("pwsh: stream ended without final event");
384
387
  return final;
385
388
  },
389
+ async cleanup(_input, ctx) {
390
+ const registry = getProcessRegistry();
391
+ const sessionId = ctx.session?.id;
392
+ if (!sessionId) return;
393
+ for (const entry of registry.bySession(sessionId)) {
394
+ if (entry.name !== "pwsh") continue;
395
+ if (entry.child && entry.child.exitCode !== null) continue;
396
+ if (entry.protected) continue;
397
+ registry.kill(entry.pid, { force: true });
398
+ }
399
+ },
386
400
  async *executeStream(input, ctx, opts) {
387
- if (!input?.command) throw new Error("pwsh: command is required");
401
+ if (!input?.command || typeof input.command !== "string" || !input.command.trim()) {
402
+ throw new ToolValidationError({
403
+ message: "pwsh: command is required and cannot be empty",
404
+ field: "command"
405
+ });
406
+ }
407
+ const callerSignal = opts?.signal ?? ctx?.signal ?? new AbortController().signal;
408
+ if (callerSignal.aborted) {
409
+ yield {
410
+ type: "final",
411
+ output: {
412
+ output: "",
413
+ exit_code: 124,
414
+ timed_out: false,
415
+ pid: null,
416
+ error: "Aborted"
417
+ }
418
+ };
419
+ return;
420
+ }
388
421
  const isBackground = !!(input.run_in_background || input.background);
389
422
  const registry = getProcessRegistry();
390
423
  if (!registry.beforeCall(isBackground)) {
@@ -438,7 +471,6 @@ var pwshTool = {
438
471
  return;
439
472
  }
440
473
  const startedAt = Date.now();
441
- const callerSignal = opts?.signal ?? ctx.signal ?? new AbortController().signal;
442
474
  const detached = !isWin;
443
475
  if (isBackground) {
444
476
  const child2 = spawn(bin, args, {
@@ -546,7 +578,8 @@ Working directory: ${targetCwd}`,
546
578
  processGroupLeader: detached && child.pid === pid
547
579
  });
548
580
  }
549
- const timeoutMs = Math.min(Math.max(1e3, input.timeout_ms ?? DEFAULT_TIMEOUT_MS), 6e5);
581
+ const rawTimeout = typeof input.timeout_ms === "number" && !Number.isNaN(input.timeout_ms) ? input.timeout_ms : DEFAULT_TIMEOUT_MS;
582
+ const timeoutMs = Math.min(Math.max(1e3, rawTimeout), 6e5);
550
583
  let timedOut = false;
551
584
  const timers = [];
552
585
  const killWithTimeout = (timeout) => {
@@ -1018,6 +1051,78 @@ var setWorkingDirTool = {
1018
1051
  };
1019
1052
 
1020
1053
  // src/builtin.ts
1054
+ var BUILTIN_TOOL_DESCRIPTIONS = {
1055
+ browser_open: "Create an isolated, agent-owned Playwright browser session, optionally opening an approved HTTP(S) URL. Use it to begin browser QA; private and localhost origins require an explicit allowlist.",
1056
+ browser_list: "List browser sessions owned by this agent, including their state and current page, without exposing sessions owned by other agents.",
1057
+ browser_status: "Check whether the managed Playwright Chromium installation is available before attempting browser automation.",
1058
+ browser_navigate: "Navigate one of this agent\u2019s browser sessions to an approved HTTP(S) URL. Use browser_open first; private and localhost origins require an explicit allowlist.",
1059
+ browser_snapshot: "Inspect the current page through a bounded accessibility snapshot, with redacted console and network summaries. Prefer this before interacting with page elements.",
1060
+ browser_screenshot: "Capture a PNG of the current page or a selected element for visual QA. The result is a sensitive artifact with integrity metadata.",
1061
+ browser_type: "Fill a form control in an owned browser session. Use secretEnv for credentials so secret values never enter tool arguments or the audit trail.",
1062
+ browser_click: "Click a verified page element in an owned browser session. Snapshot first and use the most specific stable selector available.",
1063
+ browser_hover: "Hover over a verified page element in an owned browser session to reveal menus, tooltips, or other hover-driven UI state.",
1064
+ browser_select: "Choose an option in a select control in an owned browser session after confirming the target selector and intended value.",
1065
+ browser_press: "Send a keyboard key or shortcut to an owned browser session, such as Enter after verifying a form is ready to submit.",
1066
+ browser_drag: "Drag one page element onto another in an owned browser session. Use only when the page\u2019s drag-and-drop interaction is the intended action.",
1067
+ browser_wait: "Wait for a selector, navigation condition, or bounded duration in an owned browser session before taking the next browser action.",
1068
+ browser_evaluate: "Run a bounded JavaScript expression in an owned page when browser APIs cannot inspect the needed state. Treat page code as arbitrary and use sparingly.",
1069
+ browser_upload: "Upload project-local files through a page file input in an owned browser session. Verify both the file path and target control before uploading.",
1070
+ browser_close: "Close an owned browser session and reclaim its resources, returning trace-artifact metadata when tracing was enabled.",
1071
+ e2e_plan: "Create an end-to-end test plan from a feature or user flow. Use it to identify scenarios and acceptance coverage; it plans tests rather than executing them.",
1072
+ read: "Read a project file safely, with optional line ranges and binary-aware output. Use it to inspect source before editing; paths must stay within the project.",
1073
+ write: "Create or replace one project file with the complete supplied content. Use for new files or intentional full rewrites, after reading existing content when applicable.",
1074
+ edit: "Make a precise, guarded text edit by replacing an expected block in a project file. Prefer it for small source changes so mismatches prevent accidental overwrites.",
1075
+ clarify: "Record or ask a focused clarification when a missing decision would materially change the implementation. Do not use it for questions that can be answered from the repository.",
1076
+ "codebase-ast-replace": "Replace a named declaration using source-aware structure instead of fragile text matching. Use it for a function, method, class, interface, or variable when the target is unambiguous.",
1077
+ "codebase-invariant-check": "Compare candidate code with its original source and report structural invariants that may have changed. Use before writing a risky refactor; it validates but does not modify files.",
1078
+ "codebase-stats": "Report codebase-index health, indexed file and symbol counts, languages, and freshness. Use it before relying on indexed discovery results.",
1079
+ "codebase-search": "Search indexed symbols, signatures, and documentation with optional language, kind, path, or LSP-kind filters. Use it for semantic discovery before broad text search.",
1080
+ "codebase-skeleton": "Extract a compact structural skeleton from a source file or directory, preserving declarations while omitting implementation detail. Use it to understand unfamiliar code quickly.",
1081
+ "codebase-repo-map": "Generate a concise map of important files, symbols, and relationships in a project area. Use it for orientation before a cross-file change.",
1082
+ "codebase-impact-analysis": "Find likely callers, dependents, related tests, and change risk for a named symbol. Use it before changing a public or widely used declaration.",
1083
+ "codebase-targeted-test": "Discover and run tests that cover a specified symbol, source file, or explicit test files. Use it for focused regression validation after a change.",
1084
+ "security-ast-scan": "Statically scan source code for supported security patterns and return findings with locations. Use it as a focused code check, not as a substitute for a full security assessment.",
1085
+ "codebase-incoming-calls": "Find indexed call sites that invoke a named function, method, or type, optionally scoped to a file. Use it to estimate breakage before changing an API.",
1086
+ "codebase-outgoing-calls": "Find indexed symbols called by a named function, method, or type, optionally scoped to a file. Use it to understand dependencies before refactoring behavior.",
1087
+ "codebase-index": "Build or refresh the local semantic codebase index, optionally for selected languages. Use it when index results are absent or stale; force performs a full reindex.",
1088
+ "dead-code-scan": "Analyze the indexed project for declarations that appear unreachable from configured entry points. Treat results as candidates for review, not automatic deletion instructions.",
1089
+ replace: "Preview or apply a regular-expression replacement across selected project files. Start with dry_run, constrain files and globs carefully, then apply only reviewed changes.",
1090
+ glob: "Find project files by glob pattern, respecting repository boundaries and ignore rules. Use it to locate candidate paths before reading or editing them.",
1091
+ grep: "Search project text with a bounded regular expression and contextual matches. Use it for exact literals or patterns when semantic codebase search is not appropriate.",
1092
+ bash: "Run a shell command in the project with bounded output and timeout controls. Use it for development commands after checking side effects; background mode returns a process handle.",
1093
+ exec: "Execute a command directly without shell interpretation, using explicit program arguments. Prefer it when argument safety and predictable process invocation matter.",
1094
+ pwsh: "Execute a PowerShell command in the project with timeout, output, and background controls. Use it for Windows-native project operations and verify commands that can modify state.",
1095
+ fetch: "Fetch and extract content from an approved HTTP(S) URL for research or integration work. Use it for a known page or endpoint, not for general web discovery.",
1096
+ search: "Search the public web for current external information, then inspect selected results with fetch. Use it when repository evidence is insufficient or the fact may have changed.",
1097
+ todo: "Create, update, or list the session\u2019s concrete work items and their progress. Use it to keep multi-step work visible; it does not implement the tasks itself.",
1098
+ plan: "Create and manage higher-level plan-board items, priorities, and status. Use it for strategic work tracking rather than small immediate edits.",
1099
+ kanban: "Manage project Kanban boards, cards, assignments, and acceptance evidence. Use it for persistent team workflow; changing board state is intentional and reviewable.",
1100
+ task: "Manage structured task records, dependencies, ownership, and promotion into actionable session work. Use it to organize bounded work before delegation or execution.",
1101
+ git: "Inspect or run scoped Git operations in the project, including status, diff, history, branches, and commits. Review the target and working tree before mutating operations.",
1102
+ patch: "Apply a unified diff to project files with patch-style context checking. Use it for a reviewed multi-file change when exact patch content is available.",
1103
+ json: "Read, query, validate, or update JSON files while preserving valid structure. Use it instead of raw text edits when changing structured JSON data.",
1104
+ diff: "Compare two files, revisions, or text inputs and return a readable unified diff. Use it to review intended changes before applying or committing them.",
1105
+ tree: "Render a bounded directory tree with depth, file, hidden-file, and ignore controls. Use it for repository orientation without reading every file.",
1106
+ lint: "Run the project\u2019s configured linter for a target path or working directory and return diagnostics. Use it after code edits to catch style and static-analysis issues.",
1107
+ format: "Run the project\u2019s configured formatter on selected files or directories. Use it after editing code, while reviewing the resulting diff for unintended formatting scope.",
1108
+ typecheck: "Run TypeScript type checking for an auto-detected or specified tsconfig. Use it after type-affecting changes; it reports diagnostics without writing source files.",
1109
+ test: "Run the detected test runner for selected tests, with optional name filtering, coverage, watch, and timeout controls. Prefer focused tests first, then broader validation as needed.",
1110
+ language_info: "Inspect detected language tooling, workspaces, and supported operations for the project or target path. Use it before invoking language-specific tooling.",
1111
+ language: "Run a supported language-tooling operation in a detected workspace. Use it when the language profile provides a safer, structured alternative to an arbitrary shell command.",
1112
+ language_package: "Plan or perform a dependency operation through the detected package ecosystem. Use dry-run first when possible and specify the workspace or dependency scope deliberately.",
1113
+ install: "Install project dependencies with the detected package manager. Use only when dependency changes are required, and inspect lockfile and manifest changes afterward.",
1114
+ audit: "Run the package manager\u2019s dependency vulnerability audit and summarize actionable findings. Use it to assess known dependency advisories, not source-code vulnerabilities.",
1115
+ outdated: "List outdated project dependencies and available versions without changing manifests or lockfiles. Use it to plan dependency maintenance.",
1116
+ logs: "Read or tail configured local, container, or process logs with bounded output. Use it to investigate a known runtime failure or service behavior.",
1117
+ document: "Generate or update project documentation from supplied scope and source context. Use it to record verified behavior; review generated text before treating it as authoritative.",
1118
+ scaffold: "Preview or generate files from a built-in or custom scaffold template. Use dry_run first to inspect paths and content before creating project files.",
1119
+ design: "Create a structured implementation design with goals, constraints, approach, and risks. Use it before a substantial change that needs an explicit technical decision.",
1120
+ tool_search: "Discover registered tools by name, description, tag, permission, or mutating status. Use it to find a lazy capability before calling it through tool-use.",
1121
+ tool_use: "Invoke a registered tool by name with its input object, including a tool discovered lazily. Use it only after confirming the target tool\u2019s schema and side effects.",
1122
+ batch_tool_use: "Invoke several independent registered tools as a batch and return each result. Use it for parallel read-only discovery; avoid batching dependent or destructive operations.",
1123
+ tool_help: "Show a tool\u2019s purpose, input schema, permission, and examples, or summarize the catalog. Use it before invoking an unfamiliar or lazily discovered tool.",
1124
+ set_working_dir: "Show or change the session working directory within the permitted project scope. Use it when subsequent commands must target another project subdirectory."
1125
+ };
1021
1126
  var OPTIONAL_TOOLS = [
1022
1127
  ...browserTools,
1023
1128
  e2ePlanTool,
@@ -1093,7 +1198,7 @@ var TIER3_TOOLS = [
1093
1198
  toolHelpTool,
1094
1199
  setWorkingDirTool
1095
1200
  ];
1096
- var builtinTools = [
1201
+ var rawBuiltinTools = [
1097
1202
  ...browserTools,
1098
1203
  e2ePlanTool,
1099
1204
  readTool,
@@ -1150,6 +1255,13 @@ var builtinTools = [
1150
1255
  toolHelpTool,
1151
1256
  setWorkingDirTool
1152
1257
  ];
1258
+ var builtinTools = rawBuiltinTools.map((tool) => {
1259
+ const description = BUILTIN_TOOL_DESCRIPTIONS[tool.name];
1260
+ if (!description) {
1261
+ throw new Error(`Missing provider-facing description for built-in tool: ${tool.name}`);
1262
+ }
1263
+ return { ...tool, description };
1264
+ });
1153
1265
 
1154
1266
  export {
1155
1267
  clarifyTool,
@@ -1157,6 +1269,7 @@ export {
1157
1269
  pwshTool,
1158
1270
  analyzeSecurityAndPerformance,
1159
1271
  securityAstScanTool,
1272
+ BUILTIN_TOOL_DESCRIPTIONS,
1160
1273
  OPTIONAL_TOOLS,
1161
1274
  OFF_ONLY_TOOLS,
1162
1275
  TIER1_TOOLS,
@@ -1164,4 +1277,4 @@ export {
1164
1277
  TIER3_TOOLS,
1165
1278
  builtinTools
1166
1279
  };
1167
- //# sourceMappingURL=chunk-VALQFAY2.js.map
1280
+ //# sourceMappingURL=chunk-4BABEJC2.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getPersistentProcessRegistry
3
- } from "./chunk-NKNOBUBU.js";
3
+ } from "./chunk-QGF2C7TF.js";
4
4
 
5
5
  // src/ps-slash.ts
6
6
  import * as os from "node:os";
@@ -334,4 +334,4 @@ export {
334
334
  formatInstanceSummary,
335
335
  createGlobalPsSlashCommand
336
336
  };
337
- //# sourceMappingURL=chunk-42BHI7TN.js.map
337
+ //# sourceMappingURL=chunk-4CQWNZ62.js.map
@@ -3,21 +3,21 @@ import {
3
3
  } from "./chunk-BTSFTGIL.js";
4
4
  import {
5
5
  getPersistentProcessRegistry
6
- } from "./chunk-NKNOBUBU.js";
6
+ } from "./chunk-QGF2C7TF.js";
7
7
  import {
8
8
  createOutputSpool,
9
9
  spoolNote
10
- } from "./chunk-2VSZC6QM.js";
10
+ } from "./chunk-SCMRM6NL.js";
11
11
  import {
12
12
  getProcessRegistry,
13
13
  redactCommand
14
- } from "./chunk-3PVYQFRQ.js";
14
+ } from "./chunk-ESLPBT5A.js";
15
15
  import {
16
16
  resolvePowerShell
17
- } from "./chunk-V43EQ6VR.js";
17
+ } from "./chunk-KE7A76VC.js";
18
18
  import {
19
19
  normalizeCommandOutput
20
- } from "./chunk-QLF74MSV.js";
20
+ } from "./chunk-ZUFHAHTE.js";
21
21
 
22
22
  // src/bash.ts
23
23
  import { spawn } from "node:child_process";
@@ -28,6 +28,7 @@ import {
28
28
  emitProcessOutput,
29
29
  emitProcessStarted
30
30
  } from "@wrongstack/core/observability";
31
+ import { ToolValidationError } from "@wrongstack/core/types";
31
32
 
32
33
  // src/_shell-pick.ts
33
34
  var POSIX_DEFAULT = "cmd";
@@ -539,7 +540,12 @@ var bashTool = {
539
540
  return final;
540
541
  },
541
542
  async *executeStream(input, ctx, opts) {
542
- if (!input?.command) throw new Error("bash: command is required");
543
+ if (!input?.command || typeof input.command !== "string" || !input.command.trim()) {
544
+ throw new ToolValidationError({
545
+ message: "bash: command is required and cannot be empty",
546
+ field: "command"
547
+ });
548
+ }
543
549
  const registry = getProcessRegistry();
544
550
  const bypassBreaker = !!input.background;
545
551
  if (!registry.beforeCall(bypassBreaker)) {
@@ -571,7 +577,8 @@ var bashTool = {
571
577
  }
572
578
  const PIPE_TO_SHELL_PATTERN = /\|\s*(sh|bash|ksh|zsh|fish|cmd|powershell|pwsh)/i;
573
579
  const pipeToShellNote = PIPE_TO_SHELL_PATTERN.test(input.command) ? "\n\n[wrongstack] Caution: this command pipes output into a shell interpreter (pipe-to-shell). Piped content executes as arbitrary code \u2014 review the source before trusting the result, and prefer downloading to a file and inspecting it first." : "";
574
- const timeoutMs = Math.max(1, Math.min(input.timeout_ms ?? DEFAULT_TIMEOUT_MS, 6e5));
580
+ const rawTimeout = typeof input.timeout_ms === "number" && !Number.isNaN(input.timeout_ms) ? input.timeout_ms : DEFAULT_TIMEOUT_MS;
581
+ const timeoutMs = Math.max(1, Math.min(rawTimeout, 6e5));
575
582
  const isWin2 = os2.platform() === "win32";
576
583
  let plan;
577
584
  let winShellKind;
@@ -605,6 +612,18 @@ var bashTool = {
605
612
  const env = buildChildEnv(ctx.session?.id);
606
613
  const spawnCwd = ctx.workingDir ?? ctx.projectRoot;
607
614
  const callerSignal = opts?.signal ?? ctx.signal ?? new AbortController().signal;
615
+ if (callerSignal.aborted) {
616
+ yield {
617
+ type: "final",
618
+ output: {
619
+ output: "Aborted",
620
+ exit_code: 124,
621
+ timed_out: true,
622
+ pid: null
623
+ }
624
+ };
625
+ return;
626
+ }
608
627
  const detached = !isWin2;
609
628
  const startedAt = Date.now();
610
629
  if (input.background) {
@@ -829,13 +848,15 @@ var bashTool = {
829
848
  if (stream === "stdout") stdoutBytes += chunk.byteLength;
830
849
  else stderrBytes += chunk.byteLength;
831
850
  emitProcessOutput({ pid, stream, chunk });
832
- if (buf.length < MAX_OUTPUT) {
833
- buf += text.slice(0, MAX_OUTPUT - buf.length);
851
+ if (text.length > 0) {
852
+ if (buf.length < MAX_OUTPUT) {
853
+ buf += text.slice(0, MAX_OUTPUT - buf.length);
854
+ }
855
+ spool.write(text);
856
+ pending += text;
857
+ push({ kind: "data", text });
858
+ pauseIfFlooded();
834
859
  }
835
- spool.write(text);
836
- pending += text;
837
- push({ kind: "data", text });
838
- pauseIfFlooded();
839
860
  };
840
861
  const onStdoutData = (chunk) => onData(chunk, "stdout");
841
862
  const onStderrData = (chunk) => onData(chunk, "stderr");
@@ -872,14 +893,17 @@ var bashTool = {
872
893
  }
873
894
  const spooled = spool.finalize();
874
895
  const hint = !timedOut && typeof c.code === "number" && c.code !== 0 && winShellKind ? diagnoseBashism(input.command, winShellKind) : void 0;
896
+ const isAborted = callerSignal.aborted;
875
897
  yield {
876
898
  type: "final",
877
899
  output: {
878
900
  output: normalizeCommandOutput(buf) + (spooled ? spoolNote(spooled) : "") + (hint ? `
879
901
 
880
902
  ${hint}` : "") + pipeToShellNote,
881
- exit_code: c.code,
882
- timed_out: timedOut
903
+ exit_code: timedOut || isAborted ? 124 : c.code,
904
+ timed_out: timedOut || isAborted,
905
+ pid: pid ?? null,
906
+ error: isAborted ? "Command aborted by user or signal" : void 0
883
907
  }
884
908
  };
885
909
  ctx.recordSideEffect?.({
@@ -953,4 +977,4 @@ export {
953
977
  checkAndBlockKillCommand,
954
978
  bashTool
955
979
  };
956
- //# sourceMappingURL=chunk-WNUJR3H4.js.map
980
+ //# sourceMappingURL=chunk-5UFVCIUB.js.map