@broberg/ai-sdk 0.56.1 → 0.57.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
@@ -2232,8 +2232,8 @@ declare const falStubAdapter: ProviderAdapter;
2232
2232
  * wires the live adapters. */
2233
2233
  declare const stubProviders: Record<string, ProviderAdapter>;
2234
2234
 
2235
- declare const VERSION: "0.56.1";
2236
- declare const SDK_TAG: "@broberg/ai-sdk@0.56.1";
2235
+ declare const VERSION: "0.57.0";
2236
+ declare const SDK_TAG: "@broberg/ai-sdk@0.57.0";
2237
2237
 
2238
2238
  /** Built-in defaults. Every entry is overridable via AiConfig.defaults or a
2239
2239
  * per-call override.
@@ -2758,4 +2758,57 @@ interface StreamTransportRequest extends TransportRequest {
2758
2758
  */
2759
2759
  declare function streamTransport(req: StreamTransportRequest): AsyncIterable<string>;
2760
2760
 
2761
- export { AZURE_DANISH_VOICES, AZURE_DANISH_VOICE_LIST, type AiClient, type AiConfig, type AzureVoiceInfo, BatchJob, BatchRequestItem, BatchResultItem, type BflAdapterConfig, type BflCredits, BudgetConfig, BudgetExceededError, BudgetGuard, BudgetStore, CONFIG_DERIVED_HOSTS, Capability, type ChatInput, ChatResult, ChatStreamEvent, type CheckVoiceOptions, type ClassifyInput, type ClassifyResult, type Contracts, type CostQuery, CostSink, type CostSummary, type CostSummaryQuery, type CostTimeseriesQuery, DEFAULT_BASE_URLS, DEFAULT_TIER_MAP, type DesignInput, type DesignResult, type DiscordSinkConfig, ELEVENLABS_DANISH_VOICES, type EmbeddingInput, EmbeddingResult, type ExtractInput, type ExtractResult, type FalAdapterConfig, type FixedHostProvider, type HttpResponse, type ImageInput, ImageResult, type JudgeInput, JudgeResult, LOCALLY_PINNED_HOSTS, type MockupInput, type MockupResult, type ModerationInput, ModerationResult, type OcrInput, OcrResult, type OpenAICompatibleConfig, type PodcastInput, PodcastResult, type PriceDriftResult, type PriceDriftRow, type PricingEntry, ProviderAdapter, type RefreshOptions, type RefreshResult, Region, type RerankInput, type RerankResult, type RouteForecast, SDK_TAG, type SqliteBudgetStoreConfig, type SqliteSinkConfig, StreamHttpError, type SubprocessResponse, Tier, TierSpec, Tool, ToolCall, type TrainStyleInput, TrainStyleResult, type TranscribeInput, TranscribeResult, type TranslateInput, TranslateResult, Transport, type TransportRequest, type TransportResponse, type TtsInput, type UpmetricsCostClientConfig, UpmetricsCostError, type UpmetricsCostRow, type UpmetricsCostSummary, type UpmetricsCostTimeseries, type UpmetricsSink, type UpmetricsSinkConfig, type UpmetricsSinkStats, Usage, VERSION, type VideoInput, type VisionInput, type VoiceInfo, type VoiceProvider, type VoiceResolveResult, type VoiceStatus, VoiceUnavailableError, aiConfigSchema, anthropicAdapter, anthropicApiAdapter, anthropicSubprocessAdapter, azureAdapter, bflAdapter, bflCredits, byokAdapter, chatInputSchema, checkPriceDrift, checkVoice, computeCost, createAI, deepinfraAdapter, deeplAdapter, deepseekAdapter, defaultBaseUrl, defaultProviders, discordSink, elevenlabsAdapter, embeddingInputSchema, falAdapter, falStubAdapter, freshUsage, fromProviderToolCall, geminiAdapter, getCostSummary, getPrice, httpTransport, imageInputSchema, isByokKeyed, listAzureDanishVoices, listVoices, makeContracts, makeOpenAICompatibleAdapter, matchLabel, messageSchema, mistralAdapter, mistralStubAdapter, multiSink, noopSink, openaiAdapter, openaiStubAdapter, openrouterAdapter, parseClaudeCliJson, parseJsonLoose, refreshAvailability, requestyAdapter, resetRefreshState, resetRegistry, resolveAzureVoice, resolveTier, resolveVoice, sqliteBudgetStore, sqliteSink, streamTransport, stubProviders, subprocessTransport, tierSpecSchema, toProviderTools, toolSchema, translateInputSchema, typesafeAdapter, upmetricsCostClient, upmetricsSink, usdFromMicro, vertexAdapter, visionInputSchema, wouldProviderRouteTo, wouldRouteTo };
2761
+ type SearchProviderId = "brave" | "cloudflare:ceramic" | "cloudflare:linkup" | "cloudflare:exa";
2762
+ interface SearchRequest {
2763
+ query: string;
2764
+ /** BCP-47-ish language of the query ("da", "en"). Routing input (F078.2); Brave also filters on it. */
2765
+ lang?: string;
2766
+ /** Country hint for providers that filter on it (Brave: "DK"). */
2767
+ country?: string;
2768
+ /** Max results. Cloudflare caps at 10. */
2769
+ limit?: number;
2770
+ /** F078.1: required until the router (F078.2) can choose. */
2771
+ provider: SearchProviderId;
2772
+ }
2773
+ interface SearchItem {
2774
+ title: string;
2775
+ url: string;
2776
+ description: string;
2777
+ provider: SearchProviderId;
2778
+ lang?: string;
2779
+ /** ISO timestamp when the provider reports one (Brave does; Cloudflare's providers do not). */
2780
+ publishedAt?: string;
2781
+ }
2782
+ interface SearchResult {
2783
+ items: SearchItem[];
2784
+ meta: {
2785
+ provider: SearchProviderId;
2786
+ latencyMs: number;
2787
+ cached: boolean;
2788
+ costUsd: number;
2789
+ requestId?: string;
2790
+ };
2791
+ }
2792
+ interface SearchCredentials {
2793
+ braveApiKey?: string;
2794
+ cloudflareAccountId?: string;
2795
+ cloudflareApiToken?: string;
2796
+ }
2797
+ interface SearchOptions {
2798
+ /** Explicit keys (BYOK); missing fields fall back to env. */
2799
+ credentials?: SearchCredentials;
2800
+ /** Injectable fetch (tests, proxies) — same contract as the model adapters (F073). */
2801
+ fetch?: typeof fetch;
2802
+ }
2803
+ /** Thrown before any request when the provider's key is absent — names the env var to set. */
2804
+ declare class SearchKeyMissingError extends Error {
2805
+ readonly provider: SearchProviderId;
2806
+ readonly envVar: string;
2807
+ constructor(provider: SearchProviderId, envVar: string);
2808
+ }
2809
+
2810
+ declare const SEARCH_PRICE_USD: Record<SearchProviderId, number>;
2811
+
2812
+ declare function search(req: SearchRequest, opts?: SearchOptions): Promise<SearchResult>;
2813
+
2814
+ export { AZURE_DANISH_VOICES, AZURE_DANISH_VOICE_LIST, type AiClient, type AiConfig, type AzureVoiceInfo, BatchJob, BatchRequestItem, BatchResultItem, type BflAdapterConfig, type BflCredits, BudgetConfig, BudgetExceededError, BudgetGuard, BudgetStore, CONFIG_DERIVED_HOSTS, Capability, type ChatInput, ChatResult, ChatStreamEvent, type CheckVoiceOptions, type ClassifyInput, type ClassifyResult, type Contracts, type CostQuery, CostSink, type CostSummary, type CostSummaryQuery, type CostTimeseriesQuery, DEFAULT_BASE_URLS, DEFAULT_TIER_MAP, type DesignInput, type DesignResult, type DiscordSinkConfig, ELEVENLABS_DANISH_VOICES, type EmbeddingInput, EmbeddingResult, type ExtractInput, type ExtractResult, type FalAdapterConfig, type FixedHostProvider, type HttpResponse, type ImageInput, ImageResult, type JudgeInput, JudgeResult, LOCALLY_PINNED_HOSTS, type MockupInput, type MockupResult, type ModerationInput, ModerationResult, type OcrInput, OcrResult, type OpenAICompatibleConfig, type PodcastInput, PodcastResult, type PriceDriftResult, type PriceDriftRow, type PricingEntry, ProviderAdapter, type RefreshOptions, type RefreshResult, Region, type RerankInput, type RerankResult, type RouteForecast, SDK_TAG, SEARCH_PRICE_USD, type SearchCredentials, type SearchItem, SearchKeyMissingError, type SearchOptions, type SearchProviderId, type SearchRequest, type SearchResult, type SqliteBudgetStoreConfig, type SqliteSinkConfig, StreamHttpError, type SubprocessResponse, Tier, TierSpec, Tool, ToolCall, type TrainStyleInput, TrainStyleResult, type TranscribeInput, TranscribeResult, type TranslateInput, TranslateResult, Transport, type TransportRequest, type TransportResponse, type TtsInput, type UpmetricsCostClientConfig, UpmetricsCostError, type UpmetricsCostRow, type UpmetricsCostSummary, type UpmetricsCostTimeseries, type UpmetricsSink, type UpmetricsSinkConfig, type UpmetricsSinkStats, Usage, VERSION, type VideoInput, type VisionInput, type VoiceInfo, type VoiceProvider, type VoiceResolveResult, type VoiceStatus, VoiceUnavailableError, aiConfigSchema, anthropicAdapter, anthropicApiAdapter, anthropicSubprocessAdapter, azureAdapter, bflAdapter, bflCredits, byokAdapter, chatInputSchema, checkPriceDrift, checkVoice, computeCost, createAI, deepinfraAdapter, deeplAdapter, deepseekAdapter, defaultBaseUrl, defaultProviders, discordSink, elevenlabsAdapter, embeddingInputSchema, falAdapter, falStubAdapter, freshUsage, fromProviderToolCall, geminiAdapter, getCostSummary, getPrice, httpTransport, imageInputSchema, isByokKeyed, listAzureDanishVoices, listVoices, makeContracts, makeOpenAICompatibleAdapter, matchLabel, messageSchema, mistralAdapter, mistralStubAdapter, multiSink, noopSink, openaiAdapter, openaiStubAdapter, openrouterAdapter, parseClaudeCliJson, parseJsonLoose, refreshAvailability, requestyAdapter, resetRefreshState, resetRegistry, resolveAzureVoice, resolveTier, resolveVoice, search, sqliteBudgetStore, sqliteSink, streamTransport, stubProviders, subprocessTransport, tierSpecSchema, toProviderTools, toolSchema, translateInputSchema, typesafeAdapter, upmetricsCostClient, upmetricsSink, usdFromMicro, vertexAdapter, visionInputSchema, wouldProviderRouteTo, wouldRouteTo };
package/dist/index.js CHANGED
@@ -3548,8 +3548,8 @@ var aiConfigSchema = z.object({
3548
3548
  import { randomUUID } from "crypto";
3549
3549
 
3550
3550
  // src/version.ts
3551
- var VERSION = "0.56.1";
3552
- var SDK_TAG = "@broberg/ai-sdk@0.56.1";
3551
+ var VERSION = "0.57.0";
3552
+ var SDK_TAG = "@broberg/ai-sdk@0.57.0";
3553
3553
 
3554
3554
  // src/cost/sinks/upmetrics.ts
3555
3555
  function isRetryableStatus(status) {
@@ -5094,6 +5094,103 @@ function wouldRouteTo(tier) {
5094
5094
  if (!spec) return { kind: "unknown-provider", provider: String(tier), onlyIf: [...ASSUMPTIONS] };
5095
5095
  return wouldProviderRouteTo(spec.provider);
5096
5096
  }
5097
+
5098
+ // src/search/brave.ts
5099
+ async function braveSearch(req, apiKey, f) {
5100
+ const params = new URLSearchParams({ q: req.query, count: String(Math.min(req.limit ?? 10, 20)) });
5101
+ if (req.lang) params.set("search_lang", req.lang);
5102
+ if (req.country) params.set("country", req.country);
5103
+ const res = await f(`https://api.search.brave.com/res/v1/web/search?${params}`, {
5104
+ headers: { accept: "application/json", "X-Subscription-Token": apiKey }
5105
+ });
5106
+ if (!res.ok) throw Object.assign(new Error(`brave search: HTTP ${res.status} ${(await res.text()).slice(0, 200)}`), { status: res.status });
5107
+ const body = await res.json();
5108
+ const items = (body.web?.results ?? []).map((r) => ({
5109
+ title: r.title ?? "",
5110
+ url: r.url ?? "",
5111
+ description: r.description ?? "",
5112
+ provider: "brave",
5113
+ ...r.language ? { lang: r.language } : {},
5114
+ ...r.page_age ? { publishedAt: new Date(r.page_age).toISOString() } : {}
5115
+ }));
5116
+ return { items, requestId: res.headers.get("x-request-id") ?? void 0 };
5117
+ }
5118
+
5119
+ // src/search/cloudflare.ts
5120
+ var CLOUDFLARE_MAX_QUERY = 1024;
5121
+ var CLOUDFLARE_MAX_LIMIT = 10;
5122
+ async function cloudflareSearch(req, creds, f) {
5123
+ if (req.query.length < 1 || req.query.length > CLOUDFLARE_MAX_QUERY) {
5124
+ throw new Error(`search: Cloudflare takes a query of 1\u2013${CLOUDFLARE_MAX_QUERY} characters, got ${req.query.length}`);
5125
+ }
5126
+ const provider = req.provider.split(":")[1];
5127
+ const res = await f(`https://api.cloudflare.com/client/v4/accounts/${encodeURIComponent(creds.accountId)}/ai/websearch/`, {
5128
+ method: "POST",
5129
+ headers: { authorization: `Bearer ${creds.apiToken}`, "content-type": "application/json" },
5130
+ body: JSON.stringify({ query: req.query, provider, limit: Math.min(req.limit ?? CLOUDFLARE_MAX_LIMIT, CLOUDFLARE_MAX_LIMIT) })
5131
+ });
5132
+ if (!res.ok) throw Object.assign(new Error(`cloudflare search (${provider}): HTTP ${res.status} ${(await res.text()).slice(0, 200)}`), { status: res.status });
5133
+ const body = await res.json();
5134
+ const inner = body.result ?? body;
5135
+ const items = (inner.items ?? []).map((r) => ({
5136
+ title: r.title ?? "",
5137
+ url: r.url ?? "",
5138
+ description: r.description ?? "",
5139
+ provider: req.provider
5140
+ }));
5141
+ return { items, requestId: inner.metadata?.requestId };
5142
+ }
5143
+
5144
+ // src/search/prices.ts
5145
+ var SEARCH_PRICE_USD = {
5146
+ "cloudflare:ceramic": 25e-5,
5147
+ "cloudflare:linkup": 5e-3,
5148
+ "cloudflare:exa": 7e-3,
5149
+ brave: 5e-3
5150
+ };
5151
+
5152
+ // src/search/types.ts
5153
+ var SearchKeyMissingError = class extends Error {
5154
+ constructor(provider, envVar) {
5155
+ super(`search: ${provider} needs ${envVar} (env or options.credentials)`);
5156
+ this.provider = provider;
5157
+ this.envVar = envVar;
5158
+ this.name = "SearchKeyMissingError";
5159
+ }
5160
+ provider;
5161
+ envVar;
5162
+ };
5163
+
5164
+ // src/search/index.ts
5165
+ async function search(req, opts = {}) {
5166
+ const f = opts.fetch ?? fetch;
5167
+ const c = opts.credentials ?? {};
5168
+ const t0 = performance.now();
5169
+ let out;
5170
+ if (req.provider === "brave") {
5171
+ const key = c.braveApiKey ?? process.env.BRAVE_API_KEY;
5172
+ if (!key) throw new SearchKeyMissingError(req.provider, "BRAVE_API_KEY");
5173
+ out = await braveSearch(req, key, f);
5174
+ } else if (req.provider.startsWith("cloudflare:")) {
5175
+ const accountId = c.cloudflareAccountId ?? process.env.CLOUDFLARE_ACCOUNT_ID;
5176
+ const apiToken = c.cloudflareApiToken ?? process.env.CLOUDFLARE_API_TOKEN;
5177
+ if (!accountId) throw new SearchKeyMissingError(req.provider, "CLOUDFLARE_ACCOUNT_ID");
5178
+ if (!apiToken) throw new SearchKeyMissingError(req.provider, "CLOUDFLARE_API_TOKEN");
5179
+ out = await cloudflareSearch(req, { accountId, apiToken }, f);
5180
+ } else {
5181
+ throw new Error(`search: unknown provider "${String(req.provider)}"`);
5182
+ }
5183
+ return {
5184
+ items: out.items,
5185
+ meta: {
5186
+ provider: req.provider,
5187
+ latencyMs: Math.round(performance.now() - t0),
5188
+ cached: false,
5189
+ costUsd: SEARCH_PRICE_USD[req.provider],
5190
+ ...out.requestId ? { requestId: out.requestId } : {}
5191
+ }
5192
+ };
5193
+ }
5097
5194
  export {
5098
5195
  AZURE_DANISH_VOICES,
5099
5196
  AZURE_DANISH_VOICE_LIST,
@@ -5109,6 +5206,8 @@ export {
5109
5206
  ModelUnavailableError,
5110
5207
  PRICING_STALE_AFTER_DAYS,
5111
5208
  SDK_TAG,
5209
+ SEARCH_PRICE_USD,
5210
+ SearchKeyMissingError,
5112
5211
  StreamHttpError,
5113
5212
  UpmetricsCostError,
5114
5213
  VERSION,
@@ -5177,6 +5276,7 @@ export {
5177
5276
  resolveModel,
5178
5277
  resolveTier,
5179
5278
  resolveVoice,
5279
+ search,
5180
5280
  sqliteBudgetStore,
5181
5281
  sqliteSink,
5182
5282
  streamTransport,