@anyr/ai-sdk-provider 0.1.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.mjs ADDED
@@ -0,0 +1,733 @@
1
+ import { withoutTrailingSlash, parseProviderOptions, postJsonToApi, createJsonResponseHandler, createJsonErrorResponseHandler, combineHeaders, createEventSourceResponseHandler, loadApiKey, generateId } from '@ai-sdk/provider-utils';
2
+ import { z } from 'zod';
3
+ import { NoSuchModelError, UnsupportedFunctionalityError } from '@ai-sdk/provider';
4
+ import { DEFAULT_BASE_URL, AnyRouter } from '@anyr/sdk';
5
+
6
+ // src/anyrouter-chat-language-model.ts
7
+ function convertToAnyRouterChatMessages(prompt) {
8
+ const messages = [];
9
+ for (const message of prompt) {
10
+ switch (message.role) {
11
+ case "system":
12
+ messages.push({ role: "system", content: message.content });
13
+ break;
14
+ case "user":
15
+ messages.push(convertUserMessage(message));
16
+ break;
17
+ case "assistant":
18
+ messages.push(convertAssistantMessage(message));
19
+ break;
20
+ case "tool":
21
+ for (const part of message.content) {
22
+ if (part.type === "tool-result") {
23
+ messages.push(convertToolResultMessage(part));
24
+ }
25
+ }
26
+ break;
27
+ default: {
28
+ const _exhaustive = message;
29
+ throw new Error(`Unsupported message role: ${_exhaustive.role}`);
30
+ }
31
+ }
32
+ }
33
+ return messages;
34
+ }
35
+ function convertUserMessage(message) {
36
+ if (message.content.length === 1 && message.content[0].type === "text") {
37
+ return { role: "user", content: message.content[0].text };
38
+ }
39
+ const parts = [];
40
+ for (const part of message.content) {
41
+ if (part.type === "text") {
42
+ parts.push({ type: "text", text: part.text });
43
+ } else if (part.type === "file") {
44
+ const filePart = part;
45
+ const mediaType = filePart.mediaType;
46
+ const url = toDataUrlOrString(filePart.data, mediaType);
47
+ if (mediaType.startsWith("image/")) {
48
+ parts.push({ type: "image_url", image_url: { url } });
49
+ } else {
50
+ parts.push({ type: "file", file: { url, media_type: mediaType } });
51
+ }
52
+ } else {
53
+ const unknown = part;
54
+ throw new UnsupportedFunctionalityError({
55
+ functionality: `User message part type: ${unknown.type ?? "unknown"}`
56
+ });
57
+ }
58
+ }
59
+ return { role: "user", content: parts };
60
+ }
61
+ function convertAssistantMessage(message) {
62
+ let text = "";
63
+ const toolCalls = [];
64
+ for (const part of message.content) {
65
+ switch (part.type) {
66
+ case "text":
67
+ text += part.text;
68
+ break;
69
+ case "tool-call": {
70
+ const tc = part;
71
+ toolCalls.push({
72
+ id: tc.toolCallId,
73
+ type: "function",
74
+ function: {
75
+ name: tc.toolName,
76
+ arguments: typeof tc.input === "string" ? tc.input : JSON.stringify(tc.input)
77
+ }
78
+ });
79
+ break;
80
+ }
81
+ }
82
+ }
83
+ const result = {
84
+ role: "assistant",
85
+ content: text || null
86
+ };
87
+ if (toolCalls.length > 0) {
88
+ result.tool_calls = toolCalls;
89
+ }
90
+ return result;
91
+ }
92
+ function convertToolResultMessage(part) {
93
+ return {
94
+ role: "tool",
95
+ tool_call_id: part.toolCallId,
96
+ content: toolResultOutputToString(part.output)
97
+ };
98
+ }
99
+ function toolResultOutputToString(output) {
100
+ switch (output.type) {
101
+ case "text":
102
+ return output.value;
103
+ case "json":
104
+ return JSON.stringify(output.value);
105
+ case "error-text":
106
+ return output.value;
107
+ case "error-json":
108
+ return JSON.stringify(output.value);
109
+ case "execution-denied":
110
+ return output.reason ?? "Tool execution denied.";
111
+ case "content": {
112
+ const segments = [];
113
+ for (const c of output.value) {
114
+ if (c.type === "text") {
115
+ segments.push(c.text);
116
+ } else {
117
+ segments.push(`[${c.type}]`);
118
+ }
119
+ }
120
+ return segments.join("\n");
121
+ }
122
+ default:
123
+ return JSON.stringify(output);
124
+ }
125
+ }
126
+ function toDataUrlOrString(data, mediaType) {
127
+ if (data instanceof URL) return data.toString();
128
+ if (typeof data === "string") {
129
+ if (data.startsWith("http") || data.startsWith("data:")) return data;
130
+ return `data:${mediaType};base64,${data}`;
131
+ }
132
+ return `data:${mediaType};base64,${uint8ArrayToBase64(data)}`;
133
+ }
134
+ function uint8ArrayToBase64(bytes) {
135
+ let binary = "";
136
+ for (let i = 0; i < bytes.length; i++) {
137
+ binary += String.fromCharCode(bytes[i]);
138
+ }
139
+ return btoa(binary);
140
+ }
141
+
142
+ // src/anyrouter-chat-language-model.ts
143
+ var anyRouterProviderOptionsSchema = z.object({
144
+ /** Routing preference forwarded as `provider` in the request body. */
145
+ provider: z.record(z.string(), z.unknown()).optional(),
146
+ /** Session ID forwarded as `session_id` in the request body. */
147
+ sessionId: z.string().optional(),
148
+ /** Extra body fields merged in last (highest precedence). */
149
+ extraBody: z.record(z.string(), z.unknown()).optional()
150
+ });
151
+ var anyRouterErrorSchema = z.object({
152
+ error: z.object({
153
+ code: z.string().optional(),
154
+ message: z.string().optional(),
155
+ metadata: z.record(z.string(), z.unknown()).optional()
156
+ }).optional()
157
+ });
158
+ var completionUsageSchema = z.object({
159
+ prompt_tokens: z.number().optional(),
160
+ completion_tokens: z.number().optional(),
161
+ total_tokens: z.number().optional()
162
+ });
163
+ var toolCallSchema = z.object({
164
+ id: z.string().optional(),
165
+ type: z.literal("function").optional(),
166
+ function: z.object({
167
+ name: z.string().optional(),
168
+ arguments: z.string().optional()
169
+ }).optional()
170
+ });
171
+ var toolCallDeltaSchema = z.object({
172
+ index: z.number(),
173
+ id: z.string().optional(),
174
+ type: z.literal("function").optional(),
175
+ function: z.object({
176
+ name: z.string().optional(),
177
+ arguments: z.string().optional()
178
+ }).optional()
179
+ });
180
+ var messageSchema = z.object({
181
+ content: z.string().nullish(),
182
+ reasoning_content: z.string().nullish(),
183
+ tool_calls: z.array(toolCallSchema).optional()
184
+ });
185
+ var choiceSchema = z.object({
186
+ message: messageSchema.optional(),
187
+ finish_reason: z.string().nullish()
188
+ });
189
+ var generateResponseSchema = z.object({
190
+ id: z.string().optional(),
191
+ model: z.string().optional(),
192
+ choices: z.array(choiceSchema).optional(),
193
+ usage: completionUsageSchema.optional()
194
+ });
195
+ var deltaSchema = z.object({
196
+ content: z.string().nullish(),
197
+ reasoning_content: z.string().nullish(),
198
+ tool_calls: z.array(toolCallDeltaSchema).optional()
199
+ });
200
+ var streamChoiceSchema = z.object({
201
+ delta: deltaSchema.optional(),
202
+ finish_reason: z.string().nullish()
203
+ });
204
+ var streamChunkSchema = z.object({
205
+ id: z.string().optional(),
206
+ model: z.string().optional(),
207
+ choices: z.array(streamChoiceSchema).optional(),
208
+ usage: completionUsageSchema.optional()
209
+ });
210
+ function mapFinishReason(raw) {
211
+ switch (raw) {
212
+ case "stop":
213
+ return { unified: "stop", raw };
214
+ case "length":
215
+ case "max_tokens":
216
+ return { unified: "length", raw };
217
+ case "tool_calls":
218
+ case "function_call":
219
+ return { unified: "tool-calls", raw };
220
+ case "content_filter":
221
+ return { unified: "content-filter", raw };
222
+ default:
223
+ return { unified: "other", raw: raw ?? void 0 };
224
+ }
225
+ }
226
+ function buildUsage(raw) {
227
+ return {
228
+ inputTokens: {
229
+ total: raw?.prompt_tokens ?? void 0,
230
+ noCache: void 0,
231
+ cacheRead: void 0,
232
+ cacheWrite: void 0
233
+ },
234
+ outputTokens: {
235
+ total: raw?.completion_tokens ?? void 0,
236
+ text: void 0,
237
+ reasoning: void 0
238
+ }
239
+ };
240
+ }
241
+ function emitResponseMetadata(chunk, state, fallbackModelId, controller) {
242
+ if (state.metadataEmitted || !(chunk.id || chunk.model)) return;
243
+ state.metadataEmitted = true;
244
+ controller.enqueue({
245
+ type: "response-metadata",
246
+ id: chunk.id,
247
+ modelId: chunk.model ?? fallbackModelId
248
+ });
249
+ }
250
+ function emitTextDelta(content, state, controller) {
251
+ if (state.activeTextId === null) {
252
+ state.activeTextId = generateId();
253
+ controller.enqueue({ type: "text-start", id: state.activeTextId });
254
+ }
255
+ controller.enqueue({ type: "text-delta", id: state.activeTextId, delta: content });
256
+ }
257
+ function emitToolCallDeltas(toolCalls, acc, controller) {
258
+ for (const tcDelta of toolCalls) {
259
+ const idx = tcDelta.index;
260
+ if (!acc[idx]) acc[idx] = { id: "", name: "", arguments: "", started: false };
261
+ const entry = acc[idx];
262
+ if (tcDelta.id) entry.id = tcDelta.id;
263
+ if (tcDelta.function?.name) entry.name = tcDelta.function.name;
264
+ if (tcDelta.function?.arguments) entry.arguments += tcDelta.function.arguments;
265
+ const toolId = entry.id || `tool-${idx}`;
266
+ if (!entry.started && entry.name) {
267
+ entry.started = true;
268
+ controller.enqueue({ type: "tool-input-start", id: toolId, toolName: entry.name });
269
+ }
270
+ if (tcDelta.function?.arguments) {
271
+ controller.enqueue({
272
+ type: "tool-input-delta",
273
+ id: toolId,
274
+ delta: tcDelta.function.arguments
275
+ });
276
+ }
277
+ }
278
+ }
279
+ function emitFinish(choice, chunk, state, acc, controller) {
280
+ if (state.activeTextId !== null) {
281
+ controller.enqueue({ type: "text-end", id: state.activeTextId });
282
+ state.activeTextId = null;
283
+ }
284
+ for (const [idxStr, entry] of Object.entries(acc)) {
285
+ if (!entry.started) continue;
286
+ const toolId = entry.id || `tool-${idxStr}`;
287
+ controller.enqueue({ type: "tool-input-end", id: toolId });
288
+ controller.enqueue({
289
+ type: "tool-call",
290
+ toolCallId: toolId,
291
+ toolName: entry.name,
292
+ input: entry.arguments
293
+ });
294
+ }
295
+ controller.enqueue({
296
+ type: "finish",
297
+ usage: buildUsage(chunk.usage),
298
+ finishReason: mapFinishReason(choice.finish_reason)
299
+ });
300
+ }
301
+ function mapToolChoice(toolChoice) {
302
+ if (!toolChoice) return void 0;
303
+ switch (toolChoice.type) {
304
+ case "auto":
305
+ return "auto";
306
+ case "none":
307
+ return "none";
308
+ case "required":
309
+ return "required";
310
+ case "tool":
311
+ return { type: "function", function: { name: toolChoice.toolName } };
312
+ }
313
+ }
314
+ function buildResponseFormat(responseFormat) {
315
+ if (!responseFormat) return void 0;
316
+ if (responseFormat.type === "text") return { type: "text" };
317
+ if (responseFormat.type === "json") {
318
+ if (responseFormat.schema) {
319
+ return {
320
+ type: "json_schema",
321
+ json_schema: {
322
+ name: responseFormat.name ?? "response",
323
+ description: responseFormat.description,
324
+ schema: responseFormat.schema,
325
+ strict: true
326
+ }
327
+ };
328
+ }
329
+ return { type: "json_object" };
330
+ }
331
+ return void 0;
332
+ }
333
+ function buildTools(tools) {
334
+ if (!tools || tools.length === 0) return void 0;
335
+ const fns = tools.filter((t) => t.type === "function").map((t) => ({
336
+ type: "function",
337
+ function: {
338
+ name: t.name,
339
+ description: t.description,
340
+ parameters: t.inputSchema,
341
+ strict: t.strict
342
+ }
343
+ }));
344
+ return fns.length > 0 ? fns : void 0;
345
+ }
346
+ function buildRequestBody(modelId, options, settings, stream, perCallOptions) {
347
+ const messages = convertToAnyRouterChatMessages(options.prompt);
348
+ const responseFormat = buildResponseFormat(options.responseFormat);
349
+ const tools = buildTools(options.tools);
350
+ const toolChoice = mapToolChoice(options.toolChoice);
351
+ const provider = perCallOptions.provider ?? settings.provider;
352
+ const sessionId = perCallOptions.sessionId ?? settings.sessionId;
353
+ const extraBody = { ...settings.extraBody, ...perCallOptions.extraBody };
354
+ const body = {
355
+ model: modelId,
356
+ messages,
357
+ ...stream ? { stream: true, stream_options: { include_usage: true } } : {},
358
+ max_tokens: options.maxOutputTokens,
359
+ temperature: options.temperature,
360
+ top_p: options.topP,
361
+ top_k: options.topK,
362
+ stop: options.stopSequences,
363
+ frequency_penalty: options.frequencyPenalty,
364
+ presence_penalty: options.presencePenalty,
365
+ seed: options.seed,
366
+ response_format: responseFormat,
367
+ tools,
368
+ tool_choice: toolChoice,
369
+ provider: provider ?? void 0,
370
+ session_id: sessionId ?? void 0,
371
+ ...extraBody
372
+ };
373
+ for (const key of Object.keys(body)) {
374
+ if (body[key] === void 0) delete body[key];
375
+ }
376
+ return body;
377
+ }
378
+ var AnyRouterChatLanguageModel = class {
379
+ specificationVersion = "v3";
380
+ provider;
381
+ modelId;
382
+ supportedUrls = {};
383
+ config;
384
+ constructor(modelId, config) {
385
+ this.modelId = modelId;
386
+ this.provider = config.provider;
387
+ this.config = config;
388
+ }
389
+ // ─── doGenerate ─────────────────────────────────────────────────────────
390
+ async doGenerate(options) {
391
+ const perCallOptions = await parseProviderOptions({
392
+ provider: "anyrouter",
393
+ providerOptions: options.providerOptions,
394
+ schema: anyRouterProviderOptionsSchema
395
+ }) ?? {};
396
+ const body = buildRequestBody(
397
+ this.modelId,
398
+ options,
399
+ this.config.settings,
400
+ false,
401
+ perCallOptions
402
+ );
403
+ const { value: response, responseHeaders } = await postJsonToApi({
404
+ url: `${this.config.baseURL}/chat/completions`,
405
+ headers: combineHeaders(this.config.headers(), options.headers),
406
+ body,
407
+ failedResponseHandler: createJsonErrorResponseHandler({
408
+ errorSchema: anyRouterErrorSchema,
409
+ errorToMessage: (data) => data.error?.message ?? "AnyRouter API error",
410
+ isRetryable: (response2) => response2.status >= 500
411
+ }),
412
+ successfulResponseHandler: createJsonResponseHandler(generateResponseSchema),
413
+ abortSignal: options.abortSignal,
414
+ fetch: this.config.fetch
415
+ });
416
+ const choice = response.choices?.[0];
417
+ const message = choice?.message;
418
+ const content = [];
419
+ if (message?.content) {
420
+ content.push({ type: "text", text: message.content });
421
+ }
422
+ if (message?.tool_calls && message.tool_calls.length > 0) {
423
+ for (const tc of message.tool_calls) {
424
+ if (tc.id && tc.function?.name) {
425
+ content.push({
426
+ type: "tool-call",
427
+ toolCallId: tc.id,
428
+ toolName: tc.function.name,
429
+ input: tc.function.arguments ?? "{}"
430
+ });
431
+ }
432
+ }
433
+ }
434
+ return {
435
+ content,
436
+ finishReason: mapFinishReason(choice?.finish_reason),
437
+ usage: buildUsage(response.usage),
438
+ warnings: [],
439
+ request: { body },
440
+ response: {
441
+ id: response.id,
442
+ modelId: response.model,
443
+ headers: responseHeaders
444
+ }
445
+ };
446
+ }
447
+ // ─── doStream ───────────────────────────────────────────────────────────
448
+ async doStream(options) {
449
+ const perCallOptions = await parseProviderOptions({
450
+ provider: "anyrouter",
451
+ providerOptions: options.providerOptions,
452
+ schema: anyRouterProviderOptionsSchema
453
+ }) ?? {};
454
+ const body = buildRequestBody(this.modelId, options, this.config.settings, true, perCallOptions);
455
+ const { value: stream, responseHeaders } = await postJsonToApi({
456
+ url: `${this.config.baseURL}/chat/completions`,
457
+ headers: combineHeaders(this.config.headers(), options.headers),
458
+ body,
459
+ failedResponseHandler: createJsonErrorResponseHandler({
460
+ errorSchema: anyRouterErrorSchema,
461
+ errorToMessage: (data) => data.error?.message ?? "AnyRouter API error",
462
+ isRetryable: (response) => response.status >= 500
463
+ }),
464
+ successfulResponseHandler: createEventSourceResponseHandler(streamChunkSchema),
465
+ abortSignal: options.abortSignal,
466
+ fetch: this.config.fetch
467
+ });
468
+ const toolCallAccumulator = {};
469
+ const state = { activeTextId: null, metadataEmitted: false };
470
+ const selfModelId = this.modelId;
471
+ const transformStream = new TransformStream({
472
+ start(controller) {
473
+ controller.enqueue({ type: "stream-start", warnings: [] });
474
+ },
475
+ transform(chunkResult, controller) {
476
+ if (!chunkResult.success) {
477
+ controller.enqueue({ type: "error", error: chunkResult.error });
478
+ return;
479
+ }
480
+ const chunk = chunkResult.value;
481
+ const choice = chunk.choices?.[0];
482
+ emitResponseMetadata(chunk, state, selfModelId, controller);
483
+ const delta = choice?.delta;
484
+ if (delta) {
485
+ if (typeof delta.content === "string" && delta.content.length > 0) {
486
+ emitTextDelta(delta.content, state, controller);
487
+ }
488
+ if (delta.tool_calls) {
489
+ emitToolCallDeltas(delta.tool_calls, toolCallAccumulator, controller);
490
+ }
491
+ }
492
+ if (choice?.finish_reason) {
493
+ emitFinish(choice, chunk, state, toolCallAccumulator, controller);
494
+ }
495
+ },
496
+ flush(controller) {
497
+ if (state.activeTextId !== null) {
498
+ controller.enqueue({ type: "text-end", id: state.activeTextId });
499
+ }
500
+ }
501
+ });
502
+ return {
503
+ stream: stream.pipeThrough(transformStream),
504
+ request: { body },
505
+ response: { headers: responseHeaders }
506
+ };
507
+ }
508
+ };
509
+ var anyRouterErrorSchema2 = z.object({
510
+ error: z.object({
511
+ code: z.string().optional(),
512
+ message: z.string().optional()
513
+ }).optional()
514
+ });
515
+ var embeddingResponseSchema = z.object({
516
+ data: z.array(
517
+ z.object({
518
+ embedding: z.array(z.number())
519
+ })
520
+ ),
521
+ usage: z.object({
522
+ prompt_tokens: z.number().optional(),
523
+ total_tokens: z.number().optional()
524
+ }).optional()
525
+ });
526
+ var AnyRouterEmbeddingModel = class {
527
+ specificationVersion = "v3";
528
+ provider;
529
+ modelId;
530
+ /** No hard per-call limit imposed by the provider layer. */
531
+ maxEmbeddingsPerCall = void 0;
532
+ supportsParallelCalls = true;
533
+ config;
534
+ constructor(modelId, config) {
535
+ this.modelId = modelId;
536
+ this.provider = config.provider;
537
+ this.config = config;
538
+ }
539
+ async doEmbed(options) {
540
+ const { value: response } = await postJsonToApi({
541
+ url: `${this.config.baseURL}/embeddings`,
542
+ headers: combineHeaders(this.config.headers(), options.headers),
543
+ body: {
544
+ model: this.modelId,
545
+ input: options.values
546
+ },
547
+ failedResponseHandler: createJsonErrorResponseHandler({
548
+ errorSchema: anyRouterErrorSchema2,
549
+ errorToMessage: (data) => data.error?.message ?? "AnyRouter embeddings API error",
550
+ isRetryable: (response2) => response2.status >= 500
551
+ }),
552
+ successfulResponseHandler: createJsonResponseHandler(embeddingResponseSchema),
553
+ abortSignal: options.abortSignal,
554
+ fetch: this.config.fetch
555
+ });
556
+ const embeddings = response.data.map((d) => d.embedding);
557
+ const tokens = response.usage?.prompt_tokens ?? response.usage?.total_tokens;
558
+ return {
559
+ embeddings,
560
+ usage: tokens !== void 0 ? { tokens } : void 0,
561
+ warnings: []
562
+ };
563
+ }
564
+ };
565
+ var anyRouterErrorSchema3 = z.object({
566
+ error: z.object({
567
+ code: z.string().optional(),
568
+ message: z.string().optional()
569
+ }).optional()
570
+ });
571
+ var imageGenerationResponseSchema = z.object({
572
+ created: z.number().optional(),
573
+ data: z.array(
574
+ z.object({
575
+ url: z.string().optional(),
576
+ b64_json: z.string().optional(),
577
+ revised_prompt: z.string().optional()
578
+ })
579
+ )
580
+ });
581
+ var AnyRouterImageModel = class {
582
+ specificationVersion = "v3";
583
+ provider;
584
+ modelId;
585
+ /**
586
+ * Most image generation APIs support only 1 image per call via the
587
+ * standard `/images/generations` endpoint.
588
+ */
589
+ maxImagesPerCall = 1;
590
+ config;
591
+ constructor(modelId, config) {
592
+ this.modelId = modelId;
593
+ this.provider = config.provider;
594
+ this.config = config;
595
+ }
596
+ async doGenerate(options) {
597
+ if (options.mask) {
598
+ throw new UnsupportedFunctionalityError({
599
+ functionality: "mask (inpainting) for AnyRouter image generation"
600
+ });
601
+ }
602
+ const warnings = [];
603
+ if (options.n > 1) {
604
+ warnings.push({
605
+ type: "unsupported",
606
+ feature: `n=${options.n} (AnyRouter image endpoint supports n=1 per call)`
607
+ });
608
+ }
609
+ const body = {
610
+ model: this.modelId,
611
+ prompt: options.prompt ?? "",
612
+ n: Math.min(options.n, 1),
613
+ ...options.size ? { size: options.size } : {},
614
+ ...options.seed !== void 0 ? { seed: options.seed } : {},
615
+ response_format: "b64_json"
616
+ };
617
+ const { value: response, responseHeaders } = await postJsonToApi({
618
+ url: `${this.config.baseURL}/images/generations`,
619
+ headers: combineHeaders(this.config.headers(), options.headers),
620
+ body,
621
+ failedResponseHandler: createJsonErrorResponseHandler({
622
+ errorSchema: anyRouterErrorSchema3,
623
+ errorToMessage: (data) => data.error?.message ?? "AnyRouter images API error",
624
+ isRetryable: (res) => res.status >= 500
625
+ }),
626
+ successfulResponseHandler: createJsonResponseHandler(imageGenerationResponseSchema),
627
+ abortSignal: options.abortSignal,
628
+ fetch: this.config.fetch
629
+ });
630
+ const images = [];
631
+ for (const item of response.data) {
632
+ if (item.b64_json) {
633
+ images.push(item.b64_json);
634
+ } else if (item.url) {
635
+ images.push(item.url);
636
+ }
637
+ }
638
+ return {
639
+ images,
640
+ warnings,
641
+ response: {
642
+ timestamp: /* @__PURE__ */ new Date(),
643
+ modelId: this.modelId,
644
+ headers: responseHeaders
645
+ }
646
+ };
647
+ }
648
+ };
649
+ var PROVIDER_ID = "anyrouter";
650
+ function createAnyRouter(options = {}) {
651
+ const baseURL = withoutTrailingSlash(options.baseURL ?? DEFAULT_BASE_URL) ?? DEFAULT_BASE_URL;
652
+ function getHeaders() {
653
+ const apiKey = loadApiKey({
654
+ apiKey: options.apiKey,
655
+ environmentVariableName: "ANYROUTER_API_KEY",
656
+ description: "AnyRouter"
657
+ });
658
+ return combineHeaders({ Authorization: `Bearer ${apiKey}` }, options.headers);
659
+ }
660
+ function chatModel(modelId) {
661
+ return new AnyRouterChatLanguageModel(modelId, {
662
+ provider: PROVIDER_ID,
663
+ baseURL,
664
+ headers: getHeaders,
665
+ fetch: options.fetch,
666
+ settings: options
667
+ });
668
+ }
669
+ function embeddingModel(modelId) {
670
+ return new AnyRouterEmbeddingModel(modelId, {
671
+ provider: PROVIDER_ID,
672
+ baseURL,
673
+ headers: getHeaders,
674
+ fetch: options.fetch
675
+ });
676
+ }
677
+ function imageModel(modelId) {
678
+ return new AnyRouterImageModel(modelId, {
679
+ provider: PROVIDER_ID,
680
+ baseURL,
681
+ headers: getHeaders,
682
+ fetch: options.fetch
683
+ });
684
+ }
685
+ const provider = (modelId) => chatModel(modelId);
686
+ const providerObj = Object.assign(provider, {
687
+ // ProviderV3 required fields
688
+ specificationVersion: "v3",
689
+ // ProviderV3 required methods
690
+ languageModel(modelId) {
691
+ return chatModel(modelId);
692
+ },
693
+ embeddingModel(modelId) {
694
+ return embeddingModel(modelId);
695
+ },
696
+ imageModel(modelId) {
697
+ return imageModel(modelId);
698
+ },
699
+ // ProviderV3 optional methods (deprecated textEmbeddingModel alias)
700
+ textEmbeddingModel(modelId) {
701
+ return embeddingModel(modelId);
702
+ },
703
+ // AnyRouter convenience alias
704
+ chat(modelId) {
705
+ return chatModel(modelId);
706
+ },
707
+ // Unsupported model types — throw NoSuchModelError per ProviderV3 contract
708
+ transcriptionModel(modelId) {
709
+ throw new NoSuchModelError({ modelId, modelType: "transcriptionModel" });
710
+ },
711
+ speechModel(modelId) {
712
+ throw new NoSuchModelError({ modelId, modelType: "speechModel" });
713
+ }
714
+ });
715
+ Object.defineProperty(providerObj, "client", {
716
+ enumerable: true,
717
+ configurable: true,
718
+ get() {
719
+ return new AnyRouter({
720
+ apiKey: options.apiKey,
721
+ baseURL: options.baseURL,
722
+ headers: options.headers,
723
+ fetch: options.fetch
724
+ });
725
+ }
726
+ });
727
+ return providerObj;
728
+ }
729
+ var anyrouter = createAnyRouter();
730
+
731
+ export { AnyRouterChatLanguageModel, AnyRouterEmbeddingModel, AnyRouterImageModel, anyrouter, createAnyRouter };
732
+ //# sourceMappingURL=index.mjs.map
733
+ //# sourceMappingURL=index.mjs.map