@wrongstack/tools 0.313.0 → 0.316.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.
- package/dist/_edit-match.d.ts +3 -2
- package/dist/_output-spool.d.ts +4 -3
- package/dist/_shell-pick.d.ts +2 -1
- package/dist/_spawn-stream.d.ts +2 -1
- package/dist/_syntax-check.d.ts +2 -1
- package/dist/audit.js +10 -4055
- package/dist/bash-kill-guard.d.ts +3 -6
- package/dist/bash.js +9 -2308
- package/dist/batch-tool-use.js +2 -187
- package/dist/browser/index.js +25 -1339
- package/dist/browser/network-guard-proxy.d.ts +2 -1
- package/dist/builtin.js +69 -33949
- package/dist/chunk-22B7GE5T.js +260 -0
- package/dist/chunk-2VSZC6QM.js +113 -0
- package/dist/chunk-3PVYQFRQ.js +472 -0
- package/dist/chunk-42BHI7TN.js +337 -0
- package/dist/chunk-4BHUSMNL.js +104 -0
- package/dist/chunk-4I4LWFOO.js +431 -0
- package/dist/chunk-4UESMQDP.js +122 -0
- package/dist/chunk-553IQUMO.js +478 -0
- package/dist/chunk-5H4GSJAI.js +223 -0
- package/dist/chunk-6RNIFLG4.js +305 -0
- package/dist/chunk-7EY5DCRO.js +434 -0
- package/dist/chunk-A6BRWIXN.js +317 -0
- package/dist/chunk-AHHDWNXC.js +200 -0
- package/dist/chunk-BSLVR56S.js +199 -0
- package/dist/chunk-BTSFTGIL.js +7 -0
- package/dist/chunk-D33S4RQG.js +222 -0
- package/dist/chunk-DA4KNE2H.js +4412 -0
- package/dist/chunk-DR7JOQTC.js +520 -0
- package/dist/chunk-EEOFQDT6.js +898 -0
- package/dist/chunk-EJWSCQ6D.js +137 -0
- package/dist/chunk-EMRGN4KM.js +170 -0
- package/dist/chunk-FQZOHLG3.js +89 -0
- package/dist/chunk-GOIZNNOA.js +221 -0
- package/dist/chunk-HFXSNKCV.js +196 -0
- package/dist/chunk-HYX2TZ7O.js +1272 -0
- package/dist/chunk-I64BS3VC.js +15 -0
- package/dist/chunk-IVWV2UM6.js +955 -0
- package/dist/chunk-IXMNTNW5.js +238 -0
- package/dist/chunk-IYK7XGDZ.js +892 -0
- package/dist/chunk-J5SKD6LN.js +235 -0
- package/dist/chunk-JNNVRHMV.js +2111 -0
- package/dist/chunk-JOHXDF3D.js +295 -0
- package/dist/chunk-JRJJX3L5.js +424 -0
- package/dist/chunk-K3WNSHUF.js +1371 -0
- package/dist/chunk-L25CVUVR.js +2830 -0
- package/dist/chunk-LIJQMYYX.js +59 -0
- package/dist/chunk-LWKUTMD5.js +197 -0
- package/dist/chunk-MQX2KXVW.js +54 -0
- package/dist/chunk-MZZN7VCD.js +359 -0
- package/dist/chunk-NBDZMMG2.js +169 -0
- package/dist/chunk-NKJW5GFO.js +366 -0
- package/dist/chunk-NKNOBUBU.js +522 -0
- package/dist/chunk-O4MBV4AX.js +134 -0
- package/dist/chunk-OUBDL3WH.js +3515 -0
- package/dist/chunk-PQKK5JH7.js +101 -0
- package/dist/chunk-PY2IOS7C.js +1000 -0
- package/dist/chunk-Q5JPPCZC.js +12 -0
- package/dist/chunk-QBV725YG.js +128 -0
- package/dist/chunk-QZQSPUBF.js +315 -0
- package/dist/chunk-RGISBZBD.js +231 -0
- package/dist/chunk-RJZQWEMS.js +84 -0
- package/dist/chunk-RXISBFR5.js +315 -0
- package/dist/chunk-S5CCLZL3.js +99 -0
- package/dist/chunk-SDLVH5RZ.js +178 -0
- package/dist/chunk-T2F4S7U4.js +1723 -0
- package/dist/chunk-TEBQ4VPZ.js +163 -0
- package/dist/chunk-U4D5S3VQ.js +21 -0
- package/dist/chunk-U4VAATKP.js +193 -0
- package/dist/chunk-UCYQTZ7F.js +113 -0
- package/dist/chunk-UKU2ZX4C.js +203 -0
- package/dist/chunk-UNSKG6DC.js +159 -0
- package/dist/chunk-V43EQ6VR.js +68 -0
- package/dist/chunk-VB3MJGCV.js +610 -0
- package/dist/chunk-VFKPWSOX.js +154 -0
- package/dist/chunk-VJNHFZ7J.js +190 -0
- package/dist/chunk-VXECAJJ7.js +1091 -0
- package/dist/chunk-WHIIIREL.js +223 -0
- package/dist/chunk-Z6DAKQ3U.js +1 -0
- package/dist/chunk-ZJQ4IGXK.js +474 -0
- package/dist/chunk-ZLTFLC25.js +385 -0
- package/dist/circuit-breaker.js +3 -191
- package/dist/codebase-index/ast-invariant-engine.d.ts +5 -4
- package/dist/codebase-index/binary-frame.d.ts +0 -2
- package/dist/codebase-index/bm25.d.ts +1 -1
- package/dist/codebase-index/circuit-breaker.d.ts +2 -1
- package/dist/codebase-index/codebase-ast-replace-tool.d.ts +3 -2
- package/dist/codebase-index/codebase-impact-analysis-tool.d.ts +4 -3
- package/dist/codebase-index/codebase-invariant-check-tool.d.ts +3 -2
- package/dist/codebase-index/codebase-repo-map-tool.d.ts +3 -2
- package/dist/codebase-index/codebase-skeleton-tool.d.ts +3 -2
- package/dist/codebase-index/codebase-targeted-test-tool.d.ts +3 -2
- package/dist/codebase-index/content-hash.d.ts +0 -2
- package/dist/codebase-index/import-extractor.d.ts +0 -13
- package/dist/codebase-index/index-service.d.ts +1 -1
- package/dist/codebase-index/index.js +84 -13688
- package/dist/codebase-index/languages.d.ts +2 -1
- package/dist/codebase-index/module-roots.d.ts +3 -2
- package/dist/codebase-index/parser-batch.d.ts +0 -5
- package/dist/codebase-index/parser-dispatch.d.ts +2 -1
- package/dist/codebase-index/parser-output.d.ts +4 -3
- package/dist/codebase-index/parser-worker-pool.d.ts +0 -2
- package/dist/codebase-index/parser-worker-script.d.ts +1 -16
- package/dist/codebase-index/parser-worker-script.js +8 -3995
- package/dist/codebase-index/project-server-client-state.d.ts +2 -2
- package/dist/codebase-index/project-server-endpoint.d.ts +0 -15
- package/dist/codebase-index/project-server.js +60 -8548
- package/dist/codebase-index/tree-sitter/visitor.d.ts +2 -1
- package/dist/codebase-index/tree-sitter-parser.d.ts +0 -2
- package/dist/codebase-index/ts-parser.d.ts +1 -1
- package/dist/codebase-index/vector-search.d.ts +2 -1
- package/dist/codebase-index/wal-maintenance.d.ts +3 -2
- package/dist/codebase-index/worker.js +20 -8416
- package/dist/codebase-index/writer-admin.d.ts +0 -1
- package/dist/codebase-index/writer-search.d.ts +0 -9
- package/dist/design.js +2 -299
- package/dist/diff.js +4 -256
- package/dist/document.js +4 -222
- package/dist/e2e.js +5 -476
- package/dist/edit.js +14 -10200
- package/dist/exec.js +16 -3131
- package/dist/fetch.js +8 -398
- package/dist/format.js +10 -3750
- package/dist/generic-parser-VUXDIAOZ.js +13 -0
- package/dist/git.js +4 -380
- package/dist/glob.js +6 -280
- package/dist/go-parser-JXYKJHRC.js +469 -0
- package/dist/grep.js +7 -604
- package/dist/index.js +318 -35387
- package/dist/install.js +10 -4091
- package/dist/json-parser-IBHZ4BZC.js +213 -0
- package/dist/json.js +4 -665
- package/dist/kanban-contract-actions.d.ts +1 -1
- package/dist/kanban-detail-actions.d.ts +2 -1
- package/dist/kanban-presence.d.ts +2 -1
- package/dist/kanban-serializer.d.ts +0 -8
- package/dist/kanban-split-task-handler.d.ts +2 -2
- package/dist/kanban-tool-types.d.ts +2 -1
- package/dist/kanban.js +3 -2096
- package/dist/languages/diagnostics.d.ts +2 -1
- package/dist/languages/index.js +23 -4664
- package/dist/languages/legacy-bridge.d.ts +3 -2
- package/dist/languages/types.d.ts +2 -1
- package/dist/legacy-bridge-7M6QLUQN.js +18 -0
- package/dist/lint.js +10 -3706
- package/dist/logs.js +4 -287
- package/dist/memory.js +6 -215
- package/dist/mode.js +3 -99
- package/dist/outdated.js +4 -5170
- package/dist/pack.js +65 -33897
- package/dist/parser-dispatch-QH4XPGG6.js +14 -0
- package/dist/patch.js +13 -9935
- package/dist/plan.js +5 -3286
- package/dist/process-registry.js +8 -651
- package/dist/ps-slash.js +12 -1439
- package/dist/pwsh.d.ts +0 -1
- package/dist/py-parser-IS4HKYMF.js +16 -0
- package/dist/read.js +13 -9816
- package/dist/replace.js +15 -10014
- package/dist/rs-parser-XHUUO2KZ.js +81 -0
- package/dist/scaffold.js +4 -253
- package/dist/search.js +5 -585
- package/dist/session-kanban-sync.d.ts +0 -6
- package/dist/session-kanban.js +30 -972
- package/dist/skill.js +2 -215
- package/dist/spawn-background.d.ts +1 -1
- package/dist/task.js +5 -3410
- package/dist/test.js +10 -3773
- package/dist/todo.js +4 -2891
- package/dist/tool-help.js +3 -123
- package/dist/tool-search.js +3 -79
- package/dist/tool-tier.js +68 -33984
- package/dist/tool-use.js +2 -93
- package/dist/tree-sitter-parser-AIERW3YI.js +15 -0
- package/dist/tree.js +4 -288
- package/dist/ts-parser-RCTYKSVI.js +232 -0
- package/dist/typecheck.js +10 -3753
- package/dist/win32.js +6 -60
- package/dist/write.js +14 -9882
- package/dist/yaml-parser-4SAXV3PL.js +157 -0
- package/package.json +5 -5
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ALLOW_PRIVATE,
|
|
3
|
+
assertNotPrivate,
|
|
4
|
+
guardedFetch
|
|
5
|
+
} from "./chunk-NBDZMMG2.js";
|
|
6
|
+
import {
|
|
7
|
+
truncateMiddle
|
|
8
|
+
} from "./chunk-D33S4RQG.js";
|
|
9
|
+
|
|
10
|
+
// src/fetch.ts
|
|
11
|
+
import { FetchError, ToolError, ToolValidationError } from "@wrongstack/core/types";
|
|
12
|
+
import TurndownService from "turndown";
|
|
13
|
+
var TD = new TurndownService({
|
|
14
|
+
// Use `# Title` for headings, not setext underline style (`Title\n=====`).
|
|
15
|
+
headingStyle: "atx",
|
|
16
|
+
// Don't wrap code blocks in <pre> — render them as triple-backtick blocks.
|
|
17
|
+
codeBlockStyle: "fenced"
|
|
18
|
+
});
|
|
19
|
+
TD.addRule("stripDangerousElements", {
|
|
20
|
+
filter: ["script", "style", "noscript"],
|
|
21
|
+
replacement: () => ""
|
|
22
|
+
});
|
|
23
|
+
var PRUNED_BOILERPLATE_TAGS = /* @__PURE__ */ new Set(["nav", "header", "footer", "aside", "svg", "iframe"]);
|
|
24
|
+
TD.remove((node) => PRUNED_BOILERPLATE_TAGS.has(node.nodeName.toLowerCase()));
|
|
25
|
+
var MAX_BYTES = 131072;
|
|
26
|
+
var TIMEOUT_MS = 2e4;
|
|
27
|
+
var combineSignals = (signals) => AbortSignal.any(signals);
|
|
28
|
+
var fetchTool = {
|
|
29
|
+
name: "fetch",
|
|
30
|
+
category: "Network",
|
|
31
|
+
description: "Fetch a URL and return its content. HTML pages are automatically converted to clean markdown. This tool has strong SSRF protections (private IPs, localhost, and cloud metadata endpoints are blocked by default).",
|
|
32
|
+
usageHint: "Use this when you need external information (documentation, API responses, web pages, etc.).\n\nSecurity notes:\n- Only HTTPS is allowed by default.\n- Internal/private networks are blocked unless explicitly enabled via environment variable.\n- Redirects are followed but re-validated at each hop.\n- Output is capped (128KB by default) to avoid flooding context.\nPrefer this over raw `bash curl` or `bash wget`.",
|
|
33
|
+
permission: "auto",
|
|
34
|
+
mutating: false,
|
|
35
|
+
capabilities: ["net.outbound"],
|
|
36
|
+
icon: "web",
|
|
37
|
+
// Trust rules for fetch match on the literal URL — declare it explicitly
|
|
38
|
+
// so a user can trust `https://api.example.com/*` without accidentally
|
|
39
|
+
// matching that pattern on any other tool that happens to have a `url`
|
|
40
|
+
// input field.
|
|
41
|
+
subjectKey: "url",
|
|
42
|
+
timeoutMs: TIMEOUT_MS,
|
|
43
|
+
maxOutputBytes: MAX_BYTES,
|
|
44
|
+
inputSchema: {
|
|
45
|
+
type: "object",
|
|
46
|
+
properties: {
|
|
47
|
+
url: {
|
|
48
|
+
type: "string",
|
|
49
|
+
description: "The target URL (must use https://)."
|
|
50
|
+
},
|
|
51
|
+
format: {
|
|
52
|
+
type: "string",
|
|
53
|
+
enum: ["markdown", "text", "raw"],
|
|
54
|
+
description: 'Output format. "markdown" is recommended for HTML pages; for non-HTML content types it falls back to plain text (JSON is pretty-printed).'
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
required: ["url"]
|
|
58
|
+
},
|
|
59
|
+
async execute(input, ctx, opts) {
|
|
60
|
+
let final;
|
|
61
|
+
const executeStream = fetchTool.executeStream;
|
|
62
|
+
if (!executeStream) {
|
|
63
|
+
throw new ToolError({
|
|
64
|
+
message: "fetchTool: stream execution unavailable",
|
|
65
|
+
code: "TOOL_EXECUTION_FAILED",
|
|
66
|
+
toolName: "fetch"
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
for await (const ev of executeStream(input, ctx, opts)) {
|
|
70
|
+
if (ev.type === "final") final = ev.output;
|
|
71
|
+
}
|
|
72
|
+
if (!final) {
|
|
73
|
+
throw new ToolError({
|
|
74
|
+
message: "fetch: stream ended without final event",
|
|
75
|
+
code: "TOOL_EXECUTION_FAILED",
|
|
76
|
+
toolName: "fetch"
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
return final;
|
|
80
|
+
},
|
|
81
|
+
async *executeStream(input, ctx, opts) {
|
|
82
|
+
if (!input?.url) {
|
|
83
|
+
throw new ToolValidationError({
|
|
84
|
+
message: "fetch: url is required",
|
|
85
|
+
field: "url"
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
const u = new URL(input.url);
|
|
89
|
+
if (u.username || u.password) {
|
|
90
|
+
throw new ToolValidationError({
|
|
91
|
+
message: "fetch: URLs with embedded credentials (user:pass@host) are not allowed",
|
|
92
|
+
field: "url"
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
if (u.protocol !== "https:" && u.protocol !== "http:") {
|
|
96
|
+
throw new ToolValidationError({
|
|
97
|
+
message: `fetch: unsupported protocol "${u.protocol}"`,
|
|
98
|
+
field: "url"
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
if (u.protocol === "http:" && !ALLOW_PRIVATE) {
|
|
102
|
+
throw new ToolValidationError({
|
|
103
|
+
message: "fetch: http:// blocked (HTTPS required by default)",
|
|
104
|
+
field: "url"
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
await assertNotPrivate(u.hostname);
|
|
108
|
+
yield { type: "log", text: `GET ${input.url}` };
|
|
109
|
+
const ctrl = new AbortController();
|
|
110
|
+
const timer = setTimeout(
|
|
111
|
+
() => ctrl.abort(
|
|
112
|
+
new ToolError({
|
|
113
|
+
message: "fetch timeout",
|
|
114
|
+
code: "TOOL_TIMEOUT",
|
|
115
|
+
toolName: "fetch"
|
|
116
|
+
})
|
|
117
|
+
),
|
|
118
|
+
TIMEOUT_MS
|
|
119
|
+
);
|
|
120
|
+
const combined = combineSignals([opts.signal, ctrl.signal]);
|
|
121
|
+
try {
|
|
122
|
+
let res;
|
|
123
|
+
try {
|
|
124
|
+
res = await guardedFetch(input.url, 5, combined);
|
|
125
|
+
} catch (err) {
|
|
126
|
+
if (opts.signal.aborted) throw err;
|
|
127
|
+
throw describeFetchError(err, input.url, ctrl.signal.aborted);
|
|
128
|
+
}
|
|
129
|
+
const ct = res.headers.get("content-type") ?? "application/octet-stream";
|
|
130
|
+
if (/^image\/|^audio\/|^video\/|application\/octet-stream/.test(ct)) {
|
|
131
|
+
throw new FetchError({
|
|
132
|
+
message: `fetch: refusing to read binary content-type "${ct}"`,
|
|
133
|
+
status: res.status,
|
|
134
|
+
context: { url: res.url, contentType: ct }
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
yield {
|
|
138
|
+
type: "log",
|
|
139
|
+
text: `HTTP ${res.status} ${ct}`,
|
|
140
|
+
data: { status: res.status, contentType: ct }
|
|
141
|
+
};
|
|
142
|
+
const reader = res.body?.getReader();
|
|
143
|
+
let received = 0;
|
|
144
|
+
const chunks = [];
|
|
145
|
+
let pendingBytes = 0;
|
|
146
|
+
const FLUSH_AT = 4 * 1024;
|
|
147
|
+
if (reader) {
|
|
148
|
+
for (; ; ) {
|
|
149
|
+
const { value, done } = await reader.read();
|
|
150
|
+
if (done) break;
|
|
151
|
+
if (!value) continue;
|
|
152
|
+
received += value.byteLength;
|
|
153
|
+
pendingBytes += value.byteLength;
|
|
154
|
+
chunks.push(value);
|
|
155
|
+
if (pendingBytes >= FLUSH_AT) {
|
|
156
|
+
const recent = Buffer.from(value).toString("utf-8");
|
|
157
|
+
yield {
|
|
158
|
+
type: "partial_output",
|
|
159
|
+
text: recent,
|
|
160
|
+
data: { received }
|
|
161
|
+
};
|
|
162
|
+
pendingBytes = 0;
|
|
163
|
+
}
|
|
164
|
+
if (received > MAX_BYTES) break;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
const text = Buffer.concat(chunks.map((c) => Buffer.from(c))).toString("utf8");
|
|
168
|
+
const format = input.format ?? (ct.includes("text/html") ? "markdown" : "text");
|
|
169
|
+
let content;
|
|
170
|
+
if (format === "raw") content = text;
|
|
171
|
+
else if (format === "markdown" && ct.includes("text/html")) content = TD.turndown(text);
|
|
172
|
+
else if (ct.includes("application/json")) content = prettyJson(text);
|
|
173
|
+
else content = text;
|
|
174
|
+
yield {
|
|
175
|
+
type: "final",
|
|
176
|
+
output: {
|
|
177
|
+
content: truncateMiddle(content, MAX_BYTES),
|
|
178
|
+
status: res.status,
|
|
179
|
+
content_type: ct,
|
|
180
|
+
url: res.url
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
ctx.recordSideEffect?.({
|
|
184
|
+
toolUseId: `fetch-${Date.now()}`,
|
|
185
|
+
toolName: "fetch",
|
|
186
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
187
|
+
input: { url: input.url, format: input.format },
|
|
188
|
+
outcome: `HTTP ${res.status} (${ct})`,
|
|
189
|
+
risk: "network"
|
|
190
|
+
});
|
|
191
|
+
} finally {
|
|
192
|
+
clearTimeout(timer);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
function describeFetchError(err, url, timedOut) {
|
|
197
|
+
if (timedOut) {
|
|
198
|
+
return new ToolError({
|
|
199
|
+
message: `fetch: GET ${url} timed out after ${TIMEOUT_MS}ms`,
|
|
200
|
+
code: "TOOL_TIMEOUT",
|
|
201
|
+
toolName: "fetch",
|
|
202
|
+
context: { url, timedOut: true, timeoutMs: TIMEOUT_MS },
|
|
203
|
+
cause: err
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
const parts = [];
|
|
207
|
+
const seen = /* @__PURE__ */ new Set();
|
|
208
|
+
let cur = err;
|
|
209
|
+
while (cur instanceof Error && !seen.has(cur)) {
|
|
210
|
+
seen.add(cur);
|
|
211
|
+
const code = cur.code;
|
|
212
|
+
const label = code ? `${code}: ${cur.message}` : cur.message;
|
|
213
|
+
if (label && label !== "fetch failed" && !parts.includes(label)) parts.push(label);
|
|
214
|
+
cur = cur.cause;
|
|
215
|
+
}
|
|
216
|
+
const detail = parts.length > 0 ? parts.join(" \u2192 ") : "fetch failed";
|
|
217
|
+
return new FetchError({
|
|
218
|
+
message: `fetch: GET ${url} failed \u2014 ${detail}`,
|
|
219
|
+
status: 502,
|
|
220
|
+
context: { url, timedOut: false, transportErrors: parts },
|
|
221
|
+
// Preserve the original undici / DNS / TLS chain so callers can inspect
|
|
222
|
+
// it via `err.cause` and structured `instanceof` checks. The flattened
|
|
223
|
+
// text version stays in the message for human readability.
|
|
224
|
+
cause: err
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
function prettyJson(s) {
|
|
228
|
+
try {
|
|
229
|
+
return JSON.stringify(JSON.parse(s), null, 2);
|
|
230
|
+
} catch {
|
|
231
|
+
return s;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
export {
|
|
236
|
+
fetchTool
|
|
237
|
+
};
|
|
238
|
+
//# sourceMappingURL=chunk-IXMNTNW5.js.map
|