@chances-ai/tools 3.1.1 → 3.2.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 (41) hide show
  1. package/dist/builtins/_shared.d.ts +15 -0
  2. package/dist/builtins/_shared.d.ts.map +1 -0
  3. package/dist/builtins/_shared.js +52 -0
  4. package/dist/builtins/_shared.js.map +1 -0
  5. package/dist/builtins/bash.d.ts +3 -0
  6. package/dist/builtins/bash.d.ts.map +1 -0
  7. package/dist/builtins/bash.js +25 -0
  8. package/dist/builtins/bash.js.map +1 -0
  9. package/dist/builtins/diff.d.ts +3 -0
  10. package/dist/builtins/diff.d.ts.map +1 -0
  11. package/dist/builtins/diff.js +83 -0
  12. package/dist/builtins/diff.js.map +1 -0
  13. package/dist/builtins/edit.d.ts +3 -0
  14. package/dist/builtins/edit.d.ts.map +1 -0
  15. package/dist/builtins/edit.js +37 -0
  16. package/dist/builtins/edit.js.map +1 -0
  17. package/dist/builtins/glob.d.ts +3 -0
  18. package/dist/builtins/glob.d.ts.map +1 -0
  19. package/dist/builtins/glob.js +37 -0
  20. package/dist/builtins/glob.js.map +1 -0
  21. package/dist/builtins/grep.d.ts +3 -0
  22. package/dist/builtins/grep.d.ts.map +1 -0
  23. package/dist/builtins/grep.js +80 -0
  24. package/dist/builtins/grep.js.map +1 -0
  25. package/dist/builtins/read.d.ts +3 -0
  26. package/dist/builtins/read.d.ts.map +1 -0
  27. package/dist/builtins/read.js +18 -0
  28. package/dist/builtins/read.js.map +1 -0
  29. package/dist/builtins/web-fetch.d.ts +4 -0
  30. package/dist/builtins/web-fetch.d.ts.map +1 -0
  31. package/dist/builtins/web-fetch.js +335 -0
  32. package/dist/builtins/web-fetch.js.map +1 -0
  33. package/dist/builtins/write.d.ts +3 -0
  34. package/dist/builtins/write.d.ts.map +1 -0
  35. package/dist/builtins/write.js +44 -0
  36. package/dist/builtins/write.js.map +1 -0
  37. package/dist/builtins.d.ts +6 -0
  38. package/dist/builtins.d.ts.map +1 -1
  39. package/dist/builtins.js +24 -353
  40. package/dist/builtins.js.map +1 -1
  41. package/package.json +4 -4
