aieo 0.1.34 → 0.1.35

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
@@ -58,6 +58,7 @@ __export(index_exports, {
58
58
  getTokenPricing: () => getTokenPricing,
59
59
  hasApiKeyForProvider: () => hasApiKeyForProvider,
60
60
  loadModelPricing: () => loadModelPricing,
61
+ normalizeApiKey: () => normalizeApiKey,
61
62
  normalizeCallerBaseURL: () => normalizeCallerBaseURL,
62
63
  normalizeUsage: () => normalizeUsage,
63
64
  resolveLLMConfig: () => resolveLLMConfig,
@@ -193,7 +194,7 @@ var ConversationStorage = class {
193
194
  }
194
195
  };
195
196
 
196
- // ../../node_modules/@ai-sdk/provider/dist/index.mjs
197
+ // ../../node_modules/@ai-sdk/anthropic/node_modules/@ai-sdk/provider/dist/index.mjs
197
198
  var marker = "vercel.ai.error";
198
199
  var symbol = Symbol.for(marker);
199
200
  var _a;
@@ -539,7 +540,7 @@ var UnsupportedFunctionalityError = class extends (_b14 = AISDKError, _a14 = sym
539
540
  }
540
541
  };
541
542
 
542
- // ../../node_modules/@ai-sdk/provider-utils/dist/index.mjs
543
+ // ../../node_modules/@ai-sdk/anthropic/node_modules/@ai-sdk/provider-utils/dist/index.mjs
543
544
  var z4 = __toESM(require("zod/v4"), 1);
544
545
  var import_v3 = require("zod/v3");
545
546
  var import_v32 = require("zod/v3");
@@ -734,7 +735,7 @@ var EventSourceParserStream = class extends TransformStream {
734
735
  }
735
736
  };
736
737
 
