@wrongstack/tools 1.0.3 → 1.0.5

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 (112) hide show
  1. package/README.md +0 -6
  2. package/dist/_util.d.ts +18 -0
  3. package/dist/audit.js +4 -4
  4. package/dist/bash.js +2 -2
  5. package/dist/browser/index.d.ts +1 -1
  6. package/dist/browser/index.js +9 -1
  7. package/dist/browser/tools.d.ts +14 -0
  8. package/dist/builtin.d.ts +16 -13
  9. package/dist/builtin.js +41 -45
  10. package/dist/{chunk-AQ5YBURX.js → chunk-2IC5FRD7.js} +2 -2
  11. package/dist/{chunk-VU3QBYL4.js → chunk-2ZWQIVEW.js} +2 -2
  12. package/dist/{chunk-JDOO4P6Z.js → chunk-3F7HQ3KS.js} +2 -2
  13. package/dist/{chunk-DX5KZEMK.js → chunk-47GYABZW.js} +2 -2
  14. package/dist/{chunk-KYVOTHG7.js → chunk-4KI4HHID.js} +2 -2
  15. package/dist/{chunk-3JVSOBHU.js → chunk-54SIRJ6D.js} +4 -4
  16. package/dist/{chunk-X6KXNHUO.js → chunk-5BKQVP56.js} +22 -5
  17. package/dist/{chunk-SMARDKAC.js → chunk-5UA4TNJJ.js} +2 -2
  18. package/dist/{chunk-SOR7OCYP.js → chunk-6XYFYLN7.js} +23 -1
  19. package/dist/{chunk-VO6M2FVG.js → chunk-6ZRP5IKQ.js} +2 -2
  20. package/dist/{chunk-E2ZD4ERD.js → chunk-7EQ2LUXU.js} +3 -3
  21. package/dist/{chunk-6LCKF5KH.js → chunk-7PEZU5Y4.js} +1 -1
  22. package/dist/{chunk-7HL23T3T.js → chunk-BU6VUXWG.js} +2 -2
  23. package/dist/{chunk-KIQTABBJ.js → chunk-C64UUXTA.js} +3 -3
  24. package/dist/{chunk-PNLDTRC5.js → chunk-CYPYJIAF.js} +7 -7
  25. package/dist/{chunk-IRUEHGCR.js → chunk-D4HWMWGE.js} +3 -3
  26. package/dist/{chunk-CVNCSMVU.js → chunk-DOHU3XHS.js} +46 -6
  27. package/dist/{chunk-32XPUSY3.js → chunk-FRIUJ534.js} +3 -3
  28. package/dist/{chunk-AMURQAJX.js → chunk-G35NLPG5.js} +3 -3
  29. package/dist/{chunk-ZUFHAHTE.js → chunk-HKR56VNF.js} +15 -2
  30. package/dist/{chunk-ASEXQRA7.js → chunk-IMIHTHF7.js} +8 -6
  31. package/dist/{chunk-77MBK46T.js → chunk-IOOFLBVM.js} +3 -3
  32. package/dist/{chunk-3LS3FYEF.js → chunk-JK5WXW4S.js} +2 -2
  33. package/dist/{chunk-GU7QJ37F.js → chunk-JQ43NVFU.js} +2 -2
  34. package/dist/{chunk-YECHJJJF.js → chunk-K7Y2IWEB.js} +4 -4
  35. package/dist/{chunk-VZGPASGD.js → chunk-MG7CUN6R.js} +2 -2
  36. package/dist/{chunk-NOCU555K.js → chunk-NKOTOW6X.js} +3 -3
  37. package/dist/{chunk-YDTRKEYY.js → chunk-OBVXDVLE.js} +3 -3
  38. package/dist/{chunk-TYRVYBHW.js → chunk-OVFQC6FU.js} +235 -176
  39. package/dist/{chunk-VKAJMHVG.js → chunk-OZVGRDCM.js} +3 -3
  40. package/dist/{chunk-FC3X7GGJ.js → chunk-R36RWYXE.js} +3 -3
  41. package/dist/{chunk-Z34CUZCZ.js → chunk-S6E2AM4U.js} +3 -3
  42. package/dist/chunk-SIIOHBNY.js +38 -0
  43. package/dist/{chunk-4YKVHCQC.js → chunk-TGVQMKVH.js} +3 -3
  44. package/dist/{chunk-QU2VRCMM.js → chunk-TL5T4A4E.js} +3 -3
  45. package/dist/{chunk-6ZLRRC74.js → chunk-WBAPU3AB.js} +40 -2
  46. package/dist/{chunk-RV7BVTDG.js → chunk-WKXL5XHU.js} +2 -2
  47. package/dist/{chunk-2CTZW6JQ.js → chunk-XHSHNOAF.js} +12 -11
  48. package/dist/{chunk-24T5XIJU.js → chunk-YA2ZYCJY.js} +4 -4
  49. package/dist/{chunk-T7YVY2BV.js → chunk-YILT3CSO.js} +2 -2
  50. package/dist/{chunk-OUEH4I4X.js → chunk-YJQQ5F5J.js} +3 -3
  51. package/dist/{chunk-MIV2RU5B.js → chunk-ZETZHHV5.js} +3 -3
  52. package/dist/{chunk-4ERMPDHV.js → chunk-ZSW5KO5S.js} +21 -17
  53. package/dist/clarify.d.ts +18 -3
  54. package/dist/codebase-index/codebase-search-tool.d.ts +2 -3
  55. package/dist/codebase-index/gitignore.d.ts +1 -1
  56. package/dist/codebase-index/index.js +7 -7
  57. package/dist/codebase-index/parser-worker-script.js +1 -1
  58. package/dist/codebase-index/project-server-endpoint.d.ts +33 -0
  59. package/dist/codebase-index/project-server.js +6 -5
  60. package/dist/codebase-index/worker.js +3 -3
  61. package/dist/diff.js +2 -2
  62. package/dist/e2e.js +2 -2
  63. package/dist/edit.js +7 -7
  64. package/dist/exec.js +2 -2
  65. package/dist/fetch.js +2 -2
  66. package/dist/format.js +4 -4
  67. package/dist/git.js +2 -2
  68. package/dist/glob.js +3 -3
  69. package/dist/grep.js +3 -3
  70. package/dist/index.d.ts +2 -8
  71. package/dist/index.js +76 -117
  72. package/dist/install.js +4 -4
  73. package/dist/json.js +2 -2
  74. package/dist/kanban.js +2 -2
  75. package/dist/languages/index.js +2 -2
  76. package/dist/{legacy-bridge-WVQ4BHDI.js → legacy-bridge-XM2GV665.js} +4 -4
  77. package/dist/lint.js +4 -4
  78. package/dist/logs.js +2 -2
  79. package/dist/outdated.js +2 -2
  80. package/dist/pack.js +42 -46
  81. package/dist/{parser-dispatch-UQAB4E6V.js → parser-dispatch-HZDZSIYH.js} +2 -2
  82. package/dist/patch.js +7 -7
  83. package/dist/plan.js +4 -4
  84. package/dist/read-url-content.d.ts +17 -0
  85. package/dist/read.js +7 -7
  86. package/dist/replace.js +7 -7
  87. package/dist/session-kanban.js +1 -1
  88. package/dist/session-shell.d.ts +12 -0
  89. package/dist/session-shell.js +8 -0
  90. package/dist/task.js +4 -4
  91. package/dist/test.js +4 -4
  92. package/dist/todo.js +3 -3
  93. package/dist/tool-search.js +1 -1
  94. package/dist/tool-tier.d.ts +12 -2
  95. package/dist/tool-tier.js +43 -47
  96. package/dist/tree.js +2 -2
  97. package/dist/typecheck.js +4 -4
  98. package/dist/write.js +7 -7
  99. package/package.json +9 -21
  100. package/dist/batch-tool-use.d.ts +0 -24
  101. package/dist/batch-tool-use.js +0 -7
  102. package/dist/chunk-7ODZTPCU.js +0 -128
  103. package/dist/chunk-CHEK3ASV.js +0 -183
  104. package/dist/chunk-KLJZ4WV4.js +0 -213
  105. package/dist/chunk-VBF2YXUW.js +0 -203
  106. package/dist/document.d.ts +0 -25
  107. package/dist/document.js +0 -8
  108. package/dist/scaffold.d.ts +0 -23
  109. package/dist/scaffold.js +0 -10
  110. package/dist/set-working-dir.d.ts +0 -17
  111. package/dist/tool-help.d.ts +0 -21
  112. package/dist/tool-help.js +0 -7
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  e2ePlanTool
3
- } from "./chunk-RV7BVTDG.js";
3
+ } from "./chunk-WKXL5XHU.js";
4
4
  import {
5
5
  codebaseAstReplaceTool,
6
6
  codebaseContextTool,
@@ -15,97 +15,85 @@ import {
15
15
  codebaseStatsTool,
16
16
  codebaseTargetedTestTool,
17
17
  deadCodeScanTool
18
- } from "./chunk-PNLDTRC5.js";
18
+ } from "./chunk-CYPYJIAF.js";
19
+ import {
20
+ designTool
21
+ } from "./chunk-IXIS7RSG.js";
19
22
  import {
20
23
  planTool
21
- } from "./chunk-NOCU555K.js";
24
+ } from "./chunk-NKOTOW6X.js";
22
25
  import {
23
26
  taskTool
24
- } from "./chunk-VKAJMHVG.js";
25
- import {
26
- toolSearchTool
27
- } from "./chunk-24T5XIJU.js";
28
- import {
29
- toolUseTool
30
- } from "./chunk-B3MGJBFI.js";
31
- import {
32
- batchToolUseTool
33
- } from "./chunk-VBF2YXUW.js";
34
- import {
35
- toolHelpTool
36
- } from "./chunk-7ODZTPCU.js";
37
- import {
38
- designTool
39
- } from "./chunk-IXIS7RSG.js";
27
+ } from "./chunk-OZVGRDCM.js";
40
28
  import {
41
29
  testTool
42
- } from "./chunk-Z34CUZCZ.js";
30
+ } from "./chunk-S6E2AM4U.js";
43
31
  import {
44
32
  installTool
45
- } from "./chunk-MIV2RU5B.js";
33
+ } from "./chunk-ZETZHHV5.js";
46
34
  import {
47
35
  auditTool
48
- } from "./chunk-KIQTABBJ.js";
36
+ } from "./chunk-C64UUXTA.js";
49
37
  import {
50
38
  outdatedTool
51
- } from "./chunk-OUEH4I4X.js";
39
+ } from "./chunk-YJQQ5F5J.js";
52
40
  import {
53
41
  logsTool
54
- } from "./chunk-VU3QBYL4.js";
42
+ } from "./chunk-2ZWQIVEW.js";
55
43
  import {
56
- documentTool
57
- } from "./chunk-CHEK3ASV.js";
44
+ toolSearchTool
45
+ } from "./chunk-YA2ZYCJY.js";
58
46
  import {
59
- scaffoldTool
60
- } from "./chunk-KLJZ4WV4.js";
47
+ toolUseTool
48
+ } from "./chunk-B3MGJBFI.js";
61
49
  import {
62
50
  gitTool
63
- } from "./chunk-AQ5YBURX.js";
51
+ } from "./chunk-2IC5FRD7.js";
64
52
  import {
65
53
  patchTool
66
- } from "./chunk-E2ZD4ERD.js";
54
+ } from "./chunk-7EQ2LUXU.js";
67
55
  import {
68
56
  jsonTool
69
- } from "./chunk-VZGPASGD.js";
57
+ } from "./chunk-MG7CUN6R.js";
70
58
  import {
71
59
  diffTool
72
- } from "./chunk-7HL23T3T.js";
60
+ } from "./chunk-BU6VUXWG.js";
73
61
  import {
74
62
  treeTool
75
- } from "./chunk-JDOO4P6Z.js";
63
+ } from "./chunk-3F7HQ3KS.js";
76
64
  import {
77
65
  lintTool
78
- } from "./chunk-FC3X7GGJ.js";
66
+ } from "./chunk-R36RWYXE.js";
79
67
  import {
80
68
  formatTool
81
- } from "./chunk-YDTRKEYY.js";
69
+ } from "./chunk-OBVXDVLE.js";
82
70
  import {
83
71
  typecheckTool
84
- } from "./chunk-IRUEHGCR.js";
72
+ } from "./chunk-D4HWMWGE.js";
85
73
  import {
86
74
  languageInfoTool,
87
75
  languagePackageTool,
88
76
  languageTool
89
- } from "./chunk-3LS3FYEF.js";
77
+ } from "./chunk-JK5WXW4S.js";
90
78
  import {
91
79
  replaceTool
92
- } from "./chunk-77MBK46T.js";
80
+ } from "./chunk-IOOFLBVM.js";
93
81
  import {
94
82
  globTool
95
- } from "./chunk-ASEXQRA7.js";
83
+ } from "./chunk-IMIHTHF7.js";
96
84
  import {
97
85
  grepTool
98
- } from "./chunk-4ERMPDHV.js";
86
+ } from "./chunk-ZSW5KO5S.js";
99
87
  import {
100
88
  bashTool,
101
89
  checkAndBlockKillCommand,
102
90
  diagnoseBashism,
103
91
  shellArgs
104
- } from "./chunk-KYVOTHG7.js";
92
+ } from "./chunk-4KI4HHID.js";
105
93
  import {
106
94
  detectDanger,
107
95
  execTool
108
- } from "./chunk-T7YVY2BV.js";
96
+ } from "./chunk-YILT3CSO.js";
109
97
  import {
110
98
  buildChildEnv
111
99
  } from "./chunk-BTSFTGIL.js";
