aieo 0.1.34 → 0.1.36

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,12 +36,15 @@ __export(index_exports, {
36
36
  OUTRO: () => OUTRO,
37
37
  PROVIDERS: () => PROVIDERS,
38
38
  SYSTEM: () => SYSTEM,
39
+ WEB_SEARCH_TOOL_NAME: () => WEB_SEARCH_TOOL_NAME,
39
40
  addUsage: () => addUsage,
40
41
  callGenerateObject: () => callGenerateObject,
41
42
  callGenerateText: () => callGenerateText,
42
43
  callModel: () => callModel,
44
+ captureNativeResults: () => captureNativeResults,
43
45
  computeSessionCost: () => computeSessionCost,
44
46
  consoleLogger: () => consoleLogger,
47
+ createWebSearch: () => createWebSearch,
45
48
  emptyUsage: () => emptyUsage,
46
49
  gatewayEnvForProviders: () => gatewayEnvForProviders,
47
50
  gatewayUrlFor: () => gatewayUrlFor,
@@ -55,12 +58,19 @@ __export(index_exports, {
55
58
  getProviderForModel: () => getProviderForModel,
56
59
  getProviderOptions: () => getProviderOptions,
57
60
  getProviderTool: () => getProviderTool,
61
+ getSearchApiKey: () => getSearchApiKey,
58
62
  getTokenPricing: () => getTokenPricing,
59
63
  hasApiKeyForProvider: () => hasApiKeyForProvider,
64
+ hasSearchApiKey: () => hasSearchApiKey,
65
+ linkifyCitations: () => linkifyCitations,
60
66
  loadModelPricing: () => loadModelPricing,
67
+ normalizeApiKey: () => normalizeApiKey,
61
68
  normalizeCallerBaseURL: () => normalizeCallerBaseURL,
62
69
  normalizeUsage: () => normalizeUsage,
63
70
  resolveLLMConfig: () => resolveLLMConfig,
71
+ resolveSearchBackend: () => resolveSearchBackend,
72
+ searchWeb: () => searchWeb,
73
+ stripCitations: () => stripCitations,
64
74
  withLegacyUsage: () => withLegacyUsage,
65
75
  withProviderCacheUsage: () => withProviderCacheUsage
66
76
  });
@@ -193,7 +203,7 @@ var ConversationStorage = class {
193
203
  }
194
204
  };
195
205
 
196
- // ../../node_modules/@ai-sdk/provider/dist/index.mjs
206
+ // ../../node_modules/@ai-sdk/anthropic/node_modules/@ai-sdk/provider/dist/index.mjs
197
207
  var marker = "vercel.ai.error";
198
208
  var symbol = Symbol.for(marker);
199
209
  var _a;
@@ -539,7 +549,7 @@ var UnsupportedFunctionalityError = class extends (_b14 = AISDKError, _a14 = sym
539
549
  }
540
550
  };
541
551
 
542
- // ../../node_modules/@ai-sdk/provider-utils/dist/index.mjs
552
+ // ../../node_modules/@ai-sdk/anthropic/node_modules/@ai-sdk/provider-utils/dist/index.mjs
543
553
  var z4 = __toESM(require("zod/v4"), 1);
544
554
  var import_v3 = require("zod/v3");
545
555
  var import_v32 = require("zod/v3");
@@ -734,7 +744,7 @@ var EventSourceParserStream = class extends TransformStream {
734
744
  }
735
745
  };
736
746
 