737
- // ../../node_modules/@ai-sdk/provider-utils/dist/index.mjs
738
+ // ../../node_modules/@ai-sdk/anthropic/node_modules/@ai-sdk/provider-utils/dist/index.mjs
738
739
  function combineHeaders(...headers) {
739
740
  return headers.reduce(
740
741
  (combinedHeaders, currentHeaders) => ({
@@ -23104,13 +23105,15 @@ function createOpenAI(options = {}) {
23104
23105
  var openai = createOpenAI();
23105
23106
 
23106
23107
  // src/provider.ts
23108
+ var import_xai = require("@ai-sdk/xai");
23107
23109
  var import_ai_sdk_provider = require("@openrouter/ai-sdk-provider");
23108
23110
  var LLM_GATEWAY_URL = process.env.LLM_GATEWAY_URL?.replace(/\/$/, "");
23109
23111
  var GATEWAY_PATHS = {
23110
23112
  anthropic: "/anthropic/v1",
23111
23113
  google: "/genai/v1beta",
23112
23114
  openai: "/openai/v1",
23113
- openrouter: "/openai/v1"
23115
+ openrouter: "/openai/v1",
23116
+ xai: "/openai/v1"
23114
23117
  };
23115
23118
  function getGatewayBaseURL(provider) {
23116
23119
  return LLM_GATEWAY_URL ? `${LLM_GATEWAY_URL}${GATEWAY_PATHS[provider]}` : void 0;
@@ -23141,7 +23144,8 @@ var PROVIDERS = [
23141
23144
  "anthropic",
23142
23145
  "google",
23143
23146
  "openai",
23144
- "openrouter"
23147
+ "openrouter",
23148
+ "xai"
23145
23149
  ];
23146
23150
  var MODELS = {
23147
23151
  anthropic: {
@@ -23157,19 +23161,24 @@ var MODELS = {
23157
23161
  },
23158
23162
  openrouter: {
23159
23163
  kimi: "moonshotai/kimi-k2.6"
23164
+ },
23165
+ xai: {
23166
+ grok: "grok-4"
23160
23167
  }
23161
23168
  };
23162
23169
  var DEFAULT_MODELS = {
23163
23170
  anthropic: MODELS.anthropic.sonnet,
23164
23171
  google: MODELS.google.gemini,
23165
23172
  openai: MODELS.openai.gpt,
23166
- openrouter: MODELS.openrouter.kimi
23173
+ openrouter: MODELS.openrouter.kimi,
23174
+ xai: MODELS.xai.grok
23167
23175
  };
23168
23176
  var LIGHT_MODELS = {
23169
23177
  anthropic: "claude-haiku-4-5",
23170
23178
  google: "gemini-2.0-flash",
23171
23179
  openai: "gpt-4.1-mini",
23172
- openrouter: "moonshotai/kimi-k2.6"
23180
+ openrouter: "moonshotai/kimi-k2.6",
23181
+ xai: "grok-4-fast-non-reasoning"
23173
23182
  };
23174
23183
  function getLightModelForProvider(provider) {
23175
23184
  return LIGHT_MODELS[provider];
@@ -23204,6 +23213,8 @@ function getProviderForModel(modelName) {
23204
23213
  return "google";
23205
23214
  case "gpt":
23206
23215
  return "openai";
23216
+ case "grok":
23217
+ return "xai";
23207
23218
  // Full model IDs
23208
23219
  case "claude-sonnet-5":
23209
23220
  case "claude-opus-4-6":
@@ -23216,24 +23227,34 @@ function getProviderForModel(modelName) {
23216
23227
  case "gpt-4.1-mini":
23217
23228
  return "openai";
23218
23229
  default:
23230
+ if (typeof modelName === "string" && modelName.toLowerCase().startsWith("grok")) {
23231
+ return "xai";
23232
+ }
23219
23233
  if (process.env.LLM_PROVIDER && PROVIDERS.includes(process.env.LLM_PROVIDER)) {
23220
23234
  return process.env.LLM_PROVIDER;
23221
23235
  }
23222
23236
  return "anthropic";
23223
23237
  }
23224
23238
  }
23239
+ function normalizeApiKey(key) {
23240
+ if (typeof key !== "string") return void 0;
23241
+ const trimmed = key.trim();
23242
+ return trimmed.length > 0 ? trimmed : void 0;
23243
+ }
23225
23244
  function lookupApiKeyForProvider(provider) {
23226
23245
  switch (provider) {
23227
23246
  case "anthropic":
23228
- return process.env.ANTHROPIC_API_KEY;
23247
+ return normalizeApiKey(process.env.ANTHROPIC_API_KEY);
23229
23248
  case "google":
23230
- return process.env.GOOGLE_API_KEY;
23249
+ return normalizeApiKey(process.env.GOOGLE_API_KEY);
23231
23250
  case "openai":
23232
- return process.env.OPENAI_API_KEY;
23251
+ return normalizeApiKey(process.env.OPENAI_API_KEY);
23233
23252
  case "openrouter":
23234
- return process.env.OPENROUTER_API_KEY;
23253
+ return normalizeApiKey(process.env.OPENROUTER_API_KEY);
23254
+ case "xai":
23255
+ return normalizeApiKey(process.env.XAI_API_KEY);
23235
23256
  case "claude_code":
23236
- return process.env.CLAUDE_CODE_API_KEY;
23257
+ return normalizeApiKey(process.env.CLAUDE_CODE_API_KEY);
23237
23258
  default:
23238
23259
  return void 0;
23239
23260
  }
@@ -23248,6 +23269,73 @@ function getApiKeyForProvider(provider) {
23248
23269
  }
23249
23270
  return apiKey;
23250
23271
  }
23272
+ var DEFAULT_LLM_HTTP_TIMEOUT_MS = parseInt(process.env.LLM_HTTP_TIMEOUT_MS || "", 10) || 3e5;
23273
+ var LLM_HTTP_TIMEOUT_RETRIES = (() => {
23274
+ const parsed = parseInt(process.env.LLM_HTTP_TIMEOUT_RETRIES || "", 10);
23275
+ return Number.isFinite(parsed) && parsed >= 0 ? parsed : 2;
23276
+ })();
23277
+ function combineSignals(signals) {
23278
+ const live = signals.filter((s) => !!s);
23279
+ if (live.length === 0) return void 0;
23280
+ if (live.length === 1) return live[0];
23281
+ if (typeof AbortSignal.any === "function") {
23282
+ return AbortSignal.any(live);
23283
+ }
23284
+ const ctrl = new AbortController();
23285
+ if (live.some((s) => s.aborted)) {
23286
+ ctrl.abort();
23287
+ return ctrl.signal;
23288
+ }
23289
+ const abort = () => {
23290
+ try {
23291
+ ctrl.abort();
23292
+ } catch (_) {
23293
+ }
23294
+ };
23295
+ for (const s of live) s.addEventListener("abort", abort, { once: true });
23296
+ return ctrl.signal;
23297
+ }
23298
+ function buildTimeoutFetch(timeoutMs, runSignal) {
23299
+ return async (input, init) => {
23300
+ const url = typeof input === "string" ? input : input.url;
23301
+ const sdkSignal = init?.signal;
23302
+ const canResend = (typeof input === "string" || input instanceof URL) && (init?.body == null || typeof init.body === "string");
23303
+ const maxAttempts = canResend ? 1 + LLM_HTTP_TIMEOUT_RETRIES : 1;
23304
+ for (let attempt = 1; ; attempt++) {
23305
+ const startMs = Date.now();
23306
+ const timeoutCtrl = new AbortController();
23307
+ let timer = setTimeout(() => {
23308
+ timeoutCtrl.abort();
23309
+ }, timeoutMs);
23310
+ const clearTimer = () => {
23311
+ if (timer !== void 0) {
23312
+ clearTimeout(timer);
23313
+ timer = void 0;
23314
+ }
23315
+ };
23316
+ const combinedSignal = combineSignals([
23317
+ sdkSignal,
23318
+ runSignal,
23319
+ timeoutCtrl.signal
23320
+ ]);
23321
+ try {
23322
+ const response = await fetch(input, { ...init, signal: combinedSignal });
23323
+ clearTimer();
23324
+ return response;
23325
+ } catch (err) {
23326
+ clearTimer();
23327
+ const elapsedMs = Date.now() - startMs;
23328
+ const isTimeout = timeoutCtrl.signal.aborted && !runSignal?.aborted && !sdkSignal?.aborted;
23329
+ const reason = isTimeout ? "timeout" : "aborted";
23330
+ console.warn(
23331
+ `[llm-fetch] ${reason} after ${elapsedMs}ms (attempt ${attempt}/${maxAttempts}): ${url} \u2014 ${err?.message ?? String(err)}`
23332
+ );
23333
+ if (isTimeout && attempt < maxAttempts) continue;
23334
+ throw err;
23335
+ }
23336
+ }
23337
+ };
23338
+ }
23251
23339
  function getModelForProvider(provider, modelName) {
23252
23340
  const model = MODELS[provider][modelName];
23253
23341
  if (!model) {
@@ -23257,22 +23345,27 @@ function getModelForProvider(provider, modelName) {
23257
23345
  }
23258
23346
  return model;
23259
23347
  }
23260
- function getModelDetails(modelName, apiKeyIn, baseUrl, headers) {
23348
+ function getModelDetails(modelName, apiKeyIn, baseUrl, headers, abortSignal, timeoutMs) {
23261
23349
  const provider = getProviderForModel(modelName);
23262
- const apiKey = apiKeyIn || getApiKeyForProvider(provider);
23350
+ const callerKey = normalizeApiKey(apiKeyIn);
23351
+ const apiKey = callerKey || getApiKeyForProvider(provider);
23263
23352
  console.log("===> getModelDetails", {
23264
23353
  provider,
23265
23354
  modelName: modelName || "(default)",
23266
- keySource: apiKeyIn ? "request body" : "env var",
23355
+ keySource: callerKey ? "request body" : "env var",
23267
23356
  apiKeyPrefix: apiKey ? apiKey.slice(0, 12) + "..." : "(missing)",
23268
23357
  baseUrl: baseUrl || "(default)",
23269
- headerKeys: headers ? Object.keys(headers) : []
23358
+ headerKeys: headers ? Object.keys(headers) : [],
23359
+ hasAbortSignal: !!abortSignal,
23360
+ timeoutMs: timeoutMs ?? DEFAULT_LLM_HTTP_TIMEOUT_MS
23270
23361
  });
23271
23362
  const model = getModel(provider, {
23272
23363
  modelName,
23273
23364
  apiKey,
23274
23365
  baseUrl,
23275
- headers
23366
+ headers,
23367
+ abortSignal,
23368
+ timeoutMs
23276
23369
  });
23277
23370
  let modelId;
23278
23371
  if (modelName && modelName.includes("/")) {
@@ -23295,7 +23388,7 @@ function getModel(provider, opts) {
23295
23388
  if (typeof opts === "string") {
23296
23389
  opts = { apiKey: opts };
23297
23390
  }
23298
- const apiKey = opts?.apiKey || getApiKeyForProvider(provider);
23391
+ const apiKey = normalizeApiKey(opts?.apiKey) || getApiKeyForProvider(provider);
23299
23392
  let modelId;
23300
23393
  if (opts?.modelName && opts.modelName.includes("/")) {
23301
23394
  const parts = opts.modelName.split("/");
@@ -23311,7 +23404,8 @@ function getModel(provider, opts) {
23311
23404
  "haiku",
23312
23405
  "gemini",
23313
23406
  "gpt",
23314
- "kimi"
23407
+ "kimi",
23408
+ "grok"
23315
23409
  ];
23316
23410
  if (knownShortcuts.includes(opts.modelName)) {
23317
23411
  modelId = getModelForProvider(provider, opts.modelName);
@@ -23335,12 +23429,17 @@ function getModel(provider, opts) {
23335
23429
  if (extraHeaders) {
23336
23430
  console.log(`[headers] attaching ${Object.keys(extraHeaders).length} custom header(s) to ${provider} client`);
23337
23431
  }
23432
+ const timeoutFetch = buildTimeoutFetch(
23433
+ opts?.timeoutMs ?? DEFAULT_LLM_HTTP_TIMEOUT_MS,
23434
+ opts?.abortSignal
23435
+ );
23338
23436
  switch (provider) {
23339
23437
  case "anthropic":
23340
23438
  const anthropic2 = createAnthropic({
23341
23439
  apiKey,
23342
23440
  ...baseURL && { baseURL },
23343
- ...extraHeaders && { headers: extraHeaders }
23441
+ ...extraHeaders && { headers: extraHeaders },
23442
+ fetch: timeoutFetch
23344
23443
  });
23345
23444
  return anthropic2(modelId);
23346
23445
  case "google": {
@@ -23353,13 +23452,15 @@ function getModel(provider, opts) {
23353
23452
  const googleCompat = createOpenAI({
23354
23453
  apiKey,
23355
23454
  baseURL: openaiCompatBase,
23356
- ...extraHeaders && { headers: extraHeaders }
23455
+ ...extraHeaders && { headers: extraHeaders },
23456
+ fetch: timeoutFetch
23357
23457
  });
23358
23458
  return googleCompat.chat(`gemini/${modelId}`);
23359
23459
  }
23360
23460
  const google2 = createGoogleGenerativeAI({
23361
23461
  apiKey,
23362
- ...extraHeaders && { headers: extraHeaders }
23462
+ ...extraHeaders && { headers: extraHeaders },
23463
+ fetch: timeoutFetch
23363
23464
  });
23364
23465
  return google2(modelId);
23365
23466
  }
@@ -23367,14 +23468,16 @@ function getModel(provider, opts) {
23367
23468
  const openai2 = createOpenAI({
23368
23469
  apiKey,
23369
23470
  ...baseURL && { baseURL },
23370
- ...extraHeaders && { headers: extraHeaders }
23471
+ ...extraHeaders && { headers: extraHeaders },
23472
+ fetch: timeoutFetch
23371
23473
  });
23372
23474
  return openai2(modelId);
23373
23475
  case "openrouter": {
23374
23476
  const openrouter = (0, import_ai_sdk_provider.createOpenRouter)({
23375
23477
  apiKey,
23376
23478
  ...baseURL && { baseURL },
23377
- ...extraHeaders && { headers: extraHeaders }
23479
+ ...extraHeaders && { headers: extraHeaders },
23480
+ fetch: timeoutFetch
23378
23481
  });
23379
23482
  const isMoonshot = modelId.startsWith("moonshotai/") || modelId.toLowerCase().includes("kimi");
23380
23483
  const settings = {
@@ -23383,6 +23486,23 @@ function getModel(provider, opts) {
23383
23486
  };
23384
23487
  return openrouter(modelId, settings);
23385
23488
  }
23489
+ case "xai": {
23490
+ if (baseURL) {
23491
+ const xaiCompat = createOpenAI({
23492
+ apiKey,
23493
+ baseURL,
23494
+ ...extraHeaders && { headers: extraHeaders },
23495
+ fetch: timeoutFetch
23496
+ });
23497
+ return xaiCompat.chat(`xai/${modelId}`);
23498
+ }
23499
+ const xai = (0, import_xai.createXai)({
23500
+ apiKey,
23501
+ ...extraHeaders && { headers: extraHeaders },
23502
+ fetch: timeoutFetch
23503
+ });
23504
+ return xai(modelId);
23505
+ }
23386
23506
  // case "claude_code":
23387
23507
  // try {
23388
23508
  // const customProvider = createClaudeCode({
@@ -23417,22 +23537,46 @@ var MODEL_CONTEXT_LIMITS = {
23417
23537
  "gemini-3-pro-preview": 1e6,
23418
23538
  "gemini-2.0-flash": 1e6,
23419
23539
  // OpenAI
23420
- "gpt-5": 128e3,
23540
+ "gpt-5": 4e5,
23541
+ "gpt-5.5": 105e4,
23542
+ "gpt-5.6-terra": 105e4,
23543
+ "gpt-5.6-luna": 105e4,
23544
+ "gpt-5.6-sol": 105e4,
23421
23545
  "gpt-4.1-mini": 1e6,
23422
23546
  // OpenRouter — values from the OpenRouter model catalog
23423
23547
  // (https://openrouter.ai/api/v1/models, context_length).
23548
+ "stealth/ox-alpha": 1048576,
23549
+ "openai/gpt-5": 4e5,
23550
+ "openai/gpt-5.5": 105e4,
23551
+ "openai/gpt-5.6-terra": 105e4,
23552
+ "openai/gpt-5.6-luna": 105e4,
23553
+ "openai/gpt-5.6-sol": 105e4,
23424
23554
  "moonshotai/kimi-k3": 1048576,
23425
23555
  "moonshotai/kimi-k2.7-code": 262144,
23426
23556
  "moonshotai/kimi-k2.6": 262144,
23427
23557
  "moonshotai/kimi-k2.5": 262144,
23428
23558
  "moonshotai/kimi-k2-thinking": 262144,
23429
- "moonshotai/kimi-k2": 131072
23559
+ "moonshotai/kimi-k2": 131072,
23560
+ // xAI (and the same models via OpenRouter as x-ai/...). Getting these
23561
+ // right matters beyond display: contextLimit drives truncateOldToolResults,
23562
+ // and premature truncation rewrites old messages — which invalidates Grok's
23563
+ // automatic prefix cache on every subsequent step.
23564
+ "grok-4": 256e3,
23565
+ "grok-4-fast": 2e6,
23566
+ "grok-4-fast-reasoning": 2e6,
23567
+ "grok-4-fast-non-reasoning": 2e6,
23568
+ "grok-code-fast-1": 256e3,
23569
+ "x-ai/grok-4": 256e3,
23570
+ "x-ai/grok-4-fast": 2e6,
23571
+ "x-ai/grok-code-fast-1": 256e3
23430
23572
  };
23431
23573
  var DEFAULT_CONTEXT_LIMITS = {
23432
23574
  anthropic: 1e6,
23433
23575
  google: 1e6,
23434
- openai: 128e3,
23435
- openrouter: 128e3
23576
+ // gpt-5.x models are all 400k+; only legacy chat models are smaller
23577
+ openai: 4e5,
23578
+ openrouter: 256e3,
23579
+ xai: 256e3
23436
23580
  };
23437
23581
  var FALLBACK_CONTEXT_LIMIT = 128e3;
23438
23582
  function getContextLimit(modelId, provider) {
@@ -23456,6 +23600,15 @@ var TOKEN_PRICING = {
23456
23600
  openrouter: {
23457
23601
  inputTokenPrice: 0.6,
23458
23602
  outputTokenPrice: 3
23603
+ },
23604
+ // grok-4 rates. cacheReadPrice matters: computeSessionCost bills cache
23605
+ // reads at full input price when it's absent, and Grok discounts cached
23606
+ // prompt tokens 4x. (Grok has no cache-write charge — writes are billed
23607
+ // as ordinary input, so no cacheWritePrice here.)
23608
+ xai: {
23609
+ inputTokenPrice: 3,
23610
+ outputTokenPrice: 15,
23611
+ cacheReadPrice: 0.75
23459
23612
  }
23460
23613
  };
23461
23614
  function getTokenPricing(provider) {
@@ -23542,6 +23695,10 @@ function getProviderOptions(provider, thinkingSpeed, modelName) {
23542
23695
  return {
23543
23696
  openrouter: { usage: { include: true } }
23544
23697
  };
23698
+ case "xai":
23699
+ return {
23700
+ xai: {}
23701
+ };
23545
23702
  default:
23546
23703
  throw new Error(`Unsupported provider: ${provider}`);
23547
23704
  }
@@ -23554,10 +23711,11 @@ function resolveLLMConfig(opts) {
23554
23711
  providerHint = void 0;
23555
23712
  }
23556
23713
  const provider = modelName ? getProviderForModel(modelName) : providerHint || process.env.LLM_PROVIDER || getProviderForModel();
23714
+ const callerKey = normalizeApiKey(opts?.apiKey);
23715
+ const apiKey = callerKey || getApiKeyForProvider(provider);
23557
23716
  console.log(
23558
- `[resolveLLMConfig] provider=${provider} modelName=${modelName || "(default)"} light=${!!opts?.light}`
23717
+ `[resolveLLMConfig] provider=${provider} modelName=${modelName || "(default)"} light=${!!opts?.light} keySource=${callerKey ? "request body" : "env var"} apiKeyPrefix=${apiKey.slice(0, 8)}...`
23559
23718
  );
23560
- const apiKey = opts?.apiKey || getApiKeyForProvider(provider);
23561
23719
  let effectiveModelName = modelName;
23562
23720
  if (!effectiveModelName && opts?.light) {
23563
23721
  effectiveModelName = getLightModelForProvider(provider);
@@ -23596,7 +23754,7 @@ function withLegacyUsage(usage) {
23596
23754
  }
23597
23755
  function normalizeUsage(raw) {
23598
23756
  const inputTokens = tokenCount(raw?.inputTokens);
23599
- const cache_read = raw?.cache_read !== void 0 ? tokenCount(raw.cache_read) : tokenCount(raw?.inputTokenDetails?.cacheReadTokens);
23757
+ const cache_read = raw?.cache_read !== void 0 ? tokenCount(raw.cache_read) : tokenCount(raw?.inputTokenDetails?.cacheReadTokens) || tokenCount(raw?.cachedInputTokens);
23600
23758
  const cache_write = raw?.cache_write !== void 0 ? tokenCount(raw.cache_write) : tokenCount(raw?.inputTokenDetails?.cacheWriteTokens);
23601
23759
  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
23760
  const output = raw?.output !== void 0 ? tokenCount(raw.output) : tokenCount(raw?.outputTokens);
@@ -23817,6 +23975,7 @@ function consoleLogger(name19) {
23817
23975
  getTokenPricing,
23818
23976
  hasApiKeyForProvider,
23819
23977
  loadModelPricing,
23978
+ normalizeApiKey,
23820
23979
  normalizeCallerBaseURL,
23821
23980
  normalizeUsage,
23822
23981
  resolveLLMConfig,