@@ -119,28 +107,31 @@ import {
119
107
  } from "./chunk-HDYUBRMF.js";
120
108
  import {
121
109
  fetchTool
122
- } from "./chunk-DX5KZEMK.js";
110
+ } from "./chunk-47GYABZW.js";
123
111
  import {
124
112
  searchTool
125
113
  } from "./chunk-62OAECEQ.js";
114
+ import {
115
+ guardedFetch
116
+ } from "./chunk-NBDZMMG2.js";
126
117
  import {
127
118
  todoTool
128
- } from "./chunk-4YKVHCQC.js";
119
+ } from "./chunk-TGVQMKVH.js";
129
120
  import {
130
121
  kanbanTool
131
- } from "./chunk-SMARDKAC.js";
122
+ } from "./chunk-5UA4TNJJ.js";
132
123
  import {
133
124
  browserTools
134
- } from "./chunk-SOR7OCYP.js";
125
+ } from "./chunk-6XYFYLN7.js";
135
126
  import {
136
127
  readTool
137
- } from "./chunk-YECHJJJF.js";
128
+ } from "./chunk-K7Y2IWEB.js";
138
129
  import {
139
130
  writeTool
140
- } from "./chunk-QU2VRCMM.js";
131
+ } from "./chunk-TL5T4A4E.js";
141
132
  import {
142
133
  editTool
143
- } from "./chunk-AMURQAJX.js";
134
+ } from "./chunk-G35NLPG5.js";
144
135
  import {
145
136
  resolvePowerShell
146
137
  } from "./chunk-5U5ULQX2.js";
