aieo 0.1.36 → 0.1.38

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
@@ -36,16 +36,20 @@ __export(index_exports, {
36
36
  OUTRO: () => OUTRO,
37
37
  PROVIDERS: () => PROVIDERS,
38
38
  SYSTEM: () => SYSTEM,
39
+ WEB_FETCH_TOOL_NAME: () => WEB_FETCH_TOOL_NAME,
39
40
  WEB_SEARCH_TOOL_NAME: () => WEB_SEARCH_TOOL_NAME,
40
41
  addUsage: () => addUsage,
41
42
  callGenerateObject: () => callGenerateObject,
42
43
  callGenerateText: () => callGenerateText,
43
44
  callModel: () => callModel,
45
+ captureNativeFetchResults: () => captureNativeFetchResults,
44
46
  captureNativeResults: () => captureNativeResults,
45
47
  computeSessionCost: () => computeSessionCost,
46
48
  consoleLogger: () => consoleLogger,
49
+ createWebFetch: () => createWebFetch,
47
50
  createWebSearch: () => createWebSearch,
48
51
  emptyUsage: () => emptyUsage,
52
+ fetchUrl: () => fetchUrl,
49
53
  gatewayEnvForProviders: () => gatewayEnvForProviders,
50
54
  gatewayUrlFor: () => gatewayUrlFor,
51
55
  gatewayUrlForModel: () => gatewayUrlForModel,
@@ -62,15 +66,19 @@ __export(index_exports, {
62
66
  getTokenPricing: () => getTokenPricing,
63
67
  hasApiKeyForProvider: () => hasApiKeyForProvider,
64
68
  hasSearchApiKey: () => hasSearchApiKey,
69
+ htmlToText: () => htmlToText,
70
+ isPrivateAddress: () => isPrivateAddress,
65
71
  linkifyCitations: () => linkifyCitations,
66
72
  loadModelPricing: () => loadModelPricing,
67
73
  normalizeApiKey: () => normalizeApiKey,
68
74
  normalizeCallerBaseURL: () => normalizeCallerBaseURL,
69
75
  normalizeUsage: () => normalizeUsage,
76
+ resolveFetchBackend: () => resolveFetchBackend,
70
77
  resolveLLMConfig: () => resolveLLMConfig,
71
78
  resolveSearchBackend: () => resolveSearchBackend,
72
79
  searchWeb: () => searchWeb,
73
80
  stripCitations: () => stripCitations,
81
+ validateFetchUrl: () => validateFetchUrl,
74
82
  withLegacyUsage: () => withLegacyUsage,
75
83
  withProviderCacheUsage: () => withProviderCacheUsage
76
84
  });
@@ -4190,35 +4198,35 @@ async function prepareTools({
4190
4198
  return { tools: void 0, toolChoice: void 0, toolWarnings, betas };
4191
4199
  }
4192
4200
  const anthropicTools2 = [];
4193
- for (const tool5 of tools) {
4194
- switch (tool5.type) {
4201
+ for (const tool6 of tools) {
4202
+ switch (tool6.type) {
4195
4203
  case "function": {
4196
- const cacheControl = validator.getCacheControl(tool5.providerOptions, {
4204
+ const cacheControl = validator.getCacheControl(tool6.providerOptions, {
4197
4205
  type: "tool definition",
4198
4206
  canCache: true
4199
4207
  });
4200
- const anthropicOptions = (_a20 = tool5.providerOptions) == null ? void 0 : _a20.anthropic;
4208
+ const anthropicOptions = (_a20 = tool6.providerOptions) == null ? void 0 : _a20.anthropic;
4201
4209
  const eagerInputStreaming = (_b20 = anthropicOptions == null ? void 0 : anthropicOptions.eagerInputStreaming) != null ? _b20 : defaultEagerInputStreaming;
4202
4210
  const deferLoading = anthropicOptions == null ? void 0 : anthropicOptions.deferLoading;
4203
4211
  const allowedCallers = anthropicOptions == null ? void 0 : anthropicOptions.allowedCallers;
4204
- if (!supportsStrictTools && tool5.strict != null) {
4212
+ if (!supportsStrictTools && tool6.strict != null) {
4205
4213
  toolWarnings.push({
4206
4214
  type: "unsupported",
4207
4215
  feature: "strict",
4208
- details: `Tool '${tool5.name}' has strict: ${tool5.strict}, but strict mode is not supported by this provider. The strict property will be ignored.`
4216
+ details: `Tool '${tool6.name}' has strict: ${tool6.strict}, but strict mode is not supported by this provider. The strict property will be ignored.`
4209
4217
  });
4210
4218
  }
4211
4219
  anthropicTools2.push({
4212
- name: tool5.name,
4213
- description: tool5.description,
4214
- input_schema: tool5.inputSchema,
4220
+ name: tool6.name,
4221
+ description: tool6.description,
4222
+ input_schema: tool6.inputSchema,
4215
4223
  cache_control: cacheControl,
4216
4224
  ...eagerInputStreaming ? { eager_input_streaming: true } : {},
4217
- ...supportsStrictTools === true && tool5.strict != null ? { strict: tool5.strict } : {},
4225
+ ...supportsStrictTools === true && tool6.strict != null ? { strict: tool6.strict } : {},
4218
4226
  ...deferLoading != null ? { defer_loading: deferLoading } : {},
4219
4227
  ...allowedCallers != null ? { allowed_callers: allowedCallers } : {},
4220
- ...tool5.inputExamples != null ? {
4221
- input_examples: tool5.inputExamples.map(
4228
+ ...tool6.inputExamples != null ? {
4229
+ input_examples: tool6.inputExamples.map(
4222
4230
  (example) => example.input
4223
4231
  )
4224
4232
  } : {}
@@ -4226,13 +4234,13 @@ async function prepareTools({
4226
4234
  if (supportsStructuredOutput === true) {
4227
4235
  betas.add("structured-outputs-2025-11-13");
4228
4236
  }
4229
- if (tool5.inputExamples != null || allowedCallers != null) {
4237
+ if (tool6.inputExamples != null || allowedCallers != null) {
4230
4238
  betas.add("advanced-tool-use-2025-11-20");
4231
4239
  }
4232
4240
  break;
4233
4241
  }
4234
4242
  case "provider": {
4235
- switch (tool5.id) {
4243
+ switch (tool6.id) {
4236
4244
  case "anthropic.code_execution_20250522": {
4237
4245
  betas.add("code-execution-2025-05-22");
4238
4246
  anthropicTools2.push({
@@ -4262,9 +4270,9 @@ async function prepareTools({
4262
4270
  anthropicTools2.push({
4263
4271
  name: "computer",
4264
4272
  type: "computer_20250124",
4265
- display_width_px: tool5.args.displayWidthPx,
4266
- display_height_px: tool5.args.displayHeightPx,
4267
- display_number: tool5.args.displayNumber,
4273
+ display_width_px: tool6.args.displayWidthPx,
4274
+ display_height_px: tool6.args.displayHeightPx,
4275
+ display_number: tool6.args.displayNumber,
4268
4276
  cache_control: void 0
4269
4277
  });
4270
4278
  break;
@@ -4274,10 +4282,10 @@ async function prepareTools({
4274
4282
  anthropicTools2.push({
4275
4283
  name: "computer",
4276
4284
  type: "computer_20251124",
4277
- display_width_px: tool5.args.displayWidthPx,
4278
- display_height_px: tool5.args.displayHeightPx,
4279
- display_number: tool5.args.displayNumber,
4280
- enable_zoom: tool5.args.enableZoom,
4285
+ display_width_px: tool6.args.displayWidthPx,
4286
+ display_height_px: tool6.args.displayHeightPx,
4287
+ display_number: tool6.args.displayNumber,
4288
+ enable_zoom: tool6.args.enableZoom,
4281
4289
  cache_control: void 0
4282
4290
  });
4283
4291
  break;
@@ -4287,9 +4295,9 @@ async function prepareTools({
4287
4295
  anthropicTools2.push({
4288
4296
  name: "computer",
4289
4297
  type: "computer_20241022",
4290
- display_width_px: tool5.args.displayWidthPx,
4291
- display_height_px: tool5.args.displayHeightPx,
4292
- display_number: tool5.args.displayNumber,
4298
+ display_width_px: tool6.args.displayWidthPx,
4299
+ display_height_px: tool6.args.displayHeightPx,
4300
+ display_number: tool6.args.displayNumber,
4293
4301
  cache_control: void 0
4294
4302
  });
4295
4303
  break;
@@ -4323,7 +4331,7 @@ async function prepareTools({
4323
4331
  }
4324
4332
  case "anthropic.text_editor_20250728": {
4325
4333
  const args = await validateTypes({
4326
- value: tool5.args,
4334
+ value: tool6.args,
4327
4335
  schema: textEditor_20250728ArgsSchema
4328
4336
  });
4329
4337
  anthropicTools2.push({
@@ -4363,7 +4371,7 @@ async function prepareTools({
4363
4371
  case "anthropic.web_fetch_20250910": {
4364
4372
  betas.add("web-fetch-2025-09-10");
4365
4373
  const args = await validateTypes({
4366
- value: tool5.args,
4374
+ value: tool6.args,
4367
4375
  schema: webFetch_20250910ArgsSchema
4368
4376
  });
4369
4377
  anthropicTools2.push({
@@ -4381,7 +4389,7 @@ async function prepareTools({
4381
4389
  case "anthropic.web_fetch_20260209": {
4382
4390
  betas.add("code-execution-web-tools-2026-02-09");
4383
4391
  const args = await validateTypes({
4384
- value: tool5.args,
4392
+ value: tool6.args,
4385
4393
  schema: webFetch_20260209ArgsSchema
4386
4394
  });
4387
4395
  anthropicTools2.push({
@@ -4398,7 +4406,7 @@ async function prepareTools({
4398
4406
  }
4399
4407
  case "anthropic.web_search_20250305": {
4400
4408
  const args = await validateTypes({
4401
- value: tool5.args,
4409
+ value: tool6.args,
4402
4410
  schema: webSearch_20250305ArgsSchema
4403
4411
  });
4404
4412
  anthropicTools2.push({
@@ -4415,7 +4423,7 @@ async function prepareTools({
4415
4423
  case "anthropic.web_search_20260209": {
4416
4424
  betas.add("code-execution-web-tools-2026-02-09");
4417
4425
  const args = await validateTypes({
4418
- value: tool5.args,
4426
+ value: tool6.args,
4419
4427
  schema: webSearch_20260209ArgsSchema
4420
4428
  });
4421
4429
  anthropicTools2.push({
@@ -4446,7 +4454,7 @@ async function prepareTools({
4446
4454
  case "anthropic.advisor_20260301": {
4447
4455
  betas.add("advisor-tool-2026-03-01");
4448
4456
  const args = await validateTypes({
4449
- value: tool5.args,
4457
+ value: tool6.args,
4450
4458
  schema: advisor_20260301ArgsSchema
4451
4459
  });
4452
4460
  anthropicTools2.push({
@@ -4461,7 +4469,7 @@ async function prepareTools({
4461
4469
  default: {
4462
4470
  toolWarnings.push({
4463
4471
  type: "unsupported",
4464
- feature: `provider-defined tool ${tool5.id}`
4472
+ feature: `provider-defined tool ${tool6.id}`
4465
4473
  });
4466
4474
  break;
4467
4475
  }
@@ -4471,7 +4479,7 @@ async function prepareTools({
4471
4479
  default: {
4472
4480
  toolWarnings.push({
4473
4481
  type: "unsupported",
4474
- feature: `tool ${tool5}`
4482
+ feature: `tool ${tool6}`
4475
4483
  });
4476
4484
  break;
4477
4485
  }
@@ -6441,7 +6449,7 @@ var AnthropicMessagesLanguageModel = class {
6441
6449
  betas.add("skills-2025-10-02");
6442
6450
  betas.add("files-api-2025-04-14");
6443
6451
  if (!(tools == null ? void 0 : tools.some(
6444
- (tool5) => tool5.type === "provider" && (tool5.id === "anthropic.code_execution_20250825" || tool5.id === "anthropic.code_execution_20260120")
6452
+ (tool6) => tool6.type === "provider" && (tool6.id === "anthropic.code_execution_20250825" || tool6.id === "anthropic.code_execution_20260120")
6445
6453
  ))) {
6446
6454
  warnings.push({
6447
6455
  type: "other",
@@ -8044,12 +8052,12 @@ function hasWebTool20260209WithoutCodeExecution(tools) {
8044
8052
  }
8045
8053
  let hasWebTool20260209 = false;
8046
8054
  let hasCodeExecutionTool = false;
8047
- for (const tool5 of tools) {
8048
- if ("type" in tool5 && (tool5.type === "web_fetch_20260209" || tool5.type === "web_search_20260209")) {
8055
+ for (const tool6 of tools) {
8056
+ if ("type" in tool6 && (tool6.type === "web_fetch_20260209" || tool6.type === "web_search_20260209")) {
8049
8057
  hasWebTool20260209 = true;
8050
8058
  continue;
8051
8059
  }
8052
- if (tool5.name === "code_execution") {
8060
+ if (tool6.name === "code_execution") {
8053
8061
  hasCodeExecutionTool = true;
8054
8062
  break;
8055
8063
  }
@@ -11758,8 +11766,8 @@ function prepareTools2({
11758
11766
  if (tools == null) {
11759
11767
  return { tools: void 0, toolConfig: void 0, toolWarnings };
11760
11768
  }
11761
- const hasFunctionTools = tools.some((tool5) => tool5.type === "function");
11762
- const hasProviderTools = tools.some((tool5) => tool5.type === "provider");
11769
+ const hasFunctionTools = tools.some((tool6) => tool6.type === "function");
11770
+ const hasProviderTools = tools.some((tool6) => tool6.type === "provider");
11763
11771
  if (hasFunctionTools && hasProviderTools && !isGemini3orNewer) {
11764
11772
  toolWarnings.push({
11765
11773
  type: "unsupported",
@@ -11768,16 +11776,16 @@ function prepareTools2({
11768
11776
  }
11769
11777
  if (hasProviderTools) {
11770
11778
  const googleTools2 = [];
11771
- const ProviderTools = tools.filter((tool5) => tool5.type === "provider");
11772
- ProviderTools.forEach((tool5) => {
11773
- switch (tool5.id) {
11779
+ const ProviderTools = tools.filter((tool6) => tool6.type === "provider");
11780
+ ProviderTools.forEach((tool6) => {
11781
+ switch (tool6.id) {
11774
11782
  case "google.google_search":
11775
11783
  if (isGemini2orNewer) {
11776
- googleTools2.push({ googleSearch: { ...tool5.args } });
11784
+ googleTools2.push({ googleSearch: { ...tool6.args } });
11777
11785
  } else {
11778
11786
  toolWarnings.push({
11779
11787
  type: "unsupported",
11780
- feature: `provider-defined tool ${tool5.id}`,
11788
+ feature: `provider-defined tool ${tool6.id}`,
11781
11789
  details: "Google Search requires Gemini 2.0 or newer."
11782
11790
  });
11783
11791
  }
@@ -11788,7 +11796,7 @@ function prepareTools2({
11788
11796
  } else {
11789
11797
  toolWarnings.push({
11790
11798
  type: "unsupported",
11791
- feature: `provider-defined tool ${tool5.id}`,
11799
+ feature: `provider-defined tool ${tool6.id}`,
11792
11800
  details: "Enterprise Web Search requires Gemini 2.0 or newer."
11793
11801
  });
11794
11802
  }
@@ -11799,7 +11807,7 @@ function prepareTools2({
11799
11807
  } else {
11800
11808
  toolWarnings.push({
11801
11809
  type: "unsupported",
11802
- feature: `provider-defined tool ${tool5.id}`,
11810
+ feature: `provider-defined tool ${tool6.id}`,
11803
11811
  details: "The URL context tool is not supported with other Gemini models than Gemini 2."
11804
11812
  });
11805
11813
  }
@@ -11810,18 +11818,18 @@ function prepareTools2({
11810
11818
  } else {
11811
11819
  toolWarnings.push({
11812
11820
  type: "unsupported",
11813
- feature: `provider-defined tool ${tool5.id}`,
11821
+ feature: `provider-defined tool ${tool6.id}`,
11814
11822
  details: "The code execution tool is not supported with other Gemini models than Gemini 2."
11815
11823
  });
11816
11824
  }
11817
11825
  break;
11818
11826
  case "google.file_search":
11819
11827
  if (supportsFileSearch) {
11820
- googleTools2.push({ fileSearch: { ...tool5.args } });
11828
+ googleTools2.push({ fileSearch: { ...tool6.args } });
11821
11829
  } else {
11822
11830
  toolWarnings.push({
11823
11831
  type: "unsupported",
11824
- feature: `provider-defined tool ${tool5.id}`,
11832
+ feature: `provider-defined tool ${tool6.id}`,
11825
11833
  details: "The file search tool is only supported with Gemini 2.5 models and Gemini 3 models."
11826
11834
  });
11827
11835
  }
@@ -11832,16 +11840,16 @@ function prepareTools2({
11832
11840
  retrieval: {
11833
11841
  vertex_rag_store: {
11834
11842
  rag_resources: {
11835
- rag_corpus: tool5.args.ragCorpus
11843
+ rag_corpus: tool6.args.ragCorpus
11836
11844
  },
11837
- similarity_top_k: tool5.args.topK
11845
+ similarity_top_k: tool6.args.topK
11838
11846
  }
11839
11847
  }
11840
11848
  });
11841
11849
  } else {
11842
11850
  toolWarnings.push({
11843
11851
  type: "unsupported",
11844
- feature: `provider-defined tool ${tool5.id}`,
11852
+ feature: `provider-defined tool ${tool6.id}`,
11845
11853
  details: "The RAG store tool is not supported with other Gemini models than Gemini 2."
11846
11854
  });
11847
11855
  }
@@ -11852,7 +11860,7 @@ function prepareTools2({
11852
11860
  } else {
11853
11861
  toolWarnings.push({
11854
11862
  type: "unsupported",
11855
- feature: `provider-defined tool ${tool5.id}`,
11863
+ feature: `provider-defined tool ${tool6.id}`,
11856
11864
  details: "The Google Maps grounding tool is not supported with Gemini models other than Gemini 2 or newer."
11857
11865
  });
11858
11866
  }
@@ -11860,19 +11868,19 @@ function prepareTools2({
11860
11868
  default:
11861
11869
  toolWarnings.push({
11862
11870
  type: "unsupported",
11863
- feature: `provider-defined tool ${tool5.id}`
11871
+ feature: `provider-defined tool ${tool6.id}`
11864
11872
  });
11865
11873
  break;
11866
11874
  }
11867
11875
  });
11868
11876
  if (hasFunctionTools && isGemini3orNewer && googleTools2.length > 0) {
11869
11877
  const functionDeclarations2 = [];
11870
- for (const tool5 of tools) {
11871
- if (tool5.type === "function") {
11878
+ for (const tool6 of tools) {
11879
+ if (tool6.type === "function") {
11872
11880
  functionDeclarations2.push({
11873
- name: tool5.name,
11874
- description: (_a20 = tool5.description) != null ? _a20 : "",
11875
- parameters: convertJSONSchemaToOpenAPISchema(tool5.inputSchema)
11881
+ name: tool6.name,
11882
+ description: (_a20 = tool6.description) != null ? _a20 : "",
11883
+ parameters: convertJSONSchemaToOpenAPISchema(tool6.inputSchema)
11876
11884
  });
11877
11885
  }
11878
11886
  }
@@ -11912,22 +11920,22 @@ function prepareTools2({
11912
11920
  }
11913
11921
  const functionDeclarations = [];
11914
11922
  let hasStrictTools = false;
11915
- for (const tool5 of tools) {
11916
- switch (tool5.type) {
11923
+ for (const tool6 of tools) {
11924
+ switch (tool6.type) {
11917
11925
  case "function":
11918
11926
  functionDeclarations.push({
11919
- name: tool5.name,
11920
- description: (_b20 = tool5.description) != null ? _b20 : "",
11921
- parameters: convertJSONSchemaToOpenAPISchema(tool5.inputSchema)
11927
+ name: tool6.name,
11928
+ description: (_b20 = tool6.description) != null ? _b20 : "",
11929
+ parameters: convertJSONSchemaToOpenAPISchema(tool6.inputSchema)
11922
11930
  });
11923
- if (tool5.strict === true) {
11931
+ if (tool6.strict === true) {
11924
11932
  hasStrictTools = true;
11925
11933
  }
11926
11934
  break;
11927
11935
  default:
11928
11936
  toolWarnings.push({
11929
11937
  type: "unsupported",
11930
- feature: `function tool ${tool5.name}`
11938
+ feature: `function tool ${tool6.name}`
11931
11939
  });
11932
11940
  break;
11933
11941
  }
@@ -12270,7 +12278,7 @@ var GoogleGenerativeAILanguageModel = class {
12270
12278
  }
12271
12279
  const isVertexProvider = this.config.provider.startsWith("google.vertex.");
12272
12280
  if ((tools == null ? void 0 : tools.some(
12273
- (tool5) => tool5.type === "provider" && tool5.id === "google.vertex_rag_store"
12281
+ (tool6) => tool6.type === "provider" && tool6.id === "google.vertex_rag_store"
12274
12282
  )) && !isVertexProvider) {
12275
12283
  warnings.push({
12276
12284
  type: "other",
@@ -17003,23 +17011,23 @@ function prepareChatTools({
17003
17011
  return { tools: void 0, toolChoice: void 0, toolWarnings };
17004
17012
  }
17005
17013
  const openaiTools2 = [];
17006
- for (const tool5 of tools) {
17007
- switch (tool5.type) {
17014
+ for (const tool6 of tools) {
17015
+ switch (tool6.type) {
17008
17016
  case "function":
17009
17017
  openaiTools2.push({
17010
17018
  type: "function",
17011
17019
  function: {
17012
- name: tool5.name,
17013
- description: tool5.description,
17014
- parameters: tool5.inputSchema,
17015
- ...tool5.strict != null ? { strict: tool5.strict } : {}
17020
+ name: tool6.name,
17021
+ description: tool6.description,
17022
+ parameters: tool6.inputSchema,
17023
+ ...tool6.strict != null ? { strict: tool6.strict } : {}
17016
17024
  }
17017
17025
  });
17018
17026
  break;
17019
17027
  default:
17020
17028
  toolWarnings.push({
17021
17029
  type: "unsupported",
17022
- feature: `tool type: ${tool5.type}`
17030
+ feature: `tool type: ${tool6.type}`
17023
17031
  });
17024
17032
  break;
17025
17033
  }
@@ -20730,26 +20738,26 @@ async function prepareResponsesTools({
20730
20738
  }
20731
20739
  const openaiTools2 = [];
20732
20740
  const resolvedCustomProviderToolNames = customProviderToolNames != null ? customProviderToolNames : /* @__PURE__ */ new Set();
20733
- for (const tool5 of tools) {
20734
- switch (tool5.type) {
20741
+ for (const tool6 of tools) {
20742
+ switch (tool6.type) {
20735
20743
  case "function": {
20736
- const openaiOptions = (_a20 = tool5.providerOptions) == null ? void 0 : _a20.openai;
20744
+ const openaiOptions = (_a20 = tool6.providerOptions) == null ? void 0 : _a20.openai;
20737
20745
  const deferLoading = openaiOptions == null ? void 0 : openaiOptions.deferLoading;
20738
20746
  openaiTools2.push({
20739
20747
  type: "function",
20740
- name: tool5.name,
20741
- description: tool5.description,
20742
- parameters: tool5.inputSchema,
20743
- ...tool5.strict != null ? { strict: tool5.strict } : {},
20748
+ name: tool6.name,
20749
+ description: tool6.description,
20750
+ parameters: tool6.inputSchema,
20751
+ ...tool6.strict != null ? { strict: tool6.strict } : {},
20744
20752
  ...deferLoading != null ? { defer_loading: deferLoading } : {}
20745
20753
  });
20746
20754
  break;
20747
20755
  }
20748
20756
  case "provider": {
20749
- switch (tool5.id) {
20757
+ switch (tool6.id) {
20750
20758
  case "openai.file_search": {
20751
20759
  const args = await validateTypes3({
20752
- value: tool5.args,
20760
+ value: tool6.args,
20753
20761
  schema: fileSearchArgsSchema2
20754
20762
  });
20755
20763
  openaiTools2.push({
@@ -20772,7 +20780,7 @@ async function prepareResponsesTools({
20772
20780
  }
20773
20781
  case "openai.shell": {
20774
20782
  const args = await validateTypes3({
20775
- value: tool5.args,
20783
+ value: tool6.args,
20776
20784
  schema: shellArgsSchema
20777
20785
  });
20778
20786
  openaiTools2.push({
@@ -20791,7 +20799,7 @@ async function prepareResponsesTools({
20791
20799
  }
20792
20800
  case "openai.web_search_preview": {
20793
20801
  const args = await validateTypes3({
20794
- value: tool5.args,
20802
+ value: tool6.args,
20795
20803
  schema: webSearchPreviewArgsSchema
20796
20804
  });
20797
20805
  openaiTools2.push({
@@ -20803,7 +20811,7 @@ async function prepareResponsesTools({
20803
20811
  }
20804
20812
  case "openai.web_search": {
20805
20813
  const args = await validateTypes3({
20806
- value: tool5.args,
20814
+ value: tool6.args,
20807
20815
  schema: webSearchArgsSchema
20808
20816
  });
20809
20817
  openaiTools2.push({
@@ -20817,7 +20825,7 @@ async function prepareResponsesTools({
20817
20825
  }
20818
20826
  case "openai.code_interpreter": {
20819
20827
  const args = await validateTypes3({
20820
- value: tool5.args,
20828
+ value: tool6.args,
20821
20829
  schema: codeInterpreterArgsSchema
20822
20830
  });
20823
20831
  openaiTools2.push({
@@ -20828,7 +20836,7 @@ async function prepareResponsesTools({
20828
20836
  }
20829
20837
  case "openai.image_generation": {
20830
20838
  const args = await validateTypes3({
20831
- value: tool5.args,
20839
+ value: tool6.args,
20832
20840
  schema: imageGenerationArgsSchema
20833
20841
  });
20834
20842
  openaiTools2.push({
@@ -20851,7 +20859,7 @@ async function prepareResponsesTools({
20851
20859
  }
20852
20860
  case "openai.mcp": {
20853
20861
  const args = await validateTypes3({
20854
- value: tool5.args,
20862
+ value: tool6.args,
20855
20863
  schema: mcpArgsSchema
20856
20864
  });
20857
20865
  const mapApprovalFilter = (filter4) => ({
@@ -20877,7 +20885,7 @@ async function prepareResponsesTools({
20877
20885
  }
20878
20886
  case "openai.custom": {
20879
20887
  const args = await validateTypes3({
20880
- value: tool5.args,
20888
+ value: tool6.args,
20881
20889
  schema: customArgsSchema
20882
20890
  });
20883
20891
  openaiTools2.push({
@@ -20891,7 +20899,7 @@ async function prepareResponsesTools({
20891
20899
  }
20892
20900
  case "openai.tool_search": {
20893
20901
  const args = await validateTypes3({
20894
- value: tool5.args,
20902
+ value: tool6.args,
20895
20903
  schema: toolSearchArgsSchema
20896
20904
  });
20897
20905
  openaiTools2.push({
@@ -20908,7 +20916,7 @@ async function prepareResponsesTools({
20908
20916
  default:
20909
20917
  toolWarnings.push({
20910
20918
  type: "unsupported",
20911
- feature: `function tool ${tool5}`
20919
+ feature: `function tool ${tool6}`
20912
20920
  });
20913
20921
  break;
20914
20922
  }
@@ -21080,7 +21088,7 @@ var OpenAIResponsesLanguageModel = class {
21080
21088
  "openai.apply_patch": "apply_patch",
21081
21089
  "openai.tool_search": "tool_search"
21082
21090
  },
21083
- resolveProviderToolName: (tool5) => tool5.id === "openai.custom" ? tool5.args.name : void 0
21091
+ resolveProviderToolName: (tool6) => tool6.id === "openai.custom" ? tool6.args.name : void 0
21084
21092
  });
21085
21093
  const customProviderToolNames = /* @__PURE__ */ new Set();
21086
21094
  const {
@@ -21117,14 +21125,14 @@ var OpenAIResponsesLanguageModel = class {
21117
21125
  }
21118
21126
  }
21119
21127
  function hasOpenAITool(id) {
21120
- return (tools == null ? void 0 : tools.find((tool5) => tool5.type === "provider" && tool5.id === id)) != null;
21128
+ return (tools == null ? void 0 : tools.find((tool6) => tool6.type === "provider" && tool6.id === id)) != null;
21121
21129
  }
21122
21130
  const topLogprobs = typeof (openaiOptions == null ? void 0 : openaiOptions.logprobs) === "number" ? openaiOptions == null ? void 0 : openaiOptions.logprobs : (openaiOptions == null ? void 0 : openaiOptions.logprobs) === true ? TOP_LOGPROBS_MAX : void 0;
21123
21131
  if (topLogprobs) {
21124
21132
  addInclude("message.output_text.logprobs");
21125
21133
  }
21126
21134
  const webSearchToolName = (_e = tools == null ? void 0 : tools.find(
21127
- (tool5) => tool5.type === "provider" && (tool5.id === "openai.web_search" || tool5.id === "openai.web_search_preview")
21135
+ (tool6) => tool6.type === "provider" && (tool6.id === "openai.web_search" || tool6.id === "openai.web_search_preview")
21128
21136
  )) == null ? void 0 : _e.name;
21129
21137
  if (webSearchToolName) {
21130
21138
  addInclude("web_search_call.action.sources");
@@ -21238,7 +21246,7 @@ var OpenAIResponsesLanguageModel = class {
21238
21246
  delete baseArgs.service_tier;
21239
21247
  }
21240
21248
  const shellToolEnvType = (_i = (_h = (_g = tools == null ? void 0 : tools.find(
21241
- (tool5) => tool5.type === "provider" && tool5.id === "openai.shell"
21249
+ (tool6) => tool6.type === "provider" && tool6.id === "openai.shell"
21242
21250
  )) == null ? void 0 : _g.args) == null ? void 0 : _h.environment) == null ? void 0 : _i.type;
21243
21251
  const isShellProviderExecuted = shellToolEnvType === "containerAuto" || shellToolEnvType === "containerReference";
21244
21252
  return {
@@ -23493,7 +23501,8 @@ function getModel(provider, opts) {
23493
23501
  usage: { include: true },
23494
23502
  ...isMoonshot ? { provider: { order: ["moonshotai"], allow_fallbacks: true } } : {}
23495
23503
  };
23496
- return openrouter(modelId, settings);
23504
+ const gatewayModelId = baseURL ? `openrouter/${modelId}` : modelId;
23505
+ return openrouter(gatewayModelId, settings);
23497
23506
  }
23498
23507
  case "xai": {
23499
23508
  if (baseURL) {
@@ -24104,11 +24113,404 @@ function linkifyCitations(markdown, results) {
24104
24113
  return { content, converted, skipped };
24105
24114
  }
24106
24115
 
24116
+ // src/fetch.ts
24117
+ var import_ai3 = require("ai");
24118
+ var import_zod2 = require("zod");
24119
+ var import_node_net = require("net");
24120
+ var import_promises = require("dns/promises");
24121
+ var WEB_FETCH_TOOL_NAME = "web_fetch";
24122
+ var DEFAULT_MAX_USES2 = 5;
24123
+ var DEFAULT_MAX_CHARACTERS2 = 4e4;
24124
+ var CHARS_PER_TOKEN = 4;
24125
+ var DEFAULT_TIMEOUT_MS = 2e4;
24126
+ var MAX_REDIRECTS = 5;
24127
+ var MAX_BODY_BYTES = 4 * 1024 * 1024;
24128
+ var USER_AGENT = "aieo-web-fetch/1 (+https://github.com/stakwork/stakgraph)";
24129
+ var ACCEPT = "text/html, application/xhtml+xml, text/plain;q=0.9, application/json;q=0.9, text/*;q=0.8, */*;q=0.5";
24130
+ function resolveFetchBackend(provider) {
24131
+ return provider === "anthropic" ? "anthropic" : "http";
24132
+ }
24133
+ var PRIVATE_ADDRESSES = buildBlockList();
24134
+ function buildBlockList() {
24135
+ const b = new import_node_net.BlockList();
24136
+ const v42 = [
24137
+ ["0.0.0.0", 8],
24138
+ // "this" network
24139
+ ["10.0.0.0", 8],
24140
+ // RFC 1918
24141
+ ["100.64.0.0", 10],
24142
+ // carrier-grade NAT
24143
+ ["127.0.0.0", 8],
24144
+ // loopback
24145
+ ["169.254.0.0", 16],
24146
+ // link-local, incl. cloud metadata at 169.254.169.254
24147
+ ["172.16.0.0", 12],
24148
+ // RFC 1918
24149
+ ["192.0.0.0", 24],
24150
+ // IETF protocol assignments
24151
+ ["192.168.0.0", 16],
24152
+ // RFC 1918
24153
+ ["198.18.0.0", 15],
24154
+ // benchmarking
24155
+ ["224.0.0.0", 4],
24156
+ // multicast
24157
+ ["240.0.0.0", 4]
24158
+ // reserved, incl. broadcast
24159
+ ];
24160
+ for (const [net, prefix] of v42) b.addSubnet(net, prefix, "ipv4");
24161
+ b.addAddress("::", "ipv6");
24162
+ b.addAddress("::1", "ipv6");
24163
+ const v6 = [
24164
+ ["64:ff9b::", 96],
24165
+ // NAT64
24166
+ ["2002::", 16],
24167
+ // 6to4
24168
+ ["fc00::", 7],
24169
+ // unique local
24170
+ ["fe80::", 10],
24171
+ // link-local
24172
+ ["fec0::", 10],
24173
+ // site-local (deprecated, still routed on old gear)
24174
+ ["ff00::", 8]
24175
+ // multicast
24176
+ ];
24177
+ for (const [net, prefix] of v6) b.addSubnet(net, prefix, "ipv6");
24178
+ return b;
24179
+ }
24180
+ function isPrivateAddress(ip) {
24181
+ const bare = ip.startsWith("[") && ip.endsWith("]") ? ip.slice(1, -1) : ip;
24182
+ const family = (0, import_node_net.isIP)(bare);
24183
+ try {
24184
+ if (family === 4) return PRIVATE_ADDRESSES.check(bare, "ipv4");
24185
+ if (family === 6) return PRIVATE_ADDRESSES.check(bare, "ipv6");
24186
+ } catch {
24187
+ }
24188
+ return true;
24189
+ }
24190
+ var defaultLookup = async (hostname) => {
24191
+ const addresses = await (0, import_promises.lookup)(hostname, { all: true });
24192
+ return addresses.map((a) => a.address);
24193
+ };
24194
+ function matchesDomain(host, domains) {
24195
+ return domains.some((d) => {
24196
+ const dom = d.trim().toLowerCase().replace(/^https?:\/\//, "").replace(/\/.*$/, "").replace(/^\*\./, "").replace(/\.$/, "");
24197
+ return !!dom && (host === dom || host.endsWith("." + dom));
24198
+ });
24199
+ }
24200
+ async function validateFetchUrl(raw, opts = {}) {
24201
+ let url;
24202
+ try {
24203
+ url = new URL(raw);
24204
+ } catch {
24205
+ throw new Error(`Not a valid absolute URL: ${raw}`);
24206
+ }
24207
+ if (url.protocol !== "http:" && url.protocol !== "https:") {
24208
+ throw new Error(`Only http(s) URLs can be fetched, got ${url.protocol}`);
24209
+ }
24210
+ if (url.username || url.password) {
24211
+ throw new Error("URLs with embedded credentials are not fetched");
24212
+ }
24213
+ const host = url.hostname.replace(/\.$/, "").toLowerCase();
24214
+ if (!host) throw new Error("URL has no host");
24215
+ if (host === "localhost" || host.endsWith(".localhost")) {
24216
+ throw new Error("Refusing to fetch a local address");
24217
+ }
24218
+ if (opts.allowedDomains?.length && !matchesDomain(host, opts.allowedDomains)) {
24219
+ throw new Error(`${host} is not in the allowed domains`);
24220
+ }
24221
+ if (opts.blockedDomains?.length && matchesDomain(host, opts.blockedDomains)) {
24222
+ throw new Error(`${host} is a blocked domain`);
24223
+ }
24224
+ const literal = host.startsWith("[") ? host.slice(1, -1) : host;
24225
+ if ((0, import_node_net.isIP)(literal)) {
24226
+ if (isPrivateAddress(literal)) {
24227
+ throw new Error("Refusing to fetch a private or reserved address");
24228
+ }
24229
+ return url;
24230
+ }
24231
+ let addresses;
24232
+ try {
24233
+ addresses = await (opts.lookup ?? defaultLookup)(host);
24234
+ } catch (err) {
24235
+ throw new Error(
24236
+ `Could not resolve ${host}: ${err instanceof Error ? err.message : String(err)}`
24237
+ );
24238
+ }
24239
+ if (!addresses.length) throw new Error(`Could not resolve ${host}`);
24240
+ if (addresses.some(isPrivateAddress)) {
24241
+ throw new Error(`Refusing to fetch ${host}: it resolves to a private or reserved address`);
24242
+ }
24243
+ return url;
24244
+ }
24245
+ async function fetchUrl(rawUrl, opts = {}) {
24246
+ const maxCharacters = opts.maxCharacters ?? DEFAULT_MAX_CHARACTERS2;
24247
+ const signals = [AbortSignal.timeout(opts.timeoutMs ?? DEFAULT_TIMEOUT_MS)];
24248
+ if (opts.abortSignal) signals.push(opts.abortSignal);
24249
+ const signal = AbortSignal.any(signals);
24250
+ let url = await validateFetchUrl(rawUrl, opts);
24251
+ let res;
24252
+ for (let hop = 0; ; hop++) {
24253
+ try {
24254
+ res = await fetch(url, {
24255
+ method: "GET",
24256
+ redirect: "manual",
24257
+ signal,
24258
+ headers: { "user-agent": USER_AGENT, accept: ACCEPT }
24259
+ });
24260
+ } catch (err) {
24261
+ throw new Error(`Could not connect to ${url.hostname}: ${describeTransportError(err)}`);
24262
+ }
24263
+ if (!isRedirect(res.status)) break;
24264
+ const location = res.headers.get("location");
24265
+ await discard(res);
24266
+ if (!location) throw new Error(`Redirect (${res.status}) without a Location header`);
24267
+ if (hop >= MAX_REDIRECTS) throw new Error(`Too many redirects (more than ${MAX_REDIRECTS})`);
24268
+ let next;
24269
+ try {
24270
+ next = new URL(location, url).toString();
24271
+ } catch {
24272
+ throw new Error(`Redirect to an invalid URL: ${location}`);
24273
+ }
24274
+ url = await validateFetchUrl(next, opts);
24275
+ }
24276
+ if (!res.ok) {
24277
+ await discard(res);
24278
+ throw new Error(`HTTP ${res.status} fetching ${url.hostname}`);
24279
+ }
24280
+ const contentType = res.headers.get("content-type") ?? "";
24281
+ const mediaType = contentType.split(";")[0].trim().toLowerCase() || null;
24282
+ if (mediaType === "application/pdf") {
24283
+ await discard(res);
24284
+ throw new Error(
24285
+ "PDF documents are not supported by this fetch backend (only Anthropic's native web_fetch reads PDFs)"
24286
+ );
24287
+ }
24288
+ if (!isTextual(mediaType)) {
24289
+ await discard(res);
24290
+ throw new Error(`Unsupported content type: ${mediaType}`);
24291
+ }
24292
+ const { bytes, capped } = await readCapped(res, MAX_BODY_BYTES);
24293
+ const raw = decode(bytes, contentType);
24294
+ const isHtml = mediaType === "text/html" || mediaType === "application/xhtml+xml" || looksLikeHtml(raw);
24295
+ const { title, text } = isHtml ? htmlToText(raw) : { title: null, text: raw.trim() };
24296
+ const truncated = capped || text.length > maxCharacters;
24297
+ return {
24298
+ url: url.toString(),
24299
+ title,
24300
+ text: truncated ? text.slice(0, maxCharacters) : text,
24301
+ mediaType,
24302
+ retrievedAt: (/* @__PURE__ */ new Date()).toISOString(),
24303
+ truncated,
24304
+ type: "web_fetch_result"
24305
+ };
24306
+ }
24307
+ function describeTransportError(err) {
24308
+ const e = err;
24309
+ if (e?.name === "TimeoutError") return "timed out";
24310
+ if (e?.name === "AbortError") return "aborted";
24311
+ const cause = e?.cause;
24312
+ if (cause?.message) return cause.code ? `${cause.message} (${cause.code})` : cause.message;
24313
+ return e?.message ?? String(err);
24314
+ }
24315
+ function isRedirect(status) {
24316
+ return status === 301 || status === 302 || status === 303 || status === 307 || status === 308;
24317
+ }
24318
+ async function discard(res) {
24319
+ await res.body?.cancel().catch(() => {
24320
+ });
24321
+ }
24322
+ function isTextual(mediaType) {
24323
+ if (!mediaType) return true;
24324
+ if (mediaType.startsWith("text/")) return true;
24325
+ if (mediaType.endsWith("+json") || mediaType.endsWith("+xml")) return true;
24326
+ return mediaType === "application/json" || mediaType === "application/xml" || mediaType === "application/xhtml+xml" || mediaType === "application/javascript";
24327
+ }
24328
+ async function readCapped(res, maxBytes) {
24329
+ const body = res.body;
24330
+ if (!body) return { bytes: new Uint8Array(await res.arrayBuffer()), capped: false };
24331
+ const reader = body.getReader();
24332
+ const chunks = [];
24333
+ let total = 0;
24334
+ let capped = false;
24335
+ for (; ; ) {
24336
+ const { done, value } = await reader.read();
24337
+ if (done) break;
24338
+ if (!value) continue;
24339
+ if (total + value.byteLength > maxBytes) {
24340
+ chunks.push(value.subarray(0, maxBytes - total));
24341
+ total = maxBytes;
24342
+ capped = true;
24343
+ await reader.cancel().catch(() => {
24344
+ });
24345
+ break;
24346
+ }
24347
+ chunks.push(value);
24348
+ total += value.byteLength;
24349
+ }
24350
+ const out = new Uint8Array(total);
24351
+ let offset = 0;
24352
+ for (const c of chunks) {
24353
+ out.set(c, offset);
24354
+ offset += c.byteLength;
24355
+ }
24356
+ return { bytes: out, capped };
24357
+ }
24358
+ function decode(bytes, contentType) {
24359
+ const charset = /charset=["']?([\w.:-]+)/i.exec(contentType)?.[1] ?? "utf-8";
24360
+ try {
24361
+ return new TextDecoder(charset).decode(bytes);
24362
+ } catch {
24363
+ return new TextDecoder("utf-8").decode(bytes);
24364
+ }
24365
+ }
24366
+ function looksLikeHtml(s) {
24367
+ return /^\s*(?:<!doctype\s+html|<html[\s>]|<head[\s>]|<body[\s>])/i.test(s.slice(0, 1024));
24368
+ }
24369
+ var NAMED_ENTITIES = {
24370
+ nbsp: " ",
24371
+ lt: "<",
24372
+ gt: ">",
24373
+ quot: '"',
24374
+ apos: "'",
24375
+ mdash: "\u2014",
24376
+ ndash: "\u2013",
24377
+ hellip: "\u2026",
24378
+ copy: "\xA9",
24379
+ reg: "\xAE",
24380
+ trade: "\u2122",
24381
+ laquo: "\xAB",
24382
+ raquo: "\xBB",
24383
+ ldquo: "\u201C",
24384
+ rdquo: "\u201D",
24385
+ lsquo: "\u2018",
24386
+ rsquo: "\u2019",
24387
+ bull: "\u2022",
24388
+ middot: "\xB7",
24389
+ times: "\xD7",
24390
+ deg: "\xB0"
24391
+ };
24392
+ function codePoint(cp, fallback) {
24393
+ if (!Number.isFinite(cp) || cp <= 0 || cp > 1114111 || cp >= 55296 && cp <= 57343) {
24394
+ return fallback;
24395
+ }
24396
+ return String.fromCodePoint(cp);
24397
+ }
24398
+ function decodeEntities(s) {
24399
+ return s.replace(/&#x([0-9a-f]{1,6});/gi, (m, hex) => codePoint(parseInt(hex, 16), m)).replace(/&#(\d{1,7});/g, (m, dec) => codePoint(parseInt(dec, 10), m)).replace(/&([a-z]+);/gi, (m, name19) => NAMED_ENTITIES[name19.toLowerCase()] ?? m).replace(/&amp;/g, "&");
24400
+ }
24401
+ var BLOCK_TAGS = "p|div|section|article|header|footer|main|aside|nav|h[1-6]|ul|ol|tr|table|thead|tbody|tfoot|blockquote|pre|hr|dd|dt|dl|figure|figcaption|form|fieldset|address|details|summary";
24402
+ function htmlToText(html) {
24403
+ const titleMatch = /<title[^>]*>([\s\S]*?)<\/title>/i.exec(html);
24404
+ const title = titleMatch ? decodeEntities(titleMatch[1]).replace(/\s+/g, " ").trim() || null : null;
24405
+ const stripped = html.replace(/<!--[\s\S]*?-->/g, " ").replace(/<(script|style|noscript|svg|template|head)\b[\s\S]*?<\/\1\s*>/gi, " ").replace(/<br\s*\/?>/gi, "\n").replace(/<li\b[^>]*>/gi, "\n- ").replace(new RegExp(`<\\/?(?:${BLOCK_TAGS})\\b[^>]*>`, "gi"), "\n").replace(/<[^>]+>/g, " ");
24406
+ const text = decodeEntities(stripped).replace(/[ \t\r\f\v ]+/g, " ").replace(/ ?\n ?/g, "\n").replace(/\n{3,}/g, "\n\n").trim();
24407
+ return { title, text };
24408
+ }
24409
+ function createWebFetch(opts) {
24410
+ const results = [];
24411
+ const backend = opts.backend ?? resolveFetchBackend(opts.provider);
24412
+ const maxUses = opts.maxUses ?? DEFAULT_MAX_USES2;
24413
+ const maxCharacters = opts.maxCharacters ?? (opts.maxContentTokens ? opts.maxContentTokens * CHARS_PER_TOKEN : DEFAULT_MAX_CHARACTERS2);
24414
+ const maxContentTokens = opts.maxContentTokens ?? (opts.maxCharacters ? Math.ceil(opts.maxCharacters / CHARS_PER_TOKEN) : void 0);
24415
+ if (backend === "anthropic") {
24416
+ const apiKey = normalizeApiKey(opts.apiKey) || normalizeApiKey(process.env.ANTHROPIC_API_KEY);
24417
+ if (!apiKey) {
24418
+ return emptyFetchHandle(results);
24419
+ }
24420
+ const baseURL = getGatewayBaseURL("anthropic");
24421
+ const anthropic2 = createAnthropic({ apiKey, ...baseURL && { baseURL } });
24422
+ return {
24423
+ tool: anthropic2.tools.webFetch_20250910({
24424
+ maxUses,
24425
+ ...maxContentTokens ? { maxContentTokens } : {},
24426
+ ...opts.allowedDomains?.length ? { allowedDomains: opts.allowedDomains } : {},
24427
+ ...opts.blockedDomains?.length ? { blockedDomains: opts.blockedDomains } : {}
24428
+ }),
24429
+ backend,
24430
+ native: true,
24431
+ results,
24432
+ capture: (stepContent) => captureNativeFetchResults(stepContent, results)
24433
+ };
24434
+ }
24435
+ let uses = 0;
24436
+ return {
24437
+ tool: (0, import_ai3.tool)({
24438
+ description: "Fetch a specific web page by URL and return its text. HTML is converted to plain text; JSON and plain text come back as-is. Use this to read a page whose address you already have \u2014 one the user gave you, or one returned by web_search. It is not a search engine: it needs a full http(s) URL. PDFs and other binary content are not supported.",
24439
+ inputSchema: import_zod2.z.object({
24440
+ url: import_zod2.z.string().describe("The absolute http(s) URL to fetch.")
24441
+ }),
24442
+ execute: async ({ url }, ctx) => {
24443
+ if (uses >= maxUses) {
24444
+ return {
24445
+ error: `web_fetch budget exhausted (${maxUses} calls). Work with what you have.`
24446
+ };
24447
+ }
24448
+ uses++;
24449
+ try {
24450
+ const page = await fetchUrl(url, {
24451
+ maxCharacters,
24452
+ allowedDomains: opts.allowedDomains,
24453
+ blockedDomains: opts.blockedDomains,
24454
+ abortSignal: ctx?.abortSignal ?? opts.abortSignal,
24455
+ lookup: opts.lookup
24456
+ });
24457
+ results.push(page);
24458
+ return page;
24459
+ } catch (err) {
24460
+ return {
24461
+ error: `Fetch failed: ${err instanceof Error ? err.message : String(err)}`
24462
+ };
24463
+ }
24464
+ }
24465
+ }),
24466
+ backend,
24467
+ native: false,
24468
+ results,
24469
+ // HTTP results are appended by `execute` above; walking the step
24470
+ // would double-count them.
24471
+ capture: () => {
24472
+ }
24473
+ };
24474
+ }
24475
+ function emptyFetchHandle(results) {
24476
+ return {
24477
+ tool: void 0,
24478
+ backend: void 0,
24479
+ native: false,
24480
+ results,
24481
+ capture: () => {
24482
+ }
24483
+ };
24484
+ }
24485
+ function captureNativeFetchResults(stepContent, target) {
24486
+ if (!Array.isArray(stepContent)) return;
24487
+ for (const content of stepContent) {
24488
+ if (content?.type !== "tool-result") continue;
24489
+ if (content?.toolName !== WEB_FETCH_TOOL_NAME) continue;
24490
+ const body = content.output ?? content.result ?? null;
24491
+ if (!body || typeof body !== "object") continue;
24492
+ if (body.type !== "web_fetch_result" || typeof body.url !== "string") continue;
24493
+ const doc = body.content ?? {};
24494
+ const source = doc.source ?? {};
24495
+ target.push({
24496
+ url: body.url,
24497
+ title: doc.title ?? null,
24498
+ ...source.type === "text" && typeof source.data === "string" ? { text: source.data } : {},
24499
+ mediaType: source.mediaType ?? source.media_type ?? null,
24500
+ retrievedAt: body.retrievedAt ?? body.retrieved_at ?? null,
24501
+ type: "web_fetch_result"
24502
+ });
24503
+ }
24504
+ }
24505
+
24107
24506
  // src/tools.ts
24108
24507
  function getProviderTool(provider, apiKey, toolName) {
24109
24508
  if (toolName === "webSearch") {
24110
24509
  return createWebSearch({ provider, apiKey }).tool;
24111
24510
  }
24511
+ if (toolName === "webFetch") {
24512
+ return createWebFetch({ provider, apiKey }).tool;
24513
+ }
24112
24514
  switch (provider) {
24113
24515
  case "anthropic":
24114
24516
  return getAnthropicTool(apiKey, toolName);
@@ -24165,16 +24567,20 @@ function consoleLogger(name19) {
24165
24567
  OUTRO,
24166
24568
  PROVIDERS,
24167
24569
  SYSTEM,
24570
+ WEB_FETCH_TOOL_NAME,
24168
24571
  WEB_SEARCH_TOOL_NAME,
24169
24572
  addUsage,
24170
24573
  callGenerateObject,
24171
24574
  callGenerateText,
24172
24575
  callModel,
24576
+ captureNativeFetchResults,
24173
24577
  captureNativeResults,
24174
24578
  computeSessionCost,
24175
24579
  consoleLogger,
24580
+ createWebFetch,
24176
24581
  createWebSearch,
24177
24582
  emptyUsage,
24583
+ fetchUrl,
24178
24584
  gatewayEnvForProviders,
24179
24585
  gatewayUrlFor,
24180
24586
  gatewayUrlForModel,
@@ -24191,15 +24597,19 @@ function consoleLogger(name19) {
24191
24597
  getTokenPricing,
24192
24598
  hasApiKeyForProvider,
24193
24599
  hasSearchApiKey,
24600
+ htmlToText,
24601
+ isPrivateAddress,
24194
24602
  linkifyCitations,
24195
24603
  loadModelPricing,
24196
24604
  normalizeApiKey,
24197
24605
  normalizeCallerBaseURL,
24198
24606
  normalizeUsage,
24607
+ resolveFetchBackend,
24199
24608
  resolveLLMConfig,
24200
24609
  resolveSearchBackend,
24201
24610
  searchWeb,
24202
24611
  stripCitations,
24612
+ validateFetchUrl,
24203
24613
  withLegacyUsage,
24204
24614
  withProviderCacheUsage
24205
24615
  });