@broberg/ai-sdk 0.60.0 → 0.61.0

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
@@ -3,7 +3,8 @@ export { p as AlignedWordTimings, q as AvailabilitySource, r as AvailabilityStat
3
3
  import { z } from 'zod';
4
4
  export { DEFAULT_CLIP_SEC, MEDIA_PRICING_CHECKED_AT, MediaPrice, MediaUnit, PRICING_STALE_AFTER_DAYS, PricingFreshness, UnitFreshness, getMediaPrice, listMediaPrices, pricingFreshness, pricingGeneratedAt } from './pricing.js';
5
5
 
6
- type SearchProviderId = "brave" | "cloudflare:ceramic" | "cloudflare:linkup" | "cloudflare:exa";
6
+ /** `tavily` is CMS-legacy only (F078.5): reachable by explicit provider, never routed to. */
7
+ type SearchProviderId = "brave" | "cloudflare:ceramic" | "cloudflare:linkup" | "cloudflare:exa" | "tavily";
7
8
  /** Why the search runs — picks the route and the cache lifetime (F078.2). */
8
9
  type SearchPurpose = "agent" | "grounding" | "discovery" | "monitor";
9
10
  interface SearchRequest {
@@ -47,6 +48,7 @@ interface SearchCredentials {
47
48
  braveApiKey?: string;
48
49
  cloudflareAccountId?: string;
49
50
  cloudflareApiToken?: string;
51
+ tavilyApiKey?: string;
50
52
  }
51
53
  interface SearchCache {
52
54
  get(key: string): SearchResult | undefined;
@@ -2330,8 +2332,8 @@ declare const falStubAdapter: ProviderAdapter;
2330
2332
  * wires the live adapters. */
2331
2333
  declare const stubProviders: Record<string, ProviderAdapter>;
2332
2334
 
2333
- declare const VERSION: "0.60.0";
2334
- declare const SDK_TAG: "@broberg/ai-sdk@0.60.0";
2335
+ declare const VERSION: "0.61.0";
2336
+ declare const SDK_TAG: "@broberg/ai-sdk@0.61.0";
2335
2337
 
2336
2338
  /** Built-in defaults. Every entry is overridable via AiConfig.defaults or a
2337
2339
  * per-call override.
package/dist/index.js CHANGED
@@ -72,12 +72,37 @@ async function cloudflareSearch(req, creds, f) {
72
72
  return { items, requestId: inner.metadata?.requestId };
73
73
  }
74
74
 
75
+ // src/search/tavily.ts
76
+ async function tavilySearch(req, apiKey, f) {
77
+ const res = await f("https://api.tavily.com/search", {
78
+ method: "POST",
79
+ headers: { authorization: `Bearer ${apiKey}`, "content-type": "application/json" },
80
+ body: JSON.stringify({ query: req.query, max_results: Math.min(req.limit ?? 10, 20), search_depth: "basic" })
81
+ });
82
+ if (!res.ok) throw Object.assign(new Error(`tavily search: HTTP ${res.status} ${(await res.text()).slice(0, 200)}`), { status: res.status });
83
+ const body = await res.json();
84
+ const items = (body.results ?? []).map((r) => {
85
+ const published = r.published_date ? new Date(r.published_date) : void 0;
86
+ return {
87
+ title: r.title ?? "",
88
+ url: r.url ?? "",
89
+ description: r.content ?? "",
90
+ provider: "tavily",
91
+ ...published && !Number.isNaN(published.getTime()) ? { publishedAt: published.toISOString() } : {}
92
+ };
93
+ });
94
+ return { items, ...body.request_id ? { requestId: body.request_id } : {} };
95
+ }
96
+
75
97
  // src/search/prices.ts
76
98
  var SEARCH_PRICE_USD = {
77
99
  "cloudflare:ceramic": 25e-5,
78
100
  "cloudflare:linkup": 5e-3,
79
101
  "cloudflare:exa": 7e-3,
80
- brave: 5e-3
102
+ brave: 5e-3,
103
+ // 1 credit per basic search; $0.0075/credit on the entry plan, less on bigger plans
104
+ // (docs.tavily.com/documentation/api-credits, 2026-10-09).
105
+ tavily: 75e-4
81
106
  };
82
107
 
83
108
  // src/search/router.ts
@@ -102,7 +127,7 @@ function routeSearch(req, routes = DEFAULT_SEARCH_ROUTES) {
102
127
  (r) => (r.when.fresh === void 0 || r.when.fresh === fresh) && (r.when.english === void 0 || r.when.english === english) && (r.when.purpose === void 0 || r.when.purpose.includes(req.purpose ?? "agent"))
103
128
  ) ?? routes[routes.length - 1];
104
129
  let chain = route.chain.filter((p) => english || p !== "cloudflare:ceramic");
105
- chain = chain.filter((p) => p !== "cloudflare:exa");
130
+ chain = chain.filter((p) => p !== "cloudflare:exa" && p !== "tavily");
106
131
  if (req.zdr) chain = chain.filter((p) => ZDR_PROVIDERS.has(p));
107
132
  return chain;
108
133
  }
@@ -255,6 +280,11 @@ async function callProvider(provider, req, opts) {
255
280
  if (!key) throw new SearchKeyMissingError(provider, "BRAVE_API_KEY");
256
281
  return braveSearch({ ...req, provider }, key, f);
257
282
  }
283
+ if (provider === "tavily") {
284
+ const key = c.tavilyApiKey ?? env.TAVILY_API_KEY;
285
+ if (!key) throw new SearchKeyMissingError(provider, "TAVILY_API_KEY");
286
+ return tavilySearch({ ...req, provider }, key, f);
287
+ }
258
288
  if (provider.startsWith("cloudflare:")) {
259
289
  const accountId = c.cloudflareAccountId ?? env.CLOUDFLARE_ACCOUNT_ID;
260
290
  const apiToken = c.cloudflareApiToken ?? env.CLOUDFLARE_API_TOKEN;
@@ -3868,8 +3898,8 @@ var aiConfigSchema = z.object({
3868
3898
  import { randomUUID } from "crypto";
3869
3899
 
3870
3900
  // src/version.ts
3871
- var VERSION = "0.60.0";
3872
- var SDK_TAG = "@broberg/ai-sdk@0.60.0";
3901
+ var VERSION = "0.61.0";
3902
+ var SDK_TAG = "@broberg/ai-sdk@0.61.0";
3873
3903
 
3874
3904
  // src/cost/sinks/upmetrics.ts
3875
3905
  function isRetryableStatus(status) {