@@ -148,7 +139,7 @@ import {
148
139
  normalizeCommandOutput,
149
140
  safeResolveProjectPath,
150
141
  safeResolveReal
151
- } from "./chunk-ZUFHAHTE.js";
142
+ } from "./chunk-HKR56VNF.js";
152
143
 
153
144
  // src/clarify.ts
154
145
  import { toErrorMessage } from "@wrongstack/core/utils";
@@ -158,8 +149,8 @@ var clarifyTool = {
158
149
  icon: "meta",
159
150
  permission: "auto",
160
151
  mutating: false,
161
- description: "Ask the user for proactive clarification with structured multiple-choice options ONLY when an architectural, database schema, or API decision is truly irreversible and has mutually exclusive trade-offs.",
162
- usageHint: "AUTONOMOUS EXECUTION PRINCIPLE (BIAS FOR ACTION):\n\n- DO NOT overuse or interrupt the user for routine implementation choices. For 95%+ of tasks, autonomously pick the standard best practice and continue executing.\n- Use ONLY when facing an irreversible fork (e.g. data destruction, fundamentally conflicting domain rules) where guessing would be catastrophic.\n- If a solid industry standard exists (e.g. E.164 phone format, indexed foreign keys, ISO dates), adopt it autonomously, execute the next steps, and document the decision in the final reply.",
152
+ description: "Ask the user structured multiple-choice clarification question(s) when an architectural, database schema, API, or domain decision has mutually exclusive trade-offs. Supports single or batch questions, recommended defaults, multi-select, and custom write-in responses across TUI, CLI, and WebUI.",
153
+ usageHint: 'Use when requirements are ambiguous or have critical trade-offs.\n- Single question: pass `question` and `options` (min 2).\n- Multiple questions: pass `questions: [{ question, options, recommendedOption? }]`.\n- Format options as clear user decisions. Prefix best practice choices with "(Recommended)".\n- Autonomous fallback: if running headless without an interactive UI, the recommended option is automatically selected.',
163
154
  inputSchema: {
164
155
  type: "object",
165
156
  properties: {
@@ -174,9 +165,9 @@ var clarifyTool = {
174
165
  options: {
175
166
  type: "array",
176
167
  items: { type: "string" },
177
- description: "2 to 4 distinct options formatted as clear user decisions.",
168
+ description: "2 to 6 distinct options formatted as clear user decisions.",
178
169
  minItems: 2,
179
- maxItems: 5
170
+ maxItems: 6
180
171
  },
181
172
  recommendedOption: {
182
173
  type: "string",
@@ -186,45 +177,112 @@ var clarifyTool = {
186
177
  type: "boolean",
187
178
  description: "Whether multiple options can be chosen simultaneously."
188
179
  },
180
+ is_multi_select: {
181
+ type: "boolean",
182
+ description: "Snake-case alias for isMultiSelect."
183
+ },
189
184
  allowCustomResponse: {
190
185
  type: "boolean",
191
- description: "Whether to allow the user to type a custom response (default: true)."
186
+ description: "Whether to allow the user to type a custom write-in response (default: true)."
187
+ },
188
+ questions: {
189
+ type: "array",
190
+ description: "List of questions for batch clarification (Antigravity ask_question parity).",
191
+ items: {
192
+ type: "object",
193
+ properties: {
194
+ question: { type: "string" },
195
+ context: { type: "string" },
196
+ options: {
197
+ type: "array",
198
+ items: { type: "string" },
199
+ minItems: 2,
200
+ maxItems: 6
201
+ },
202
+ recommendedOption: { type: "string" },
203
+ isMultiSelect: { type: "boolean" },
204
+ is_multi_select: { type: "boolean" },
205
+ allowCustomResponse: { type: "boolean" }
206
+ },
207
+ required: ["question", "options"]
208
+ }
192
209
  }
193
210
  },
194
- required: ["question", "options"],
195
211
  additionalProperties: false
196
212
  },
197
213
  async execute(input, ctx, opts) {
198
214
  try {
199
215
  const signal = opts?.signal ?? ctx?.signal;
200
216
  signal?.throwIfAborted();
201
- const options = input.options;
202
- if (!options || options.length < 2) {
203
- throw new Error("clarify requires at least 2 distinct options.");
204
- }
205
- const hostAsk = ctx.askUserChoices;
206
- if (typeof hostAsk === "function") {
207
- const res = await hostAsk(input.question, options, input.isMultiSelect);
208
- const selected = Array.isArray(res?.selected) ? res.selected : [];
209
- return {
210
- status: "answered",
217
+ const items = [];
218
+ if (Array.isArray(input.questions) && input.questions.length > 0) {
219
+ items.push(...input.questions);
220
+ } else if (input.question && Array.isArray(input.options)) {
221
+ items.push({
211
222
  question: input.question,
212
- selectedOptions: selected,
213
- customResponse: res?.custom,
214
- decisionSummary: `User selected: ${selected.join(", ")}${res?.custom ? ` (Custom: ${res.custom})` : ""}`
215
- };
223
+ context: input.context,
224
+ options: input.options,
225
+ recommendedOption: input.recommendedOption,
226
+ isMultiSelect: input.isMultiSelect ?? input.is_multi_select,
227
+ allowCustomResponse: input.allowCustomResponse
228
+ });
229
+ }
230
+ if (items.length === 0) {
231
+ throw new Error("clarify requires either `question` with `options`, or a `questions` array with at least 1 item.");
216
232
  }
217
- const defaultChoice = input.recommendedOption ?? options[0] ?? "Default";
233
+ for (const item of items) {
234
+ if (!item.options || item.options.length < 2) {
235
+ throw new Error(`clarify question "${item.question}" requires at least 2 distinct options.`);
236
+ }
237
+ }
238
+ const hostAsk = ctx?.askUserChoices;
239
+ const answers = [];
240
+ let isAutoDecided = false;
241
+ for (const item of items) {
242
+ const multi = item.isMultiSelect ?? item.is_multi_select ?? false;
243
+ const options = item.options;
244
+ if (typeof hostAsk === "function") {
245
+ const res = await hostAsk(item.question, options, {
246
+ isMultiSelect: multi,
247
+ ...item.context === void 0 ? {} : { context: item.context },
248
+ ...item.recommendedOption === void 0 ? {} : { recommendedOption: item.recommendedOption },
249
+ allowCustomResponse: item.allowCustomResponse ?? true
250
+ });
251
+ const selected = Array.isArray(res?.selected) ? res.selected : [];
252
+ answers.push({
253
+ question: item.question,
254
+ selectedOptions: selected,
255
+ customResponse: res?.custom
256
+ });
257
+ } else {
258
+ isAutoDecided = true;
259
+ const rec = item.recommendedOption ?? options.find((opt) => /^\(?recommended\)?/i.test(opt)) ?? options[0] ?? "Default";
260
+ answers.push({
261
+ question: item.question,
262
+ selectedOptions: [rec],
263
+ customResponse: void 0
264
+ });
265
+ }
266
+ }
267
+ const primary = answers[0];
268
+ const summaries = answers.map((ans) => {
269
+ const customPart = ans.customResponse ? ` (Custom: "${ans.customResponse}")` : "";
270
+ return `"${ans.question}": ${ans.selectedOptions.join(", ")}${customPart}`;
271
+ });
272
+ const decisionSummary = isAutoDecided ? `Auto-selected recommended option(s) in non-interactive mode: ${summaries.join("; ")}` : `User clarified: ${summaries.join("; ")}`;
218
273
  return {
219
- status: "auto_decided",
220
- question: input.question,
221
- selectedOptions: [defaultChoice],
222
- decisionSummary: `Auto-selected recommended option: "${defaultChoice}" (Non-interactive mode)`
274
+ status: isAutoDecided ? "auto_decided" : "answered",
275
+ question: primary.question,
276
+ selectedOptions: primary.selectedOptions,
277
+ customResponse: primary.customResponse,
278
+ answers,
279
+ decisionSummary
223
280
  };
224
281
  } catch (err) {
282
+ const fallbackQuestion = input.question ?? input.questions?.[0]?.question ?? "";
225
283
  return {
226
284
  status: "skipped",
227
- question: input.question ?? "",
285
+ question: fallbackQuestion,
228
286
  selectedOptions: [],
229
287
  decisionSummary: "",
230
288
  error: toErrorMessage(err)
@@ -920,6 +978,91 @@ ${hint}` : "") + cautionText;
920
978
  }
921
979
  };
922
980
 
981
+ // src/read-url-content.ts
982
+ import TurndownService from "turndown";
983
+ var TD = new TurndownService({
984
+ headingStyle: "atx",
985
+ codeBlockStyle: "fenced"
986
+ });
987
+ TD.addRule("stripDangerousElements", {
988
+ filter: ["script", "style", "noscript"],
989
+ replacement: () => ""
990
+ });
991
+ var PRUNED_BOILERPLATE_TAGS = /* @__PURE__ */ new Set(["nav", "header", "footer", "aside", "svg", "iframe"]);
992
+ TD.remove((node) => PRUNED_BOILERPLATE_TAGS.has(node.nodeName.toLowerCase()));
993
+ var DEFAULT_MAX_BYTES = 131072;
994
+ var TIMEOUT_MS = 25e3;
995
+ var readUrlContentTool = {
996
+ name: "read_url_content",
997
+ category: "Network",
998
+ icon: "web",
999
+ permission: "auto",
1000
+ mutating: false,
1001
+ capabilities: ["net.outbound"],
1002
+ subjectKey: "url",
1003
+ timeoutMs: TIMEOUT_MS,
1004
+ maxOutputBytes: DEFAULT_MAX_BYTES,
1005
+ description: "Fetch content from a URL via HTTP request (invisible to USER). Use when: (1) extracting text from public pages, (2) reading static content/documentation, (3) batch processing multiple URLs, (4) speed is important, or (5) no visual interaction needed. Converts HTML to clean markdown. No JavaScript execution, no authentication.",
1006
+ usageHint: 'Provide `url` (e.g. "https://example.com/docs"). Converts HTML to readable markdown, stripping scripts, styles, navigation bars, headers, and footers to conserve token budget. For pages requiring interactive login, JavaScript rendering, or visual inspection, use browser tools instead.',
1007
+ inputSchema: {
1008
+ type: "object",
1009
+ properties: {
1010
+ url: {
1011
+ type: "string",
1012
+ description: "URL to read content from."
1013
+ },
1014
+ Url: {
1015
+ type: "string",
1016
+ description: "Case-tolerant alias for URL."
1017
+ },
1018
+ maxBytes: {
1019
+ type: "number",
1020
+ description: "Maximum bytes to retrieve (default: 128KB)."
1021
+ }
1022
+ },
1023
+ additionalProperties: false
1024
+ },
1025
+ async execute(input, ctx, opts) {
1026
+ const rawUrl = (input.url ?? input.Url)?.trim();
1027
+ if (!rawUrl) {
1028
+ throw new Error("read_url_content requires a valid `url` parameter.");
1029
+ }
1030
+ const maxBytes = input.maxBytes ?? DEFAULT_MAX_BYTES;
1031
+ const signal = opts?.signal ?? ctx?.signal ?? new AbortController().signal;
1032
+ const res = await guardedFetch(rawUrl, 5, signal, {
1033
+ "user-agent": "Mozilla/5.0 (compatible; WrongStackReader/1.0; +https://wrongstack.dev)",
1034
+ accept: "text/html,application/xhtml+xml,application/xml;q=0.9,text/plain;q=0.8,application/json;q=0.5,*/*;q=0.1"
1035
+ });
1036
+ const contentType = res.headers.get("content-type") ?? "text/plain";
1037
+ const rawBody = await res.text();
1038
+ let content;
1039
+ if (contentType.includes("text/html") || contentType.includes("application/xhtml+xml")) {
1040
+ content = TD.turndown(rawBody).trim();
1041
+ } else if (contentType.includes("application/json")) {
1042
+ try {
1043
+ const parsed = JSON.parse(rawBody);
1044
+ content = JSON.stringify(parsed, null, 2);
1045
+ } catch {
1046
+ content = rawBody;
1047
+ }
1048
+ } else {
1049
+ content = rawBody;
1050
+ }
1051
+ if (Buffer.byteLength(content, "utf8") > maxBytes) {
1052
+ const buf = Buffer.from(content, "utf8");
1053
+ content = `${buf.subarray(0, maxBytes).toString("utf8")}
1054
+
1055
+ [Content truncated at ${maxBytes} bytes]`;
1056
+ }
1057
+ return {
1058
+ url: res.url || rawUrl,
1059
+ status: res.status,
1060
+ content_type: contentType,
1061
+ content
1062
+ };
1063
+ }
1064
+ };
1065
+
923
1066
  // src/security-ast-scan-tool.ts
924
1067
  import * as fs from "node:fs/promises";
925
1068
  import * as path from "node:path";
@@ -1138,74 +1281,6 @@ var securityAstScanTool = {
1138
1281
  }
1139
1282
  };
1140
1283
 
1141
- // src/set-working-dir.ts
1142
- import * as fs2 from "node:fs/promises";
1143
- import { toErrorMessage as toErrorMessage3 } from "@wrongstack/core/utils";
1144
- var setWorkingDirTool = {
1145
- name: "set_working_dir",
1146
- category: "Context",
1147
- description: "Change the current working directory for subsequent file operations and shell tools (`bash`/`exec` spawn in this directory unless given an explicit cwd). The new directory must be inside the project root. Use this to navigate between subdirectories when working on files in different parts of the project.",
1148
- usageHint: "Change the working directory so relative paths in subsequent tool calls resolve from a different directory. Pass `path` to set a new directory, or omit to query the current one. The directory must exist and be inside the project root.",
1149
- permission: "confirm",
1150
- mutating: true,
1151
- capabilities: ["fs.read"],
1152
- icon: "settings",
1153
- timeoutMs: 5e3,
1154
- inputSchema: {
1155
- type: "object",
1156
- properties: {
1157
- path: {
1158
- type: "string",
1159
- description: "Directory to navigate to. Can be relative (to projectRoot) or absolute. If omitted, returns the current working directory without changing it."
1160
- }
1161
- }
1162
- },
1163
- async execute(input, ctx, _opts) {
1164
- if (!input.path) {
1165
- return {
1166
- current: ctx.workingDir,
1167
- message: `Current working directory is ${ctx.workingDir}`
1168
- };
1169
- }
1170
- const previous = ctx.workingDir;
1171
- let resolved;
1172
- try {
1173
- resolved = ctx.setWorkingDir(input.path);
1174
- } catch (err) {
1175
- return {
1176
- current: ctx.workingDir,
1177
- error: toErrorMessage3(err)
1178
- };
1179
- }
1180
- let isDirectory = false;
1181
- try {
1182
- isDirectory = (await fs2.stat(resolved)).isDirectory();
1183
- } catch {
1184
- isDirectory = false;
1185
- }
1186
- if (!isDirectory) {
1187
- try {
1188
- if (typeof previous === "string") {
1189
- ctx.setWorkingDir(previous);
1190
- } else {
1191
- ctx.workingDir = previous;
1192
- }
1193
- } catch {
1194
- ctx.workingDir = previous;
1195
- }
1196
- return {
1197
- current: ctx.workingDir,
1198
- error: `Directory does not exist (or is not a directory): ${resolved}`
1199
- };
1200
- }
1201
- return {
1202
- current: resolved,
1203
- previous,
1204
- message: `Working directory changed to ${resolved}`
1205
- };
1206
- }
1207
- };
1208
-
1209
1284
  // src/builtin.ts
1210
1285
  var BUILTIN_TOOL_DESCRIPTIONS = {
1211
1286
  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.",
@@ -1226,6 +1301,7 @@ var BUILTIN_TOOL_DESCRIPTIONS = {
1226
1301
  browser_close: "Close an owned browser session and reclaim its resources, returning trace-artifact metadata when tracing was enabled.",
1227
1302
  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.",
1228
1303
  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.",
1304
+ read_url_content: "Fetch content from a URL via HTTP request and convert HTML directly to clean markdown. Use for public docs and web pages without browser overhead.",
1229
1305
  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.",
1230
1306
  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.",
1231
1307
  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.",
@@ -1271,14 +1347,9 @@ var BUILTIN_TOOL_DESCRIPTIONS = {
1271
1347
  audit: "Run the package manager\u2019s dependency vulnerability audit and summarize actionable findings. Use it to assess known dependency advisories, not source-code vulnerabilities.",
1272
1348
  outdated: "List outdated project dependencies and available versions without changing manifests or lockfiles. Use it to plan dependency maintenance.",
1273
1349
  logs: "Read or tail configured local, container, or process logs with bounded output. Use it to investigate a known runtime failure or service behavior.",
1274
- document: "List undocumented symbols as read-only candidates; this deprecated preview stub does not generate docstrings or write files. Use the auto-doc plugin when it is enabled.",
1275
- scaffold: "Preview or generate files from a built-in or custom scaffold template. Writes files to disk unless dry_run is set. Use dry_run first to inspect paths and content before creating project files.",
1276
1350
  design: "Choose, preview, or materialize a UI design kit (e.g. minimal-clarity, neo-brutalist) for the active stack. Lists available kits, previews tokens, or writes a design-token source file to the project.",
1277
- 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.",
1278
- 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.",
1279
- 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.",
1280
- 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.",
1281
- 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."
1351
+ tool_search: "Search the full tool catalog by name or description, including tools whose schemas were withheld from this request to save tokens. Use it before concluding a capability is unavailable; invoke what you find with tool_use.",
1352
+ tool_use: "Invoke a registered tool by its exact name, including one not listed in this request. Use it for a tool found through tool_search; the call still goes through the same permission and capability checks as a direct call."
1282
1353
  };
1283
1354
  var OPTIONAL_TOOLS = [
1284
1355
  ...browserTools,
@@ -1286,14 +1357,7 @@ var OPTIONAL_TOOLS = [
1286
1357
  installTool,
1287
1358
  auditTool,
1288
1359
  outdatedTool,
1289
- logsTool,
1290
- documentTool,
1291
- scaffoldTool,
1292
- toolSearchTool,
1293
- toolUseTool,
1294
- batchToolUseTool,
1295
- toolHelpTool,
1296
- setWorkingDirTool
1360
+ logsTool
1297
1361
  ];
1298
1362
  var OFF_ONLY_TOOLS = [...browserTools, e2ePlanTool];
1299
1363
  var TIER1_TOOLS = [
@@ -1320,13 +1384,19 @@ var TIER1_TOOLS = [
1320
1384
  diffTool,
1321
1385
  patchTool,
1322
1386
  jsonTool,
1323
- searchTool
1387
+ searchTool,
1388
+ // The gateway pair must be in the smallest tier: every tier below `off`
1389
+ // withholds tool schemas, and these two are the only way the model can find
1390
+ // and call what was withheld.
1391
+ toolSearchTool,
1392
+ toolUseTool
1324
1393
  ];
1325
1394
  var TIER2_TOOLS = [
1326
1395
  replaceTool,
1327
1396
  execTool,
1328
1397
  pwshTool,
1329
1398
  fetchTool,
1399
+ readUrlContentTool,
1330
1400
  gitTool,
1331
1401
  treeTool,
1332
1402
  lintTool,
@@ -1347,19 +1417,13 @@ var TIER2_TOOLS = [
1347
1417
  var TIER3_TOOLS = [
1348
1418
  outdatedTool,
1349
1419
  logsTool,
1350
- documentTool,
1351
- scaffoldTool,
1352
- deadCodeScanTool,
1353
- toolSearchTool,
1354
- toolUseTool,
1355
- batchToolUseTool,
1356
- toolHelpTool,
1357
- setWorkingDirTool
1420
+ deadCodeScanTool
1358
1421
  ];
1359
1422
  var rawBuiltinTools = [
1360
1423
  ...browserTools,
1361
1424
  e2ePlanTool,
1362
1425
  readTool,
1426
+ readUrlContentTool,
1363
1427
  writeTool,
1364
1428
  editTool,
1365
1429
  clarifyTool,
@@ -1405,14 +1469,9 @@ var rawBuiltinTools = [
1405
1469
  auditTool,
1406
1470
  outdatedTool,
1407
1471
  logsTool,
1408
- documentTool,
1409
- scaffoldTool,
1410
1472
  designTool,
1411
1473
  toolSearchTool,
1412
- toolUseTool,
1413
- batchToolUseTool,
1414
- toolHelpTool,
1415
- setWorkingDirTool
1474
+ toolUseTool
1416
1475
  ];
1417
1476
  var builtinTools = rawBuiltinTools.map((tool) => {
1418
1477
  const description = BUILTIN_TOOL_DESCRIPTIONS[tool.name];
@@ -1427,9 +1486,9 @@ export {
1427
1486
  PWSH_TOOL_DESCRIPTION,
1428
1487
  PWSH_TOOL_USAGE_HINT,
1429
1488
  pwshTool,
1489
+ readUrlContentTool,
1430
1490
  analyzeSecurityAndPerformance,
1431
1491
  securityAstScanTool,
1432
- setWorkingDirTool,
1433
1492
  BUILTIN_TOOL_DESCRIPTIONS,
1434
1493
  OPTIONAL_TOOLS,
1435
1494
  OFF_ONLY_TOOLS,
@@ -1438,4 +1497,4 @@ export {
1438
1497
  TIER3_TOOLS,
1439
1498
  builtinTools
1440
1499
  };
1441
- //# sourceMappingURL=chunk-TYRVYBHW.js.map
1500
+ //# sourceMappingURL=chunk-OVFQC6FU.js.map
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  todoTool
3
- } from "./chunk-4YKVHCQC.js";
3
+ } from "./chunk-TGVQMKVH.js";
4
4
  import {
5
5
  mirrorSessionTasksToKanban
6
- } from "./chunk-X6KXNHUO.js";
6
+ } from "./chunk-5BKQVP56.js";
7
7
 
8
8
  // src/task.ts
9
9
  import { randomUUID } from "node:crypto";
@@ -582,4 +582,4 @@ ${formatTaskList(file.tasks)}` : file.tasks.length > 0 ? formatTaskList(file.tas
582
582
  export {
583
583
  taskTool
584
584
  };
585
- //# sourceMappingURL=chunk-VKAJMHVG.js.map
585
+ //# sourceMappingURL=chunk-OZVGRDCM.js.map
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  tryLegacyCodeOperation
3
- } from "./chunk-GU7QJ37F.js";
3
+ } from "./chunk-JQ43NVFU.js";
4
4
  import {
5
5
  spawnStream
6
6
  } from "./chunk-EMA2XENR.js";
7
7
  import {
8
8
  normalizeCommandOutput,
9
9
  safeResolveReal
10
- } from "./chunk-ZUFHAHTE.js";
10
+ } from "./chunk-HKR56VNF.js";
11
11
 
12
12
  // src/lint.ts
13
13
  import { ToolValidationError } from "@wrongstack/core/types";
@@ -189,4 +189,4 @@ async function detectLinter(cwd) {
189
189
  export {
190
190
  lintTool
191
191
  };
192
- //# sourceMappingURL=chunk-FC3X7GGJ.js.map
192
+ //# sourceMappingURL=chunk-R36RWYXE.js.map
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  tryLegacyCodeOperation
3
- } from "./chunk-GU7QJ37F.js";
3
+ } from "./chunk-JQ43NVFU.js";
4
4
  import {
5
5
  spawnStream
6
6
  } from "./chunk-EMA2XENR.js";
7
7
  import {
8
8
  normalizeCommandOutput,
9
9
  safeResolveReal
10
- } from "./chunk-ZUFHAHTE.js";
10
+ } from "./chunk-HKR56VNF.js";
11
11
 
12
12
  // src/test.ts
13
13
  import * as path from "node:path";
@@ -231,4 +231,4 @@ ${result.stderr}` : result.stdout || result.stderr || result.error || "";
231
231
  export {
232
232
  testTool
233
233
  };
234
- //# sourceMappingURL=chunk-Z34CUZCZ.js.map
234
+ //# sourceMappingURL=chunk-S6E2AM4U.js.map