@anyr/ai-sdk-provider 0.1.3 → 0.1.6
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/README.md +22 -0
- package/dist/index.d.cts +155 -16
- package/dist/index.d.ts +155 -16
- package/dist/index.js +220 -38
- package/dist/index.mjs +220 -40
- package/package.json +8 -8
package/dist/index.mjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { withoutTrailingSlash, parseProviderOptions, postJsonToApi, createJsonResponseHandler, createJsonErrorResponseHandler, combineHeaders, createEventSourceResponseHandler, loadApiKey, generateId } from '@ai-sdk/provider-utils';
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import { NoSuchModelError, UnsupportedFunctionalityError } from '@ai-sdk/provider';
|
|
4
|
-
import { DEFAULT_BASE_URL, AnyRouter } from '@anyr/sdk';
|
|
4
|
+
import { DEFAULT_BASE_URL, AnyRouter, buildAppAttributionHeaders } from '@anyr/sdk';
|
|
5
5
|
|
|
6
6
|
// src/anyrouter-chat-language-model.ts
|
|
7
|
-
function convertToAnyRouterChatMessages(prompt) {
|
|
7
|
+
function convertToAnyRouterChatMessages(prompt, fileCache) {
|
|
8
8
|
const messages = [];
|
|
9
9
|
for (const message of prompt) {
|
|
10
10
|
switch (message.role) {
|
|
@@ -12,7 +12,7 @@ function convertToAnyRouterChatMessages(prompt) {
|
|
|
12
12
|
messages.push({ role: "system", content: message.content });
|
|
13
13
|
break;
|
|
14
14
|
case "user":
|
|
15
|
-
messages.push(convertUserMessage(message));
|
|
15
|
+
messages.push(convertUserMessage(message, fileCache));
|
|
16
16
|
break;
|
|
17
17
|
case "assistant":
|
|
18
18
|
messages.push(convertAssistantMessage(message));
|
|
@@ -32,7 +32,7 @@ function convertToAnyRouterChatMessages(prompt) {
|
|
|
32
32
|
}
|
|
33
33
|
return messages;
|
|
34
34
|
}
|
|
35
|
-
function convertUserMessage(message) {
|
|
35
|
+
function convertUserMessage(message, fileCache) {
|
|
36
36
|
if (message.content.length === 1 && message.content[0].type === "text") {
|
|
37
37
|
return { role: "user", content: message.content[0].text };
|
|
38
38
|
}
|
|
@@ -43,7 +43,7 @@ function convertUserMessage(message) {
|
|
|
43
43
|
} else if (part.type === "file") {
|
|
44
44
|
const filePart = part;
|
|
45
45
|
const mediaType = filePart.mediaType;
|
|
46
|
-
const url =
|
|
46
|
+
const url = fileDataToString(filePart, mediaType, fileCache);
|
|
47
47
|
if (mediaType.startsWith("image/")) {
|
|
48
48
|
parts.push({ type: "image_url", image_url: { url } });
|
|
49
49
|
} else {
|
|
@@ -123,13 +123,28 @@ function toolResultOutputToString(output) {
|
|
|
123
123
|
return JSON.stringify(output);
|
|
124
124
|
}
|
|
125
125
|
}
|
|
126
|
-
function
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
126
|
+
function fileDataToString(filePart, mediaType, fileCache) {
|
|
127
|
+
const d = filePart.data;
|
|
128
|
+
switch (d.type) {
|
|
129
|
+
case "data": {
|
|
130
|
+
if (typeof d.data === "string") {
|
|
131
|
+
if (d.data.startsWith("data:")) return d.data;
|
|
132
|
+
return `data:${mediaType};base64,${d.data}`;
|
|
133
|
+
}
|
|
134
|
+
return `data:${mediaType};base64,${uint8ArrayToBase64(d.data)}`;
|
|
135
|
+
}
|
|
136
|
+
case "url":
|
|
137
|
+
return d.url.toString();
|
|
138
|
+
case "text":
|
|
139
|
+
return `data:${mediaType};base64,${btoa(d.text)}`;
|
|
140
|
+
case "reference": {
|
|
141
|
+
const entry = fileCache?.lookup(d.reference);
|
|
142
|
+
if (entry) return entry.url;
|
|
143
|
+
throw new UnsupportedFunctionalityError({
|
|
144
|
+
functionality: "Unresolved provider file reference \u2014 call provider.files().uploadFile() first to register the file in the session cache"
|
|
145
|
+
});
|
|
146
|
+
}
|
|
131
147
|
}
|
|
132
|
-
return `data:${mediaType};base64,${uint8ArrayToBase64(data)}`;
|
|
133
148
|
}
|
|
134
149
|
function uint8ArrayToBase64(bytes) {
|
|
135
150
|
let binary = "";
|
|
@@ -146,7 +161,13 @@ var anyRouterProviderOptionsSchema = z.object({
|
|
|
146
161
|
/** Session ID forwarded as `session_id` in the request body. */
|
|
147
162
|
sessionId: z.string().optional(),
|
|
148
163
|
/** Extra body fields merged in last (highest precedence). */
|
|
149
|
-
extraBody: z.record(z.string(), z.unknown()).optional()
|
|
164
|
+
extraBody: z.record(z.string(), z.unknown()).optional(),
|
|
165
|
+
/** Cache this response for N seconds, forwarded as the `cf-aig-cache-ttl` header. */
|
|
166
|
+
cacheTtl: z.number().optional(),
|
|
167
|
+
/** Custom cache key, forwarded as the `cf-aig-cache-key` header. */
|
|
168
|
+
cacheKey: z.string().optional(),
|
|
169
|
+
/** Skip response caching for this call, forwarded as `cf-aig-skip-cache: true`. */
|
|
170
|
+
skipCache: z.boolean().optional()
|
|
150
171
|
});
|
|
151
172
|
var anyRouterErrorSchema = z.object({
|
|
152
173
|
error: z.object({
|
|
@@ -238,6 +259,11 @@ function buildUsage(raw) {
|
|
|
238
259
|
}
|
|
239
260
|
};
|
|
240
261
|
}
|
|
262
|
+
function mapReasoningEffort(reasoning) {
|
|
263
|
+
if (!reasoning || reasoning === "provider-default") return void 0;
|
|
264
|
+
if (reasoning === "xhigh") return "high";
|
|
265
|
+
return reasoning;
|
|
266
|
+
}
|
|
241
267
|
function emitResponseMetadata(chunk, state, fallbackModelId, controller) {
|
|
242
268
|
if (state.metadataEmitted || !(chunk.id || chunk.model)) return;
|
|
243
269
|
state.metadataEmitted = true;
|
|
@@ -247,7 +273,21 @@ function emitResponseMetadata(chunk, state, fallbackModelId, controller) {
|
|
|
247
273
|
modelId: chunk.model ?? fallbackModelId
|
|
248
274
|
});
|
|
249
275
|
}
|
|
276
|
+
function closeReasoning(state, controller) {
|
|
277
|
+
if (state.activeReasoningId !== null) {
|
|
278
|
+
controller.enqueue({ type: "reasoning-end", id: state.activeReasoningId });
|
|
279
|
+
state.activeReasoningId = null;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
function emitReasoningDelta(content, state, controller) {
|
|
283
|
+
if (state.activeReasoningId === null) {
|
|
284
|
+
state.activeReasoningId = generateId();
|
|
285
|
+
controller.enqueue({ type: "reasoning-start", id: state.activeReasoningId });
|
|
286
|
+
}
|
|
287
|
+
controller.enqueue({ type: "reasoning-delta", id: state.activeReasoningId, delta: content });
|
|
288
|
+
}
|
|
250
289
|
function emitTextDelta(content, state, controller) {
|
|
290
|
+
closeReasoning(state, controller);
|
|
251
291
|
if (state.activeTextId === null) {
|
|
252
292
|
state.activeTextId = generateId();
|
|
253
293
|
controller.enqueue({ type: "text-start", id: state.activeTextId });
|
|
@@ -276,7 +316,8 @@ function emitToolCallDeltas(toolCalls, acc, controller) {
|
|
|
276
316
|
}
|
|
277
317
|
}
|
|
278
318
|
}
|
|
279
|
-
function emitFinish(choice,
|
|
319
|
+
function emitFinish(choice, usage, state, acc, controller) {
|
|
320
|
+
closeReasoning(state, controller);
|
|
280
321
|
if (state.activeTextId !== null) {
|
|
281
322
|
controller.enqueue({ type: "text-end", id: state.activeTextId });
|
|
282
323
|
state.activeTextId = null;
|
|
@@ -294,8 +335,8 @@ function emitFinish(choice, chunk, state, acc, controller) {
|
|
|
294
335
|
}
|
|
295
336
|
controller.enqueue({
|
|
296
337
|
type: "finish",
|
|
297
|
-
usage: buildUsage(
|
|
298
|
-
finishReason: mapFinishReason(choice
|
|
338
|
+
usage: buildUsage(usage),
|
|
339
|
+
finishReason: mapFinishReason(choice?.finish_reason)
|
|
299
340
|
});
|
|
300
341
|
}
|
|
301
342
|
function mapToolChoice(toolChoice) {
|
|
@@ -343,14 +384,15 @@ function buildTools(tools) {
|
|
|
343
384
|
}));
|
|
344
385
|
return fns.length > 0 ? fns : void 0;
|
|
345
386
|
}
|
|
346
|
-
function buildRequestBody(modelId, options, settings, stream, perCallOptions) {
|
|
347
|
-
const messages = convertToAnyRouterChatMessages(options.prompt);
|
|
387
|
+
function buildRequestBody(modelId, options, settings, stream, perCallOptions, fileCache) {
|
|
388
|
+
const messages = convertToAnyRouterChatMessages(options.prompt, fileCache);
|
|
348
389
|
const responseFormat = buildResponseFormat(options.responseFormat);
|
|
349
390
|
const tools = buildTools(options.tools);
|
|
350
391
|
const toolChoice = mapToolChoice(options.toolChoice);
|
|
351
392
|
const provider = perCallOptions.provider ?? settings.provider;
|
|
352
393
|
const sessionId = perCallOptions.sessionId ?? settings.sessionId;
|
|
353
394
|
const extraBody = { ...settings.extraBody, ...perCallOptions.extraBody };
|
|
395
|
+
const reasoningEffort = mapReasoningEffort(options.reasoning);
|
|
354
396
|
const body = {
|
|
355
397
|
model: modelId,
|
|
356
398
|
messages,
|
|
@@ -368,6 +410,7 @@ function buildRequestBody(modelId, options, settings, stream, perCallOptions) {
|
|
|
368
410
|
tool_choice: toolChoice,
|
|
369
411
|
provider: provider ?? void 0,
|
|
370
412
|
session_id: sessionId ?? void 0,
|
|
413
|
+
reasoning_effort: reasoningEffort,
|
|
371
414
|
...extraBody
|
|
372
415
|
};
|
|
373
416
|
for (const key of Object.keys(body)) {
|
|
@@ -375,8 +418,18 @@ function buildRequestBody(modelId, options, settings, stream, perCallOptions) {
|
|
|
375
418
|
}
|
|
376
419
|
return body;
|
|
377
420
|
}
|
|
421
|
+
function buildCacheHeaders(settings, perCallOptions) {
|
|
422
|
+
const cacheTtl = perCallOptions.cacheTtl ?? settings.cacheTtl;
|
|
423
|
+
const cacheKey = perCallOptions.cacheKey ?? settings.cacheKey;
|
|
424
|
+
const skipCache = perCallOptions.skipCache ?? settings.skipCache;
|
|
425
|
+
const headers = {};
|
|
426
|
+
if (cacheTtl !== void 0) headers["cf-aig-cache-ttl"] = String(cacheTtl);
|
|
427
|
+
if (cacheKey !== void 0) headers["cf-aig-cache-key"] = cacheKey;
|
|
428
|
+
if (skipCache === true) headers["cf-aig-skip-cache"] = "true";
|
|
429
|
+
return headers;
|
|
430
|
+
}
|
|
378
431
|
var AnyRouterChatLanguageModel = class {
|
|
379
|
-
specificationVersion = "
|
|
432
|
+
specificationVersion = "v4";
|
|
380
433
|
provider;
|
|
381
434
|
modelId;
|
|
382
435
|
supportedUrls = {};
|
|
@@ -398,11 +451,16 @@ var AnyRouterChatLanguageModel = class {
|
|
|
398
451
|
options,
|
|
399
452
|
this.config.settings,
|
|
400
453
|
false,
|
|
401
|
-
perCallOptions
|
|
454
|
+
perCallOptions,
|
|
455
|
+
this.config.fileCache
|
|
402
456
|
);
|
|
403
457
|
const { value: response, responseHeaders } = await postJsonToApi({
|
|
404
458
|
url: `${this.config.baseURL}/chat/completions`,
|
|
405
|
-
headers: combineHeaders(
|
|
459
|
+
headers: combineHeaders(
|
|
460
|
+
this.config.headers(),
|
|
461
|
+
buildCacheHeaders(this.config.settings, perCallOptions),
|
|
462
|
+
options.headers
|
|
463
|
+
),
|
|
406
464
|
body,
|
|
407
465
|
failedResponseHandler: createJsonErrorResponseHandler({
|
|
408
466
|
errorSchema: anyRouterErrorSchema,
|
|
@@ -416,6 +474,9 @@ var AnyRouterChatLanguageModel = class {
|
|
|
416
474
|
const choice = response.choices?.[0];
|
|
417
475
|
const message = choice?.message;
|
|
418
476
|
const content = [];
|
|
477
|
+
if (message?.reasoning_content) {
|
|
478
|
+
content.push({ type: "reasoning", text: message.reasoning_content });
|
|
479
|
+
}
|
|
419
480
|
if (message?.content) {
|
|
420
481
|
content.push({ type: "text", text: message.content });
|
|
421
482
|
}
|
|
@@ -451,10 +512,21 @@ var AnyRouterChatLanguageModel = class {
|
|
|
451
512
|
providerOptions: options.providerOptions,
|
|
452
513
|
schema: anyRouterProviderOptionsSchema
|
|
453
514
|
}) ?? {};
|
|
454
|
-
const body = buildRequestBody(
|
|
515
|
+
const body = buildRequestBody(
|
|
516
|
+
this.modelId,
|
|
517
|
+
options,
|
|
518
|
+
this.config.settings,
|
|
519
|
+
true,
|
|
520
|
+
perCallOptions,
|
|
521
|
+
this.config.fileCache
|
|
522
|
+
);
|
|
455
523
|
const { value: stream, responseHeaders } = await postJsonToApi({
|
|
456
524
|
url: `${this.config.baseURL}/chat/completions`,
|
|
457
|
-
headers: combineHeaders(
|
|
525
|
+
headers: combineHeaders(
|
|
526
|
+
this.config.headers(),
|
|
527
|
+
buildCacheHeaders(this.config.settings, perCallOptions),
|
|
528
|
+
options.headers
|
|
529
|
+
),
|
|
458
530
|
body,
|
|
459
531
|
failedResponseHandler: createJsonErrorResponseHandler({
|
|
460
532
|
errorSchema: anyRouterErrorSchema,
|
|
@@ -466,8 +538,14 @@ var AnyRouterChatLanguageModel = class {
|
|
|
466
538
|
fetch: this.config.fetch
|
|
467
539
|
});
|
|
468
540
|
const toolCallAccumulator = {};
|
|
469
|
-
const state = {
|
|
541
|
+
const state = {
|
|
542
|
+
activeTextId: null,
|
|
543
|
+
activeReasoningId: null,
|
|
544
|
+
metadataEmitted: false
|
|
545
|
+
};
|
|
470
546
|
const selfModelId = this.modelId;
|
|
547
|
+
let streamUsage;
|
|
548
|
+
let finishChoice;
|
|
471
549
|
const transformStream = new TransformStream({
|
|
472
550
|
start(controller) {
|
|
473
551
|
controller.enqueue({ type: "stream-start", warnings: [] });
|
|
@@ -479,9 +557,13 @@ var AnyRouterChatLanguageModel = class {
|
|
|
479
557
|
}
|
|
480
558
|
const chunk = chunkResult.value;
|
|
481
559
|
const choice = chunk.choices?.[0];
|
|
560
|
+
if (chunk.usage) streamUsage = chunk.usage;
|
|
482
561
|
emitResponseMetadata(chunk, state, selfModelId, controller);
|
|
483
562
|
const delta = choice?.delta;
|
|
484
563
|
if (delta) {
|
|
564
|
+
if (typeof delta.reasoning_content === "string" && delta.reasoning_content.length > 0) {
|
|
565
|
+
emitReasoningDelta(delta.reasoning_content, state, controller);
|
|
566
|
+
}
|
|
485
567
|
if (typeof delta.content === "string" && delta.content.length > 0) {
|
|
486
568
|
emitTextDelta(delta.content, state, controller);
|
|
487
569
|
}
|
|
@@ -490,13 +572,11 @@ var AnyRouterChatLanguageModel = class {
|
|
|
490
572
|
}
|
|
491
573
|
}
|
|
492
574
|
if (choice?.finish_reason) {
|
|
493
|
-
|
|
575
|
+
finishChoice = choice;
|
|
494
576
|
}
|
|
495
577
|
},
|
|
496
578
|
flush(controller) {
|
|
497
|
-
|
|
498
|
-
controller.enqueue({ type: "text-end", id: state.activeTextId });
|
|
499
|
-
}
|
|
579
|
+
emitFinish(finishChoice, streamUsage, state, toolCallAccumulator, controller);
|
|
500
580
|
}
|
|
501
581
|
});
|
|
502
582
|
return {
|
|
@@ -524,7 +604,7 @@ var embeddingResponseSchema = z.object({
|
|
|
524
604
|
}).optional()
|
|
525
605
|
});
|
|
526
606
|
var AnyRouterEmbeddingModel = class {
|
|
527
|
-
specificationVersion = "
|
|
607
|
+
specificationVersion = "v4";
|
|
528
608
|
provider;
|
|
529
609
|
modelId;
|
|
530
610
|
/** No hard per-call limit imposed by the provider layer. */
|
|
@@ -562,6 +642,94 @@ var AnyRouterEmbeddingModel = class {
|
|
|
562
642
|
};
|
|
563
643
|
}
|
|
564
644
|
};
|
|
645
|
+
|
|
646
|
+
// src/file-reference-cache.ts
|
|
647
|
+
var PROVIDER_KEY = "anyrouter";
|
|
648
|
+
var FileReferenceCache = class {
|
|
649
|
+
store = /* @__PURE__ */ new Map();
|
|
650
|
+
/**
|
|
651
|
+
* Look up a cached entry via a `SharedV4ProviderReference`.
|
|
652
|
+
* Returns `undefined` when the reference was not created by this cache.
|
|
653
|
+
*/
|
|
654
|
+
lookup(reference) {
|
|
655
|
+
const hash = reference[PROVIDER_KEY];
|
|
656
|
+
return hash ? this.store.get(hash) : void 0;
|
|
657
|
+
}
|
|
658
|
+
/** Add an entry and return the corresponding provider reference. */
|
|
659
|
+
set(hash, entry) {
|
|
660
|
+
this.store.set(hash, entry);
|
|
661
|
+
return { [PROVIDER_KEY]: hash };
|
|
662
|
+
}
|
|
663
|
+
/** Returns true when the content hash is already cached. */
|
|
664
|
+
has(hash) {
|
|
665
|
+
return this.store.has(hash);
|
|
666
|
+
}
|
|
667
|
+
/**
|
|
668
|
+
* Build a `SharedV4ProviderReference` for the given hash without writing
|
|
669
|
+
* to the cache. Use this to construct the return value of `uploadFile`
|
|
670
|
+
* after confirming the hash is already stored.
|
|
671
|
+
*/
|
|
672
|
+
referenceFor(hash) {
|
|
673
|
+
return { [PROVIDER_KEY]: hash };
|
|
674
|
+
}
|
|
675
|
+
};
|
|
676
|
+
async function hashFileData(data) {
|
|
677
|
+
let bytes;
|
|
678
|
+
if (data.type === "text") {
|
|
679
|
+
bytes = new TextEncoder().encode(data.text);
|
|
680
|
+
} else if (typeof data.data === "string") {
|
|
681
|
+
bytes = new TextEncoder().encode(data.data);
|
|
682
|
+
} else {
|
|
683
|
+
bytes = data.data;
|
|
684
|
+
}
|
|
685
|
+
const hashBuffer = await crypto.subtle.digest("SHA-256", Uint8Array.from(bytes));
|
|
686
|
+
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
687
|
+
return hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
688
|
+
}
|
|
689
|
+
function fileDataVariantToUrl(data, mediaType) {
|
|
690
|
+
if (data.type === "text") {
|
|
691
|
+
return `data:${mediaType};base64,${btoa(data.text)}`;
|
|
692
|
+
}
|
|
693
|
+
if (typeof data.data === "string") {
|
|
694
|
+
if (data.data.startsWith("data:")) return data.data;
|
|
695
|
+
return `data:${mediaType};base64,${data.data}`;
|
|
696
|
+
}
|
|
697
|
+
let binary = "";
|
|
698
|
+
for (let i = 0; i < data.data.length; i++) {
|
|
699
|
+
binary += String.fromCharCode(data.data[i]);
|
|
700
|
+
}
|
|
701
|
+
return `data:${mediaType};base64,${btoa(binary)}`;
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
// src/anyrouter-files.ts
|
|
705
|
+
var AnyRouterFiles = class {
|
|
706
|
+
specificationVersion = "v4";
|
|
707
|
+
provider;
|
|
708
|
+
cache;
|
|
709
|
+
constructor(provider, cache) {
|
|
710
|
+
this.provider = provider;
|
|
711
|
+
this.cache = cache;
|
|
712
|
+
}
|
|
713
|
+
/**
|
|
714
|
+
* Register a file in the in-session cache and return a provider reference.
|
|
715
|
+
*
|
|
716
|
+
* Calling this multiple times with the same file content is idempotent —
|
|
717
|
+
* the hash check prevents redundant re-encoding.
|
|
718
|
+
*/
|
|
719
|
+
async uploadFile(options) {
|
|
720
|
+
const hash = await hashFileData(options.data);
|
|
721
|
+
if (!this.cache.has(hash)) {
|
|
722
|
+
const url = fileDataVariantToUrl(options.data, options.mediaType);
|
|
723
|
+
this.cache.set(hash, { url, mediaType: options.mediaType });
|
|
724
|
+
}
|
|
725
|
+
return {
|
|
726
|
+
providerReference: this.cache.referenceFor(hash),
|
|
727
|
+
mediaType: options.mediaType,
|
|
728
|
+
filename: options.filename,
|
|
729
|
+
warnings: []
|
|
730
|
+
};
|
|
731
|
+
}
|
|
732
|
+
};
|
|
565
733
|
var anyRouterErrorSchema3 = z.object({
|
|
566
734
|
error: z.object({
|
|
567
735
|
code: z.string().optional(),
|
|
@@ -579,7 +747,7 @@ var imageGenerationResponseSchema = z.object({
|
|
|
579
747
|
)
|
|
580
748
|
});
|
|
581
749
|
var AnyRouterImageModel = class {
|
|
582
|
-
specificationVersion = "
|
|
750
|
+
specificationVersion = "v4";
|
|
583
751
|
provider;
|
|
584
752
|
modelId;
|
|
585
753
|
/**
|
|
@@ -599,6 +767,11 @@ var AnyRouterImageModel = class {
|
|
|
599
767
|
functionality: "mask (inpainting) for AnyRouter image generation"
|
|
600
768
|
});
|
|
601
769
|
}
|
|
770
|
+
if (options.files && options.files.length > 0) {
|
|
771
|
+
throw new UnsupportedFunctionalityError({
|
|
772
|
+
functionality: "image editing (files) for AnyRouter image generation"
|
|
773
|
+
});
|
|
774
|
+
}
|
|
602
775
|
const warnings = [];
|
|
603
776
|
if (options.n > 1) {
|
|
604
777
|
warnings.push({
|
|
@@ -649,13 +822,18 @@ var AnyRouterImageModel = class {
|
|
|
649
822
|
var PROVIDER_ID = "anyrouter";
|
|
650
823
|
function createAnyRouter(options = {}) {
|
|
651
824
|
const baseURL = withoutTrailingSlash(options.baseURL ?? DEFAULT_BASE_URL) ?? DEFAULT_BASE_URL;
|
|
825
|
+
const sharedFileCache = new FileReferenceCache();
|
|
652
826
|
function getHeaders() {
|
|
827
|
+
const attribution = options.app ? buildAppAttributionHeaders(options.app) : {};
|
|
828
|
+
if (options.keyless) {
|
|
829
|
+
return combineHeaders(attribution, options.headers);
|
|
830
|
+
}
|
|
653
831
|
const apiKey = loadApiKey({
|
|
654
832
|
apiKey: options.apiKey,
|
|
655
833
|
environmentVariableName: "ANYROUTER_API_KEY",
|
|
656
834
|
description: "AnyRouter"
|
|
657
835
|
});
|
|
658
|
-
return combineHeaders({ Authorization: `Bearer ${apiKey}
|
|
836
|
+
return combineHeaders({ Authorization: `Bearer ${apiKey}`, ...attribution }, options.headers);
|
|
659
837
|
}
|
|
660
838
|
function chatModel(modelId) {
|
|
661
839
|
return new AnyRouterChatLanguageModel(modelId, {
|
|
@@ -663,7 +841,8 @@ function createAnyRouter(options = {}) {
|
|
|
663
841
|
baseURL,
|
|
664
842
|
headers: getHeaders,
|
|
665
843
|
fetch: options.fetch,
|
|
666
|
-
settings: options
|
|
844
|
+
settings: options,
|
|
845
|
+
fileCache: sharedFileCache
|
|
667
846
|
});
|
|
668
847
|
}
|
|
669
848
|
function embeddingModel(modelId) {
|
|
@@ -684,9 +863,9 @@ function createAnyRouter(options = {}) {
|
|
|
684
863
|
}
|
|
685
864
|
const provider = (modelId) => chatModel(modelId);
|
|
686
865
|
const providerObj = Object.assign(provider, {
|
|
687
|
-
//
|
|
688
|
-
specificationVersion: "
|
|
689
|
-
//
|
|
866
|
+
// ProviderV4 required fields
|
|
867
|
+
specificationVersion: "v4",
|
|
868
|
+
// ProviderV4 required methods
|
|
690
869
|
languageModel(modelId) {
|
|
691
870
|
return chatModel(modelId);
|
|
692
871
|
},
|
|
@@ -696,15 +875,15 @@ function createAnyRouter(options = {}) {
|
|
|
696
875
|
imageModel(modelId) {
|
|
697
876
|
return imageModel(modelId);
|
|
698
877
|
},
|
|
699
|
-
// ProviderV3 optional methods (deprecated textEmbeddingModel alias)
|
|
700
|
-
textEmbeddingModel(modelId) {
|
|
701
|
-
return embeddingModel(modelId);
|
|
702
|
-
},
|
|
703
878
|
// AnyRouter convenience alias
|
|
704
879
|
chat(modelId) {
|
|
705
880
|
return chatModel(modelId);
|
|
706
881
|
},
|
|
707
|
-
//
|
|
882
|
+
// ProviderV4 file-management interface
|
|
883
|
+
files() {
|
|
884
|
+
return new AnyRouterFiles(PROVIDER_ID, sharedFileCache);
|
|
885
|
+
},
|
|
886
|
+
// Unsupported optional model types — throw NoSuchModelError per ProviderV4 contract
|
|
708
887
|
transcriptionModel(modelId) {
|
|
709
888
|
throw new NoSuchModelError({ modelId, modelType: "transcriptionModel" });
|
|
710
889
|
},
|
|
@@ -720,6 +899,7 @@ function createAnyRouter(options = {}) {
|
|
|
720
899
|
apiKey: options.apiKey,
|
|
721
900
|
baseURL: options.baseURL,
|
|
722
901
|
headers: options.headers,
|
|
902
|
+
app: options.app,
|
|
723
903
|
fetch: options.fetch
|
|
724
904
|
});
|
|
725
905
|
}
|
|
@@ -728,4 +908,4 @@ function createAnyRouter(options = {}) {
|
|
|
728
908
|
}
|
|
729
909
|
var anyrouter = createAnyRouter();
|
|
730
910
|
|
|
731
|
-
export { AnyRouterChatLanguageModel, AnyRouterEmbeddingModel, AnyRouterImageModel, anyrouter, createAnyRouter };
|
|
911
|
+
export { AnyRouterChatLanguageModel, AnyRouterEmbeddingModel, AnyRouterFiles, AnyRouterImageModel, FileReferenceCache, anyrouter, createAnyRouter };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@anyr/ai-sdk-provider",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "The AnyRouter provider for the Vercel AI SDK — call every AnyRouter model through `createAnyRouter`.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -61,19 +61,19 @@
|
|
|
61
61
|
"access": "public"
|
|
62
62
|
},
|
|
63
63
|
"dependencies": {
|
|
64
|
-
"@anyr/sdk": "^0.1.
|
|
64
|
+
"@anyr/sdk": "^0.1.3"
|
|
65
65
|
},
|
|
66
66
|
"peerDependencies": {
|
|
67
|
-
"@ai-sdk/provider": "^
|
|
68
|
-
"@ai-sdk/provider-utils": "^
|
|
69
|
-
"ai": "^
|
|
67
|
+
"@ai-sdk/provider": "^4.0.0",
|
|
68
|
+
"@ai-sdk/provider-utils": "^5.0.0",
|
|
69
|
+
"ai": "^7.0.0",
|
|
70
70
|
"zod": "^3.25.0 || ^4.0.0"
|
|
71
71
|
},
|
|
72
72
|
"devDependencies": {
|
|
73
|
-
"@ai-sdk/provider": "^
|
|
74
|
-
"@ai-sdk/provider-utils": "^
|
|
73
|
+
"@ai-sdk/provider": "^4.0.0",
|
|
74
|
+
"@ai-sdk/provider-utils": "^5.0.0",
|
|
75
75
|
"@types/node": "^24.0.0",
|
|
76
|
-
"ai": "^
|
|
76
|
+
"ai": "^7.0.0",
|
|
77
77
|
"zod": "^4.4.3"
|
|
78
78
|
}
|
|
79
79
|
}
|