@broberg/ai-sdk 0.62.0 → 0.62.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -2334,8 +2334,8 @@ declare const falStubAdapter: ProviderAdapter;
2334
2334
  * wires the live adapters. */
2335
2335
  declare const stubProviders: Record<string, ProviderAdapter>;
2336
2336
 
2337
- declare const VERSION: "0.62.0";
2338
- declare const SDK_TAG: "@broberg/ai-sdk@0.62.0";
2337
+ declare const VERSION: "0.62.2";
2338
+ declare const SDK_TAG: "@broberg/ai-sdk@0.62.2";
2339
2339
 
2340
2340
  /** Built-in defaults. Every entry is overridable via AiConfig.defaults or a
2341
2341
  * per-call override.
package/dist/index.js CHANGED
@@ -185,6 +185,9 @@ function classifyFailure(err) {
185
185
  return { errorCode: "unknown", errorKind: "other" };
186
186
  }
187
187
 
188
+ // src/search/index.ts
189
+ import { createHash } from "crypto";
190
+
188
191
  // src/search/types.ts
189
192
  var SearchKeyMissingError = class extends Error {
190
193
  constructor(provider, envVar) {
@@ -270,6 +273,15 @@ var sharedCapStore = /* @__PURE__ */ (() => {
270
273
  getSpent: (k) => m.get(k) ?? 0
271
274
  };
272
275
  })();
276
+ var COOLDOWN_MS = 10 * 6e4;
277
+ var COOLDOWN_STATUS = /* @__PURE__ */ new Set(["401", "402", "403"]);
278
+ var coolingUntil = /* @__PURE__ */ new Map();
279
+ function cooldownKey(provider, opts) {
280
+ const c = opts.credentials ?? {};
281
+ const env = opts.byok ? {} : process.env;
282
+ const secret = provider === "brave" ? c.braveApiKey ?? env.BRAVE_API_KEY : provider === "tavily" ? c.tavilyApiKey ?? env.TAVILY_API_KEY : `${c.cloudflareAccountId ?? env.CLOUDFLARE_ACCOUNT_ID}:${c.cloudflareApiToken ?? env.CLOUDFLARE_API_TOKEN}`;
283
+ return `${provider}:${createHash("sha256").update(String(secret)).digest("hex").slice(0, 16)}`;
284
+ }
273
285
  var copenhagenDay = (d) => new Intl.DateTimeFormat("en-CA", { timeZone: "Europe/Copenhagen" }).format(d);
274
286
  async function callProvider(provider, req, opts) {
275
287
  const f = opts.fetch ?? fetch;
@@ -325,11 +337,16 @@ async function search(req, opts = {}) {
325
337
  const tenant = req.labels?.tenantId ?? "_";
326
338
  const day = copenhagenDay((opts.now ?? (() => /* @__PURE__ */ new Date()))());
327
339
  const capKey = JSON.stringify([tenant, day]);
340
+ const nowMs = () => (opts.now ?? (() => /* @__PURE__ */ new Date()))().getTime();
328
341
  let lastErr;
329
- for (const provider of chain) {
342
+ for (const [i, provider] of chain.entries()) {
330
343
  const key = searchCacheKey(provider, req);
331
344
  const hit = cache?.get(key);
332
345
  if (hit) return { items: hit.items, meta: { ...hit.meta, cached: true, costUsd: 0, latencyMs: 0 } };
346
+ const coolKey = cooldownKey(provider, opts);
347
+ const until = coolingUntil.get(coolKey);
348
+ if (until !== void 0 && until <= nowMs()) coolingUntil.delete(coolKey);
349
+ else if (until !== void 0 && i < chain.length - 1) continue;
333
350
  const price = SEARCH_PRICE_USD[provider];
334
351
  const cap = opts.dailyCapUsd ?? Infinity;
335
352
  if (!await capStore.reserve(capKey, price, cap)) {
@@ -343,6 +360,7 @@ async function search(req, opts = {}) {
343
360
  items: dedupe(out.items),
344
361
  meta: { provider, latencyMs, cached: false, costUsd: SEARCH_PRICE_USD[provider], ...out.requestId ? { requestId: out.requestId } : {} }
345
362
  };
363
+ coolingUntil.delete(coolKey);
346
364
  cache?.set(key, result, ttl);
347
365
  try {
348
366
  await sink?.record(usageRow(provider, req, result.meta.costUsd, latencyMs));
@@ -352,6 +370,7 @@ async function search(req, opts = {}) {
352
370
  } catch (e) {
353
371
  lastErr = e;
354
372
  await capStore.release(capKey, price);
373
+ if (COOLDOWN_STATUS.has(classifyFailure(e).errorCode)) coolingUntil.set(coolKey, nowMs() + COOLDOWN_MS);
355
374
  if (sink?.recordFailure) {
356
375
  try {
357
376
  await sink.recordFailure({
@@ -3899,8 +3918,8 @@ var aiConfigSchema = z.object({
3899
3918
  import { randomUUID } from "crypto";
3900
3919
 
3901
3920
  // src/version.ts
3902
- var VERSION = "0.62.0";
3903
- var SDK_TAG = "@broberg/ai-sdk@0.62.0";
3921
+ var VERSION = "0.62.2";
3922
+ var SDK_TAG = "@broberg/ai-sdk@0.62.2";
3904
3923
 
3905
3924
  // src/cost/sinks/upmetrics.ts
3906
3925
  function isRetryableStatus(status) {