737
- // ../../node_modules/@ai-sdk/provider-utils/dist/index.mjs
747
+ // ../../node_modules/@ai-sdk/anthropic/node_modules/@ai-sdk/provider-utils/dist/index.mjs
738
748
  function combineHeaders(...headers) {
739
749
  return headers.reduce(
740
750
  (combinedHeaders, currentHeaders) => ({
@@ -4180,35 +4190,35 @@ async function prepareTools({
4180
4190
  return { tools: void 0, toolChoice: void 0, toolWarnings, betas };
4181
4191
  }
4182
4192
  const anthropicTools2 = [];
4183
- for (const tool4 of tools) {
4184
- switch (tool4.type) {
4193
+ for (const tool5 of tools) {
4194
+ switch (tool5.type) {
4185
4195
  case "function": {
4186
- const cacheControl = validator.getCacheControl(tool4.providerOptions, {
4196
+ const cacheControl = validator.getCacheControl(tool5.providerOptions, {
4187
4197
  type: "tool definition",
4188
4198
  canCache: true
4189
4199
  });
4190
- const anthropicOptions = (_a20 = tool4.providerOptions) == null ? void 0 : _a20.anthropic;
4200
+ const anthropicOptions = (_a20 = tool5.providerOptions) == null ? void 0 : _a20.anthropic;
4191
4201
  const eagerInputStreaming = (_b20 = anthropicOptions == null ? void 0 : anthropicOptions.eagerInputStreaming) != null ? _b20 : defaultEagerInputStreaming;
4192
4202
  const deferLoading = anthropicOptions == null ? void 0 : anthropicOptions.deferLoading;
4193
4203
  const allowedCallers = anthropicOptions == null ? void 0 : anthropicOptions.allowedCallers;
4194
- if (!supportsStrictTools && tool4.strict != null) {
4204
+ if (!supportsStrictTools && tool5.strict != null) {
4195
4205
  toolWarnings.push({
4196
4206
  type: "unsupported",
4197
4207
  feature: "strict",
4198
- details: `Tool '${tool4.name}' has strict: ${tool4.strict}, but strict mode is not supported by this provider. The strict property will be ignored.`
4208
+ details: `Tool '${tool5.name}' has strict: ${tool5.strict}, but strict mode is not supported by this provider. The strict property will be ignored.`
4199
4209
  });
4200
4210
  }
4201
4211
  anthropicTools2.push({
4202
- name: tool4.name,
4203
- description: tool4.description,
4204
- input_schema: tool4.inputSchema,
4212
+ name: tool5.name,
4213
+ description: tool5.description,
4214
+ input_schema: tool5.inputSchema,
4205
4215
  cache_control: cacheControl,
4206
4216
  ...eagerInputStreaming ? { eager_input_streaming: true } : {},
4207
- ...supportsStrictTools === true && tool4.strict != null ? { strict: tool4.strict } : {},
4217
+ ...supportsStrictTools === true && tool5.strict != null ? { strict: tool5.strict } : {},
4208
4218
  ...deferLoading != null ? { defer_loading: deferLoading } : {},
4209
4219
  ...allowedCallers != null ? { allowed_callers: allowedCallers } : {},
4210
- ...tool4.inputExamples != null ? {
4211
- input_examples: tool4.inputExamples.map(
4220
+ ...tool5.inputExamples != null ? {
4221
+ input_examples: tool5.inputExamples.map(
4212
4222
  (example) => example.input
4213
4223
  )
4214
4224
  } : {}
@@ -4216,13 +4226,13 @@ async function prepareTools({
4216
4226
  if (supportsStructuredOutput === true) {
4217
4227
  betas.add("structured-outputs-2025-11-13");
4218
4228
  }
4219
- if (tool4.inputExamples != null || allowedCallers != null) {
4229
+ if (tool5.inputExamples != null || allowedCallers != null) {
4220
4230
  betas.add("advanced-tool-use-2025-11-20");
4221
4231
  }
4222
4232
  break;
4223
4233
  }
4224
4234
  case "provider": {
4225
- switch (tool4.id) {
4235
+ switch (tool5.id) {
4226
4236
  case "anthropic.code_execution_20250522": {
4227
4237
  betas.add("code-execution-2025-05-22");
4228
4238
  anthropicTools2.push({
@@ -4252,9 +4262,9 @@ async function prepareTools({
4252
4262
  anthropicTools2.push({
4253
4263
  name: "computer",
4254
4264
  type: "computer_20250124",
4255
- display_width_px: tool4.args.displayWidthPx,
4256
- display_height_px: tool4.args.displayHeightPx,
4257
- display_number: tool4.args.displayNumber,
4265
+ display_width_px: tool5.args.displayWidthPx,
4266
+ display_height_px: tool5.args.displayHeightPx,
4267
+ display_number: tool5.args.displayNumber,
4258
4268
  cache_control: void 0
4259
4269
  });
4260
4270
  break;
@@ -4264,10 +4274,10 @@ async function prepareTools({
4264
4274
  anthropicTools2.push({
4265
4275
  name: "computer",
4266
4276
  type: "computer_20251124",
4267
- display_width_px: tool4.args.displayWidthPx,
4268
- display_height_px: tool4.args.displayHeightPx,
4269
- display_number: tool4.args.displayNumber,
4270
- enable_zoom: tool4.args.enableZoom,
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,
4271
4281
  cache_control: void 0
4272
4282
  });
4273
4283
  break;
@@ -4277,9 +4287,9 @@ async function prepareTools({
4277
4287
  anthropicTools2.push({
4278
4288
  name: "computer",
4279
4289
  type: "computer_20241022",
4280
- display_width_px: tool4.args.displayWidthPx,
4281
- display_height_px: tool4.args.displayHeightPx,
4282
- display_number: tool4.args.displayNumber,
4290
+ display_width_px: tool5.args.displayWidthPx,
4291
+ display_height_px: tool5.args.displayHeightPx,
4292
+ display_number: tool5.args.displayNumber,
4283
4293
  cache_control: void 0
4284
4294
  });
4285
4295
  break;
@@ -4313,7 +4323,7 @@ async function prepareTools({
4313
4323
  }
4314
4324
  case "anthropic.text_editor_20250728": {
4315
4325
  const args = await validateTypes({
4316
- value: tool4.args,
4326
+ value: tool5.args,
4317
4327
  schema: textEditor_20250728ArgsSchema
4318
4328
  });
4319
4329
  anthropicTools2.push({
@@ -4353,7 +4363,7 @@ async function prepareTools({
4353
4363
  case "anthropic.web_fetch_20250910": {
4354
4364
  betas.add("web-fetch-2025-09-10");
4355
4365
  const args = await validateTypes({
4356
- value: tool4.args,
4366
+ value: tool5.args,
4357
4367
  schema: webFetch_20250910ArgsSchema
4358
4368
  });
4359
4369
  anthropicTools2.push({
@@ -4371,7 +4381,7 @@ async function prepareTools({
4371
4381
  case "anthropic.web_fetch_20260209": {
4372
4382
  betas.add("code-execution-web-tools-2026-02-09");
4373
4383
  const args = await validateTypes({
4374
- value: tool4.args,
4384
+ value: tool5.args,
4375
4385
  schema: webFetch_20260209ArgsSchema
4376
4386
  });
4377
4387
  anthropicTools2.push({
@@ -4388,7 +4398,7 @@ async function prepareTools({
4388
4398
  }
4389
4399
  case "anthropic.web_search_20250305": {
4390
4400
  const args = await validateTypes({
4391
- value: tool4.args,
4401
+ value: tool5.args,
4392
4402
  schema: webSearch_20250305ArgsSchema
4393
4403
  });
4394
4404
  anthropicTools2.push({
@@ -4405,7 +4415,7 @@ async function prepareTools({
4405
4415
  case "anthropic.web_search_20260209": {
4406
4416
  betas.add("code-execution-web-tools-2026-02-09");
4407
4417
  const args = await validateTypes({
4408
- value: tool4.args,
4418
+ value: tool5.args,
4409
4419
  schema: webSearch_20260209ArgsSchema
4410
4420
  });
4411
4421
  anthropicTools2.push({
@@ -4436,7 +4446,7 @@ async function prepareTools({
4436
4446
  case "anthropic.advisor_20260301": {
4437
4447
  betas.add("advisor-tool-2026-03-01");
4438
4448
  const args = await validateTypes({
4439
- value: tool4.args,
4449
+ value: tool5.args,
4440
4450
  schema: advisor_20260301ArgsSchema
4441
4451
  });
4442
4452
  anthropicTools2.push({
@@ -4451,7 +4461,7 @@ async function prepareTools({
4451
4461
  default: {
4452
4462
  toolWarnings.push({
4453
4463
  type: "unsupported",
4454
- feature: `provider-defined tool ${tool4.id}`
4464
+ feature: `provider-defined tool ${tool5.id}`
4455
4465
  });
4456
4466
  break;
4457
4467
  }
@@ -4461,7 +4471,7 @@ async function prepareTools({
4461
4471
  default: {
4462
4472
  toolWarnings.push({
4463
4473
  type: "unsupported",
4464
- feature: `tool ${tool4}`
4474
+ feature: `tool ${tool5}`
4465
4475
  });
4466
4476
  break;
4467
4477
  }
@@ -6431,7 +6441,7 @@ var AnthropicMessagesLanguageModel = class {
6431
6441
  betas.add("skills-2025-10-02");
6432
6442
  betas.add("files-api-2025-04-14");
6433
6443
  if (!(tools == null ? void 0 : tools.some(
6434
- (tool4) => tool4.type === "provider" && (tool4.id === "anthropic.code_execution_20250825" || tool4.id === "anthropic.code_execution_20260120")
6444
+ (tool5) => tool5.type === "provider" && (tool5.id === "anthropic.code_execution_20250825" || tool5.id === "anthropic.code_execution_20260120")
6435
6445
  ))) {
6436
6446
  warnings.push({
6437
6447
  type: "other",
@@ -8034,12 +8044,12 @@ function hasWebTool20260209WithoutCodeExecution(tools) {
8034
8044
  }
8035
8045
  let hasWebTool20260209 = false;
8036
8046
  let hasCodeExecutionTool = false;
8037
- for (const tool4 of tools) {
8038
- if ("type" in tool4 && (tool4.type === "web_fetch_20260209" || tool4.type === "web_search_20260209")) {
8047
+ for (const tool5 of tools) {
8048
+ if ("type" in tool5 && (tool5.type === "web_fetch_20260209" || tool5.type === "web_search_20260209")) {
8039
8049
  hasWebTool20260209 = true;
8040
8050
  continue;
8041
8051
  }
8042
- if (tool4.name === "code_execution") {
8052
+ if (tool5.name === "code_execution") {
8043
8053
  hasCodeExecutionTool = true;
8044
8054
  break;
8045
8055
  }
@@ -11748,8 +11758,8 @@ function prepareTools2({
11748
11758
  if (tools == null) {
11749
11759
  return { tools: void 0, toolConfig: void 0, toolWarnings };
11750
11760
  }
11751
- const hasFunctionTools = tools.some((tool4) => tool4.type === "function");
11752
- const hasProviderTools = tools.some((tool4) => tool4.type === "provider");
11761
+ const hasFunctionTools = tools.some((tool5) => tool5.type === "function");
11762
+ const hasProviderTools = tools.some((tool5) => tool5.type === "provider");
11753
11763
  if (hasFunctionTools && hasProviderTools && !isGemini3orNewer) {
11754
11764
  toolWarnings.push({
11755
11765
  type: "unsupported",
@@ -11758,16 +11768,16 @@ function prepareTools2({
11758
11768
  }
11759
11769
  if (hasProviderTools) {
11760
11770
  const googleTools2 = [];
11761
- const ProviderTools = tools.filter((tool4) => tool4.type === "provider");
11762
- ProviderTools.forEach((tool4) => {
11763
- switch (tool4.id) {
11771
+ const ProviderTools = tools.filter((tool5) => tool5.type === "provider");
11772
+ ProviderTools.forEach((tool5) => {
11773
+ switch (tool5.id) {
11764
11774
  case "google.google_search":
11765
11775
  if (isGemini2orNewer) {
11766
- googleTools2.push({ googleSearch: { ...tool4.args } });
11776
+ googleTools2.push({ googleSearch: { ...tool5.args } });
11767
11777
  } else {
11768
11778
  toolWarnings.push({
11769
11779
  type: "unsupported",
11770
- feature: `provider-defined tool ${tool4.id}`,
11780
+ feature: `provider-defined tool ${tool5.id}`,
11771
11781
  details: "Google Search requires Gemini 2.0 or newer."
11772
11782
  });
11773
11783
  }
@@ -11778,7 +11788,7 @@ function prepareTools2({
11778
11788
  } else {
11779
11789
  toolWarnings.push({
11780
11790
  type: "unsupported",
11781
- feature: `provider-defined tool ${tool4.id}`,
11791
+ feature: `provider-defined tool ${tool5.id}`,
11782
11792
  details: "Enterprise Web Search requires Gemini 2.0 or newer."
11783
11793
  });
11784
11794
  }
@@ -11789,7 +11799,7 @@ function prepareTools2({
11789
11799
  } else {
11790
11800
  toolWarnings.push({
11791
11801
  type: "unsupported",
11792
- feature: `provider-defined tool ${tool4.id}`,
11802
+ feature: `provider-defined tool ${tool5.id}`,
11793
11803
  details: "The URL context tool is not supported with other Gemini models than Gemini 2."
11794
11804
  });
11795
11805
  }
@@ -11800,18 +11810,18 @@ function prepareTools2({
11800
11810
  } else {
11801
11811
  toolWarnings.push({
11802
11812
  type: "unsupported",
11803
- feature: `provider-defined tool ${tool4.id}`,
11813
+ feature: `provider-defined tool ${tool5.id}`,
11804
11814
  details: "The code execution tool is not supported with other Gemini models than Gemini 2."
11805
11815
  });
11806
11816
  }
11807
11817
  break;
11808
11818
  case "google.file_search":
11809
11819
  if (supportsFileSearch) {
11810
- googleTools2.push({ fileSearch: { ...tool4.args } });
11820
+ googleTools2.push({ fileSearch: { ...tool5.args } });
11811
11821
  } else {
11812
11822
  toolWarnings.push({
11813
11823
  type: "unsupported",
11814
- feature: `provider-defined tool ${tool4.id}`,
11824
+ feature: `provider-defined tool ${tool5.id}`,
11815
11825
  details: "The file search tool is only supported with Gemini 2.5 models and Gemini 3 models."
11816
11826
  });
11817
11827
  }
@@ -11822,16 +11832,16 @@ function prepareTools2({
11822
11832
  retrieval: {
11823
11833
  vertex_rag_store: {
11824
11834
  rag_resources: {
11825
- rag_corpus: tool4.args.ragCorpus
11835
+ rag_corpus: tool5.args.ragCorpus
11826
11836
  },
11827
- similarity_top_k: tool4.args.topK
11837
+ similarity_top_k: tool5.args.topK
11828
11838
  }
11829
11839
  }
11830
11840
  });
11831
11841
  } else {
11832
11842
  toolWarnings.push({
11833
11843
  type: "unsupported",
11834
- feature: `provider-defined tool ${tool4.id}`,
11844
+ feature: `provider-defined tool ${tool5.id}`,
11835
11845
  details: "The RAG store tool is not supported with other Gemini models than Gemini 2."
11836
11846
  });
11837
11847
  }
@@ -11842,7 +11852,7 @@ function prepareTools2({
11842
11852
  } else {
11843
11853
  toolWarnings.push({
11844
11854
  type: "unsupported",
11845
- feature: `provider-defined tool ${tool4.id}`,
11855
+ feature: `provider-defined tool ${tool5.id}`,
11846
11856
  details: "The Google Maps grounding tool is not supported with Gemini models other than Gemini 2 or newer."
11847
11857
  });
11848
11858
  }
@@ -11850,19 +11860,19 @@ function prepareTools2({
11850
11860
  default:
11851
11861
  toolWarnings.push({
11852
11862
  type: "unsupported",
11853
- feature: `provider-defined tool ${tool4.id}`
11863
+ feature: `provider-defined tool ${tool5.id}`
11854
11864
  });
11855
11865
  break;
11856
11866
  }
11857
11867
  });
11858
11868
  if (hasFunctionTools && isGemini3orNewer && googleTools2.length > 0) {
11859
11869
  const functionDeclarations2 = [];
11860
- for (const tool4 of tools) {
11861
- if (tool4.type === "function") {
11870
+ for (const tool5 of tools) {
11871
+ if (tool5.type === "function") {
11862
11872
  functionDeclarations2.push({
11863
- name: tool4.name,
11864
- description: (_a20 = tool4.description) != null ? _a20 : "",
11865
- parameters: convertJSONSchemaToOpenAPISchema(tool4.inputSchema)
11873
+ name: tool5.name,
11874
+ description: (_a20 = tool5.description) != null ? _a20 : "",
11875
+ parameters: convertJSONSchemaToOpenAPISchema(tool5.inputSchema)
11866
11876
  });
11867
11877
  }
11868
11878
  }
@@ -11902,22 +11912,22 @@ function prepareTools2({
11902
11912
  }
11903
11913
  const functionDeclarations = [];
11904
11914
  let hasStrictTools = false;
11905
- for (const tool4 of tools) {
11906
- switch (tool4.type) {
11915
+ for (const tool5 of tools) {
11916
+ switch (tool5.type) {
11907
11917
  case "function":
11908
11918
  functionDeclarations.push({
11909
- name: tool4.name,
11910
- description: (_b20 = tool4.description) != null ? _b20 : "",
11911
- parameters: convertJSONSchemaToOpenAPISchema(tool4.inputSchema)
11919
+ name: tool5.name,
11920
+ description: (_b20 = tool5.description) != null ? _b20 : "",
11921
+ parameters: convertJSONSchemaToOpenAPISchema(tool5.inputSchema)
11912
11922
  });
11913
- if (tool4.strict === true) {
11923
+ if (tool5.strict === true) {
11914
11924
  hasStrictTools = true;
11915
11925
  }
11916
11926
  break;
11917
11927
  default:
11918
11928
  toolWarnings.push({
11919
11929
  type: "unsupported",
11920
- feature: `function tool ${tool4.name}`
11930
+ feature: `function tool ${tool5.name}`
11921
11931
  });
11922
11932
  break;
11923
11933
  }
@@ -12260,7 +12270,7 @@ var GoogleGenerativeAILanguageModel = class {
12260
12270
  }
12261
12271
  const isVertexProvider = this.config.provider.startsWith("google.vertex.");
12262
12272
  if ((tools == null ? void 0 : tools.some(
12263
- (tool4) => tool4.type === "provider" && tool4.id === "google.vertex_rag_store"
12273
+ (tool5) => tool5.type === "provider" && tool5.id === "google.vertex_rag_store"
12264
12274
  )) && !isVertexProvider) {
12265
12275
  warnings.push({
12266
12276
  type: "other",
@@ -16993,23 +17003,23 @@ function prepareChatTools({
16993
17003
  return { tools: void 0, toolChoice: void 0, toolWarnings };
16994
17004
  }
16995
17005
  const openaiTools2 = [];
16996
- for (const tool4 of tools) {
16997
- switch (tool4.type) {
17006
+ for (const tool5 of tools) {
17007
+ switch (tool5.type) {
16998
17008
  case "function":
16999
17009
  openaiTools2.push({
17000
17010
  type: "function",
17001
17011
  function: {
17002
- name: tool4.name,
17003
- description: tool4.description,
17004
- parameters: tool4.inputSchema,
17005
- ...tool4.strict != null ? { strict: tool4.strict } : {}
17012
+ name: tool5.name,
17013
+ description: tool5.description,
17014
+ parameters: tool5.inputSchema,
17015
+ ...tool5.strict != null ? { strict: tool5.strict } : {}
17006
17016
  }
17007
17017
  });
17008
17018
  break;
17009
17019
  default:
17010
17020
  toolWarnings.push({
17011
17021
  type: "unsupported",
17012
- feature: `tool type: ${tool4.type}`
17022
+ feature: `tool type: ${tool5.type}`
17013
17023
  });
17014
17024
  break;
17015
17025
  }
@@ -20720,26 +20730,26 @@ async function prepareResponsesTools({
20720
20730
  }
20721
20731
  const openaiTools2 = [];
20722
20732
  const resolvedCustomProviderToolNames = customProviderToolNames != null ? customProviderToolNames : /* @__PURE__ */ new Set();
20723
- for (const tool4 of tools) {
20724
- switch (tool4.type) {
20733
+ for (const tool5 of tools) {
20734
+ switch (tool5.type) {
20725
20735
  case "function": {
20726
- const openaiOptions = (_a20 = tool4.providerOptions) == null ? void 0 : _a20.openai;
20736
+ const openaiOptions = (_a20 = tool5.providerOptions) == null ? void 0 : _a20.openai;
20727
20737
  const deferLoading = openaiOptions == null ? void 0 : openaiOptions.deferLoading;
20728
20738
  openaiTools2.push({
20729
20739
  type: "function",
20730
- name: tool4.name,
20731
- description: tool4.description,
20732
- parameters: tool4.inputSchema,
20733
- ...tool4.strict != null ? { strict: tool4.strict } : {},
20740
+ name: tool5.name,
20741
+ description: tool5.description,
20742
+ parameters: tool5.inputSchema,
20743
+ ...tool5.strict != null ? { strict: tool5.strict } : {},
20734
20744
  ...deferLoading != null ? { defer_loading: deferLoading } : {}
20735
20745
  });
20736
20746
  break;
20737
20747
  }
20738
20748
  case "provider": {
20739
- switch (tool4.id) {
20749
+ switch (tool5.id) {
20740
20750
  case "openai.file_search": {
20741
20751
  const args = await validateTypes3({
20742
- value: tool4.args,
20752
+ value: tool5.args,
20743
20753
  schema: fileSearchArgsSchema2
20744
20754
  });
20745
20755
  openaiTools2.push({
@@ -20762,7 +20772,7 @@ async function prepareResponsesTools({
20762
20772
  }
20763
20773
  case "openai.shell": {
20764
20774
  const args = await validateTypes3({
20765
- value: tool4.args,
20775
+ value: tool5.args,
20766
20776
  schema: shellArgsSchema
20767
20777
  });
20768
20778
  openaiTools2.push({
@@ -20781,7 +20791,7 @@ async function prepareResponsesTools({
20781
20791
  }
20782
20792
  case "openai.web_search_preview": {
20783
20793
  const args = await validateTypes3({
20784
- value: tool4.args,
20794
+ value: tool5.args,
20785
20795
  schema: webSearchPreviewArgsSchema
20786
20796
  });
20787
20797
  openaiTools2.push({
@@ -20793,7 +20803,7 @@ async function prepareResponsesTools({
20793
20803
  }
20794
20804
  case "openai.web_search": {
20795
20805
  const args = await validateTypes3({
20796
- value: tool4.args,
20806
+ value: tool5.args,
20797
20807
  schema: webSearchArgsSchema
20798
20808
  });
20799
20809
  openaiTools2.push({
@@ -20807,7 +20817,7 @@ async function prepareResponsesTools({
20807
20817
  }
20808
20818
  case "openai.code_interpreter": {
20809
20819
  const args = await validateTypes3({
20810
- value: tool4.args,
20820
+ value: tool5.args,
20811
20821
  schema: codeInterpreterArgsSchema
20812
20822
  });
20813
20823
  openaiTools2.push({
@@ -20818,7 +20828,7 @@ async function prepareResponsesTools({
20818
20828
  }
20819
20829
  case "openai.image_generation": {
20820
20830
  const args = await validateTypes3({
20821
- value: tool4.args,
20831
+ value: tool5.args,
20822
20832
  schema: imageGenerationArgsSchema
20823
20833
  });
20824
20834
  openaiTools2.push({
@@ -20841,7 +20851,7 @@ async function prepareResponsesTools({
20841
20851
  }
20842
20852
  case "openai.mcp": {
20843
20853
  const args = await validateTypes3({
20844
- value: tool4.args,
20854
+ value: tool5.args,
20845
20855
  schema: mcpArgsSchema
20846
20856
  });
20847
20857
  const mapApprovalFilter = (filter4) => ({
@@ -20867,7 +20877,7 @@ async function prepareResponsesTools({
20867
20877
  }
20868
20878
  case "openai.custom": {
20869
20879
  const args = await validateTypes3({
20870
- value: tool4.args,
20880
+ value: tool5.args,
20871
20881
  schema: customArgsSchema
20872
20882
  });
20873
20883
  openaiTools2.push({
@@ -20881,7 +20891,7 @@ async function prepareResponsesTools({
20881
20891
  }
20882
20892
  case "openai.tool_search": {
20883
20893
  const args = await validateTypes3({
20884
- value: tool4.args,
20894
+ value: tool5.args,
20885
20895
  schema: toolSearchArgsSchema
20886
20896
  });
20887
20897
  openaiTools2.push({
@@ -20898,7 +20908,7 @@ async function prepareResponsesTools({
20898
20908
  default:
20899
20909
  toolWarnings.push({
20900
20910
  type: "unsupported",
20901
- feature: `function tool ${tool4}`
20911
+ feature: `function tool ${tool5}`
20902
20912
  });
20903
20913
  break;
20904
20914
  }
@@ -21070,7 +21080,7 @@ var OpenAIResponsesLanguageModel = class {
21070
21080
  "openai.apply_patch": "apply_patch",
21071
21081
  "openai.tool_search": "tool_search"
21072
21082
  },
21073
- resolveProviderToolName: (tool4) => tool4.id === "openai.custom" ? tool4.args.name : void 0
21083
+ resolveProviderToolName: (tool5) => tool5.id === "openai.custom" ? tool5.args.name : void 0
21074
21084
  });
21075
21085
  const customProviderToolNames = /* @__PURE__ */ new Set();
21076
21086
  const {
@@ -21107,14 +21117,14 @@ var OpenAIResponsesLanguageModel = class {
21107
21117
  }
21108
21118
  }
21109
21119
  function hasOpenAITool(id) {
21110
- return (tools == null ? void 0 : tools.find((tool4) => tool4.type === "provider" && tool4.id === id)) != null;
21120
+ return (tools == null ? void 0 : tools.find((tool5) => tool5.type === "provider" && tool5.id === id)) != null;
21111
21121
  }
21112
21122
  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;
21113
21123
  if (topLogprobs) {
21114
21124
  addInclude("message.output_text.logprobs");
21115
21125
  }
21116
21126
  const webSearchToolName = (_e = tools == null ? void 0 : tools.find(
21117
- (tool4) => tool4.type === "provider" && (tool4.id === "openai.web_search" || tool4.id === "openai.web_search_preview")
21127
+ (tool5) => tool5.type === "provider" && (tool5.id === "openai.web_search" || tool5.id === "openai.web_search_preview")
21118
21128
  )) == null ? void 0 : _e.name;
21119
21129
  if (webSearchToolName) {
21120
21130
  addInclude("web_search_call.action.sources");
@@ -21228,7 +21238,7 @@ var OpenAIResponsesLanguageModel = class {
21228
21238
  delete baseArgs.service_tier;
21229
21239
  }
21230
21240
  const shellToolEnvType = (_i = (_h = (_g = tools == null ? void 0 : tools.find(
21231
- (tool4) => tool4.type === "provider" && tool4.id === "openai.shell"
21241
+ (tool5) => tool5.type === "provider" && tool5.id === "openai.shell"
21232
21242
  )) == null ? void 0 : _g.args) == null ? void 0 : _h.environment) == null ? void 0 : _i.type;
21233
21243
  const isShellProviderExecuted = shellToolEnvType === "containerAuto" || shellToolEnvType === "containerReference";
21234
21244
  return {
@@ -23104,13 +23114,15 @@ function createOpenAI(options = {}) {
23104
23114
  var openai = createOpenAI();
23105
23115
 
23106
23116
  // src/provider.ts
23117
+ var import_xai = require("@ai-sdk/xai");
23107
23118
  var import_ai_sdk_provider = require("@openrouter/ai-sdk-provider");
23108
23119
  var LLM_GATEWAY_URL = process.env.LLM_GATEWAY_URL?.replace(/\/$/, "");
23109
23120
  var GATEWAY_PATHS = {
23110
23121
  anthropic: "/anthropic/v1",
23111
23122
  google: "/genai/v1beta",
23112
23123
  openai: "/openai/v1",
23113
- openrouter: "/openai/v1"
23124
+ openrouter: "/openai/v1",
23125
+ xai: "/openai/v1"
23114
23126
  };
23115
23127
  function getGatewayBaseURL(provider) {
23116
23128
  return LLM_GATEWAY_URL ? `${LLM_GATEWAY_URL}${GATEWAY_PATHS[provider]}` : void 0;
@@ -23141,7 +23153,8 @@ var PROVIDERS = [
23141
23153
  "anthropic",
23142
23154
  "google",
23143
23155
  "openai",
23144
- "openrouter"
23156
+ "openrouter",
23157
+ "xai"
23145
23158
  ];
23146
23159
  var MODELS = {
23147
23160
  anthropic: {
@@ -23157,19 +23170,24 @@ var MODELS = {
23157
23170
  },
23158
23171
  openrouter: {
23159
23172
  kimi: "moonshotai/kimi-k2.6"
23173
+ },
23174
+ xai: {
23175
+ grok: "grok-4"
23160
23176
  }
23161
23177
  };
23162
23178
  var DEFAULT_MODELS = {
23163
23179
  anthropic: MODELS.anthropic.sonnet,
23164
23180
  google: MODELS.google.gemini,
23165
23181
  openai: MODELS.openai.gpt,
23166
- openrouter: MODELS.openrouter.kimi
23182
+ openrouter: MODELS.openrouter.kimi,
23183
+ xai: MODELS.xai.grok
23167
23184
  };
23168
23185
  var LIGHT_MODELS = {
23169
23186
  anthropic: "claude-haiku-4-5",
23170
23187
  google: "gemini-2.0-flash",
23171
23188
  openai: "gpt-4.1-mini",
23172
- openrouter: "moonshotai/kimi-k2.6"
23189
+ openrouter: "moonshotai/kimi-k2.6",
23190
+ xai: "grok-4-fast-non-reasoning"
23173
23191
  };
23174
23192
  function getLightModelForProvider(provider) {
23175
23193
  return LIGHT_MODELS[provider];
@@ -23204,6 +23222,8 @@ function getProviderForModel(modelName) {
23204
23222
  return "google";
23205
23223
  case "gpt":
23206
23224
  return "openai";
23225
+ case "grok":
23226
+ return "xai";
23207
23227
  // Full model IDs
23208
23228
  case "claude-sonnet-5":
23209
23229
  case "claude-opus-4-6":
@@ -23216,24 +23236,34 @@ function getProviderForModel(modelName) {
23216
23236
  case "gpt-4.1-mini":
23217
23237
  return "openai";
23218
23238
  default:
23239
+ if (typeof modelName === "string" && modelName.toLowerCase().startsWith("grok")) {
23240
+ return "xai";
23241
+ }
23219
23242
  if (process.env.LLM_PROVIDER && PROVIDERS.includes(process.env.LLM_PROVIDER)) {
23220
23243
  return process.env.LLM_PROVIDER;
23221
23244
  }
23222
23245
  return "anthropic";
23223
23246
  }
23224
23247
  }
23248
+ function normalizeApiKey(key) {
23249
+ if (typeof key !== "string") return void 0;
23250
+ const trimmed = key.trim();
23251
+ return trimmed.length > 0 ? trimmed : void 0;
23252
+ }
23225
23253
  function lookupApiKeyForProvider(provider) {
23226
23254
  switch (provider) {
23227
23255
  case "anthropic":
23228
- return process.env.ANTHROPIC_API_KEY;
23256
+ return normalizeApiKey(process.env.ANTHROPIC_API_KEY);
23229
23257
  case "google":
23230
- return process.env.GOOGLE_API_KEY;
23258
+ return normalizeApiKey(process.env.GOOGLE_API_KEY);
23231
23259
  case "openai":
23232
- return process.env.OPENAI_API_KEY;
23260
+ return normalizeApiKey(process.env.OPENAI_API_KEY);
23233
23261
  case "openrouter":
23234
- return process.env.OPENROUTER_API_KEY;
23262
+ return normalizeApiKey(process.env.OPENROUTER_API_KEY);
23263
+ case "xai":
23264
+ return normalizeApiKey(process.env.XAI_API_KEY);
23235
23265
  case "claude_code":
23236
- return process.env.CLAUDE_CODE_API_KEY;
23266
+ return normalizeApiKey(process.env.CLAUDE_CODE_API_KEY);
23237
23267
  default:
23238
23268
  return void 0;
23239
23269
  }
@@ -23248,6 +23278,73 @@ function getApiKeyForProvider(provider) {
23248
23278
  }
23249
23279
  return apiKey;
23250
23280
  }
23281
+ var DEFAULT_LLM_HTTP_TIMEOUT_MS = parseInt(process.env.LLM_HTTP_TIMEOUT_MS || "", 10) || 3e5;
23282
+ var LLM_HTTP_TIMEOUT_RETRIES = (() => {
23283
+ const parsed = parseInt(process.env.LLM_HTTP_TIMEOUT_RETRIES || "", 10);
23284
+ return Number.isFinite(parsed) && parsed >= 0 ? parsed : 2;
23285
+ })();
23286
+ function combineSignals(signals) {
23287
+ const live = signals.filter((s) => !!s);
23288
+ if (live.length === 0) return void 0;
23289
+ if (live.length === 1) return live[0];
23290
+ if (typeof AbortSignal.any === "function") {
23291
+ return AbortSignal.any(live);
23292
+ }
23293
+ const ctrl = new AbortController();
23294
+ if (live.some((s) => s.aborted)) {
23295
+ ctrl.abort();
23296
+ return ctrl.signal;
23297
+ }
23298
+ const abort = () => {
23299
+ try {
23300
+ ctrl.abort();
23301
+ } catch (_) {
23302
+ }
23303
+ };
23304
+ for (const s of live) s.addEventListener("abort", abort, { once: true });
23305
+ return ctrl.signal;
23306
+ }
23307
+ function buildTimeoutFetch(timeoutMs, runSignal) {
23308
+ return async (input, init) => {
23309
+ const url = typeof input === "string" ? input : input.url;
23310
+ const sdkSignal = init?.signal;
23311
+ const canResend = (typeof input === "string" || input instanceof URL) && (init?.body == null || typeof init.body === "string");
23312
+ const maxAttempts = canResend ? 1 + LLM_HTTP_TIMEOUT_RETRIES : 1;
23313
+ for (let attempt = 1; ; attempt++) {
23314
+ const startMs = Date.now();
23315
+ const timeoutCtrl = new AbortController();
23316
+ let timer = setTimeout(() => {
23317
+ timeoutCtrl.abort();
23318
+ }, timeoutMs);
23319
+ const clearTimer = () => {
23320
+ if (timer !== void 0) {
23321
+ clearTimeout(timer);
23322
+ timer = void 0;
23323
+ }
23324
+ };
23325
+ const combinedSignal = combineSignals([
23326
+ sdkSignal,
23327
+ runSignal,
23328
+ timeoutCtrl.signal
23329
+ ]);
23330
+ try {
23331
+ const response = await fetch(input, { ...init, signal: combinedSignal });
23332
+ clearTimer();
23333
+ return response;
23334
+ } catch (err) {
23335
+ clearTimer();
23336
+ const elapsedMs = Date.now() - startMs;
23337
+ const isTimeout = timeoutCtrl.signal.aborted && !runSignal?.aborted && !sdkSignal?.aborted;
23338
+ const reason = isTimeout ? "timeout" : "aborted";
23339
+ console.warn(
23340
+ `[llm-fetch] ${reason} after ${elapsedMs}ms (attempt ${attempt}/${maxAttempts}): ${url} \u2014 ${err?.message ?? String(err)}`
23341
+ );
23342
+ if (isTimeout && attempt < maxAttempts) continue;
23343
+ throw err;
23344
+ }
23345
+ }
23346
+ };
23347
+ }
23251
23348
  function getModelForProvider(provider, modelName) {
23252
23349
  const model = MODELS[provider][modelName];
23253
23350
  if (!model) {
@@ -23257,22 +23354,27 @@ function getModelForProvider(provider, modelName) {
23257
23354
  }
23258
23355
  return model;
23259
23356
  }
23260
- function getModelDetails(modelName, apiKeyIn, baseUrl, headers) {
23357
+ function getModelDetails(modelName, apiKeyIn, baseUrl, headers, abortSignal, timeoutMs) {
23261
23358
  const provider = getProviderForModel(modelName);
23262
- const apiKey = apiKeyIn || getApiKeyForProvider(provider);
23359
+ const callerKey = normalizeApiKey(apiKeyIn);
23360
+ const apiKey = callerKey || getApiKeyForProvider(provider);
23263
23361
  console.log("===> getModelDetails", {
23264
23362
  provider,
23265
23363
  modelName: modelName || "(default)",
23266
- keySource: apiKeyIn ? "request body" : "env var",
23364
+ keySource: callerKey ? "request body" : "env var",
23267
23365
  apiKeyPrefix: apiKey ? apiKey.slice(0, 12) + "..." : "(missing)",
23268
23366
  baseUrl: baseUrl || "(default)",
23269
- headerKeys: headers ? Object.keys(headers) : []
23367
+ headerKeys: headers ? Object.keys(headers) : [],
23368
+ hasAbortSignal: !!abortSignal,
23369
+ timeoutMs: timeoutMs ?? DEFAULT_LLM_HTTP_TIMEOUT_MS
23270
23370
  });
23271
23371
  const model = getModel(provider, {
23272
23372
  modelName,
23273
23373
  apiKey,
23274
23374
  baseUrl,
23275
- headers
23375
+ headers,
23376
+ abortSignal,
23377
+ timeoutMs
23276
23378
  });
23277
23379
  let modelId;
23278
23380
  if (modelName && modelName.includes("/")) {
@@ -23295,7 +23397,7 @@ function getModel(provider, opts) {
23295
23397
  if (typeof opts === "string") {
23296
23398
  opts = { apiKey: opts };
23297
23399
  }
23298
- const apiKey = opts?.apiKey || getApiKeyForProvider(provider);
23400
+ const apiKey = normalizeApiKey(opts?.apiKey) || getApiKeyForProvider(provider);
23299
23401
  let modelId;
23300
23402
  if (opts?.modelName && opts.modelName.includes("/")) {
23301
23403
  const parts = opts.modelName.split("/");
@@ -23311,7 +23413,8 @@ function getModel(provider, opts) {
23311
23413
  "haiku",
23312
23414
  "gemini",
23313
23415
  "gpt",
23314
- "kimi"
23416
+ "kimi",
23417
+ "grok"
23315
23418
  ];
23316
23419
  if (knownShortcuts.includes(opts.modelName)) {
23317
23420
  modelId = getModelForProvider(provider, opts.modelName);
@@ -23335,12 +23438,17 @@ function getModel(provider, opts) {
23335
23438
  if (extraHeaders) {
23336
23439
  console.log(`[headers] attaching ${Object.keys(extraHeaders).length} custom header(s) to ${provider} client`);
23337
23440
  }
23441
+ const timeoutFetch = buildTimeoutFetch(
23442
+ opts?.timeoutMs ?? DEFAULT_LLM_HTTP_TIMEOUT_MS,
23443
+ opts?.abortSignal
23444
+ );
23338
23445
  switch (provider) {
23339
23446
  case "anthropic":
23340
23447
  const anthropic2 = createAnthropic({
23341
23448
  apiKey,
23342
23449
  ...baseURL && { baseURL },
23343
- ...extraHeaders && { headers: extraHeaders }
23450
+ ...extraHeaders && { headers: extraHeaders },
23451
+ fetch: timeoutFetch
23344
23452
  });
23345
23453
  return anthropic2(modelId);
23346
23454
  case "google": {
@@ -23353,13 +23461,15 @@ function getModel(provider, opts) {
23353
23461
  const googleCompat = createOpenAI({
23354
23462
  apiKey,
23355
23463
  baseURL: openaiCompatBase,
23356
- ...extraHeaders && { headers: extraHeaders }
23464
+ ...extraHeaders && { headers: extraHeaders },
23465
+ fetch: timeoutFetch
23357
23466
  });
23358
23467
  return googleCompat.chat(`gemini/${modelId}`);
23359
23468
  }
23360
23469
  const google2 = createGoogleGenerativeAI({
23361
23470
  apiKey,
23362
- ...extraHeaders && { headers: extraHeaders }
23471
+ ...extraHeaders && { headers: extraHeaders },
23472
+ fetch: timeoutFetch
23363
23473
  });
23364
23474
  return google2(modelId);
23365
23475
  }
@@ -23367,14 +23477,16 @@ function getModel(provider, opts) {
23367
23477
  const openai2 = createOpenAI({
23368
23478
  apiKey,
23369
23479
  ...baseURL && { baseURL },
23370
- ...extraHeaders && { headers: extraHeaders }
23480
+ ...extraHeaders && { headers: extraHeaders },
23481
+ fetch: timeoutFetch
23371
23482
  });
23372
23483
  return openai2(modelId);
23373
23484
  case "openrouter": {
23374
23485
  const openrouter = (0, import_ai_sdk_provider.createOpenRouter)({
23375
23486
  apiKey,
23376
23487
  ...baseURL && { baseURL },
23377
- ...extraHeaders && { headers: extraHeaders }
23488
+ ...extraHeaders && { headers: extraHeaders },
23489
+ fetch: timeoutFetch
23378
23490
  });
23379
23491
  const isMoonshot = modelId.startsWith("moonshotai/") || modelId.toLowerCase().includes("kimi");
23380
23492
  const settings = {
@@ -23383,6 +23495,23 @@ function getModel(provider, opts) {
23383
23495
  };
23384
23496
  return openrouter(modelId, settings);
23385
23497
  }
23498
+ case "xai": {
23499
+ if (baseURL) {
23500
+ const xaiCompat = createOpenAI({
23501
+ apiKey,
23502
+ baseURL,
23503
+ ...extraHeaders && { headers: extraHeaders },
23504
+ fetch: timeoutFetch
23505
+ });
23506
+ return xaiCompat.chat(`xai/${modelId}`);
23507
+ }
23508
+ const xai = (0, import_xai.createXai)({
23509
+ apiKey,
23510
+ ...extraHeaders && { headers: extraHeaders },
23511
+ fetch: timeoutFetch
23512
+ });
23513
+ return xai(modelId);
23514
+ }
23386
23515
  // case "claude_code":
23387
23516
  // try {
23388
23517
  // const customProvider = createClaudeCode({
@@ -23417,22 +23546,46 @@ var MODEL_CONTEXT_LIMITS = {
23417
23546
  "gemini-3-pro-preview": 1e6,
23418
23547
  "gemini-2.0-flash": 1e6,
23419
23548
  // OpenAI
23420
- "gpt-5": 128e3,
23549
+ "gpt-5": 4e5,
23550
+ "gpt-5.5": 105e4,
23551
+ "gpt-5.6-terra": 105e4,
23552
+ "gpt-5.6-luna": 105e4,
23553
+ "gpt-5.6-sol": 105e4,
23421
23554
  "gpt-4.1-mini": 1e6,
23422
23555
  // OpenRouter — values from the OpenRouter model catalog
23423
23556
  // (https://openrouter.ai/api/v1/models, context_length).
23557
+ "stealth/ox-alpha": 1048576,
23558
+ "openai/gpt-5": 4e5,
23559
+ "openai/gpt-5.5": 105e4,
23560
+ "openai/gpt-5.6-terra": 105e4,
23561
+ "openai/gpt-5.6-luna": 105e4,
23562
+ "openai/gpt-5.6-sol": 105e4,
23424
23563
  "moonshotai/kimi-k3": 1048576,
23425
23564
  "moonshotai/kimi-k2.7-code": 262144,
23426
23565
  "moonshotai/kimi-k2.6": 262144,
23427
23566
  "moonshotai/kimi-k2.5": 262144,
23428
23567
  "moonshotai/kimi-k2-thinking": 262144,
23429
- "moonshotai/kimi-k2": 131072
23568
+ "moonshotai/kimi-k2": 131072,
23569
+ // xAI (and the same models via OpenRouter as x-ai/...). Getting these
23570
+ // right matters beyond display: contextLimit drives truncateOldToolResults,
23571
+ // and premature truncation rewrites old messages — which invalidates Grok's
23572
+ // automatic prefix cache on every subsequent step.
23573
+ "grok-4": 256e3,
23574
+ "grok-4-fast": 2e6,
23575
+ "grok-4-fast-reasoning": 2e6,
23576
+ "grok-4-fast-non-reasoning": 2e6,
23577
+ "grok-code-fast-1": 256e3,
23578
+ "x-ai/grok-4": 256e3,
23579
+ "x-ai/grok-4-fast": 2e6,
23580
+ "x-ai/grok-code-fast-1": 256e3
23430
23581
  };
23431
23582
  var DEFAULT_CONTEXT_LIMITS = {
23432
23583
  anthropic: 1e6,
23433
23584
  google: 1e6,
23434
- openai: 128e3,
23435
- openrouter: 128e3
23585
+ // gpt-5.x models are all 400k+; only legacy chat models are smaller
23586
+ openai: 4e5,
23587
+ openrouter: 256e3,
23588
+ xai: 256e3
23436
23589
  };
23437
23590
  var FALLBACK_CONTEXT_LIMIT = 128e3;
23438
23591
  function getContextLimit(modelId, provider) {
@@ -23456,6 +23609,15 @@ var TOKEN_PRICING = {
23456
23609
  openrouter: {
23457
23610
  inputTokenPrice: 0.6,
23458
23611
  outputTokenPrice: 3
23612
+ },
23613
+ // grok-4 rates. cacheReadPrice matters: computeSessionCost bills cache
23614
+ // reads at full input price when it's absent, and Grok discounts cached
23615
+ // prompt tokens 4x. (Grok has no cache-write charge — writes are billed
23616
+ // as ordinary input, so no cacheWritePrice here.)
23617
+ xai: {
23618
+ inputTokenPrice: 3,
23619
+ outputTokenPrice: 15,
23620
+ cacheReadPrice: 0.75
23459
23621
  }
23460
23622
  };
23461
23623
  function getTokenPricing(provider) {
@@ -23542,6 +23704,10 @@ function getProviderOptions(provider, thinkingSpeed, modelName) {
23542
23704
  return {
23543
23705
  openrouter: { usage: { include: true } }
23544
23706
  };
23707
+ case "xai":
23708
+ return {
23709
+ xai: {}
23710
+ };
23545
23711
  default:
23546
23712
  throw new Error(`Unsupported provider: ${provider}`);
23547
23713
  }
@@ -23554,10 +23720,11 @@ function resolveLLMConfig(opts) {
23554
23720
  providerHint = void 0;
23555
23721
  }
23556
23722
  const provider = modelName ? getProviderForModel(modelName) : providerHint || process.env.LLM_PROVIDER || getProviderForModel();
23723
+ const callerKey = normalizeApiKey(opts?.apiKey);
23724
+ const apiKey = callerKey || getApiKeyForProvider(provider);
23557
23725
  console.log(
23558
- `[resolveLLMConfig] provider=${provider} modelName=${modelName || "(default)"} light=${!!opts?.light}`
23726
+ `[resolveLLMConfig] provider=${provider} modelName=${modelName || "(default)"} light=${!!opts?.light} keySource=${callerKey ? "request body" : "env var"} apiKeyPrefix=${apiKey.slice(0, 8)}...`
23559
23727
  );
23560
- const apiKey = opts?.apiKey || getApiKeyForProvider(provider);
23561
23728
  let effectiveModelName = modelName;
23562
23729
  if (!effectiveModelName && opts?.light) {
23563
23730
  effectiveModelName = getLightModelForProvider(provider);
@@ -23596,7 +23763,7 @@ function withLegacyUsage(usage) {
23596
23763
  }
23597
23764
  function normalizeUsage(raw) {
23598
23765
  const inputTokens = tokenCount(raw?.inputTokens);
23599
- const cache_read = raw?.cache_read !== void 0 ? tokenCount(raw.cache_read) : tokenCount(raw?.inputTokenDetails?.cacheReadTokens);
23766
+ const cache_read = raw?.cache_read !== void 0 ? tokenCount(raw.cache_read) : tokenCount(raw?.inputTokenDetails?.cacheReadTokens) || tokenCount(raw?.cachedInputTokens);
23600
23767
  const cache_write = raw?.cache_write !== void 0 ? tokenCount(raw.cache_write) : tokenCount(raw?.inputTokenDetails?.cacheWriteTokens);
23601
23768
  const input = raw?.input !== void 0 ? tokenCount(raw.input) : raw?.inputTokenDetails?.noCacheTokens !== void 0 ? tokenCount(raw.inputTokenDetails.noCacheTokens) : Math.max(inputTokens - cache_read - cache_write, 0);
23602
23769
  const output = raw?.output !== void 0 ? tokenCount(raw.output) : tokenCount(raw?.outputTokens);
@@ -23737,8 +23904,211 @@ var OUTRO = `
23737
23904
  Please write all the necessary code to fully implement the feature end-to-end. Do not make mock data or example placeholders!!!
23738
23905
  `;
23739
23906
 
23907
+ // src/search.ts
23908
+ var import_ai2 = require("ai");
23909
+ var import_zod = require("zod");
23910
+ var WEB_SEARCH_TOOL_NAME = "web_search";
23911
+ var EXA_SEARCH_URL = "https://api.exa.ai/search";
23912
+ var DEFAULT_MAX_USES = 3;
23913
+ var DEFAULT_NUM_RESULTS = 5;
23914
+ var DEFAULT_MAX_CHARACTERS = 4e3;
23915
+ function getSearchApiKey() {
23916
+ return normalizeApiKey(process.env.EXA_API_KEY);
23917
+ }
23918
+ function hasSearchApiKey() {
23919
+ return !!getSearchApiKey();
23920
+ }
23921
+ function resolveSearchBackend(provider) {
23922
+ return provider === "anthropic" ? "anthropic" : "exa";
23923
+ }
23924
+ async function searchWeb(query, opts = {}) {
23925
+ const apiKey = normalizeApiKey(opts.apiKey) || getSearchApiKey();
23926
+ if (!apiKey) throw new Error("EXA_API_KEY not configured");
23927
+ const res = await fetch(EXA_SEARCH_URL, {
23928
+ method: "POST",
23929
+ headers: { "content-type": "application/json", "x-api-key": apiKey },
23930
+ signal: opts.abortSignal,
23931
+ body: JSON.stringify({
23932
+ query,
23933
+ type: "auto",
23934
+ numResults: opts.numResults ?? DEFAULT_NUM_RESULTS,
23935
+ contents: {
23936
+ text: { maxCharacters: opts.maxCharacters ?? DEFAULT_MAX_CHARACTERS }
23937
+ },
23938
+ ...opts.allowedDomains?.length ? { includeDomains: opts.allowedDomains } : {},
23939
+ ...opts.blockedDomains?.length ? { excludeDomains: opts.blockedDomains } : {}
23940
+ })
23941
+ });
23942
+ if (!res.ok) {
23943
+ const body = await res.text().catch(() => "");
23944
+ throw new Error(`Exa search failed (${res.status}): ${body.slice(0, 300)}`);
23945
+ }
23946
+ const json = await res.json();
23947
+ const results = Array.isArray(json.results) ? json.results : [];
23948
+ return results.filter((r) => typeof r.url === "string").map((r) => ({
23949
+ url: r.url,
23950
+ title: r.title ?? null,
23951
+ pageAge: r.publishedDate ?? null,
23952
+ ...r.text ? { text: r.text } : {},
23953
+ type: "web_search_result"
23954
+ }));
23955
+ }
23956
+ function citationSnippet(backend) {
23957
+ const indexRule = backend === "exa" ? "Every result carries an `index` field. Use that number exactly as returned \u2014 never invent or renumber one. Indices are global across all searches in this conversation." : "Use the index Anthropic assigns to the search result you are citing.";
23958
+ return `
23959
+
23960
+ ## Citing web search results
23961
+ When you use information from a \`${WEB_SEARCH_TOOL_NAME}\` result, cite it inline as \`<cite index="N">anchor text</cite>\`. ${indexRule}
23962
+
23963
+ The anchor text is REQUIRED and becomes the link text \u2014 put the words being sourced inside the tag, e.g. \`<cite index="3">runs on the Lightning Network</cite>\`. Never emit an empty tag like \`<cite index="3"></cite>\`; a trailing marker with no anchor produces a broken link.
23964
+
23965
+ Do NOT name sources parenthetically (e.g. \`(Bitcoin Magazine)\`) or as bare URLs \u2014 observed models fall back to that style and it produces no link. Every source reference must be a cite tag.`;
23966
+ }
23967
+ function createWebSearch(opts) {
23968
+ const results = [];
23969
+ const backend = opts.backend ?? resolveSearchBackend(opts.provider);
23970
+ const maxUses = opts.maxUses ?? DEFAULT_MAX_USES;
23971
+ if (backend === "anthropic") {
23972
+ const apiKey = normalizeApiKey(opts.apiKey) || normalizeApiKey(process.env.ANTHROPIC_API_KEY);
23973
+ if (!apiKey) {
23974
+ return emptyHandle(results);
23975
+ }
23976
+ const baseURL = getGatewayBaseURL("anthropic");
23977
+ const anthropic2 = createAnthropic({ apiKey, ...baseURL && { baseURL } });
23978
+ return {
23979
+ tool: anthropic2.tools.webSearch_20250305({
23980
+ maxUses,
23981
+ ...opts.allowedDomains?.length ? { allowedDomains: opts.allowedDomains } : {},
23982
+ ...opts.blockedDomains?.length ? { blockedDomains: opts.blockedDomains } : {}
23983
+ }),
23984
+ backend,
23985
+ native: true,
23986
+ results,
23987
+ capture: (stepContent) => captureNativeResults(stepContent, results),
23988
+ promptSnippet: opts.citations ? citationSnippet("anthropic") : "",
23989
+ formatOutput: (markdown) => formatOutput(markdown, results, !!opts.citations)
23990
+ };
23991
+ }
23992
+ const searchApiKey = normalizeApiKey(opts.searchApiKey) || getSearchApiKey();
23993
+ if (!searchApiKey) {
23994
+ return emptyHandle(results);
23995
+ }
23996
+ let uses = 0;
23997
+ return {
23998
+ tool: (0, import_ai2.tool)({
23999
+ description: "Search the web for current information. Returns numbered results with page text. Prefer one specific query per call over broad multi-topic queries.",
24000
+ inputSchema: import_zod.z.object({
24001
+ query: import_zod.z.string().describe("The search query."),
24002
+ num_results: import_zod.z.number().int().min(1).max(10).optional().describe("How many results to return. Default 5.")
24003
+ }),
24004
+ execute: async ({
24005
+ query,
24006
+ num_results
24007
+ }) => {
24008
+ if (uses >= maxUses) {
24009
+ return {
24010
+ error: `web_search budget exhausted (${maxUses} calls). Answer with what you have.`
24011
+ };
24012
+ }
24013
+ uses++;
24014
+ try {
24015
+ const hits = await searchWeb(query, {
24016
+ numResults: num_results ?? opts.numResults,
24017
+ maxCharacters: opts.maxCharacters,
24018
+ allowedDomains: opts.allowedDomains,
24019
+ blockedDomains: opts.blockedDomains,
24020
+ apiKey: searchApiKey,
24021
+ abortSignal: opts.abortSignal
24022
+ });
24023
+ return hits.map((hit) => {
24024
+ const indexed = { ...hit, index: results.length + 1 };
24025
+ results.push(indexed);
24026
+ return indexed;
24027
+ });
24028
+ } catch (err) {
24029
+ return {
24030
+ error: `Search failed: ${err instanceof Error ? err.message : String(err)}`
24031
+ };
24032
+ }
24033
+ }
24034
+ }),
24035
+ backend,
24036
+ native: false,
24037
+ results,
24038
+ // Exa results are appended by `execute` above; walking the step
24039
+ // would double-count them.
24040
+ capture: () => {
24041
+ },
24042
+ promptSnippet: opts.citations ? citationSnippet("exa") : "",
24043
+ formatOutput: (markdown) => formatOutput(markdown, results, !!opts.citations)
24044
+ };
24045
+ }
24046
+ function emptyHandle(results) {
24047
+ return {
24048
+ tool: void 0,
24049
+ backend: void 0,
24050
+ native: false,
24051
+ results,
24052
+ capture: () => {
24053
+ },
24054
+ promptSnippet: "",
24055
+ formatOutput: (markdown) => formatOutput(markdown, results, false)
24056
+ };
24057
+ }
24058
+ function formatOutput(markdown, results, citations) {
24059
+ return citations ? linkifyCitations(markdown, results) : { content: stripCitations(markdown), converted: 0, skipped: 0 };
24060
+ }
24061
+ function captureNativeResults(stepContent, target) {
24062
+ if (!Array.isArray(stepContent)) return;
24063
+ for (const content of stepContent) {
24064
+ if (content?.type !== "tool-result") continue;
24065
+ if (content?.toolName !== WEB_SEARCH_TOOL_NAME) continue;
24066
+ const body = content.output ?? content.result ?? null;
24067
+ if (!Array.isArray(body)) continue;
24068
+ for (const r of body) {
24069
+ if (r && typeof r === "object" && typeof r.url === "string") {
24070
+ target.push({
24071
+ url: r.url,
24072
+ title: r.title ?? null,
24073
+ pageAge: r.pageAge ?? null,
24074
+ // Assigned here too, so `results` is shape-identical to the
24075
+ // Exa path. Anthropic's model derives its own indices from
24076
+ // the same ordering, so these agree by construction.
24077
+ index: target.length + 1,
24078
+ type: "web_search_result"
24079
+ });
24080
+ }
24081
+ }
24082
+ }
24083
+ }
24084
+ function stripCitations(markdown) {
24085
+ return markdown.replace(/[ \t]*<cite\b[^>]*>\s*<\/cite>/g, "").replace(/<cite\b[^>]*>(.*?)<\/cite>/g, "$1").replace(/<\/?cite\b[^>]*>/g, "");
24086
+ }
24087
+ function linkifyCitations(markdown, results) {
24088
+ let converted = 0;
24089
+ let skipped = 0;
24090
+ const content = markdown.replace(
24091
+ /<cite index="(\d+)(?:-\d+(?:,\d+-\d+)*)?">(.*?)<\/cite>/g,
24092
+ (_match, indexStr, anchor) => {
24093
+ const index = parseInt(indexStr, 10);
24094
+ const hit = results[index - 1];
24095
+ if (!hit || typeof hit.url !== "string") {
24096
+ skipped++;
24097
+ return anchor;
24098
+ }
24099
+ converted++;
24100
+ const text = anchor.trim() ? anchor.replace(/\]/g, "\\]") : `[${index}]`;
24101
+ return `[${text}](${hit.url})`;
24102
+ }
24103
+ );
24104
+ return { content, converted, skipped };
24105
+ }
24106
+
23740
24107
  // src/tools.ts
23741
24108
  function getProviderTool(provider, apiKey, toolName) {
24109
+ if (toolName === "webSearch") {
24110
+ return createWebSearch({ provider, apiKey }).tool;
24111
+ }
23742
24112
  switch (provider) {
23743
24113
  case "anthropic":
23744
24114
  return getAnthropicTool(apiKey, toolName);
@@ -23795,12 +24165,15 @@ function consoleLogger(name19) {
23795
24165
  OUTRO,
23796
24166
  PROVIDERS,
23797
24167
  SYSTEM,
24168
+ WEB_SEARCH_TOOL_NAME,
23798
24169
  addUsage,
23799
24170
  callGenerateObject,
23800
24171
  callGenerateText,
23801
24172
  callModel,
24173
+ captureNativeResults,
23802
24174
  computeSessionCost,
23803
24175
  consoleLogger,
24176
+ createWebSearch,
23804
24177
  emptyUsage,
23805
24178
  gatewayEnvForProviders,
23806
24179
  gatewayUrlFor,
@@ -23814,12 +24187,19 @@ function consoleLogger(name19) {
23814
24187
  getProviderForModel,
23815
24188
  getProviderOptions,
23816
24189
  getProviderTool,
24190
+ getSearchApiKey,
23817
24191
  getTokenPricing,
23818
24192
  hasApiKeyForProvider,
24193
+ hasSearchApiKey,
24194
+ linkifyCitations,
23819
24195
  loadModelPricing,
24196
+ normalizeApiKey,
23820
24197
  normalizeCallerBaseURL,
23821
24198
  normalizeUsage,
23822
24199
  resolveLLMConfig,
24200
+ resolveSearchBackend,
24201
+ searchWeb,
24202
+ stripCitations,
23823
24203
  withLegacyUsage,
23824
24204
  withProviderCacheUsage
23825
24205
  });