@easynet/agent-tool-buildin 0.0.3 → 0.0.4

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/index.cjs CHANGED
@@ -1801,7 +1801,7 @@ var init_mustache = __esm({
1801
1801
  Context.prototype.push = function push(view) {
1802
1802
  return new Context(view, this);
1803
1803
  };
1804
- Context.prototype.lookup = function lookup2(name) {
1804
+ Context.prototype.lookup = function lookup(name) {
1805
1805
  var cache = this.cache;
1806
1806
  var value;
1807
1807
  if (cache.hasOwnProperty(name)) {
@@ -2021,21 +2021,21 @@ __export(index_exports, {
2021
2021
  getBuiltinContext: () => getBuiltinContext,
2022
2022
  hashTextSpec: () => hashTextSpec,
2023
2023
  headSpec: () => headSpec,
2024
- isIpInBlockedCidrs: () => isIpInBlockedCidrs,
2024
+ isIpInBlockedCidrs: () => import_agent_tool25.isIpInBlockedCidrs,
2025
2025
  jsonSelectSpec: () => jsonSelectSpec,
2026
2026
  listDirSpec: () => listDirSpec,
2027
2027
  nowHandler: () => nowHandler,
2028
2028
  nowSpec: () => nowSpec,
2029
2029
  readTextSpec: () => readTextSpec,
2030
2030
  registerCoreTools: () => registerCoreTools,
2031
- resolveSandboxedPath: () => resolveSandboxedPath,
2031
+ resolveSandboxedPath: () => import_agent_tool25.resolveSandboxedPath,
2032
2032
  runCommandSpec: () => runCommandSpec,
2033
2033
  runWithBuiltinContext: () => runWithBuiltinContext,
2034
2034
  searchTextSpec: () => searchTextSpec,
2035
2035
  sha256Spec: () => sha256Spec,
2036
2036
  templateRenderSpec: () => templateRenderSpec,
2037
2037
  truncateSpec: () => truncateSpec,
2038
- validateUrl: () => validateUrl,
2038
+ validateUrl: () => import_agent_tool25.validateUrl,
2039
2039
  writeTextSpec: () => writeTextSpec,
2040
2040
  yahooFinanceQuoteSpec: () => yahooFinanceQuoteSpec
2041
2041
  });
@@ -2143,51 +2143,8 @@ var DEFAULT_CORE_TOOLS_CONFIG = {
2143
2143
  };
2144
2144
 
2145
2145
  // fs/readText.ts
2146
- var import_promises2 = require("fs/promises");
2147
-
2148
- // security/sandbox.ts
2149
- var import_node_path = require("path");
2150
2146
  var import_promises = require("fs/promises");
2151
2147
  var import_agent_tool = require("@easynet/agent-tool");
2152
- async function resolveSandboxedPath(inputPath, sandboxRoot) {
2153
- let normalizedRoot;
2154
- try {
2155
- normalizedRoot = await (0, import_promises.realpath)((0, import_node_path.resolve)(sandboxRoot));
2156
- } catch {
2157
- normalizedRoot = (0, import_node_path.normalize)((0, import_node_path.resolve)(sandboxRoot));
2158
- }
2159
- const resolved = (0, import_node_path.resolve)(normalizedRoot, inputPath);
2160
- let real;
2161
- try {
2162
- await (0, import_promises.access)(resolved);
2163
- real = await (0, import_promises.realpath)(resolved);
2164
- } catch {
2165
- const parentDir = (0, import_node_path.dirname)(resolved);
2166
- let realParent;
2167
- try {
2168
- await (0, import_promises.access)(parentDir);
2169
- realParent = await (0, import_promises.realpath)(parentDir);
2170
- } catch {
2171
- realParent = (0, import_node_path.normalize)(parentDir);
2172
- }
2173
- real = (0, import_node_path.resolve)(realParent, (0, import_node_path.basename)(resolved));
2174
- }
2175
- if (!isWithinRoot(real, normalizedRoot)) {
2176
- throw (0, import_agent_tool.createTaggedError)(
2177
- "PATH_OUTSIDE_SANDBOX",
2178
- `Path "${inputPath}" resolves to "${real}" which is outside sandbox "${normalizedRoot}"`,
2179
- { inputPath, resolvedPath: real, sandboxRoot: normalizedRoot }
2180
- );
2181
- }
2182
- return real;
2183
- }
2184
- function isWithinRoot(path, root) {
2185
- const normalizedPath = (0, import_node_path.normalize)(path);
2186
- const normalizedRoot = (0, import_node_path.normalize)(root);
2187
- return normalizedPath === normalizedRoot || normalizedPath.startsWith(normalizedRoot + "/");
2188
- }
2189
-
2190
- // fs/readText.ts
2191
2148
  var import_agent_tool2 = require("@easynet/agent-tool");
2192
2149
  var readTextHandler = (async (args) => {
2193
2150
  const ctx = getBuiltinContext();
@@ -2196,8 +2153,8 @@ var readTextHandler = (async (args) => {
2196
2153
  throw (0, import_agent_tool2.createTaggedError)("FS_INVALID", "path is required (pass 'path' or 'filePath')", {});
2197
2154
  }
2198
2155
  const maxBytes = args.maxBytes ?? ctx.config.maxReadBytes;
2199
- const resolvedPath = await resolveSandboxedPath(inputPath, ctx.config.sandboxRoot);
2200
- const fileStat = await (0, import_promises2.stat)(resolvedPath);
2156
+ const resolvedPath = await (0, import_agent_tool.resolveSandboxedPath)(inputPath, ctx.config.sandboxRoot);
2157
+ const fileStat = await (0, import_promises.stat)(resolvedPath);
2201
2158
  if (fileStat.size > maxBytes) {
2202
2159
  throw (0, import_agent_tool2.createTaggedError)(
2203
2160
  "FILE_TOO_LARGE",
@@ -2205,7 +2162,7 @@ var readTextHandler = (async (args) => {
2205
2162
  { path: resolvedPath, size: fileStat.size, limit: maxBytes }
2206
2163
  );
2207
2164
  }
2208
- const text = await (0, import_promises2.readFile)(resolvedPath, "utf-8");
2165
+ const text = await (0, import_promises.readFile)(resolvedPath, "utf-8");
2209
2166
  return {
2210
2167
  result: {
2211
2168
  path: resolvedPath,
@@ -2224,9 +2181,10 @@ var readTextHandler = (async (args) => {
2224
2181
  });
2225
2182
 
2226
2183
  // fs/writeText.ts
2227
- var import_promises3 = require("fs/promises");
2184
+ var import_promises2 = require("fs/promises");
2228
2185
  var import_node_crypto = require("crypto");
2229
- var import_node_path2 = require("path");
2186
+ var import_node_path = require("path");
2187
+ var import_agent_tool3 = require("@easynet/agent-tool");
2230
2188
  var writeTextHandler = (async (args) => {
2231
2189
  const ctx = getBuiltinContext();
2232
2190
  const inputPath = (args.path ?? args.filePath)?.trim();
@@ -2236,11 +2194,11 @@ var writeTextHandler = (async (args) => {
2236
2194
  const text = args.text ?? args.content ?? "";
2237
2195
  const overwrite = args.overwrite ?? false;
2238
2196
  const mkdirp = args.mkdirp ?? true;
2239
- const resolvedPath = await resolveSandboxedPath(inputPath, ctx.config.sandboxRoot);
2197
+ const resolvedPath = await (0, import_agent_tool3.resolveSandboxedPath)(inputPath, ctx.config.sandboxRoot);
2240
2198
  if (!overwrite) {
2241
- const { access: access2 } = await import("fs/promises");
2199
+ const { access } = await import("fs/promises");
2242
2200
  try {
2243
- await access2(resolvedPath);
2201
+ await access(resolvedPath);
2244
2202
  throw new Error(
2245
2203
  `File already exists: ${resolvedPath}. Set overwrite=true to allow overwriting.`
2246
2204
  );
@@ -2252,9 +2210,9 @@ var writeTextHandler = (async (args) => {
2252
2210
  }
2253
2211
  }
2254
2212
  if (mkdirp) {
2255
- await (0, import_promises3.mkdir)((0, import_node_path2.dirname)(resolvedPath), { recursive: true });
2213
+ await (0, import_promises2.mkdir)((0, import_node_path.dirname)(resolvedPath), { recursive: true });
2256
2214
  }
2257
- await (0, import_promises3.writeFile)(resolvedPath, text, "utf-8");
2215
+ await (0, import_promises2.writeFile)(resolvedPath, text, "utf-8");
2258
2216
  const bytes = Buffer.byteLength(text, "utf-8");
2259
2217
  const sha256 = (0, import_node_crypto.createHash)("sha256").update(text).digest("hex");
2260
2218
  return {
@@ -2275,8 +2233,9 @@ var writeTextHandler = (async (args) => {
2275
2233
  });
2276
2234
 
2277
2235
  // fs/listDir.ts
2278
- var import_promises4 = require("fs/promises");
2279
- var import_node_path3 = require("path");
2236
+ var import_promises3 = require("fs/promises");
2237
+ var import_node_path2 = require("path");
2238
+ var import_agent_tool4 = require("@easynet/agent-tool");
2280
2239
  var listDirHandler = (async (args) => {
2281
2240
  const ctx = getBuiltinContext();
2282
2241
  const inputPath = (args.path ?? args.filePath ?? args.dir ?? args.directory)?.trim();
@@ -2287,7 +2246,7 @@ var listDirHandler = (async (args) => {
2287
2246
  const includeHidden = args.includeHidden ?? false;
2288
2247
  const recursive = args.recursive ?? false;
2289
2248
  const maxDepth = args.maxDepth ?? 5;
2290
- const resolvedPath = await resolveSandboxedPath(inputPath, ctx.config.sandboxRoot);
2249
+ const resolvedPath = await (0, import_agent_tool4.resolveSandboxedPath)(inputPath, ctx.config.sandboxRoot);
2291
2250
  const entries = [];
2292
2251
  let truncated = false;
2293
2252
  await walkDir(resolvedPath, "", entries, {
@@ -2322,8 +2281,8 @@ async function walkDir(basePath, relativePath, entries, options) {
2322
2281
  options.onTruncate();
2323
2282
  return;
2324
2283
  }
2325
- const fullPath = relativePath ? (0, import_node_path3.resolve)(basePath, relativePath) : basePath;
2326
- const dirEntries = await (0, import_promises4.readdir)(fullPath, { withFileTypes: true });
2284
+ const fullPath = relativePath ? (0, import_node_path2.resolve)(basePath, relativePath) : basePath;
2285
+ const dirEntries = await (0, import_promises3.readdir)(fullPath, { withFileTypes: true });
2327
2286
  for (const dirent of dirEntries) {
2328
2287
  if (entries.length >= options.maxEntries) {
2329
2288
  options.onTruncate();
@@ -2332,8 +2291,8 @@ async function walkDir(basePath, relativePath, entries, options) {
2332
2291
  if (!options.includeHidden && dirent.name.startsWith(".")) {
2333
2292
  continue;
2334
2293
  }
2335
- const entryPath = (0, import_node_path3.join)(fullPath, dirent.name);
2336
- const entryRelative = relativePath ? (0, import_node_path3.join)(relativePath, dirent.name) : dirent.name;
2294
+ const entryPath = (0, import_node_path2.join)(fullPath, dirent.name);
2295
+ const entryRelative = relativePath ? (0, import_node_path2.join)(relativePath, dirent.name) : dirent.name;
2337
2296
  let entryType;
2338
2297
  if (dirent.isSymbolicLink()) {
2339
2298
  entryType = "symlink";
@@ -2347,7 +2306,7 @@ async function walkDir(basePath, relativePath, entries, options) {
2347
2306
  let size = 0;
2348
2307
  let mtime = "";
2349
2308
  try {
2350
- const entryStat = await (0, import_promises4.stat)(entryPath);
2309
+ const entryStat = await (0, import_promises3.stat)(entryPath);
2351
2310
  size = entryStat.size;
2352
2311
  mtime = entryStat.mtime.toISOString();
2353
2312
  } catch {
@@ -2368,10 +2327,11 @@ async function walkDir(basePath, relativePath, entries, options) {
2368
2327
  }
2369
2328
 
2370
2329
  // fs/searchText.ts
2371
- var import_promises5 = require("fs/promises");
2330
+ var import_promises4 = require("fs/promises");
2372
2331
  var import_node_fs = require("fs");
2373
2332
  var import_node_readline = require("readline");
2374
- var import_node_path4 = require("path");
2333
+ var import_node_path3 = require("path");
2334
+ var import_agent_tool5 = require("@easynet/agent-tool");
2375
2335
  var searchTextHandler = (async (args) => {
2376
2336
  const ctx = getBuiltinContext();
2377
2337
  const rootPath = (args.root ?? args.path ?? args.dir ?? args.directory)?.trim();
@@ -2385,7 +2345,7 @@ var searchTextHandler = (async (args) => {
2385
2345
  const glob = args.glob ?? "**/*.{md,txt,log,json,ts,js,py,java,scala}";
2386
2346
  const maxMatches = args.maxMatches ?? 100;
2387
2347
  const maxFiles = args.maxFiles ?? 500;
2388
- const resolvedRoot = await resolveSandboxedPath(rootPath, ctx.config.sandboxRoot);
2348
+ const resolvedRoot = await (0, import_agent_tool5.resolveSandboxedPath)(rootPath, ctx.config.sandboxRoot);
2389
2349
  let regex;
2390
2350
  try {
2391
2351
  regex = new RegExp(query, "i");
@@ -2432,13 +2392,13 @@ async function collectFiles(dirPath, files, options) {
2432
2392
  if (files.length >= options.maxFiles) return;
2433
2393
  let entries;
2434
2394
  try {
2435
- entries = await (0, import_promises5.readdir)(dirPath, { withFileTypes: true });
2395
+ entries = await (0, import_promises4.readdir)(dirPath, { withFileTypes: true });
2436
2396
  } catch {
2437
2397
  return;
2438
2398
  }
2439
2399
  for (const entry of entries) {
2440
2400
  if (files.length >= options.maxFiles) return;
2441
- const fullPath = (0, import_node_path4.join)(dirPath, entry.name);
2401
+ const fullPath = (0, import_node_path3.join)(dirPath, entry.name);
2442
2402
  if (entry.isDirectory()) {
2443
2403
  if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
2444
2404
  await collectFiles(fullPath, files, options);
@@ -2452,7 +2412,7 @@ async function collectFiles(dirPath, files, options) {
2452
2412
  }
2453
2413
  }
2454
2414
  async function searchFile(filePath, root, regex, matches, maxMatches) {
2455
- const fileStat = await (0, import_promises5.stat)(filePath).catch(() => null);
2415
+ const fileStat = await (0, import_promises4.stat)(filePath).catch(() => null);
2456
2416
  if (!fileStat || fileStat.size > 1024 * 1024) return;
2457
2417
  const stream = (0, import_node_fs.createReadStream)(filePath, { encoding: "utf-8" });
2458
2418
  const rl = (0, import_node_readline.createInterface)({ input: stream, crlfDelay: Infinity });
@@ -2465,7 +2425,7 @@ async function searchFile(filePath, root, regex, matches, maxMatches) {
2465
2425
  }
2466
2426
  if (regex.test(line)) {
2467
2427
  matches.push({
2468
- file: (0, import_node_path4.relative)(root, filePath),
2428
+ file: (0, import_node_path3.relative)(root, filePath),
2469
2429
  lineNo,
2470
2430
  excerpt: line.slice(0, 200)
2471
2431
  });
@@ -2498,22 +2458,23 @@ function escapeRegExp(str) {
2498
2458
 
2499
2459
  // fs/sha256.ts
2500
2460
  var import_node_fs2 = require("fs");
2501
- var import_promises6 = require("fs/promises");
2461
+ var import_promises5 = require("fs/promises");
2502
2462
  var import_node_crypto2 = require("crypto");
2503
- var import_agent_tool3 = require("@easynet/agent-tool");
2463
+ var import_agent_tool6 = require("@easynet/agent-tool");
2464
+ var import_agent_tool7 = require("@easynet/agent-tool");
2504
2465
  var sha256Handler = (async (args) => {
2505
2466
  const ctx = getBuiltinContext();
2506
2467
  const inputPath = (args.path ?? args.filePath)?.trim();
2507
2468
  if (!inputPath) {
2508
- throw (0, import_agent_tool3.createTaggedError)("FS_INVALID", "path is required (pass 'path' or 'filePath')", {});
2469
+ throw (0, import_agent_tool7.createTaggedError)("FS_INVALID", "path is required (pass 'path' or 'filePath')", {});
2509
2470
  }
2510
- const resolvedPath = await resolveSandboxedPath(inputPath, ctx.config.sandboxRoot);
2511
- const fileStat = await (0, import_promises6.stat)(resolvedPath);
2512
- const hash = await new Promise((resolve3, reject) => {
2471
+ const resolvedPath = await (0, import_agent_tool6.resolveSandboxedPath)(inputPath, ctx.config.sandboxRoot);
2472
+ const fileStat = await (0, import_promises5.stat)(resolvedPath);
2473
+ const hash = await new Promise((resolve2, reject) => {
2513
2474
  const hasher = (0, import_node_crypto2.createHash)("sha256");
2514
2475
  const stream = (0, import_node_fs2.createReadStream)(resolvedPath);
2515
2476
  stream.on("data", (chunk) => hasher.update(chunk));
2516
- stream.on("end", () => resolve3(hasher.digest("hex")));
2477
+ stream.on("end", () => resolve2(hasher.digest("hex")));
2517
2478
  stream.on("error", reject);
2518
2479
  });
2519
2480
  return {
@@ -2534,7 +2495,8 @@ var sha256Handler = (async (args) => {
2534
2495
  });
2535
2496
 
2536
2497
  // fs/deletePath.ts
2537
- var import_promises7 = require("fs/promises");
2498
+ var import_promises6 = require("fs/promises");
2499
+ var import_agent_tool8 = require("@easynet/agent-tool");
2538
2500
  var deletePathHandler = (async (args) => {
2539
2501
  const ctx = getBuiltinContext();
2540
2502
  const inputPath = (args.path ?? args.filePath)?.trim();
@@ -2548,7 +2510,7 @@ var deletePathHandler = (async (args) => {
2548
2510
  "Deletion not confirmed. Set confirm=true to proceed with deletion."
2549
2511
  );
2550
2512
  }
2551
- const resolvedPath = await resolveSandboxedPath(inputPath, ctx.config.sandboxRoot);
2513
+ const resolvedPath = await (0, import_agent_tool8.resolveSandboxedPath)(inputPath, ctx.config.sandboxRoot);
2552
2514
  let realSandboxRoot;
2553
2515
  try {
2554
2516
  const { realpath: rp } = await import("fs/promises");
@@ -2559,16 +2521,16 @@ var deletePathHandler = (async (args) => {
2559
2521
  if (resolvedPath === realSandboxRoot) {
2560
2522
  throw new Error("Cannot delete the sandbox root directory.");
2561
2523
  }
2562
- const fileStat = await (0, import_promises7.stat)(resolvedPath);
2524
+ const fileStat = await (0, import_promises6.stat)(resolvedPath);
2563
2525
  const isDirectory = fileStat.isDirectory();
2564
2526
  if (isDirectory) {
2565
2527
  if (recursive) {
2566
- await (0, import_promises7.rm)(resolvedPath, { recursive: true, force: true });
2528
+ await (0, import_promises6.rm)(resolvedPath, { recursive: true, force: true });
2567
2529
  } else {
2568
- await (0, import_promises7.rmdir)(resolvedPath);
2530
+ await (0, import_promises6.rmdir)(resolvedPath);
2569
2531
  }
2570
2532
  } else {
2571
- await (0, import_promises7.unlink)(resolvedPath);
2533
+ await (0, import_promises6.unlink)(resolvedPath);
2572
2534
  }
2573
2535
  return {
2574
2536
  result: {
@@ -2587,175 +2549,25 @@ var deletePathHandler = (async (args) => {
2587
2549
  };
2588
2550
  });
2589
2551
 
2590
- // security/ssrf.ts
2591
- var import_promises8 = require("dns/promises");
2592
- var import_agent_tool4 = require("@easynet/agent-tool");
2593
- async function validateUrl(url, allowedHosts, blockedCidrs) {
2594
- let parsed;
2595
- try {
2596
- parsed = new URL(url);
2597
- } catch {
2598
- throw (0, import_agent_tool4.createTaggedError)(
2599
- "HTTP_DISALLOWED_HOST",
2600
- `Invalid URL: ${url}`,
2601
- { url }
2602
- );
2603
- }
2604
- if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
2605
- throw (0, import_agent_tool4.createTaggedError)(
2606
- "HTTP_DISALLOWED_HOST",
2607
- `Protocol not allowed: ${parsed.protocol}. Only http: and https: are supported.`,
2608
- { url, protocol: parsed.protocol }
2609
- );
2610
- }
2611
- const hostname = parsed.hostname;
2612
- if (!isHostAllowed(hostname, allowedHosts)) {
2613
- throw (0, import_agent_tool4.createTaggedError)(
2614
- "HTTP_DISALLOWED_HOST",
2615
- `Host "${hostname}" is not in the allowed hosts list`,
2616
- { url, hostname, allowedHosts }
2617
- );
2618
- }
2619
- try {
2620
- const { address } = await (0, import_promises8.lookup)(hostname);
2621
- if (isIpInBlockedCidrs(address, blockedCidrs)) {
2622
- throw (0, import_agent_tool4.createTaggedError)(
2623
- "HTTP_DISALLOWED_HOST",
2624
- `Host "${hostname}" resolves to blocked IP: ${address}`,
2625
- { url, hostname, resolvedIp: address }
2626
- );
2627
- }
2628
- } catch (err) {
2629
- if (err instanceof Error && err.kind === "HTTP_DISALLOWED_HOST") {
2630
- throw err;
2631
- }
2632
- throw (0, import_agent_tool4.createTaggedError)(
2633
- "HTTP_DISALLOWED_HOST",
2634
- `DNS resolution failed for host "${hostname}": ${err instanceof Error ? err.message : String(err)}`,
2635
- { url, hostname }
2636
- );
2637
- }
2638
- return parsed;
2639
- }
2640
- function isHostAllowed(hostname, allowedHosts) {
2641
- for (const pattern of allowedHosts) {
2642
- if (pattern === "*") {
2643
- return true;
2644
- }
2645
- if (pattern.startsWith("*.")) {
2646
- const suffix = pattern.slice(1);
2647
- if (hostname.endsWith(suffix) || hostname === pattern.slice(2)) {
2648
- return true;
2649
- }
2650
- } else if (hostname === pattern) {
2651
- return true;
2652
- }
2653
- }
2654
- return false;
2655
- }
2656
- function isIpInBlockedCidrs(ip, cidrs) {
2657
- const normalizedIp = normalizeIp(ip);
2658
- if (!normalizedIp) return false;
2659
- for (const cidr of cidrs) {
2660
- if (cidr.includes(":")) {
2661
- if (!ip.includes(":")) continue;
2662
- if (isIpv6InCidr(ip, cidr)) return true;
2663
- } else {
2664
- if (isIpv4InCidr(normalizedIp, cidr)) return true;
2665
- }
2666
- }
2667
- return false;
2668
- }
2669
- function normalizeIp(ip) {
2670
- if (ip.startsWith("::ffff:")) {
2671
- return ip.slice(7);
2672
- }
2673
- if (/^\d+\.\d+\.\d+\.\d+$/.test(ip)) {
2674
- return ip;
2675
- }
2676
- return null;
2677
- }
2678
- function isIpv4InCidr(ip, cidr) {
2679
- const [cidrIp, prefixStr] = cidr.split("/");
2680
- if (!cidrIp || !prefixStr) return false;
2681
- const prefix = parseInt(prefixStr, 10);
2682
- if (isNaN(prefix) || prefix < 0 || prefix > 32) return false;
2683
- const ipNum = ipv4ToNum(ip);
2684
- const cidrNum = ipv4ToNum(cidrIp);
2685
- if (ipNum === null || cidrNum === null) return false;
2686
- const mask = prefix === 0 ? 0 : ~0 << 32 - prefix >>> 0;
2687
- return (ipNum & mask) === (cidrNum & mask);
2688
- }
2689
- function ipv4ToNum(ip) {
2690
- const parts = ip.split(".");
2691
- if (parts.length !== 4) return null;
2692
- let num = 0;
2693
- for (const part of parts) {
2694
- const n = parseInt(part, 10);
2695
- if (isNaN(n) || n < 0 || n > 255) return null;
2696
- num = num << 8 | n;
2697
- }
2698
- return num >>> 0;
2699
- }
2700
- function isIpv6InCidr(ip, cidr) {
2701
- const [cidrIp, prefixStr] = cidr.split("/");
2702
- if (!cidrIp || !prefixStr) return false;
2703
- const prefix = parseInt(prefixStr, 10);
2704
- if (isNaN(prefix)) return false;
2705
- const ipBytes = expandIpv6(ip);
2706
- const cidrBytes = expandIpv6(cidrIp);
2707
- if (!ipBytes || !cidrBytes) return false;
2708
- const fullBytes = Math.floor(prefix / 8);
2709
- for (let i = 0; i < fullBytes && i < 16; i++) {
2710
- if (ipBytes[i] !== cidrBytes[i]) return false;
2711
- }
2712
- const remainingBits = prefix % 8;
2713
- if (remainingBits > 0 && fullBytes < 16) {
2714
- const mask = ~0 << 8 - remainingBits & 255;
2715
- if ((ipBytes[fullBytes] & mask) !== (cidrBytes[fullBytes] & mask)) return false;
2716
- }
2717
- return true;
2718
- }
2719
- function expandIpv6(ip) {
2720
- const zoneIdx = ip.indexOf("%");
2721
- if (zoneIdx !== -1) ip = ip.slice(0, zoneIdx);
2722
- const parts = ip.split("::");
2723
- if (parts.length > 2) return null;
2724
- const bytes = new Array(16).fill(0);
2725
- const expandGroup = (group) => {
2726
- if (!group) return [];
2727
- return group.split(":").flatMap((hex) => {
2728
- const val = parseInt(hex || "0", 16);
2729
- return [val >> 8 & 255, val & 255];
2730
- });
2731
- };
2732
- if (parts.length === 1) {
2733
- const expanded = expandGroup(parts[0]);
2734
- if (expanded.length !== 16) return null;
2735
- return expanded;
2736
- }
2737
- const left = expandGroup(parts[0]);
2738
- const right = expandGroup(parts[1]);
2739
- if (left.length + right.length > 16) return null;
2740
- for (let i = 0; i < left.length; i++) bytes[i] = left[i];
2741
- for (let i = 0; i < right.length; i++) bytes[16 - right.length + i] = right[i];
2742
- return bytes;
2743
- }
2744
-
2745
2552
  // http/fetchText.ts
2746
- var import_agent_tool5 = require("@easynet/agent-tool");
2553
+ var import_agent_tool9 = require("@easynet/agent-tool");
2554
+ var import_agent_tool10 = require("@easynet/agent-tool");
2747
2555
  var fetchTextHandler = (async (args) => {
2748
2556
  const ctx = getBuiltinContext();
2749
2557
  const url = (args.url ?? args.uri)?.trim();
2750
2558
  if (!url) {
2751
- throw (0, import_agent_tool5.createTaggedError)("HTTP_INVALID", "url is required (pass 'url' or 'uri')", {});
2559
+ throw (0, import_agent_tool10.createTaggedError)("HTTP_INVALID", "url is required (pass 'url' or 'uri')", {});
2752
2560
  }
2753
2561
  const method = args.method ?? "GET";
2754
2562
  const headers = args.headers ?? {};
2755
2563
  const body = args.body ?? void 0;
2756
2564
  const timeoutMs = args.timeoutMs ?? ctx.config.defaultTimeoutMs;
2757
2565
  const maxBytes = args.maxBytes ?? ctx.config.maxHttpBytes;
2758
- await validateUrl(url, ctx.config.allowedHosts, ctx.config.blockedCidrs);
2566
+ await (0, import_agent_tool9.validateUrl)(url, {
2567
+ allowedHosts: ctx.config.allowedHosts,
2568
+ blockedHosts: ctx.config.blockedHosts,
2569
+ blockedCidrs: ctx.config.blockedCidrs
2570
+ });
2759
2571
  if (!headers["User-Agent"] && !headers["user-agent"]) {
2760
2572
  headers["User-Agent"] = ctx.config.httpUserAgent;
2761
2573
  }
@@ -2771,13 +2583,13 @@ var fetchTextHandler = (async (args) => {
2771
2583
  });
2772
2584
  } catch (err) {
2773
2585
  if (err instanceof Error && err.name === "AbortError") {
2774
- throw (0, import_agent_tool5.createTaggedError)(
2586
+ throw (0, import_agent_tool10.createTaggedError)(
2775
2587
  "HTTP_TIMEOUT",
2776
2588
  `Request to ${url} timed out after ${timeoutMs}ms`,
2777
2589
  { url, timeoutMs }
2778
2590
  );
2779
2591
  }
2780
- throw (0, import_agent_tool5.createTaggedError)(
2592
+ throw (0, import_agent_tool10.createTaggedError)(
2781
2593
  "UPSTREAM_ERROR",
2782
2594
  `Fetch failed for ${url}: ${err instanceof Error ? err.message : String(err)}`,
2783
2595
  { url }
@@ -2787,7 +2599,7 @@ var fetchTextHandler = (async (args) => {
2787
2599
  }
2788
2600
  const contentLength = response.headers.get("content-length");
2789
2601
  if (contentLength && parseInt(contentLength, 10) > maxBytes) {
2790
- throw (0, import_agent_tool5.createTaggedError)(
2602
+ throw (0, import_agent_tool10.createTaggedError)(
2791
2603
  "HTTP_TOO_LARGE",
2792
2604
  `Response Content-Length ${contentLength} exceeds limit of ${maxBytes} bytes`,
2793
2605
  { url, contentLength: parseInt(contentLength, 10), limit: maxBytes }
@@ -2832,7 +2644,7 @@ async function readResponseWithLimit(response, maxBytes, url) {
2832
2644
  totalBytes += value.byteLength;
2833
2645
  if (totalBytes > maxBytes) {
2834
2646
  reader.cancel();
2835
- throw (0, import_agent_tool5.createTaggedError)(
2647
+ throw (0, import_agent_tool10.createTaggedError)(
2836
2648
  "HTTP_TOO_LARGE",
2837
2649
  `Response body exceeded limit of ${maxBytes} bytes while reading from ${url}`,
2838
2650
  { url, bytesRead: totalBytes, limit: maxBytes }
@@ -2848,19 +2660,24 @@ async function readResponseWithLimit(response, maxBytes, url) {
2848
2660
  }
2849
2661
 
2850
2662
  // http/fetchJson.ts
2851
- var import_agent_tool6 = require("@easynet/agent-tool");
2663
+ var import_agent_tool11 = require("@easynet/agent-tool");
2664
+ var import_agent_tool12 = require("@easynet/agent-tool");
2852
2665
  var fetchJsonHandler = (async (args) => {
2853
2666
  const ctx = getBuiltinContext();
2854
2667
  const url = (args.url ?? args.uri)?.trim();
2855
2668
  if (!url) {
2856
- throw (0, import_agent_tool6.createTaggedError)("HTTP_INVALID", "url is required (pass 'url' or 'uri')", {});
2669
+ throw (0, import_agent_tool12.createTaggedError)("HTTP_INVALID", "url is required (pass 'url' or 'uri')", {});
2857
2670
  }
2858
2671
  const method = args.method ?? "GET";
2859
2672
  const headers = args.headers ?? {};
2860
2673
  const body = args.body ?? void 0;
2861
2674
  const timeoutMs = args.timeoutMs ?? ctx.config.defaultTimeoutMs;
2862
2675
  const maxBytes = args.maxBytes ?? ctx.config.maxHttpBytes;
2863
- await validateUrl(url, ctx.config.allowedHosts, ctx.config.blockedCidrs);
2676
+ await (0, import_agent_tool11.validateUrl)(url, {
2677
+ allowedHosts: ctx.config.allowedHosts,
2678
+ blockedHosts: ctx.config.blockedHosts,
2679
+ blockedCidrs: ctx.config.blockedCidrs
2680
+ });
2864
2681
  if (!headers["Accept"] && !headers["accept"]) {
2865
2682
  headers["Accept"] = "application/json";
2866
2683
  }
@@ -2879,13 +2696,13 @@ var fetchJsonHandler = (async (args) => {
2879
2696
  });
2880
2697
  } catch (err) {
2881
2698
  if (err instanceof Error && err.name === "AbortError") {
2882
- throw (0, import_agent_tool6.createTaggedError)(
2699
+ throw (0, import_agent_tool12.createTaggedError)(
2883
2700
  "HTTP_TIMEOUT",
2884
2701
  `Request to ${url} timed out after ${timeoutMs}ms`,
2885
2702
  { url, timeoutMs }
2886
2703
  );
2887
2704
  }
2888
- throw (0, import_agent_tool6.createTaggedError)(
2705
+ throw (0, import_agent_tool12.createTaggedError)(
2889
2706
  "UPSTREAM_ERROR",
2890
2707
  `Fetch failed for ${url}: ${err instanceof Error ? err.message : String(err)}`,
2891
2708
  { url }
@@ -2895,7 +2712,7 @@ var fetchJsonHandler = (async (args) => {
2895
2712
  }
2896
2713
  const contentLength = response.headers.get("content-length");
2897
2714
  if (contentLength && parseInt(contentLength, 10) > maxBytes) {
2898
- throw (0, import_agent_tool6.createTaggedError)(
2715
+ throw (0, import_agent_tool12.createTaggedError)(
2899
2716
  "HTTP_TOO_LARGE",
2900
2717
  `Response Content-Length ${contentLength} exceeds limit of ${maxBytes} bytes`,
2901
2718
  { url, contentLength: parseInt(contentLength, 10), limit: maxBytes }
@@ -2904,7 +2721,7 @@ var fetchJsonHandler = (async (args) => {
2904
2721
  const text = await response.text();
2905
2722
  const bytes = Buffer.byteLength(text, "utf-8");
2906
2723
  if (bytes > maxBytes) {
2907
- throw (0, import_agent_tool6.createTaggedError)(
2724
+ throw (0, import_agent_tool12.createTaggedError)(
2908
2725
  "HTTP_TOO_LARGE",
2909
2726
  `Response body ${bytes} bytes exceeds limit of ${maxBytes} bytes`,
2910
2727
  { url, bytes, limit: maxBytes }
@@ -2914,7 +2731,7 @@ var fetchJsonHandler = (async (args) => {
2914
2731
  try {
2915
2732
  json = JSON.parse(text);
2916
2733
  } catch {
2917
- throw (0, import_agent_tool6.createTaggedError)(
2734
+ throw (0, import_agent_tool12.createTaggedError)(
2918
2735
  "UPSTREAM_ERROR",
2919
2736
  `Failed to parse JSON response from ${url}: ${text.slice(0, 200)}`,
2920
2737
  { url, status: response.status, textPreview: text.slice(0, 500) }
@@ -2939,30 +2756,35 @@ var fetchJsonHandler = (async (args) => {
2939
2756
  });
2940
2757
 
2941
2758
  // http/downloadFile.ts
2942
- var import_promises9 = require("fs/promises");
2759
+ var import_promises7 = require("fs/promises");
2943
2760
  var import_node_crypto3 = require("crypto");
2944
- var import_node_path5 = require("path");
2945
- var import_agent_tool7 = require("@easynet/agent-tool");
2761
+ var import_node_path4 = require("path");
2762
+ var import_agent_tool13 = require("@easynet/agent-tool");
2763
+ var import_agent_tool14 = require("@easynet/agent-tool");
2946
2764
  var downloadFileHandler = (async (args) => {
2947
2765
  const ctx = getBuiltinContext();
2948
2766
  const url = (args.url ?? args.uri)?.trim();
2949
2767
  if (!url) {
2950
- throw (0, import_agent_tool7.createTaggedError)("HTTP_INVALID", "url is required (pass 'url' or 'uri')", {});
2768
+ throw (0, import_agent_tool14.createTaggedError)("HTTP_INVALID", "url is required (pass 'url' or 'uri')", {});
2951
2769
  }
2952
2770
  const destPath = (args.destPath ?? args.destination ?? args.filePath)?.trim();
2953
2771
  if (!destPath) {
2954
- throw (0, import_agent_tool7.createTaggedError)("HTTP_INVALID", "destPath is required (pass 'destPath', 'destination', or 'filePath')", {});
2772
+ throw (0, import_agent_tool14.createTaggedError)("HTTP_INVALID", "destPath is required (pass 'destPath', 'destination', or 'filePath')", {});
2955
2773
  }
2956
2774
  const headers = args.headers ?? {};
2957
2775
  const timeoutMs = args.timeoutMs ?? ctx.config.defaultTimeoutMs;
2958
2776
  const maxBytes = args.maxBytes ?? ctx.config.maxDownloadBytes;
2959
2777
  const overwrite = args.overwrite ?? false;
2960
- await validateUrl(url, ctx.config.allowedHosts, ctx.config.blockedCidrs);
2961
- const resolvedDest = await resolveSandboxedPath(destPath, ctx.config.sandboxRoot);
2778
+ await (0, import_agent_tool13.validateUrl)(url, {
2779
+ allowedHosts: ctx.config.allowedHosts,
2780
+ blockedHosts: ctx.config.blockedHosts,
2781
+ blockedCidrs: ctx.config.blockedCidrs
2782
+ });
2783
+ const resolvedDest = await (0, import_agent_tool13.resolveSandboxedPath)(destPath, ctx.config.sandboxRoot);
2962
2784
  if (!overwrite) {
2963
- const { access: access2 } = await import("fs/promises");
2785
+ const { access } = await import("fs/promises");
2964
2786
  try {
2965
- await access2(resolvedDest);
2787
+ await access(resolvedDest);
2966
2788
  throw new Error(
2967
2789
  `File already exists: ${resolvedDest}. Set overwrite=true to allow overwriting.`
2968
2790
  );
@@ -2987,13 +2809,13 @@ var downloadFileHandler = (async (args) => {
2987
2809
  });
2988
2810
  } catch (err) {
2989
2811
  if (err instanceof Error && err.name === "AbortError") {
2990
- throw (0, import_agent_tool7.createTaggedError)(
2812
+ throw (0, import_agent_tool14.createTaggedError)(
2991
2813
  "HTTP_TIMEOUT",
2992
2814
  `Download from ${url} timed out after ${timeoutMs}ms`,
2993
2815
  { url, timeoutMs }
2994
2816
  );
2995
2817
  }
2996
- throw (0, import_agent_tool7.createTaggedError)(
2818
+ throw (0, import_agent_tool14.createTaggedError)(
2997
2819
  "UPSTREAM_ERROR",
2998
2820
  `Download failed for ${url}: ${err instanceof Error ? err.message : String(err)}`,
2999
2821
  { url }
@@ -3003,14 +2825,14 @@ var downloadFileHandler = (async (args) => {
3003
2825
  }
3004
2826
  const contentLength = response.headers.get("content-length");
3005
2827
  if (contentLength && parseInt(contentLength, 10) > maxBytes) {
3006
- throw (0, import_agent_tool7.createTaggedError)(
2828
+ throw (0, import_agent_tool14.createTaggedError)(
3007
2829
  "HTTP_TOO_LARGE",
3008
2830
  `Download Content-Length ${contentLength} exceeds limit of ${maxBytes} bytes`,
3009
2831
  { url, contentLength: parseInt(contentLength, 10), limit: maxBytes }
3010
2832
  );
3011
2833
  }
3012
2834
  if (!response.body) {
3013
- throw (0, import_agent_tool7.createTaggedError)("UPSTREAM_ERROR", `No response body from ${url}`, { url });
2835
+ throw (0, import_agent_tool14.createTaggedError)("UPSTREAM_ERROR", `No response body from ${url}`, { url });
3014
2836
  }
3015
2837
  const reader = response.body.getReader();
3016
2838
  const chunks = [];
@@ -3023,7 +2845,7 @@ var downloadFileHandler = (async (args) => {
3023
2845
  totalBytes += value.byteLength;
3024
2846
  if (totalBytes > maxBytes) {
3025
2847
  reader.cancel();
3026
- throw (0, import_agent_tool7.createTaggedError)(
2848
+ throw (0, import_agent_tool14.createTaggedError)(
3027
2849
  "HTTP_TOO_LARGE",
3028
2850
  `Download from ${url} exceeded limit of ${maxBytes} bytes (received ${totalBytes})`,
3029
2851
  { url, bytesRead: totalBytes, limit: maxBytes }
@@ -3036,9 +2858,9 @@ var downloadFileHandler = (async (args) => {
3036
2858
  reader.releaseLock();
3037
2859
  }
3038
2860
  const sha256 = hasher.digest("hex");
3039
- await (0, import_promises9.mkdir)((0, import_node_path5.dirname)(resolvedDest), { recursive: true });
2861
+ await (0, import_promises7.mkdir)((0, import_node_path4.dirname)(resolvedDest), { recursive: true });
3040
2862
  const buffer = Buffer.concat(chunks);
3041
- await (0, import_promises9.writeFile)(resolvedDest, buffer);
2863
+ await (0, import_promises7.writeFile)(resolvedDest, buffer);
3042
2864
  return {
3043
2865
  result: {
3044
2866
  destPath: resolvedDest,
@@ -3065,16 +2887,21 @@ var downloadFileHandler = (async (args) => {
3065
2887
  });
3066
2888
 
3067
2889
  // http/head.ts
3068
- var import_agent_tool8 = require("@easynet/agent-tool");
2890
+ var import_agent_tool15 = require("@easynet/agent-tool");
2891
+ var import_agent_tool16 = require("@easynet/agent-tool");
3069
2892
  var headHandler = (async (args) => {
3070
2893
  const ctx = getBuiltinContext();
3071
2894
  const url = (args.url ?? args.uri)?.trim();
3072
2895
  if (!url) {
3073
- throw (0, import_agent_tool8.createTaggedError)("HTTP_INVALID", "url is required (pass 'url' or 'uri')", {});
2896
+ throw (0, import_agent_tool16.createTaggedError)("HTTP_INVALID", "url is required (pass 'url' or 'uri')", {});
3074
2897
  }
3075
2898
  const headers = args.headers ?? {};
3076
2899
  const timeoutMs = args.timeoutMs ?? ctx.config.defaultTimeoutMs;
3077
- await validateUrl(url, ctx.config.allowedHosts, ctx.config.blockedCidrs);
2900
+ await (0, import_agent_tool15.validateUrl)(url, {
2901
+ allowedHosts: ctx.config.allowedHosts,
2902
+ blockedHosts: ctx.config.blockedHosts,
2903
+ blockedCidrs: ctx.config.blockedCidrs
2904
+ });
3078
2905
  if (!headers["User-Agent"] && !headers["user-agent"]) {
3079
2906
  headers["User-Agent"] = ctx.config.httpUserAgent;
3080
2907
  }
@@ -3089,13 +2916,13 @@ var headHandler = (async (args) => {
3089
2916
  });
3090
2917
  } catch (err) {
3091
2918
  if (err instanceof Error && err.name === "AbortError") {
3092
- throw (0, import_agent_tool8.createTaggedError)(
2919
+ throw (0, import_agent_tool16.createTaggedError)(
3093
2920
  "HTTP_TIMEOUT",
3094
2921
  `HEAD request to ${url} timed out after ${timeoutMs}ms`,
3095
2922
  { url, timeoutMs }
3096
2923
  );
3097
2924
  }
3098
- throw (0, import_agent_tool8.createTaggedError)(
2925
+ throw (0, import_agent_tool16.createTaggedError)(
3099
2926
  "UPSTREAM_ERROR",
3100
2927
  `HEAD request failed for ${url}: ${err instanceof Error ? err.message : String(err)}`,
3101
2928
  { url }
@@ -3125,18 +2952,23 @@ var headHandler = (async (args) => {
3125
2952
  });
3126
2953
 
3127
2954
  // http/duckduckgoSearch.ts
3128
- var import_agent_tool9 = require("@easynet/agent-tool");
2955
+ var import_agent_tool17 = require("@easynet/agent-tool");
2956
+ var import_agent_tool18 = require("@easynet/agent-tool");
3129
2957
  var DUCKDUCKGO_API = "https://api.duckduckgo.com/";
3130
2958
  var duckduckgoSearchHandler = (async (args) => {
3131
2959
  const ctx = getBuiltinContext();
3132
2960
  const query = (args.query ?? args.q)?.trim();
3133
2961
  if (!query) {
3134
- throw (0, import_agent_tool9.createTaggedError)("DUCKDUCKGO_INVALID", "query is required (pass 'query' or 'q')", {});
2962
+ throw (0, import_agent_tool18.createTaggedError)("DUCKDUCKGO_INVALID", "query is required (pass 'query' or 'q')", {});
3135
2963
  }
3136
2964
  const timeoutMs = args.timeoutMs ?? ctx.config.defaultTimeoutMs;
3137
2965
  const maxResults = args.maxResults ?? 10;
3138
2966
  const url = `${DUCKDUCKGO_API}?q=${encodeURIComponent(query)}&format=json`;
3139
- await validateUrl(url, ctx.config.allowedHosts, ctx.config.blockedCidrs);
2967
+ await (0, import_agent_tool17.validateUrl)(url, {
2968
+ allowedHosts: ctx.config.allowedHosts,
2969
+ blockedHosts: ctx.config.blockedHosts,
2970
+ blockedCidrs: ctx.config.blockedCidrs
2971
+ });
3140
2972
  const controller = new AbortController();
3141
2973
  const timer = setTimeout(() => controller.abort(), timeoutMs);
3142
2974
  let response;
@@ -3149,13 +2981,13 @@ var duckduckgoSearchHandler = (async (args) => {
3149
2981
  } catch (err) {
3150
2982
  clearTimeout(timer);
3151
2983
  if (err instanceof Error && err.name === "AbortError") {
3152
- throw (0, import_agent_tool9.createTaggedError)(
2984
+ throw (0, import_agent_tool18.createTaggedError)(
3153
2985
  "HTTP_TIMEOUT",
3154
2986
  `DuckDuckGo search timed out after ${timeoutMs}ms`,
3155
2987
  { query, timeoutMs }
3156
2988
  );
3157
2989
  }
3158
- throw (0, import_agent_tool9.createTaggedError)(
2990
+ throw (0, import_agent_tool18.createTaggedError)(
3159
2991
  "UPSTREAM_ERROR",
3160
2992
  `DuckDuckGo search failed: ${err instanceof Error ? err.message : String(err)}`,
3161
2993
  { query }
@@ -3166,7 +2998,7 @@ var duckduckgoSearchHandler = (async (args) => {
3166
2998
  const text = await response.text();
3167
2999
  const bytes = Buffer.byteLength(text, "utf-8");
3168
3000
  if (bytes > maxBytes) {
3169
- throw (0, import_agent_tool9.createTaggedError)(
3001
+ throw (0, import_agent_tool18.createTaggedError)(
3170
3002
  "HTTP_TOO_LARGE",
3171
3003
  `DuckDuckGo response ${bytes} bytes exceeds limit of ${maxBytes} bytes`,
3172
3004
  { query, bytes, limit: maxBytes }
@@ -3176,7 +3008,7 @@ var duckduckgoSearchHandler = (async (args) => {
3176
3008
  try {
3177
3009
  raw = JSON.parse(text);
3178
3010
  } catch {
3179
- throw (0, import_agent_tool9.createTaggedError)(
3011
+ throw (0, import_agent_tool18.createTaggedError)(
3180
3012
  "UPSTREAM_ERROR",
3181
3013
  `DuckDuckGo returned invalid JSON`,
3182
3014
  { query, textPreview: text.slice(0, 200) }
@@ -3227,7 +3059,8 @@ var duckduckgoSearchHandler = (async (args) => {
3227
3059
 
3228
3060
  // http/fetchPageMainContent.ts
3229
3061
  var import_node_html_parser = require("node-html-parser");
3230
- var import_agent_tool10 = require("@easynet/agent-tool");
3062
+ var import_agent_tool19 = require("@easynet/agent-tool");
3063
+ var import_agent_tool20 = require("@easynet/agent-tool");
3231
3064
  var MAIN_SELECTORS = [
3232
3065
  "main",
3233
3066
  "article",
@@ -3270,11 +3103,15 @@ var fetchPageMainContentHandler = (async (args) => {
3270
3103
  const ctx = getBuiltinContext();
3271
3104
  const url = (args.url ?? args.uri)?.trim();
3272
3105
  if (!url) {
3273
- throw (0, import_agent_tool10.createTaggedError)("HTTP_INVALID", "url is required (pass 'url' or 'uri')", {});
3106
+ throw (0, import_agent_tool20.createTaggedError)("HTTP_INVALID", "url is required (pass 'url' or 'uri')", {});
3274
3107
  }
3275
3108
  const timeoutMs = args.timeoutMs ?? ctx.config.defaultTimeoutMs;
3276
3109
  const maxBytes = args.maxBytes ?? ctx.config.maxHttpBytes;
3277
- await validateUrl(url, ctx.config.allowedHosts, ctx.config.blockedCidrs);
3110
+ await (0, import_agent_tool19.validateUrl)(url, {
3111
+ allowedHosts: ctx.config.allowedHosts,
3112
+ blockedHosts: ctx.config.blockedHosts,
3113
+ blockedCidrs: ctx.config.blockedCidrs
3114
+ });
3278
3115
  const controller = new AbortController();
3279
3116
  const timer = setTimeout(() => controller.abort(), timeoutMs);
3280
3117
  let response;
@@ -3287,13 +3124,13 @@ var fetchPageMainContentHandler = (async (args) => {
3287
3124
  } catch (err) {
3288
3125
  clearTimeout(timer);
3289
3126
  if (err instanceof Error && err.name === "AbortError") {
3290
- throw (0, import_agent_tool10.createTaggedError)(
3127
+ throw (0, import_agent_tool20.createTaggedError)(
3291
3128
  "HTTP_TIMEOUT",
3292
3129
  `Request to ${url} timed out after ${timeoutMs}ms`,
3293
3130
  { url, timeoutMs }
3294
3131
  );
3295
3132
  }
3296
- throw (0, import_agent_tool10.createTaggedError)(
3133
+ throw (0, import_agent_tool20.createTaggedError)(
3297
3134
  "UPSTREAM_ERROR",
3298
3135
  `Fetch failed for ${url}: ${err instanceof Error ? err.message : String(err)}`,
3299
3136
  { url }
@@ -3302,7 +3139,7 @@ var fetchPageMainContentHandler = (async (args) => {
3302
3139
  clearTimeout(timer);
3303
3140
  const contentLength = response.headers.get("content-length");
3304
3141
  if (contentLength && parseInt(contentLength, 10) > maxBytes) {
3305
- throw (0, import_agent_tool10.createTaggedError)(
3142
+ throw (0, import_agent_tool20.createTaggedError)(
3306
3143
  "HTTP_TOO_LARGE",
3307
3144
  `Response Content-Length ${contentLength} exceeds limit of ${maxBytes} bytes`,
3308
3145
  { url, contentLength: parseInt(contentLength, 10), limit: maxBytes }
@@ -3311,7 +3148,7 @@ var fetchPageMainContentHandler = (async (args) => {
3311
3148
  const rawText = await response.text();
3312
3149
  const rawBytes = Buffer.byteLength(rawText, "utf-8");
3313
3150
  if (rawBytes > maxBytes) {
3314
- throw (0, import_agent_tool10.createTaggedError)(
3151
+ throw (0, import_agent_tool20.createTaggedError)(
3315
3152
  "HTTP_TOO_LARGE",
3316
3153
  `Response body ${rawBytes} bytes exceeds limit of ${maxBytes} bytes`,
3317
3154
  { url, bytes: rawBytes, limit: maxBytes }
@@ -3354,14 +3191,15 @@ var fetchPageMainContentHandler = (async (args) => {
3354
3191
  });
3355
3192
 
3356
3193
  // http/yahooFinance.ts
3357
- var import_agent_tool11 = require("@easynet/agent-tool");
3194
+ var import_agent_tool21 = require("@easynet/agent-tool");
3195
+ var import_agent_tool22 = require("@easynet/agent-tool");
3358
3196
  var YAHOO_CHART_BASE = "https://query1.finance.yahoo.com/v8/finance/chart/";
3359
3197
  var yahooFinanceQuoteHandler = (async (args) => {
3360
3198
  const ctx = getBuiltinContext();
3361
3199
  const rawSymbols = args.symbols ?? args.symbol ?? args.tickers;
3362
3200
  const symbols = Array.isArray(rawSymbols) ? rawSymbols.map((s) => String(s).trim().toUpperCase()).filter(Boolean) : rawSymbols != null ? [String(rawSymbols).trim().toUpperCase()].filter(Boolean) : [];
3363
3201
  if (symbols.length === 0) {
3364
- throw (0, import_agent_tool11.createTaggedError)(
3202
+ throw (0, import_agent_tool22.createTaggedError)(
3365
3203
  "YAHOO_INVALID",
3366
3204
  "At least one symbol is required",
3367
3205
  {}
@@ -3373,7 +3211,11 @@ var yahooFinanceQuoteHandler = (async (args) => {
3373
3211
  const quotes = [];
3374
3212
  for (const symbol of symbols) {
3375
3213
  const url2 = `${YAHOO_CHART_BASE}${encodeURIComponent(symbol)}?interval=1d&range=${range}`;
3376
- await validateUrl(url2, ctx.config.allowedHosts, ctx.config.blockedCidrs);
3214
+ await (0, import_agent_tool21.validateUrl)(url2, {
3215
+ allowedHosts: ctx.config.allowedHosts,
3216
+ blockedHosts: ctx.config.blockedHosts,
3217
+ blockedCidrs: ctx.config.blockedCidrs
3218
+ });
3377
3219
  const controller = new AbortController();
3378
3220
  const timer = setTimeout(() => controller.abort(), timeoutMs);
3379
3221
  let response;
@@ -3389,13 +3231,13 @@ var yahooFinanceQuoteHandler = (async (args) => {
3389
3231
  } catch (err) {
3390
3232
  clearTimeout(timer);
3391
3233
  if (err instanceof Error && err.name === "AbortError") {
3392
- throw (0, import_agent_tool11.createTaggedError)(
3234
+ throw (0, import_agent_tool22.createTaggedError)(
3393
3235
  "HTTP_TIMEOUT",
3394
3236
  `Yahoo Finance request for ${symbol} timed out after ${timeoutMs}ms`,
3395
3237
  { symbol, timeoutMs }
3396
3238
  );
3397
3239
  }
3398
- throw (0, import_agent_tool11.createTaggedError)(
3240
+ throw (0, import_agent_tool22.createTaggedError)(
3399
3241
  "UPSTREAM_ERROR",
3400
3242
  `Yahoo Finance request failed: ${err instanceof Error ? err.message : String(err)}`,
3401
3243
  { symbol }
@@ -3405,7 +3247,7 @@ var yahooFinanceQuoteHandler = (async (args) => {
3405
3247
  const text = await response.text();
3406
3248
  const bytes = Buffer.byteLength(text, "utf-8");
3407
3249
  if (bytes > maxBytes) {
3408
- throw (0, import_agent_tool11.createTaggedError)(
3250
+ throw (0, import_agent_tool22.createTaggedError)(
3409
3251
  "HTTP_TOO_LARGE",
3410
3252
  `Yahoo Finance response ${bytes} bytes exceeds limit of ${maxBytes} bytes`,
3411
3253
  { symbol, bytes, limit: maxBytes }
@@ -3415,7 +3257,7 @@ var yahooFinanceQuoteHandler = (async (args) => {
3415
3257
  try {
3416
3258
  data = JSON.parse(text);
3417
3259
  } catch {
3418
- throw (0, import_agent_tool11.createTaggedError)(
3260
+ throw (0, import_agent_tool22.createTaggedError)(
3419
3261
  "UPSTREAM_ERROR",
3420
3262
  "Yahoo Finance returned invalid JSON",
3421
3263
  { symbol, textPreview: text.slice(0, 200) }
@@ -3423,7 +3265,7 @@ var yahooFinanceQuoteHandler = (async (args) => {
3423
3265
  }
3424
3266
  const error = data.chart?.error;
3425
3267
  if (error?.description) {
3426
- throw (0, import_agent_tool11.createTaggedError)(
3268
+ throw (0, import_agent_tool22.createTaggedError)(
3427
3269
  "YAHOO_ERROR",
3428
3270
  `Yahoo Finance error for ${symbol}: ${error.description}`,
3429
3271
  { symbol, code: error.code }
@@ -3635,13 +3477,14 @@ var templateRenderHandler = (async (args) => {
3635
3477
 
3636
3478
  // exec/runCommand.ts
3637
3479
  var import_node_child_process = require("child_process");
3638
- var import_node_path6 = require("path");
3639
- var import_agent_tool12 = require("@easynet/agent-tool");
3480
+ var import_node_path5 = require("path");
3481
+ var import_agent_tool23 = require("@easynet/agent-tool");
3482
+ var import_agent_tool24 = require("@easynet/agent-tool");
3640
3483
  var runCommandHandler = (async (args) => {
3641
3484
  const ctx = getBuiltinContext();
3642
3485
  const { allowedCommands, maxCommandOutputBytes, commandTimeoutMs } = ctx.config;
3643
3486
  if (!allowedCommands.length) {
3644
- throw (0, import_agent_tool12.createTaggedError)(
3487
+ throw (0, import_agent_tool24.createTaggedError)(
3645
3488
  "EXEC_DISABLED",
3646
3489
  "Exec is disabled: allowedCommands is empty",
3647
3490
  {}
@@ -3649,18 +3492,18 @@ var runCommandHandler = (async (args) => {
3649
3492
  }
3650
3493
  const rawCommand = (args.command ?? args.cmd)?.trim();
3651
3494
  if (!rawCommand) {
3652
- throw (0, import_agent_tool12.createTaggedError)("EXEC_INVALID", "command is required (pass 'command' or 'cmd')", {});
3495
+ throw (0, import_agent_tool24.createTaggedError)("EXEC_INVALID", "command is required (pass 'command' or 'cmd')", {});
3653
3496
  }
3654
3497
  const baseName = rawCommand.replace(/^.*\//, "").trim();
3655
3498
  if (baseName !== rawCommand || /[;&|$`\s]/.test(rawCommand)) {
3656
- throw (0, import_agent_tool12.createTaggedError)(
3499
+ throw (0, import_agent_tool24.createTaggedError)(
3657
3500
  "EXEC_INVALID",
3658
3501
  "command must be a single executable name (no path, no shell chars)",
3659
3502
  { command: rawCommand }
3660
3503
  );
3661
3504
  }
3662
3505
  if (!allowedCommands.includes(baseName)) {
3663
- throw (0, import_agent_tool12.createTaggedError)(
3506
+ throw (0, import_agent_tool24.createTaggedError)(
3664
3507
  "EXEC_NOT_ALLOWED",
3665
3508
  `Command "${baseName}" is not in allowedCommands`,
3666
3509
  { command: baseName, allowed: allowedCommands }
@@ -3668,9 +3511,9 @@ var runCommandHandler = (async (args) => {
3668
3511
  }
3669
3512
  const cmdArgs = Array.isArray(args.args) ? args.args : Array.isArray(args.arguments) ? args.arguments : [];
3670
3513
  const timeoutMs = args.timeoutMs ?? commandTimeoutMs;
3671
- let cwd = (0, import_node_path6.resolve)(ctx.config.sandboxRoot);
3514
+ let cwd = (0, import_node_path5.resolve)(ctx.config.sandboxRoot);
3672
3515
  if (args.cwd != null && args.cwd !== "") {
3673
- cwd = await resolveSandboxedPath(args.cwd, ctx.config.sandboxRoot);
3516
+ cwd = await (0, import_agent_tool23.resolveSandboxedPath)(args.cwd, ctx.config.sandboxRoot);
3674
3517
  }
3675
3518
  return new Promise((resolvePromise, rejectPromise) => {
3676
3519
  const proc = (0, import_node_child_process.spawn)(baseName, cmdArgs, {
@@ -3687,7 +3530,7 @@ var runCommandHandler = (async (args) => {
3687
3530
  if (totalBytes + len > maxCommandOutputBytes) {
3688
3531
  proc.kill("SIGKILL");
3689
3532
  rejectPromise(
3690
- (0, import_agent_tool12.createTaggedError)(
3533
+ (0, import_agent_tool24.createTaggedError)(
3691
3534
  "EXEC_OUTPUT_TOO_LARGE",
3692
3535
  `Command output exceeded ${maxCommandOutputBytes} bytes`,
3693
3536
  { maxBytes: maxCommandOutputBytes }
@@ -3725,7 +3568,7 @@ var runCommandHandler = (async (args) => {
3725
3568
  proc.on("error", (err) => {
3726
3569
  clearTimeout(timeout);
3727
3570
  rejectPromise(
3728
- (0, import_agent_tool12.createTaggedError)("EXEC_SPAWN_ERROR", err.message, { command: baseName })
3571
+ (0, import_agent_tool24.createTaggedError)("EXEC_SPAWN_ERROR", err.message, { command: baseName })
3729
3572
  );
3730
3573
  });
3731
3574
  proc.on("close", (code, signal) => {
@@ -3959,7 +3802,8 @@ var CORE_GROUP_PREFIX = {
3959
3802
  function registerCoreTools(registry, userConfig, options) {
3960
3803
  const config = {
3961
3804
  ...DEFAULT_CORE_TOOLS_CONFIG,
3962
- ...userConfig
3805
+ ...userConfig,
3806
+ blockedHosts: userConfig.blockedHosts ?? []
3963
3807
  };
3964
3808
  const adapter = new CoreAdapter(config);
3965
3809
  const onlySet = options?.only?.length ? new Set(options.only) : null;
@@ -3976,6 +3820,9 @@ function registerCoreTools(registry, userConfig, options) {
3976
3820
  }
3977
3821
  return adapter;
3978
3822
  }
3823
+
3824
+ // index.ts
3825
+ var import_agent_tool25 = require("@easynet/agent-tool");
3979
3826
  // Annotate the CommonJS export names for ESM import in node:
3980
3827
  0 && (module.exports = {
3981
3828
  CoreAdapter,