@easynet/agent-tool-buildin 0.0.1 → 0.0.2

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
@@ -2036,7 +2036,8 @@ __export(index_exports, {
2036
2036
  templateRenderSpec: () => templateRenderSpec,
2037
2037
  truncateSpec: () => truncateSpec,
2038
2038
  validateUrl: () => validateUrl,
2039
- writeTextSpec: () => writeTextSpec
2039
+ writeTextSpec: () => writeTextSpec,
2040
+ yahooFinanceQuoteSpec: () => yahooFinanceQuoteSpec
2040
2041
  });
2041
2042
  module.exports = __toCommonJS(index_exports);
2042
2043
 
@@ -2190,7 +2191,10 @@ function isWithinRoot(path, root) {
2190
2191
  var import_agent_tool2 = require("@easynet/agent-tool");
2191
2192
  var readTextHandler = (async (args) => {
2192
2193
  const ctx = getBuiltinContext();
2193
- const inputPath = args.path;
2194
+ const inputPath = (args.path ?? args.filePath)?.trim();
2195
+ if (!inputPath) {
2196
+ throw (0, import_agent_tool2.createTaggedError)("FS_INVALID", "path is required (pass 'path' or 'filePath')", {});
2197
+ }
2194
2198
  const maxBytes = args.maxBytes ?? ctx.config.maxReadBytes;
2195
2199
  const resolvedPath = await resolveSandboxedPath(inputPath, ctx.config.sandboxRoot);
2196
2200
  const fileStat = await (0, import_promises2.stat)(resolvedPath);
@@ -2225,8 +2229,11 @@ var import_node_crypto = require("crypto");
2225
2229
  var import_node_path2 = require("path");
2226
2230
  var writeTextHandler = (async (args) => {
2227
2231
  const ctx = getBuiltinContext();
2228
- const inputPath = args.path;
2229
- const text = args.text;
2232
+ const inputPath = (args.path ?? args.filePath)?.trim();
2233
+ if (!inputPath) {
2234
+ throw new Error("path is required (pass 'path' or 'filePath')");
2235
+ }
2236
+ const text = args.text ?? args.content ?? "";
2230
2237
  const overwrite = args.overwrite ?? false;
2231
2238
  const mkdirp = args.mkdirp ?? true;
2232
2239
  const resolvedPath = await resolveSandboxedPath(inputPath, ctx.config.sandboxRoot);
@@ -2272,7 +2279,10 @@ var import_promises4 = require("fs/promises");
2272
2279
  var import_node_path3 = require("path");
2273
2280
  var listDirHandler = (async (args) => {
2274
2281
  const ctx = getBuiltinContext();
2275
- const inputPath = args.path;
2282
+ const inputPath = (args.path ?? args.filePath ?? args.dir ?? args.directory)?.trim();
2283
+ if (!inputPath) {
2284
+ throw new Error("path is required (pass 'path', 'filePath', 'dir', or 'directory')");
2285
+ }
2276
2286
  const maxEntries = args.maxEntries ?? 2e3;
2277
2287
  const includeHidden = args.includeHidden ?? false;
2278
2288
  const recursive = args.recursive ?? false;
@@ -2364,8 +2374,14 @@ var import_node_readline = require("readline");
2364
2374
  var import_node_path4 = require("path");
2365
2375
  var searchTextHandler = (async (args) => {
2366
2376
  const ctx = getBuiltinContext();
2367
- const rootPath = args.root;
2368
- const query = args.query;
2377
+ const rootPath = (args.root ?? args.path ?? args.dir ?? args.directory)?.trim();
2378
+ if (!rootPath) {
2379
+ throw new Error("root is required (pass 'root', 'path', 'dir', or 'directory')");
2380
+ }
2381
+ const query = (args.query ?? args.q)?.trim();
2382
+ if (!query) {
2383
+ throw new Error("query is required (pass 'query' or 'q')");
2384
+ }
2369
2385
  const glob = args.glob ?? "**/*.{md,txt,log,json,ts,js,py,java,scala}";
2370
2386
  const maxMatches = args.maxMatches ?? 100;
2371
2387
  const maxFiles = args.maxFiles ?? 500;
@@ -2484,9 +2500,13 @@ function escapeRegExp(str) {
2484
2500
  var import_node_fs2 = require("fs");
2485
2501
  var import_promises6 = require("fs/promises");
2486
2502
  var import_node_crypto2 = require("crypto");
2503
+ var import_agent_tool3 = require("@easynet/agent-tool");
2487
2504
  var sha256Handler = (async (args) => {
2488
2505
  const ctx = getBuiltinContext();
2489
- const inputPath = args.path;
2506
+ const inputPath = (args.path ?? args.filePath)?.trim();
2507
+ if (!inputPath) {
2508
+ throw (0, import_agent_tool3.createTaggedError)("FS_INVALID", "path is required (pass 'path' or 'filePath')", {});
2509
+ }
2490
2510
  const resolvedPath = await resolveSandboxedPath(inputPath, ctx.config.sandboxRoot);
2491
2511
  const fileStat = await (0, import_promises6.stat)(resolvedPath);
2492
2512
  const hash = await new Promise((resolve3, reject) => {
@@ -2517,7 +2537,10 @@ var sha256Handler = (async (args) => {
2517
2537
  var import_promises7 = require("fs/promises");
2518
2538
  var deletePathHandler = (async (args) => {
2519
2539
  const ctx = getBuiltinContext();
2520
- const inputPath = args.path;
2540
+ const inputPath = (args.path ?? args.filePath)?.trim();
2541
+ if (!inputPath) {
2542
+ throw new Error("path is required (pass 'path' or 'filePath')");
2543
+ }
2521
2544
  const recursive = args.recursive ?? false;
2522
2545
  const confirm = args.confirm;
2523
2546
  if (!confirm) {
@@ -2566,20 +2589,20 @@ var deletePathHandler = (async (args) => {
2566
2589
 
2567
2590
  // security/ssrf.ts
2568
2591
  var import_promises8 = require("dns/promises");
2569
- var import_agent_tool3 = require("@easynet/agent-tool");
2592
+ var import_agent_tool4 = require("@easynet/agent-tool");
2570
2593
  async function validateUrl(url, allowedHosts, blockedCidrs) {
2571
2594
  let parsed;
2572
2595
  try {
2573
2596
  parsed = new URL(url);
2574
2597
  } catch {
2575
- throw (0, import_agent_tool3.createTaggedError)(
2598
+ throw (0, import_agent_tool4.createTaggedError)(
2576
2599
  "HTTP_DISALLOWED_HOST",
2577
2600
  `Invalid URL: ${url}`,
2578
2601
  { url }
2579
2602
  );
2580
2603
  }
2581
2604
  if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
2582
- throw (0, import_agent_tool3.createTaggedError)(
2605
+ throw (0, import_agent_tool4.createTaggedError)(
2583
2606
  "HTTP_DISALLOWED_HOST",
2584
2607
  `Protocol not allowed: ${parsed.protocol}. Only http: and https: are supported.`,
2585
2608
  { url, protocol: parsed.protocol }
@@ -2587,7 +2610,7 @@ async function validateUrl(url, allowedHosts, blockedCidrs) {
2587
2610
  }
2588
2611
  const hostname = parsed.hostname;
2589
2612
  if (!isHostAllowed(hostname, allowedHosts)) {
2590
- throw (0, import_agent_tool3.createTaggedError)(
2613
+ throw (0, import_agent_tool4.createTaggedError)(
2591
2614
  "HTTP_DISALLOWED_HOST",
2592
2615
  `Host "${hostname}" is not in the allowed hosts list`,
2593
2616
  { url, hostname, allowedHosts }
@@ -2596,7 +2619,7 @@ async function validateUrl(url, allowedHosts, blockedCidrs) {
2596
2619
  try {
2597
2620
  const { address } = await (0, import_promises8.lookup)(hostname);
2598
2621
  if (isIpInBlockedCidrs(address, blockedCidrs)) {
2599
- throw (0, import_agent_tool3.createTaggedError)(
2622
+ throw (0, import_agent_tool4.createTaggedError)(
2600
2623
  "HTTP_DISALLOWED_HOST",
2601
2624
  `Host "${hostname}" resolves to blocked IP: ${address}`,
2602
2625
  { url, hostname, resolvedIp: address }
@@ -2606,7 +2629,7 @@ async function validateUrl(url, allowedHosts, blockedCidrs) {
2606
2629
  if (err instanceof Error && err.kind === "HTTP_DISALLOWED_HOST") {
2607
2630
  throw err;
2608
2631
  }
2609
- throw (0, import_agent_tool3.createTaggedError)(
2632
+ throw (0, import_agent_tool4.createTaggedError)(
2610
2633
  "HTTP_DISALLOWED_HOST",
2611
2634
  `DNS resolution failed for host "${hostname}": ${err instanceof Error ? err.message : String(err)}`,
2612
2635
  { url, hostname }
@@ -2717,10 +2740,13 @@ function expandIpv6(ip) {
2717
2740
  }
2718
2741
 
2719
2742
  // http/fetchText.ts
2720
- var import_agent_tool4 = require("@easynet/agent-tool");
2743
+ var import_agent_tool5 = require("@easynet/agent-tool");
2721
2744
  var fetchTextHandler = (async (args) => {
2722
2745
  const ctx = getBuiltinContext();
2723
- const url = args.url;
2746
+ const url = (args.url ?? args.uri)?.trim();
2747
+ if (!url) {
2748
+ throw (0, import_agent_tool5.createTaggedError)("HTTP_INVALID", "url is required (pass 'url' or 'uri')", {});
2749
+ }
2724
2750
  const method = args.method ?? "GET";
2725
2751
  const headers = args.headers ?? {};
2726
2752
  const body = args.body ?? void 0;
@@ -2742,13 +2768,13 @@ var fetchTextHandler = (async (args) => {
2742
2768
  });
2743
2769
  } catch (err) {
2744
2770
  if (err instanceof Error && err.name === "AbortError") {
2745
- throw (0, import_agent_tool4.createTaggedError)(
2771
+ throw (0, import_agent_tool5.createTaggedError)(
2746
2772
  "HTTP_TIMEOUT",
2747
2773
  `Request to ${url} timed out after ${timeoutMs}ms`,
2748
2774
  { url, timeoutMs }
2749
2775
  );
2750
2776
  }
2751
- throw (0, import_agent_tool4.createTaggedError)(
2777
+ throw (0, import_agent_tool5.createTaggedError)(
2752
2778
  "UPSTREAM_ERROR",
2753
2779
  `Fetch failed for ${url}: ${err instanceof Error ? err.message : String(err)}`,
2754
2780
  { url }
@@ -2758,7 +2784,7 @@ var fetchTextHandler = (async (args) => {
2758
2784
  }
2759
2785
  const contentLength = response.headers.get("content-length");
2760
2786
  if (contentLength && parseInt(contentLength, 10) > maxBytes) {
2761
- throw (0, import_agent_tool4.createTaggedError)(
2787
+ throw (0, import_agent_tool5.createTaggedError)(
2762
2788
  "HTTP_TOO_LARGE",
2763
2789
  `Response Content-Length ${contentLength} exceeds limit of ${maxBytes} bytes`,
2764
2790
  { url, contentLength: parseInt(contentLength, 10), limit: maxBytes }
@@ -2803,7 +2829,7 @@ async function readResponseWithLimit(response, maxBytes, url) {
2803
2829
  totalBytes += value.byteLength;
2804
2830
  if (totalBytes > maxBytes) {
2805
2831
  reader.cancel();
2806
- throw (0, import_agent_tool4.createTaggedError)(
2832
+ throw (0, import_agent_tool5.createTaggedError)(
2807
2833
  "HTTP_TOO_LARGE",
2808
2834
  `Response body exceeded limit of ${maxBytes} bytes while reading from ${url}`,
2809
2835
  { url, bytesRead: totalBytes, limit: maxBytes }
@@ -2819,10 +2845,13 @@ async function readResponseWithLimit(response, maxBytes, url) {
2819
2845
  }
2820
2846
 
2821
2847
  // http/fetchJson.ts
2822
- var import_agent_tool5 = require("@easynet/agent-tool");
2848
+ var import_agent_tool6 = require("@easynet/agent-tool");
2823
2849
  var fetchJsonHandler = (async (args) => {
2824
2850
  const ctx = getBuiltinContext();
2825
- const url = args.url;
2851
+ const url = (args.url ?? args.uri)?.trim();
2852
+ if (!url) {
2853
+ throw (0, import_agent_tool6.createTaggedError)("HTTP_INVALID", "url is required (pass 'url' or 'uri')", {});
2854
+ }
2826
2855
  const method = args.method ?? "GET";
2827
2856
  const headers = args.headers ?? {};
2828
2857
  const body = args.body ?? void 0;
@@ -2847,13 +2876,13 @@ var fetchJsonHandler = (async (args) => {
2847
2876
  });
2848
2877
  } catch (err) {
2849
2878
  if (err instanceof Error && err.name === "AbortError") {
2850
- throw (0, import_agent_tool5.createTaggedError)(
2879
+ throw (0, import_agent_tool6.createTaggedError)(
2851
2880
  "HTTP_TIMEOUT",
2852
2881
  `Request to ${url} timed out after ${timeoutMs}ms`,
2853
2882
  { url, timeoutMs }
2854
2883
  );
2855
2884
  }
2856
- throw (0, import_agent_tool5.createTaggedError)(
2885
+ throw (0, import_agent_tool6.createTaggedError)(
2857
2886
  "UPSTREAM_ERROR",
2858
2887
  `Fetch failed for ${url}: ${err instanceof Error ? err.message : String(err)}`,
2859
2888
  { url }
@@ -2863,7 +2892,7 @@ var fetchJsonHandler = (async (args) => {
2863
2892
  }
2864
2893
  const contentLength = response.headers.get("content-length");
2865
2894
  if (contentLength && parseInt(contentLength, 10) > maxBytes) {
2866
- throw (0, import_agent_tool5.createTaggedError)(
2895
+ throw (0, import_agent_tool6.createTaggedError)(
2867
2896
  "HTTP_TOO_LARGE",
2868
2897
  `Response Content-Length ${contentLength} exceeds limit of ${maxBytes} bytes`,
2869
2898
  { url, contentLength: parseInt(contentLength, 10), limit: maxBytes }
@@ -2872,7 +2901,7 @@ var fetchJsonHandler = (async (args) => {
2872
2901
  const text = await response.text();
2873
2902
  const bytes = Buffer.byteLength(text, "utf-8");
2874
2903
  if (bytes > maxBytes) {
2875
- throw (0, import_agent_tool5.createTaggedError)(
2904
+ throw (0, import_agent_tool6.createTaggedError)(
2876
2905
  "HTTP_TOO_LARGE",
2877
2906
  `Response body ${bytes} bytes exceeds limit of ${maxBytes} bytes`,
2878
2907
  { url, bytes, limit: maxBytes }
@@ -2882,7 +2911,7 @@ var fetchJsonHandler = (async (args) => {
2882
2911
  try {
2883
2912
  json = JSON.parse(text);
2884
2913
  } catch {
2885
- throw (0, import_agent_tool5.createTaggedError)(
2914
+ throw (0, import_agent_tool6.createTaggedError)(
2886
2915
  "UPSTREAM_ERROR",
2887
2916
  `Failed to parse JSON response from ${url}: ${text.slice(0, 200)}`,
2888
2917
  { url, status: response.status, textPreview: text.slice(0, 500) }
@@ -2910,11 +2939,17 @@ var fetchJsonHandler = (async (args) => {
2910
2939
  var import_promises9 = require("fs/promises");
2911
2940
  var import_node_crypto3 = require("crypto");
2912
2941
  var import_node_path5 = require("path");
2913
- var import_agent_tool6 = require("@easynet/agent-tool");
2942
+ var import_agent_tool7 = require("@easynet/agent-tool");
2914
2943
  var downloadFileHandler = (async (args) => {
2915
2944
  const ctx = getBuiltinContext();
2916
- const url = args.url;
2917
- const destPath = args.destPath;
2945
+ const url = (args.url ?? args.uri)?.trim();
2946
+ if (!url) {
2947
+ throw (0, import_agent_tool7.createTaggedError)("HTTP_INVALID", "url is required (pass 'url' or 'uri')", {});
2948
+ }
2949
+ const destPath = (args.destPath ?? args.destination ?? args.filePath)?.trim();
2950
+ if (!destPath) {
2951
+ throw (0, import_agent_tool7.createTaggedError)("HTTP_INVALID", "destPath is required (pass 'destPath', 'destination', or 'filePath')", {});
2952
+ }
2918
2953
  const headers = args.headers ?? {};
2919
2954
  const timeoutMs = args.timeoutMs ?? ctx.config.defaultTimeoutMs;
2920
2955
  const maxBytes = args.maxBytes ?? ctx.config.maxDownloadBytes;
@@ -2949,13 +2984,13 @@ var downloadFileHandler = (async (args) => {
2949
2984
  });
2950
2985
  } catch (err) {
2951
2986
  if (err instanceof Error && err.name === "AbortError") {
2952
- throw (0, import_agent_tool6.createTaggedError)(
2987
+ throw (0, import_agent_tool7.createTaggedError)(
2953
2988
  "HTTP_TIMEOUT",
2954
2989
  `Download from ${url} timed out after ${timeoutMs}ms`,
2955
2990
  { url, timeoutMs }
2956
2991
  );
2957
2992
  }
2958
- throw (0, import_agent_tool6.createTaggedError)(
2993
+ throw (0, import_agent_tool7.createTaggedError)(
2959
2994
  "UPSTREAM_ERROR",
2960
2995
  `Download failed for ${url}: ${err instanceof Error ? err.message : String(err)}`,
2961
2996
  { url }
@@ -2965,14 +3000,14 @@ var downloadFileHandler = (async (args) => {
2965
3000
  }
2966
3001
  const contentLength = response.headers.get("content-length");
2967
3002
  if (contentLength && parseInt(contentLength, 10) > maxBytes) {
2968
- throw (0, import_agent_tool6.createTaggedError)(
3003
+ throw (0, import_agent_tool7.createTaggedError)(
2969
3004
  "HTTP_TOO_LARGE",
2970
3005
  `Download Content-Length ${contentLength} exceeds limit of ${maxBytes} bytes`,
2971
3006
  { url, contentLength: parseInt(contentLength, 10), limit: maxBytes }
2972
3007
  );
2973
3008
  }
2974
3009
  if (!response.body) {
2975
- throw (0, import_agent_tool6.createTaggedError)("UPSTREAM_ERROR", `No response body from ${url}`, { url });
3010
+ throw (0, import_agent_tool7.createTaggedError)("UPSTREAM_ERROR", `No response body from ${url}`, { url });
2976
3011
  }
2977
3012
  const reader = response.body.getReader();
2978
3013
  const chunks = [];
@@ -2985,7 +3020,7 @@ var downloadFileHandler = (async (args) => {
2985
3020
  totalBytes += value.byteLength;
2986
3021
  if (totalBytes > maxBytes) {
2987
3022
  reader.cancel();
2988
- throw (0, import_agent_tool6.createTaggedError)(
3023
+ throw (0, import_agent_tool7.createTaggedError)(
2989
3024
  "HTTP_TOO_LARGE",
2990
3025
  `Download from ${url} exceeded limit of ${maxBytes} bytes (received ${totalBytes})`,
2991
3026
  { url, bytesRead: totalBytes, limit: maxBytes }
@@ -3027,10 +3062,13 @@ var downloadFileHandler = (async (args) => {
3027
3062
  });
3028
3063
 
3029
3064
  // http/head.ts
3030
- var import_agent_tool7 = require("@easynet/agent-tool");
3065
+ var import_agent_tool8 = require("@easynet/agent-tool");
3031
3066
  var headHandler = (async (args) => {
3032
3067
  const ctx = getBuiltinContext();
3033
- const url = args.url;
3068
+ const url = (args.url ?? args.uri)?.trim();
3069
+ if (!url) {
3070
+ throw (0, import_agent_tool8.createTaggedError)("HTTP_INVALID", "url is required (pass 'url' or 'uri')", {});
3071
+ }
3034
3072
  const headers = args.headers ?? {};
3035
3073
  const timeoutMs = args.timeoutMs ?? ctx.config.defaultTimeoutMs;
3036
3074
  await validateUrl(url, ctx.config.allowedHosts, ctx.config.blockedCidrs);
@@ -3048,13 +3086,13 @@ var headHandler = (async (args) => {
3048
3086
  });
3049
3087
  } catch (err) {
3050
3088
  if (err instanceof Error && err.name === "AbortError") {
3051
- throw (0, import_agent_tool7.createTaggedError)(
3089
+ throw (0, import_agent_tool8.createTaggedError)(
3052
3090
  "HTTP_TIMEOUT",
3053
3091
  `HEAD request to ${url} timed out after ${timeoutMs}ms`,
3054
3092
  { url, timeoutMs }
3055
3093
  );
3056
3094
  }
3057
- throw (0, import_agent_tool7.createTaggedError)(
3095
+ throw (0, import_agent_tool8.createTaggedError)(
3058
3096
  "UPSTREAM_ERROR",
3059
3097
  `HEAD request failed for ${url}: ${err instanceof Error ? err.message : String(err)}`,
3060
3098
  { url }
@@ -3084,13 +3122,13 @@ var headHandler = (async (args) => {
3084
3122
  });
3085
3123
 
3086
3124
  // http/duckduckgoSearch.ts
3087
- var import_agent_tool8 = require("@easynet/agent-tool");
3125
+ var import_agent_tool9 = require("@easynet/agent-tool");
3088
3126
  var DUCKDUCKGO_API = "https://api.duckduckgo.com/";
3089
3127
  var duckduckgoSearchHandler = (async (args) => {
3090
3128
  const ctx = getBuiltinContext();
3091
- const query = args.query?.trim();
3129
+ const query = (args.query ?? args.q)?.trim();
3092
3130
  if (!query) {
3093
- throw (0, import_agent_tool8.createTaggedError)("DUCKDUCKGO_INVALID", "query is required", {});
3131
+ throw (0, import_agent_tool9.createTaggedError)("DUCKDUCKGO_INVALID", "query is required (pass 'query' or 'q')", {});
3094
3132
  }
3095
3133
  const timeoutMs = args.timeoutMs ?? ctx.config.defaultTimeoutMs;
3096
3134
  const maxResults = args.maxResults ?? 10;
@@ -3108,13 +3146,13 @@ var duckduckgoSearchHandler = (async (args) => {
3108
3146
  } catch (err) {
3109
3147
  clearTimeout(timer);
3110
3148
  if (err instanceof Error && err.name === "AbortError") {
3111
- throw (0, import_agent_tool8.createTaggedError)(
3149
+ throw (0, import_agent_tool9.createTaggedError)(
3112
3150
  "HTTP_TIMEOUT",
3113
3151
  `DuckDuckGo search timed out after ${timeoutMs}ms`,
3114
3152
  { query, timeoutMs }
3115
3153
  );
3116
3154
  }
3117
- throw (0, import_agent_tool8.createTaggedError)(
3155
+ throw (0, import_agent_tool9.createTaggedError)(
3118
3156
  "UPSTREAM_ERROR",
3119
3157
  `DuckDuckGo search failed: ${err instanceof Error ? err.message : String(err)}`,
3120
3158
  { query }
@@ -3125,7 +3163,7 @@ var duckduckgoSearchHandler = (async (args) => {
3125
3163
  const text = await response.text();
3126
3164
  const bytes = Buffer.byteLength(text, "utf-8");
3127
3165
  if (bytes > maxBytes) {
3128
- throw (0, import_agent_tool8.createTaggedError)(
3166
+ throw (0, import_agent_tool9.createTaggedError)(
3129
3167
  "HTTP_TOO_LARGE",
3130
3168
  `DuckDuckGo response ${bytes} bytes exceeds limit of ${maxBytes} bytes`,
3131
3169
  { query, bytes, limit: maxBytes }
@@ -3135,7 +3173,7 @@ var duckduckgoSearchHandler = (async (args) => {
3135
3173
  try {
3136
3174
  raw = JSON.parse(text);
3137
3175
  } catch {
3138
- throw (0, import_agent_tool8.createTaggedError)(
3176
+ throw (0, import_agent_tool9.createTaggedError)(
3139
3177
  "UPSTREAM_ERROR",
3140
3178
  `DuckDuckGo returned invalid JSON`,
3141
3179
  { query, textPreview: text.slice(0, 200) }
@@ -3186,7 +3224,7 @@ var duckduckgoSearchHandler = (async (args) => {
3186
3224
 
3187
3225
  // http/fetchPageMainContent.ts
3188
3226
  var import_node_html_parser = require("node-html-parser");
3189
- var import_agent_tool9 = require("@easynet/agent-tool");
3227
+ var import_agent_tool10 = require("@easynet/agent-tool");
3190
3228
  var MAIN_SELECTORS = [
3191
3229
  "main",
3192
3230
  "article",
@@ -3227,7 +3265,10 @@ function extractMainContent(html) {
3227
3265
  }
3228
3266
  var fetchPageMainContentHandler = (async (args) => {
3229
3267
  const ctx = getBuiltinContext();
3230
- const url = args.url;
3268
+ const url = (args.url ?? args.uri)?.trim();
3269
+ if (!url) {
3270
+ throw (0, import_agent_tool10.createTaggedError)("HTTP_INVALID", "url is required (pass 'url' or 'uri')", {});
3271
+ }
3231
3272
  const timeoutMs = args.timeoutMs ?? ctx.config.defaultTimeoutMs;
3232
3273
  const maxBytes = args.maxBytes ?? ctx.config.maxHttpBytes;
3233
3274
  await validateUrl(url, ctx.config.allowedHosts, ctx.config.blockedCidrs);
@@ -3243,13 +3284,13 @@ var fetchPageMainContentHandler = (async (args) => {
3243
3284
  } catch (err) {
3244
3285
  clearTimeout(timer);
3245
3286
  if (err instanceof Error && err.name === "AbortError") {
3246
- throw (0, import_agent_tool9.createTaggedError)(
3287
+ throw (0, import_agent_tool10.createTaggedError)(
3247
3288
  "HTTP_TIMEOUT",
3248
3289
  `Request to ${url} timed out after ${timeoutMs}ms`,
3249
3290
  { url, timeoutMs }
3250
3291
  );
3251
3292
  }
3252
- throw (0, import_agent_tool9.createTaggedError)(
3293
+ throw (0, import_agent_tool10.createTaggedError)(
3253
3294
  "UPSTREAM_ERROR",
3254
3295
  `Fetch failed for ${url}: ${err instanceof Error ? err.message : String(err)}`,
3255
3296
  { url }
@@ -3258,7 +3299,7 @@ var fetchPageMainContentHandler = (async (args) => {
3258
3299
  clearTimeout(timer);
3259
3300
  const contentLength = response.headers.get("content-length");
3260
3301
  if (contentLength && parseInt(contentLength, 10) > maxBytes) {
3261
- throw (0, import_agent_tool9.createTaggedError)(
3302
+ throw (0, import_agent_tool10.createTaggedError)(
3262
3303
  "HTTP_TOO_LARGE",
3263
3304
  `Response Content-Length ${contentLength} exceeds limit of ${maxBytes} bytes`,
3264
3305
  { url, contentLength: parseInt(contentLength, 10), limit: maxBytes }
@@ -3267,7 +3308,7 @@ var fetchPageMainContentHandler = (async (args) => {
3267
3308
  const rawText = await response.text();
3268
3309
  const rawBytes = Buffer.byteLength(rawText, "utf-8");
3269
3310
  if (rawBytes > maxBytes) {
3270
- throw (0, import_agent_tool9.createTaggedError)(
3311
+ throw (0, import_agent_tool10.createTaggedError)(
3271
3312
  "HTTP_TOO_LARGE",
3272
3313
  `Response body ${rawBytes} bytes exceeds limit of ${maxBytes} bytes`,
3273
3314
  { url, bytes: rawBytes, limit: maxBytes }
@@ -3309,10 +3350,133 @@ var fetchPageMainContentHandler = (async (args) => {
3309
3350
  };
3310
3351
  });
3311
3352
 
3353
+ // http/yahooFinance.ts
3354
+ var import_agent_tool11 = require("@easynet/agent-tool");
3355
+ var YAHOO_CHART_BASE = "https://query1.finance.yahoo.com/v8/finance/chart/";
3356
+ var yahooFinanceQuoteHandler = (async (args) => {
3357
+ const ctx = getBuiltinContext();
3358
+ const rawSymbols = args.symbols ?? args.symbol ?? args.tickers;
3359
+ const symbols = Array.isArray(rawSymbols) ? rawSymbols.map((s) => String(s).trim().toUpperCase()).filter(Boolean) : rawSymbols != null ? [String(rawSymbols).trim().toUpperCase()].filter(Boolean) : [];
3360
+ if (symbols.length === 0) {
3361
+ throw (0, import_agent_tool11.createTaggedError)(
3362
+ "YAHOO_INVALID",
3363
+ "At least one symbol is required",
3364
+ {}
3365
+ );
3366
+ }
3367
+ const range = args.range ?? "1d";
3368
+ const timeoutMs = args.timeoutMs ?? ctx.config.defaultTimeoutMs;
3369
+ const maxBytes = ctx.config.maxHttpBytes;
3370
+ const quotes = [];
3371
+ for (const symbol of symbols) {
3372
+ const url2 = `${YAHOO_CHART_BASE}${encodeURIComponent(symbol)}?interval=1d&range=${range}`;
3373
+ await validateUrl(url2, ctx.config.allowedHosts, ctx.config.blockedCidrs);
3374
+ const controller = new AbortController();
3375
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
3376
+ let response;
3377
+ try {
3378
+ response = await fetch(url2, {
3379
+ method: "GET",
3380
+ headers: {
3381
+ "User-Agent": ctx.config.httpUserAgent,
3382
+ Accept: "application/json"
3383
+ },
3384
+ signal: controller.signal
3385
+ });
3386
+ } catch (err) {
3387
+ clearTimeout(timer);
3388
+ if (err instanceof Error && err.name === "AbortError") {
3389
+ throw (0, import_agent_tool11.createTaggedError)(
3390
+ "HTTP_TIMEOUT",
3391
+ `Yahoo Finance request for ${symbol} timed out after ${timeoutMs}ms`,
3392
+ { symbol, timeoutMs }
3393
+ );
3394
+ }
3395
+ throw (0, import_agent_tool11.createTaggedError)(
3396
+ "UPSTREAM_ERROR",
3397
+ `Yahoo Finance request failed: ${err instanceof Error ? err.message : String(err)}`,
3398
+ { symbol }
3399
+ );
3400
+ }
3401
+ clearTimeout(timer);
3402
+ const text = await response.text();
3403
+ const bytes = Buffer.byteLength(text, "utf-8");
3404
+ if (bytes > maxBytes) {
3405
+ throw (0, import_agent_tool11.createTaggedError)(
3406
+ "HTTP_TOO_LARGE",
3407
+ `Yahoo Finance response ${bytes} bytes exceeds limit of ${maxBytes} bytes`,
3408
+ { symbol, bytes, limit: maxBytes }
3409
+ );
3410
+ }
3411
+ let data;
3412
+ try {
3413
+ data = JSON.parse(text);
3414
+ } catch {
3415
+ throw (0, import_agent_tool11.createTaggedError)(
3416
+ "UPSTREAM_ERROR",
3417
+ "Yahoo Finance returned invalid JSON",
3418
+ { symbol, textPreview: text.slice(0, 200) }
3419
+ );
3420
+ }
3421
+ const error = data.chart?.error;
3422
+ if (error?.description) {
3423
+ throw (0, import_agent_tool11.createTaggedError)(
3424
+ "YAHOO_ERROR",
3425
+ `Yahoo Finance error for ${symbol}: ${error.description}`,
3426
+ { symbol, code: error.code }
3427
+ );
3428
+ }
3429
+ const result = data.chart?.result?.[0];
3430
+ if (!result) {
3431
+ quotes.push({ symbol });
3432
+ continue;
3433
+ }
3434
+ const meta = result.meta ?? {};
3435
+ const quoteArr = result.indicators?.quote?.[0];
3436
+ const lastIdx = (result.timestamp?.length ?? 1) - 1;
3437
+ const price = meta.regularMarketPrice ?? meta.previousClose ?? quoteArr?.close?.[lastIdx] ?? void 0;
3438
+ const previousClose = meta.previousClose ?? meta.chartPreviousClose ?? quoteArr?.close?.[Math.max(0, lastIdx - 1)] ?? void 0;
3439
+ const change = price != null && previousClose != null ? price - previousClose : void 0;
3440
+ const changePercent = change != null && previousClose != null && previousClose !== 0 ? change / previousClose * 100 : void 0;
3441
+ quotes.push({
3442
+ symbol: meta.symbol ?? symbol,
3443
+ currency: meta.currency,
3444
+ price: price ?? void 0,
3445
+ previousClose: previousClose ?? void 0,
3446
+ change,
3447
+ changePercent,
3448
+ open: quoteArr?.open?.[lastIdx] ?? void 0,
3449
+ high: quoteArr?.high?.[lastIdx] ?? void 0,
3450
+ low: quoteArr?.low?.[lastIdx] ?? void 0,
3451
+ volume: quoteArr?.volume?.[lastIdx] ?? void 0,
3452
+ timestamp: result.timestamp?.[lastIdx]
3453
+ });
3454
+ }
3455
+ const url = `${YAHOO_CHART_BASE}${encodeURIComponent(symbols[0])}?interval=1d&range=${range}`;
3456
+ return {
3457
+ result: {
3458
+ symbols: quotes.map((q) => q.symbol),
3459
+ quotes,
3460
+ range
3461
+ },
3462
+ evidence: [
3463
+ {
3464
+ type: "url",
3465
+ ref: url,
3466
+ summary: `Yahoo Finance quote: ${symbols.join(", ")} (${quotes.length} result(s))`,
3467
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
3468
+ }
3469
+ ]
3470
+ };
3471
+ });
3472
+
3312
3473
  // util/jsonSelect.ts
3313
3474
  var jsonSelectHandler = (async (args) => {
3314
3475
  const json = args.json;
3315
- const path = args.path;
3476
+ const path = (args.path ?? args.expression)?.trim();
3477
+ if (path === void 0 || path === "") {
3478
+ throw new Error("path is required (pass 'path' or 'expression')");
3479
+ }
3316
3480
  let jmespath;
3317
3481
  try {
3318
3482
  jmespath = await Promise.resolve().then(() => __toESM(require_jmespath(), 1));
@@ -3469,37 +3633,37 @@ var templateRenderHandler = (async (args) => {
3469
3633
  // exec/runCommand.ts
3470
3634
  var import_node_child_process = require("child_process");
3471
3635
  var import_node_path6 = require("path");
3472
- var import_agent_tool10 = require("@easynet/agent-tool");
3636
+ var import_agent_tool12 = require("@easynet/agent-tool");
3473
3637
  var runCommandHandler = (async (args) => {
3474
3638
  const ctx = getBuiltinContext();
3475
3639
  const { allowedCommands, maxCommandOutputBytes, commandTimeoutMs } = ctx.config;
3476
3640
  if (!allowedCommands.length) {
3477
- throw (0, import_agent_tool10.createTaggedError)(
3641
+ throw (0, import_agent_tool12.createTaggedError)(
3478
3642
  "EXEC_DISABLED",
3479
3643
  "Exec is disabled: allowedCommands is empty",
3480
3644
  {}
3481
3645
  );
3482
3646
  }
3483
- const rawCommand = args.command?.trim();
3647
+ const rawCommand = (args.command ?? args.cmd)?.trim();
3484
3648
  if (!rawCommand) {
3485
- throw (0, import_agent_tool10.createTaggedError)("EXEC_INVALID", "command is required", {});
3649
+ throw (0, import_agent_tool12.createTaggedError)("EXEC_INVALID", "command is required (pass 'command' or 'cmd')", {});
3486
3650
  }
3487
3651
  const baseName = rawCommand.replace(/^.*\//, "").trim();
3488
3652
  if (baseName !== rawCommand || /[;&|$`\s]/.test(rawCommand)) {
3489
- throw (0, import_agent_tool10.createTaggedError)(
3653
+ throw (0, import_agent_tool12.createTaggedError)(
3490
3654
  "EXEC_INVALID",
3491
3655
  "command must be a single executable name (no path, no shell chars)",
3492
3656
  { command: rawCommand }
3493
3657
  );
3494
3658
  }
3495
3659
  if (!allowedCommands.includes(baseName)) {
3496
- throw (0, import_agent_tool10.createTaggedError)(
3660
+ throw (0, import_agent_tool12.createTaggedError)(
3497
3661
  "EXEC_NOT_ALLOWED",
3498
3662
  `Command "${baseName}" is not in allowedCommands`,
3499
3663
  { command: baseName, allowed: allowedCommands }
3500
3664
  );
3501
3665
  }
3502
- const cmdArgs = Array.isArray(args.args) ? args.args : [];
3666
+ const cmdArgs = Array.isArray(args.args) ? args.args : Array.isArray(args.arguments) ? args.arguments : [];
3503
3667
  const timeoutMs = args.timeoutMs ?? commandTimeoutMs;
3504
3668
  let cwd = (0, import_node_path6.resolve)(ctx.config.sandboxRoot);
3505
3669
  if (args.cwd != null && args.cwd !== "") {
@@ -3520,7 +3684,7 @@ var runCommandHandler = (async (args) => {
3520
3684
  if (totalBytes + len > maxCommandOutputBytes) {
3521
3685
  proc.kill("SIGKILL");
3522
3686
  rejectPromise(
3523
- (0, import_agent_tool10.createTaggedError)(
3687
+ (0, import_agent_tool12.createTaggedError)(
3524
3688
  "EXEC_OUTPUT_TOO_LARGE",
3525
3689
  `Command output exceeded ${maxCommandOutputBytes} bytes`,
3526
3690
  { maxBytes: maxCommandOutputBytes }
@@ -3558,7 +3722,7 @@ var runCommandHandler = (async (args) => {
3558
3722
  proc.on("error", (err) => {
3559
3723
  clearTimeout(timeout);
3560
3724
  rejectPromise(
3561
- (0, import_agent_tool10.createTaggedError)("EXEC_SPAWN_ERROR", err.message, { command: baseName })
3725
+ (0, import_agent_tool12.createTaggedError)("EXEC_SPAWN_ERROR", err.message, { command: baseName })
3562
3726
  );
3563
3727
  });
3564
3728
  proc.on("close", (code, signal) => {
@@ -3590,7 +3754,7 @@ var CORE_TOOL_MANIFEST = [
3590
3754
  {
3591
3755
  name: "core/fs.readText",
3592
3756
  kind: "core",
3593
- description: "Read a UTF-8 text file from the sandbox",
3757
+ description: "Read a UTF-8 text file from the sandbox. Input: path (or filePath), optional maxBytes.",
3594
3758
  tags: ["filesystem", "read", "core"],
3595
3759
  capabilities: ["read:fs"],
3596
3760
  sideEffect: "none"
@@ -3598,7 +3762,7 @@ var CORE_TOOL_MANIFEST = [
3598
3762
  {
3599
3763
  name: "core/fs.writeText",
3600
3764
  kind: "core",
3601
- description: "Write UTF-8 text to a file in the sandbox",
3765
+ description: "Write UTF-8 text to a file in the sandbox. Input: path (or filePath), text (or content), optional overwrite, mkdirp.",
3602
3766
  tags: ["filesystem", "write", "core"],
3603
3767
  capabilities: ["write:fs"],
3604
3768
  sideEffect: "local_write"
@@ -3606,7 +3770,7 @@ var CORE_TOOL_MANIFEST = [
3606
3770
  {
3607
3771
  name: "core/fs.listDir",
3608
3772
  kind: "core",
3609
- description: "List directory contents in the sandbox",
3773
+ description: "List directory contents in the sandbox. Input: path (or filePath, dir, directory), optional maxEntries, includeHidden, recursive, maxDepth.",
3610
3774
  tags: ["filesystem", "read", "core"],
3611
3775
  capabilities: ["read:fs"],
3612
3776
  sideEffect: "none"
@@ -3614,7 +3778,7 @@ var CORE_TOOL_MANIFEST = [
3614
3778
  {
3615
3779
  name: "core/fs.searchText",
3616
3780
  kind: "core",
3617
- description: "Search for text patterns in files within the sandbox",
3781
+ description: "Search for text patterns in files within the sandbox. Input: root (or path, dir, directory), query (or q), optional glob, maxMatches, maxFiles.",
3618
3782
  tags: ["filesystem", "search", "core"],
3619
3783
  capabilities: ["read:fs"],
3620
3784
  sideEffect: "none"
@@ -3622,7 +3786,7 @@ var CORE_TOOL_MANIFEST = [
3622
3786
  {
3623
3787
  name: "core/fs.sha256",
3624
3788
  kind: "core",
3625
- description: "Compute SHA-256 hash of a file in the sandbox",
3789
+ description: "Compute SHA-256 hash of a file in the sandbox. Input: path (or filePath).",
3626
3790
  tags: ["filesystem", "hash", "core"],
3627
3791
  capabilities: ["read:fs"],
3628
3792
  sideEffect: "none"
@@ -3630,7 +3794,7 @@ var CORE_TOOL_MANIFEST = [
3630
3794
  {
3631
3795
  name: "core/fs.deletePath",
3632
3796
  kind: "core",
3633
- description: "Delete a file or directory in the sandbox (dangerous, requires explicit confirmation)",
3797
+ description: "Delete a file or directory in the sandbox (dangerous, requires explicit confirmation). Input: path (or filePath), confirm=true, optional recursive.",
3634
3798
  tags: ["filesystem", "delete", "dangerous", "core"],
3635
3799
  capabilities: ["danger:destructive", "write:fs"],
3636
3800
  sideEffect: "destructive"
@@ -3639,7 +3803,7 @@ var CORE_TOOL_MANIFEST = [
3639
3803
  {
3640
3804
  name: "core/http.fetchText",
3641
3805
  kind: "core",
3642
- description: "Fetch a URL and return the response as text",
3806
+ description: "Fetch a URL and return the response as text. Input: url (or uri), optional method, headers, body, timeoutMs, maxBytes.",
3643
3807
  tags: ["http", "network", "core"],
3644
3808
  capabilities: ["network"],
3645
3809
  sideEffect: "none"
@@ -3647,7 +3811,7 @@ var CORE_TOOL_MANIFEST = [
3647
3811
  {
3648
3812
  name: "core/http.fetchJson",
3649
3813
  kind: "core",
3650
- description: "Fetch a URL and return the response as parsed JSON",
3814
+ description: "Fetch a URL and return the response as parsed JSON. Input: url (or uri), optional method, headers, body, timeoutMs, maxBytes.",
3651
3815
  tags: ["http", "network", "json", "core"],
3652
3816
  capabilities: ["network"],
3653
3817
  sideEffect: "none"
@@ -3655,7 +3819,7 @@ var CORE_TOOL_MANIFEST = [
3655
3819
  {
3656
3820
  name: "core/http.downloadFile",
3657
3821
  kind: "core",
3658
- description: "Download a file from a URL to the sandbox",
3822
+ description: "Download a file from a URL to the sandbox. Input: url (or uri), destPath (or destination, filePath), optional headers, timeoutMs, maxBytes, overwrite.",
3659
3823
  tags: ["http", "network", "download", "core"],
3660
3824
  capabilities: ["network", "write:fs"],
3661
3825
  sideEffect: "local_write"
@@ -3663,7 +3827,7 @@ var CORE_TOOL_MANIFEST = [
3663
3827
  {
3664
3828
  name: "core/http.head",
3665
3829
  kind: "core",
3666
- description: "Send a HEAD request to get response headers without body",
3830
+ description: "Send a HEAD request to get response headers without body. Input: url (or uri), optional headers, timeoutMs.",
3667
3831
  tags: ["http", "network", "core"],
3668
3832
  capabilities: ["network"],
3669
3833
  sideEffect: "none"
@@ -3671,7 +3835,7 @@ var CORE_TOOL_MANIFEST = [
3671
3835
  {
3672
3836
  name: "core/http.duckduckgoSearch",
3673
3837
  kind: "core",
3674
- description: "Search DuckDuckGo via Instant Answer API (no API key). Add api.duckduckgo.com to allowedHosts.",
3838
+ description: "Search DuckDuckGo via Instant Answer API (no API key). Add api.duckduckgo.com to allowedHosts. Input: use 'query' (or 'q') for the search string, optional 'maxResults'.",
3675
3839
  tags: ["http", "search", "duckduckgo", "core"],
3676
3840
  capabilities: ["network"],
3677
3841
  sideEffect: "none"
@@ -3679,16 +3843,24 @@ var CORE_TOOL_MANIFEST = [
3679
3843
  {
3680
3844
  name: "core/http.fetchPageMainContent",
3681
3845
  kind: "core",
3682
- description: "Fetch a URL and return only the main content (main/article/body text). Strips nav, header, footer, scripts.",
3846
+ description: "Fetch a URL and return only the main content (main/article/body text). Strips nav, header, footer, scripts. Input: url (or uri), optional timeoutMs, maxBytes.",
3683
3847
  tags: ["http", "network", "html", "main-content", "core"],
3684
3848
  capabilities: ["network"],
3685
3849
  sideEffect: "none"
3686
3850
  },
3851
+ {
3852
+ name: "core/http.yahooFinanceQuote",
3853
+ kind: "core",
3854
+ description: "Fetch stock quote(s) from Yahoo Finance chart API (no API key). Add query1.finance.yahoo.com to allowedHosts. Input: symbols (or symbol, tickers), optional range, timeoutMs.",
3855
+ tags: ["http", "finance", "yahoo", "stock", "quote", "core"],
3856
+ capabilities: ["network"],
3857
+ sideEffect: "none"
3858
+ },
3687
3859
  // Utils
3688
3860
  {
3689
3861
  name: "core/util.json.select",
3690
3862
  kind: "core",
3691
- description: "Select fields from JSON data using JMESPath expressions",
3863
+ description: "Select fields from JSON data using JMESPath expressions. Input: json, path (or expression).",
3692
3864
  tags: ["util", "json", "core"],
3693
3865
  capabilities: [],
3694
3866
  sideEffect: "none"
@@ -3729,7 +3901,7 @@ var CORE_TOOL_MANIFEST = [
3729
3901
  {
3730
3902
  name: "core/exec.runCommand",
3731
3903
  kind: "core",
3732
- description: "Run a Linux command in the sandbox (allowlist, timeout, no shell). Command name only; args as array.",
3904
+ description: "Run a Linux command in the sandbox (allowlist, timeout, no shell). Input: command (or cmd), optional args (or arguments), cwd, timeoutMs.",
3733
3905
  tags: ["exec", "shell", "linux", "core"],
3734
3906
  capabilities: ["exec"],
3735
3907
  sideEffect: "local_write"
@@ -3748,6 +3920,7 @@ var CORE_TOOL_HANDLERS = [
3748
3920
  headHandler,
3749
3921
  duckduckgoSearchHandler,
3750
3922
  fetchPageMainContentHandler,
3923
+ yahooFinanceQuoteHandler,
3751
3924
  jsonSelectHandler,
3752
3925
  truncateHandler,
3753
3926
  hashTextHandler,
@@ -3765,14 +3938,15 @@ var fetchTextSpec = (0, import_core.createToolSpec)(CORE_TOOL_MANIFEST[6]);
3765
3938
  var fetchJsonSpec = (0, import_core.createToolSpec)(CORE_TOOL_MANIFEST[7]);
3766
3939
  var downloadFileSpec = (0, import_core.createToolSpec)(CORE_TOOL_MANIFEST[8]);
3767
3940
  var headSpec = (0, import_core.createToolSpec)(CORE_TOOL_MANIFEST[9]);
3768
- var jsonSelectSpec = (0, import_core.createToolSpec)(CORE_TOOL_MANIFEST[10]);
3769
- var truncateSpec = (0, import_core.createToolSpec)(CORE_TOOL_MANIFEST[11]);
3770
- var hashTextSpec = (0, import_core.createToolSpec)(CORE_TOOL_MANIFEST[12]);
3771
- var nowSpec = (0, import_core.createToolSpec)(CORE_TOOL_MANIFEST[13]);
3772
- var templateRenderSpec = (0, import_core.createToolSpec)(CORE_TOOL_MANIFEST[14]);
3773
- var runCommandSpec = (0, import_core.createToolSpec)(CORE_TOOL_MANIFEST[15]);
3774
- var duckduckgoSearchSpec = (0, import_core.createToolSpec)(CORE_TOOL_MANIFEST[16]);
3775
- var fetchPageMainContentSpec = (0, import_core.createToolSpec)(CORE_TOOL_MANIFEST[17]);
3941
+ var duckduckgoSearchSpec = (0, import_core.createToolSpec)(CORE_TOOL_MANIFEST[10]);
3942
+ var fetchPageMainContentSpec = (0, import_core.createToolSpec)(CORE_TOOL_MANIFEST[11]);
3943
+ var yahooFinanceQuoteSpec = (0, import_core.createToolSpec)(CORE_TOOL_MANIFEST[12]);
3944
+ var jsonSelectSpec = (0, import_core.createToolSpec)(CORE_TOOL_MANIFEST[13]);
3945
+ var truncateSpec = (0, import_core.createToolSpec)(CORE_TOOL_MANIFEST[14]);
3946
+ var hashTextSpec = (0, import_core.createToolSpec)(CORE_TOOL_MANIFEST[15]);
3947
+ var nowSpec = (0, import_core.createToolSpec)(CORE_TOOL_MANIFEST[16]);
3948
+ var templateRenderSpec = (0, import_core.createToolSpec)(CORE_TOOL_MANIFEST[17]);
3949
+ var runCommandSpec = (0, import_core.createToolSpec)(CORE_TOOL_MANIFEST[18]);
3776
3950
  var CORE_GROUP_PREFIX = {
3777
3951
  fs: "core/fs.",
3778
3952
  http: "core/http.",
@@ -3827,7 +4001,8 @@ function registerCoreTools(registry, userConfig, options) {
3827
4001
  templateRenderSpec,
3828
4002
  truncateSpec,
3829
4003
  validateUrl,
3830
- writeTextSpec
4004
+ writeTextSpec,
4005
+ yahooFinanceQuoteSpec
3831
4006
  });
3832
4007
  /*! Bundled license information:
3833
4008