@@ -0,0 +1,335 @@
1
+ import { AppError, ErrorCode } from "@chances-ai/runtime";
2
+ import { optBool, optNum, str } from "./_shared.js";
3
+ const DEFAULT_TIMEOUT_MS = 30_000;
4
+ const DEFAULT_MAX_BYTES = 250 * 1024;
5
+ /** Absolute ceiling on caller-supplied `maxBytes`. A misbehaving model could
6
+ * otherwise ask for a multi-GB body and force memory growth. 4 MiB is
7
+ * generous for any realistic doc page while still bounded. */
8
+ const MAX_BYTES_CEILING = 4 * 1024 * 1024;
9
+ const MAX_REDIRECTS = 10;
10
+ const URL_MAX_LENGTH = 2048;
11
+ /**
12
+ * Refuses RFC1918, loopback, link-local, CGNAT, and common internal hostnames.
13
+ * The goal is SSRF defense: a model that asks for `http://169.254.169.254/...`
14
+ * (cloud metadata) or `http://10.0.0.5/admin` (an internal box) must be denied
15
+ * before the gate even prompts. Operators who legitimately want to fetch a
16
+ * local dev server can edit the config — the explicit override is the trust
17
+ * signal, not a silent fallback.
18
+ */
19
+ function isPrivateIPv4(a, b) {
20
+ if (a === 0)
21
+ return true; // 0.0.0.0/8
22
+ if (a === 10)
23
+ return true; // 10.0.0.0/8
24
+ if (a === 127)
25
+ return true; // loopback
26
+ if (a === 169 && b === 254)
27
+ return true; // link-local
28
+ if (a === 172 && b >= 16 && b <= 31)
29
+ return true; // 172.16.0.0/12
30
+ if (a === 192 && b === 168)
31
+ return true; // 192.168.0.0/16
32
+ if (a === 100 && b >= 64 && b <= 127)
33
+ return true; // CGNAT 100.64.0.0/10
34
+ return false;
35
+ }
36
+ /**
37
+ * If `inner` is an IPv4-mapped IPv6 address (`::ffff:a.b.c.d` or its hex
38
+ * canonicalization like `::ffff:7f00:1`), return the embedded IPv4 octets.
39
+ * URL parsers (Bun's included) silently canonicalize the dotted form into
40
+ * hex, so a check that only sees `127.0.0.1` literals misses an attacker
41
+ * who writes `[::ffff:127.0.0.1]` — it lands as `[::ffff:7f00:1]` and
42
+ * defeats the IPv4 branch entirely.
43
+ */
44
+ function parseMappedIPv4(inner) {
45
+ // Bun normalizes `::ffff:127.0.0.1` to `::ffff:7f00:1` and elides leading zeros.
46
+ // Reject early if the address isn't a mapped form.
47
+ const mapped = inner.match(/^::ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/i);
48
+ if (mapped) {
49
+ const hi = parseInt(mapped[1], 16);
50
+ const lo = parseInt(mapped[2], 16);
51
+ return [(hi >> 8) & 0xff, hi & 0xff, (lo >> 8) & 0xff, lo & 0xff];
52
+ }
53
+ // Dotted-quad form preserved (e.g. some parsers leave `::ffff:127.0.0.1`).
54
+ const dotted = inner.match(/^::ffff:(\d+)\.(\d+)\.(\d+)\.(\d+)$/i);
55
+ if (dotted) {
56
+ return [Number(dotted[1]), Number(dotted[2]), Number(dotted[3]), Number(dotted[4])];
57
+ }
58
+ return null;
59
+ }
60
+ function isPrivateHost(hostname) {
61
+ // Normalize once: lowercase + strip *all* trailing dots. `localhost.` is
62
+ // the same host as `localhost` in DNS; `localhost..` is malformed but a
63
+ // resolver may still accept it, so a single-dot strip would leave a
64
+ // bypass. Trailing dots are never load-bearing for the public suffix.
65
+ const host = hostname.toLowerCase().replace(/\.+$/, "");
66
+ const ipv4 = host.match(/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/);
67
+ if (ipv4)
68
+ return isPrivateIPv4(Number(ipv4[1]), Number(ipv4[2]));
69
+ if (host.startsWith("[") && host.endsWith("]")) {
70
+ const inner = host.slice(1, -1);
71
+ if (inner === "::1" || inner === "::")
72
+ return true;
73
+ const mapped = parseMappedIPv4(inner);
74
+ if (mapped)
75
+ return isPrivateIPv4(mapped[0], mapped[1]);
76
+ // Unique local addresses fc00::/7 (covers fc** and fd**).
77
+ if (inner.startsWith("fc") || inner.startsWith("fd"))
78
+ return true;
79
+ // Link-local fe80::/10 — top 10 bits of the first hextet are 1111111010,
80
+ // so the first hextet falls in the range fe80–febf inclusive. `fe80:`
81
+ // alone misses `fea0::1`, `febf::1`, etc.
82
+ const firstHextet = parseInt(inner.split(":")[0], 16);
83
+ if (!Number.isNaN(firstHextet) && (firstHextet & 0xffc0) === 0xfe80)
84
+ return true;
85
+ return false;
86
+ }
87
+ if (host === "localhost")
88
+ return true;
89
+ if (host.endsWith(".localhost"))
90
+ return true;
91
+ if (host.endsWith(".local"))
92
+ return true;
93
+ if (host.endsWith(".internal"))
94
+ return true;
95
+ return false;
96
+ }
97
+ function validateUrl(raw) {
98
+ if (raw.length > URL_MAX_LENGTH) {
99
+ throw new AppError(ErrorCode.Tool, `URL too long (>${URL_MAX_LENGTH} chars)`);
100
+ }
101
+ let u;
102
+ try {
103
+ u = new URL(raw);
104
+ }
105
+ catch {
106
+ throw new AppError(ErrorCode.Tool, `Invalid URL: ${raw}`);
107
+ }
108
+ if (u.protocol !== "http:" && u.protocol !== "https:") {
109
+ throw new AppError(ErrorCode.Tool, `Unsupported URL scheme: ${u.protocol}`);
110
+ }
111
+ if (u.username || u.password) {
112
+ throw new AppError(ErrorCode.Tool, "URL must not contain credentials");
113
+ }
114
+ if (isPrivateHost(u.hostname)) {
115
+ throw new AppError(ErrorCode.Tool, `Refusing to fetch private/local address: ${u.hostname}`);
116
+ }
117
+ return u;
118
+ }
119
+ /** Same registrable host, or one is the `www.` variant of the other. */
120
+ function isSameHostOrWwwVariant(a, b) {
121
+ if (a.host === b.host)
122
+ return true;
123
+ const stripWww = (h) => (h.startsWith("www.") ? h.slice(4) : h);
124
+ return stripWww(a.host) === stripWww(b.host);
125
+ }
126
+ /**
127
+ * Minimal HTML → readable text. Deliberately string-based (no DOM, no turndown
128
+ * dep) for v1: we trade markdown fidelity for a 60-LoC implementation with
129
+ * zero new dependencies. Most use cases (docs, README mirrors, news pages)
130
+ * survive this cleanly; rich pages still produce *readable* text even if the
131
+ * markdown is rough. `raw: true` bypasses this entirely for callers that want
132
+ * the original HTML. A turndown / readability upgrade is a v2+ candidate.
133
+ */
134
+ function decodeEntities(s) {
135
+ return s
136
+ .replace(/&nbsp;/g, " ")
137
+ .replace(/&amp;/g, "&")
138
+ .replace(/&lt;/g, "<")
139
+ .replace(/&gt;/g, ">")
140
+ .replace(/&quot;/g, '"')
141
+ .replace(/&#39;/g, "'")
142
+ .replace(/&apos;/g, "'");
143
+ }
144
+ export function htmlToText(html) {
145
+ // Capture title before we touch tags — a title like `<title>A <b>B</b></title>`
146
+ // would otherwise either keep `<b>` (bad heading) or get duplicated as body
147
+ // text after we strip and replace block tags.
148
+ const titleMatch = html.match(/<title[^>]*>([\s\S]*?)<\/title>/i);
149
+ const title = titleMatch?.[1] ? decodeEntities(titleMatch[1].replace(/<[^>]+>/g, "")).trim() : "";
150
+ let s = html
151
+ .replace(/<script\b[^>]*>[\s\S]*?<\/script>/gi, "")
152
+ .replace(/<style\b[^>]*>[\s\S]*?<\/style>/gi, "")
153
+ // Best-effort: an unclosed <script> or <style> would otherwise leak its
154
+ // body into output. Drop everything from an unclosed opener to end.
155
+ .replace(/<script\b[^>]*>[\s\S]*$/gi, "")
156
+ .replace(/<style\b[^>]*>[\s\S]*$/gi, "")
157
+ .replace(/<!--[\s\S]*?-->/g, "")
158
+ // Strip the captured title block so it isn't duplicated in body output.
159
+ .replace(/<title[^>]*>[\s\S]*?<\/title>/gi, "")
160
+ .replace(/<\/(p|div|section|article|li|tr|h[1-6])[^>]*>/gi, "\n\n")
161
+ .replace(/<(p|div|section|article|li|tr|h[1-6])[^>]*>/gi, "\n")
162
+ .replace(/<br\s*\/?>/gi, "\n")
163
+ .replace(/<hr\s*\/?>/gi, "\n---\n")
164
+ .replace(/<[^>]+>/g, "");
165
+ s = decodeEntities(s)
166
+ .replace(/[ \t]+/g, " ")
167
+ .replace(/\n[ \t]+/g, "\n")
168
+ .replace(/\n{3,}/g, "\n\n")
169
+ .trim();
170
+ if (title)
171
+ return `# ${title}\n\n${s}`;
172
+ return s;
173
+ }
174
+ async function readBodyCapped(res, maxBytes) {
175
+ const reader = res.body?.getReader();
176
+ if (!reader)
177
+ return { body: "", truncated: false };
178
+ const chunks = [];
179
+ let received = 0;
180
+ let truncated = false;
181
+ for (;;) {
182
+ const { value, done } = await reader.read();
183
+ if (done)
184
+ break;
185
+ if (received + value.byteLength > maxBytes) {
186
+ const room = maxBytes - received;
187
+ if (room > 0)
188
+ chunks.push(value.subarray(0, room));
189
+ truncated = true;
190
+ try {
191
+ await reader.cancel();
192
+ }
193
+ catch {
194
+ /* best-effort */
195
+ }
196
+ break;
197
+ }
198
+ chunks.push(value);
199
+ received += value.byteLength;
200
+ }
201
+ // Decode as UTF-8; lossy for non-UTF responses but the LLM will see "?" runs
202
+ // rather than crash. We mark Content-Type in the header so the model knows.
203
+ const total = chunks.reduce((acc, c) => acc + c.byteLength, 0);
204
+ const merged = new Uint8Array(total);
205
+ let offset = 0;
206
+ for (const c of chunks) {
207
+ merged.set(c, offset);
208
+ offset += c.byteLength;
209
+ }
210
+ return { body: new TextDecoder("utf-8", { fatal: false }).decode(merged), truncated };
211
+ }
212
+ async function followRedirects(initial, signal, maxBytes) {
213
+ let url = initial;
214
+ let redirectsLeft = MAX_REDIRECTS;
215
+ for (;;) {
216
+ const res = await fetch(url.toString(), { redirect: "manual", signal });
217
+ const status = res.status;
218
+ if (status >= 300 && status < 400) {
219
+ const loc = res.headers.get("location");
220
+ if (loc) {
221
+ if (redirectsLeft-- === 0) {
222
+ throw new AppError(ErrorCode.Tool, `Too many redirects (>${MAX_REDIRECTS})`);
223
+ }
224
+ const target = new URL(loc, url);
225
+ // Re-validate: a redirect to file://, localhost, or a private IP must
226
+ // be refused regardless of how friendly the source URL looked.
227
+ validateUrl(target.toString());
228
+ if (!isSameHostOrWwwVariant(url, target)) {
229
+ try {
230
+ await res.body?.cancel();
231
+ }
232
+ catch {
233
+ /* best-effort */
234
+ }
235
+ return {
236
+ finalUrl: url.toString(),
237
+ status,
238
+ contentType: "text/plain",
239
+ body: `Cross-host redirect to ${target.toString()} — re-invoke web_fetch with the new URL if you trust it.`,
240
+ truncated: false,
241
+ };
242
+ }
243
+ try {
244
+ await res.body?.cancel();
245
+ }
246
+ catch {
247
+ /* best-effort */
248
+ }
249
+ url = target;
250
+ continue;
251
+ }
252
+ }
253
+ const contentType = res.headers.get("content-type") ?? "application/octet-stream";
254
+ const { body, truncated } = await readBodyCapped(res, maxBytes);
255
+ return { finalUrl: url.toString(), status, contentType, body, truncated };
256
+ }
257
+ }
258
+ export const webFetchTool = {
259
+ name: "web_fetch",
260
+ description: "Fetch a URL and return its content as text the model can read. http(s) only; literal private IPs (RFC1918, loopback, link-local, CGNAT, IPv4-mapped IPv6) and credentials in the URL are rejected. Note: lexical filtering only — a public hostname that DNS-resolves to a private address is NOT blocked at the validator (a v2+ item); the per-call `network-read` prompt is the user-side defense. text/html is reduced to readable text; JSON / markdown / plain text pass through. Use raw:true to get the unprocessed body. Cross-host redirects are not followed automatically — a one-line note is returned instead so the model can re-invoke with the new URL.",
261
+ category: "network-read",
262
+ parameters: {
263
+ type: "object",
264
+ properties: {
265
+ url: { type: "string", description: "Absolute http(s) URL to fetch." },
266
+ raw: { type: "boolean", description: "Skip HTML→text reduction; return the body as received." },
267
+ maxBytes: {
268
+ type: "number",
269
+ description: `Cap on body bytes (default ${DEFAULT_MAX_BYTES}). Responses are truncated to fit.`,
270
+ },
271
+ timeoutMs: {
272
+ type: "number",
273
+ description: `Per-request timeout in ms (default ${DEFAULT_TIMEOUT_MS}).`,
274
+ },
275
+ },
276
+ required: ["url"],
277
+ },
278
+ summarize: (args) => `web_fetch ${str(args, "url")}`,
279
+ async execute(args, ctx) {
280
+ const raw = optBool(args, "raw") ?? false;
281
+ const requestedMaxBytes = optNum(args, "maxBytes") ?? DEFAULT_MAX_BYTES;
282
+ // Clamp model-controlled cap into [1, MAX_BYTES_CEILING]. Non-positive /
283
+ // non-finite values fall through to the default — silently accepting "0"
284
+ // would always return an empty body which is unhelpful, and accepting a
285
+ // huge value would let a model force memory growth.
286
+ const maxBytes = Number.isFinite(requestedMaxBytes) && requestedMaxBytes >= 1
287
+ ? Math.min(Math.floor(requestedMaxBytes), MAX_BYTES_CEILING)
288
+ : DEFAULT_MAX_BYTES;
289
+ const timeoutMs = optNum(args, "timeoutMs") ?? DEFAULT_TIMEOUT_MS;
290
+ let initial;
291
+ try {
292
+ initial = validateUrl(str(args, "url"));
293
+ }
294
+ catch (e) {
295
+ return { ok: false, output: e.message };
296
+ }
297
+ // Compose request timeout + caller cancel into one signal.
298
+ const ac = new AbortController();
299
+ const timer = setTimeout(() => ac.abort(new Error(`Timeout after ${timeoutMs} ms`)), timeoutMs);
300
+ let onAbort;
301
+ if (ctx.signal.aborted) {
302
+ ac.abort(ctx.signal.reason ?? new Error("Cancelled"));
303
+ }
304
+ else {
305
+ onAbort = () => ac.abort(ctx.signal.reason ?? new Error("Cancelled"));
306
+ ctx.signal.addEventListener("abort", onAbort, { once: true });
307
+ }
308
+ try {
309
+ const r = await followRedirects(initial, ac.signal, maxBytes);
310
+ const isHtml = /^\s*text\/html\b/i.test(r.contentType);
311
+ const body = !raw && isHtml ? htmlToText(r.body) : r.body;
312
+ const header = [
313
+ `URL: ${initial.toString()}`,
314
+ `Final-URL: ${r.finalUrl}`,
315
+ `Status: ${r.status}`,
316
+ `Content-Type: ${r.contentType}`,
317
+ `Truncated: ${r.truncated}`,
318
+ ].join("\n");
319
+ // ok:true even for HTTP 4xx/5xx — the model can read the status line in
320
+ // the header and the error body below. ok:false is reserved for network
321
+ // / validation / timeout failures where there's nothing meaningful to return.
322
+ return { ok: true, output: `${header}\n\n${body}` };
323
+ }
324
+ catch (e) {
325
+ const err = e;
326
+ return { ok: false, output: `web_fetch failed: ${err.message}` };
327
+ }
328
+ finally {
329
+ clearTimeout(timer);
330
+ if (onAbort)
331
+ ctx.signal.removeEventListener("abort", onAbort);
332
+ }
333
+ },
334
+ };
335
+ //# sourceMappingURL=web-fetch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web-fetch.js","sourceRoot":"","sources":["../../src/builtins/web-fetch.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Tool } from "../types.js";
2
+ export declare const writeTool: Tool;
3
+ //# sourceMappingURL=write.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../src/builtins/write.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAc,MAAM,aAAa,CAAC;AAGpD,eAAO,MAAM,SAAS,EAAE,IAoCvB,CAAC"}
@@ -0,0 +1,44 @@
1
+ import { existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
2
+ import { dirname } from "node:path";
3
+ import { linesDiff } from "../diff.js";
4
+ import { PREVIEW_BYTE_CAP, safePath, str } from "./_shared.js";
5
+ export const writeTool = {
6
+ name: "write",
7
+ description: "Create or overwrite a file in the workspace.",
8
+ category: "file-write",
9
+ parameters: {
10
+ type: "object",
11
+ properties: { path: { type: "string" }, content: { type: "string" } },
12
+ required: ["path", "content"],
13
+ },
14
+ summarize: (args, ctx) => {
15
+ const path = str(args, "path");
16
+ const content = str(args, "content");
17
+ let abs = null;
18
+ try {
19
+ abs = safePath(ctx, path);
20
+ }
21
+ catch {
22
+ return `write ${path} (${content.length} bytes)`;
23
+ }
24
+ if (!existsSync(abs)) {
25
+ const lineCount = content === "" ? 0 : content.split("\n").length;
26
+ return `create ${path} (${content.length} bytes, ${lineCount} lines)`;
27
+ }
28
+ const priorSize = statSync(abs).size;
29
+ if (priorSize > PREVIEW_BYTE_CAP || content.length > PREVIEW_BYTE_CAP) {
30
+ return `overwrite ${path} (${priorSize} → ${content.length} bytes; diff preview skipped)`;
31
+ }
32
+ const before = readFileSync(abs, "utf8");
33
+ if (before === content)
34
+ return `overwrite ${path} (no changes)`;
35
+ return `overwrite ${path}\n${linesDiff(before, content)}`;
36
+ },
37
+ async execute(args, ctx) {
38
+ const path = safePath(ctx, str(args, "path"));
39
+ mkdirSync(dirname(path), { recursive: true });
40
+ writeFileSync(path, str(args, "content"));
41
+ return { ok: true, output: `Wrote ${str(args, "path")}` };
42
+ },
43
+ };
44
+ //# sourceMappingURL=write.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write.js","sourceRoot":"","sources":["../../src/builtins/write.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACvF,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAE/D,MAAM,CAAC,MAAM,SAAS,GAAS;IAC7B,IAAI,EAAE,OAAO;IACb,WAAW,EAAE,8CAA8C;IAC3D,QAAQ,EAAE,YAAY;IACtB,UAAU,EAAE;QACV,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;QACrE,QAAQ,EAAE,CAAC,MAAM,EAAE,SAAS,CAAC;KAC9B;IACD,SAAS,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;QACvB,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC/B,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QACrC,IAAI,GAAG,GAAkB,IAAI,CAAC;QAC9B,IAAI,CAAC;YACH,GAAG,GAAG,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC5B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,SAAS,IAAI,KAAK,OAAO,CAAC,MAAM,SAAS,CAAC;QACnD,CAAC;QACD,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACrB,MAAM,SAAS,GAAG,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;YAClE,OAAO,UAAU,IAAI,KAAK,OAAO,CAAC,MAAM,WAAW,SAAS,SAAS,CAAC;QACxE,CAAC;QACD,MAAM,SAAS,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;QACrC,IAAI,SAAS,GAAG,gBAAgB,IAAI,OAAO,CAAC,MAAM,GAAG,gBAAgB,EAAE,CAAC;YACtE,OAAO,aAAa,IAAI,KAAK,SAAS,MAAM,OAAO,CAAC,MAAM,+BAA+B,CAAC;QAC5F,CAAC;QACD,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QACzC,IAAI,MAAM,KAAK,OAAO;YAAE,OAAO,aAAa,IAAI,eAAe,CAAC;QAChE,OAAO,aAAa,IAAI,KAAK,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IAC5D,CAAC;IACD,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG;QACrB,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;QAC9C,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9C,aAAa,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC;QAC1C,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC;IAC5D,CAAC;CACF,CAAC"}
@@ -1,3 +1,9 @@
1
1
  import type { Tool } from "./types.js";
2
+ /**
3
+ * Registry of first-party tools the engine ships with. New tools live in their
4
+ * own module under `./builtins/<name>.ts`; this file is a pure barrel so the
5
+ * registration surface stays one-line-per-tool and reviewers can see the full
6
+ * tool inventory at a glance.
7
+ */
2
8
  export declare const builtinTools: Tool[];
3
9
  //# sourceMappingURL=builtins.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"builtins.d.ts","sourceRoot":"","sources":["../src/builtins.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,IAAI,EAA2B,MAAM,YAAY,CAAC;AAsWhE,eAAO,MAAM,YAAY,EAAE,IAAI,EAA4E,CAAC"}
1
+ {"version":3,"file":"builtins.d.ts","sourceRoot":"","sources":["../src/builtins.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAUvC;;;;;GAKG;AACH,eAAO,MAAM,YAAY,EAAE,IAAI,EAS9B,CAAC"}