@anyr/ai-sdk-provider 0.1.6 → 0.1.7
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 +2 -20
- package/dist/index.d.cts +41 -30
- package/dist/index.d.ts +41 -30
- package/dist/index.js +74 -129
- package/dist/index.mjs +73 -129
- package/package.json +13 -9
package/README.md
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
The [AnyRouter](https://anyrouter.dev) provider for the [Vercel AI SDK](https://ai-sdk.dev).
|
|
4
4
|
|
|
5
5
|
Call every model on the AnyRouter gateway through the standard AI SDK
|
|
6
|
-
interface — `generateText`, `streamText`, `generateObject`, `embedMany
|
|
7
|
-
|
|
6
|
+
interface — `generateText`, `streamText`, `generateObject`, `embedMany` —
|
|
7
|
+
with one key and one provider.
|
|
8
8
|
|
|
9
9
|
## Install
|
|
10
10
|
|
|
@@ -147,23 +147,6 @@ const { embeddings } = await embedMany({
|
|
|
147
147
|
console.log(embeddings[0]) // [0.123, -0.456, ...]
|
|
148
148
|
```
|
|
149
149
|
|
|
150
|
-
### Image generation
|
|
151
|
-
|
|
152
|
-
```ts
|
|
153
|
-
import { createAnyRouter } from "@anyr/ai-sdk-provider"
|
|
154
|
-
import { generateImage } from "ai"
|
|
155
|
-
|
|
156
|
-
const anyrouter = createAnyRouter()
|
|
157
|
-
|
|
158
|
-
const { image } = await generateImage({
|
|
159
|
-
model: anyrouter.imageModel("openai/dall-e-3"),
|
|
160
|
-
prompt: "A serene mountain lake at dawn, oil painting.",
|
|
161
|
-
size: "1024x1024",
|
|
162
|
-
})
|
|
163
|
-
|
|
164
|
-
// image.base64 — base64-encoded PNG or URL depending on the model
|
|
165
|
-
```
|
|
166
|
-
|
|
167
150
|
### Provider options (routing, session, extra body)
|
|
168
151
|
|
|
169
152
|
```ts
|
|
@@ -227,7 +210,6 @@ const anyrouter = createAnyRouter({
|
|
|
227
210
|
| `anyrouter.chat(modelId)` | `LanguageModelV3` | Chat / instruction language model |
|
|
228
211
|
| `anyrouter.languageModel(modelId)` | `LanguageModelV3` | Alias for `.chat()` (ProviderV3 interface) |
|
|
229
212
|
| `anyrouter.embeddingModel(modelId)` | `EmbeddingModelV3` | Text embedding model |
|
|
230
|
-
| `anyrouter.imageModel(modelId)` | `ImageModelV3` | Image generation model |
|
|
231
213
|
| `anyrouter.client` | `AnyRouter` | Raw `@anyr/sdk` client (escape hatch) |
|
|
232
214
|
|
|
233
215
|
## Default export
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,43 @@
|
|
|
1
|
-
import { SharedV4ProviderReference, LanguageModelV4, LanguageModelV4CallOptions, LanguageModelV4GenerateResult, LanguageModelV4StreamResult, EmbeddingModelV4, EmbeddingModelV4CallOptions, EmbeddingModelV4Result, FilesV4, FilesV4UploadFileCallOptions, FilesV4UploadFileResult,
|
|
2
|
-
import {
|
|
1
|
+
import { SharedV4ProviderReference, LanguageModelV4, LanguageModelV4CallOptions, LanguageModelV4GenerateResult, LanguageModelV4StreamResult, EmbeddingModelV4, EmbeddingModelV4CallOptions, EmbeddingModelV4Result, FilesV4, FilesV4UploadFileCallOptions, FilesV4UploadFileResult, ProviderV4 } from '@ai-sdk/provider';
|
|
2
|
+
import { AnyRouter } from '@anyr/sdk';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Identity of the client making the request. Mirrors the `X-AnyRouter-*`
|
|
6
|
+
* headers the gateway reads in `inference-telemetry.ts`.
|
|
7
|
+
*/
|
|
8
|
+
interface AppAttribution {
|
|
9
|
+
/**
|
|
10
|
+
* Stable machine identifier, becomes `generations.app_source`. Use a slug
|
|
11
|
+
* (`anyr-cli`, `anyr-agent`), not a display name.
|
|
12
|
+
*/
|
|
13
|
+
source?: string;
|
|
14
|
+
/** Human-readable name, becomes `generations.app_title`. */
|
|
15
|
+
title?: string;
|
|
16
|
+
/** Client version, becomes `generations.app_version`. */
|
|
17
|
+
version?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Curation categories (e.g. `cli-agent`). The gateway allowlists these and
|
|
20
|
+
* keeps at most two per request; unknown values are dropped server-side.
|
|
21
|
+
*/
|
|
22
|
+
categories?: string[];
|
|
23
|
+
/**
|
|
24
|
+
* Public URL identifying the app, sent as `HTTP-Referer`. Only meaningful for
|
|
25
|
+
* apps that want to appear in the public app rankings.
|
|
26
|
+
*/
|
|
27
|
+
url?: string;
|
|
28
|
+
}
|
|
29
|
+
/** This provider's own identity, used when the caller supplies no `app`. */
|
|
30
|
+
declare const PROVIDER_ATTRIBUTION: AppAttribution;
|
|
31
|
+
/**
|
|
32
|
+
* Translate an {@link AppAttribution} into wire headers. Blank/whitespace-only
|
|
33
|
+
* values are omitted rather than sent empty, so a partially-filled identity
|
|
34
|
+
* never overwrites a good value with `""`.
|
|
35
|
+
*
|
|
36
|
+
* Returns `{}` when `app` is undefined, so callers that pass no `app` send no
|
|
37
|
+
* attribution headers by default. This matches the provider contract in
|
|
38
|
+
* `types.ts`: browser callers are attributed by Referer instead.
|
|
39
|
+
*/
|
|
40
|
+
declare function buildAppAttributionHeaders(app: AppAttribution | undefined): Record<string, string>;
|
|
3
41
|
|
|
4
42
|
/**
|
|
5
43
|
* The resolved representation of a cached file — a URL string ready to drop
|
|
@@ -107,13 +145,6 @@ interface AnyRouterProviderSettings {
|
|
|
107
145
|
* Per-call `providerOptions.anyrouter.cacheTtl` takes precedence.
|
|
108
146
|
*/
|
|
109
147
|
cacheTtl?: number;
|
|
110
|
-
/**
|
|
111
|
-
* Custom cache key for Cloudflare AI Gateway response caching, so requests
|
|
112
|
-
* with different content can share a cached response. Sent as
|
|
113
|
-
* `cf-aig-cache-key`. Per-call `providerOptions.anyrouter.cacheKey` takes
|
|
114
|
-
* precedence.
|
|
115
|
-
*/
|
|
116
|
-
cacheKey?: string;
|
|
117
148
|
/**
|
|
118
149
|
* Skip Cloudflare AI Gateway response caching for every request, even if a
|
|
119
150
|
* default cache policy would otherwise apply. Sent as
|
|
@@ -201,26 +232,6 @@ declare class AnyRouterFiles implements FilesV4 {
|
|
|
201
232
|
uploadFile(options: FilesV4UploadFileCallOptions): Promise<FilesV4UploadFileResult>;
|
|
202
233
|
}
|
|
203
234
|
|
|
204
|
-
interface AnyRouterImageConfig {
|
|
205
|
-
provider: string;
|
|
206
|
-
baseURL: string;
|
|
207
|
-
headers: () => Record<string, string | undefined>;
|
|
208
|
-
fetch?: typeof globalThis.fetch;
|
|
209
|
-
}
|
|
210
|
-
declare class AnyRouterImageModel implements ImageModelV4 {
|
|
211
|
-
readonly specificationVersion: "v4";
|
|
212
|
-
readonly provider: string;
|
|
213
|
-
readonly modelId: string;
|
|
214
|
-
/**
|
|
215
|
-
* Most image generation APIs support only 1 image per call via the
|
|
216
|
-
* standard `/images/generations` endpoint.
|
|
217
|
-
*/
|
|
218
|
-
readonly maxImagesPerCall = 1;
|
|
219
|
-
private readonly config;
|
|
220
|
-
constructor(modelId: string, config: AnyRouterImageConfig);
|
|
221
|
-
doGenerate(options: ImageModelV4CallOptions): Promise<ImageModelV4Result>;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
235
|
interface AnyRouterProvider extends ProviderV4 {
|
|
225
236
|
/** Create a chat language model by calling the provider directly. */
|
|
226
237
|
(modelId: string): LanguageModelV4;
|
|
@@ -285,4 +296,4 @@ declare function createAnyRouter(options?: AnyRouterProviderSettings): AnyRouter
|
|
|
285
296
|
*/
|
|
286
297
|
declare const anyrouter: AnyRouterProvider;
|
|
287
298
|
|
|
288
|
-
export { type AnyRouterChatConfig, AnyRouterChatLanguageModel, type AnyRouterEmbeddingConfig, AnyRouterEmbeddingModel, AnyRouterFiles, type
|
|
299
|
+
export { type AnyRouterChatConfig, AnyRouterChatLanguageModel, type AnyRouterEmbeddingConfig, AnyRouterEmbeddingModel, AnyRouterFiles, type AnyRouterProvider, type AnyRouterProviderSettings, type AppAttribution, FileReferenceCache, PROVIDER_ATTRIBUTION, type ResolvedFileEntry, anyrouter, buildAppAttributionHeaders, createAnyRouter };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,43 @@
|
|
|
1
|
-
import { SharedV4ProviderReference, LanguageModelV4, LanguageModelV4CallOptions, LanguageModelV4GenerateResult, LanguageModelV4StreamResult, EmbeddingModelV4, EmbeddingModelV4CallOptions, EmbeddingModelV4Result, FilesV4, FilesV4UploadFileCallOptions, FilesV4UploadFileResult,
|
|
2
|
-
import {
|
|
1
|
+
import { SharedV4ProviderReference, LanguageModelV4, LanguageModelV4CallOptions, LanguageModelV4GenerateResult, LanguageModelV4StreamResult, EmbeddingModelV4, EmbeddingModelV4CallOptions, EmbeddingModelV4Result, FilesV4, FilesV4UploadFileCallOptions, FilesV4UploadFileResult, ProviderV4 } from '@ai-sdk/provider';
|
|
2
|
+
import { AnyRouter } from '@anyr/sdk';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Identity of the client making the request. Mirrors the `X-AnyRouter-*`
|
|
6
|
+
* headers the gateway reads in `inference-telemetry.ts`.
|
|
7
|
+
*/
|
|
8
|
+
interface AppAttribution {
|
|
9
|
+
/**
|
|
10
|
+
* Stable machine identifier, becomes `generations.app_source`. Use a slug
|
|
11
|
+
* (`anyr-cli`, `anyr-agent`), not a display name.
|
|
12
|
+
*/
|
|
13
|
+
source?: string;
|
|
14
|
+
/** Human-readable name, becomes `generations.app_title`. */
|
|
15
|
+
title?: string;
|
|
16
|
+
/** Client version, becomes `generations.app_version`. */
|
|
17
|
+
version?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Curation categories (e.g. `cli-agent`). The gateway allowlists these and
|
|
20
|
+
* keeps at most two per request; unknown values are dropped server-side.
|
|
21
|
+
*/
|
|
22
|
+
categories?: string[];
|
|
23
|
+
/**
|
|
24
|
+
* Public URL identifying the app, sent as `HTTP-Referer`. Only meaningful for
|
|
25
|
+
* apps that want to appear in the public app rankings.
|
|
26
|
+
*/
|
|
27
|
+
url?: string;
|
|
28
|
+
}
|
|
29
|
+
/** This provider's own identity, used when the caller supplies no `app`. */
|
|
30
|
+
declare const PROVIDER_ATTRIBUTION: AppAttribution;
|
|
31
|
+
/**
|
|
32
|
+
* Translate an {@link AppAttribution} into wire headers. Blank/whitespace-only
|
|
33
|
+
* values are omitted rather than sent empty, so a partially-filled identity
|
|
34
|
+
* never overwrites a good value with `""`.
|
|
35
|
+
*
|
|
36
|
+
* Returns `{}` when `app` is undefined, so callers that pass no `app` send no
|
|
37
|
+
* attribution headers by default. This matches the provider contract in
|
|
38
|
+
* `types.ts`: browser callers are attributed by Referer instead.
|
|
39
|
+
*/
|
|
40
|
+
declare function buildAppAttributionHeaders(app: AppAttribution | undefined): Record<string, string>;
|
|
3
41
|
|
|
4
42
|
/**
|
|
5
43
|
* The resolved representation of a cached file — a URL string ready to drop
|
|
@@ -107,13 +145,6 @@ interface AnyRouterProviderSettings {
|
|
|
107
145
|
* Per-call `providerOptions.anyrouter.cacheTtl` takes precedence.
|
|
108
146
|
*/
|
|
109
147
|
cacheTtl?: number;
|
|
110
|
-
/**
|
|
111
|
-
* Custom cache key for Cloudflare AI Gateway response caching, so requests
|
|
112
|
-
* with different content can share a cached response. Sent as
|
|
113
|
-
* `cf-aig-cache-key`. Per-call `providerOptions.anyrouter.cacheKey` takes
|
|
114
|
-
* precedence.
|
|
115
|
-
*/
|
|
116
|
-
cacheKey?: string;
|
|
117
148
|
/**
|
|
118
149
|
* Skip Cloudflare AI Gateway response caching for every request, even if a
|
|
119
150
|
* default cache policy would otherwise apply. Sent as
|
|
@@ -201,26 +232,6 @@ declare class AnyRouterFiles implements FilesV4 {
|
|
|
201
232
|
uploadFile(options: FilesV4UploadFileCallOptions): Promise<FilesV4UploadFileResult>;
|
|
202
233
|
}
|
|
203
234
|
|
|
204
|
-
interface AnyRouterImageConfig {
|
|
205
|
-
provider: string;
|
|
206
|
-
baseURL: string;
|
|
207
|
-
headers: () => Record<string, string | undefined>;
|
|
208
|
-
fetch?: typeof globalThis.fetch;
|
|
209
|
-
}
|
|
210
|
-
declare class AnyRouterImageModel implements ImageModelV4 {
|
|
211
|
-
readonly specificationVersion: "v4";
|
|
212
|
-
readonly provider: string;
|
|
213
|
-
readonly modelId: string;
|
|
214
|
-
/**
|
|
215
|
-
* Most image generation APIs support only 1 image per call via the
|
|
216
|
-
* standard `/images/generations` endpoint.
|
|
217
|
-
*/
|
|
218
|
-
readonly maxImagesPerCall = 1;
|
|
219
|
-
private readonly config;
|
|
220
|
-
constructor(modelId: string, config: AnyRouterImageConfig);
|
|
221
|
-
doGenerate(options: ImageModelV4CallOptions): Promise<ImageModelV4Result>;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
235
|
interface AnyRouterProvider extends ProviderV4 {
|
|
225
236
|
/** Create a chat language model by calling the provider directly. */
|
|
226
237
|
(modelId: string): LanguageModelV4;
|
|
@@ -285,4 +296,4 @@ declare function createAnyRouter(options?: AnyRouterProviderSettings): AnyRouter
|
|
|
285
296
|
*/
|
|
286
297
|
declare const anyrouter: AnyRouterProvider;
|
|
287
298
|
|
|
288
|
-
export { type AnyRouterChatConfig, AnyRouterChatLanguageModel, type AnyRouterEmbeddingConfig, AnyRouterEmbeddingModel, AnyRouterFiles, type
|
|
299
|
+
export { type AnyRouterChatConfig, AnyRouterChatLanguageModel, type AnyRouterEmbeddingConfig, AnyRouterEmbeddingModel, AnyRouterFiles, type AnyRouterProvider, type AnyRouterProviderSettings, type AppAttribution, FileReferenceCache, PROVIDER_ATTRIBUTION, type ResolvedFileEntry, anyrouter, buildAppAttributionHeaders, createAnyRouter };
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,34 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var provider = require('@ai-sdk/provider');
|
|
3
4
|
var providerUtils = require('@ai-sdk/provider-utils');
|
|
4
5
|
var zod = require('zod');
|
|
5
|
-
var provider = require('@ai-sdk/provider');
|
|
6
6
|
var sdk = require('@anyr/sdk');
|
|
7
7
|
|
|
8
|
-
// src/
|
|
8
|
+
// src/app-attribution.ts
|
|
9
|
+
var APP_SOURCE = "anyr-ai-sdk-provider";
|
|
10
|
+
var APP_TITLE = "AnyRouter AI SDK Provider";
|
|
11
|
+
var APP_VERSION = "0.1.7";
|
|
12
|
+
var PROVIDER_ATTRIBUTION = {
|
|
13
|
+
source: APP_SOURCE,
|
|
14
|
+
title: APP_TITLE,
|
|
15
|
+
version: APP_VERSION
|
|
16
|
+
};
|
|
17
|
+
function buildAppAttributionHeaders(app) {
|
|
18
|
+
if (!app) return {};
|
|
19
|
+
const headers = {};
|
|
20
|
+
const put = (name, value) => {
|
|
21
|
+
const trimmed = value?.trim();
|
|
22
|
+
if (trimmed) headers[name] = trimmed;
|
|
23
|
+
};
|
|
24
|
+
put("X-AnyRouter-Source", app.source);
|
|
25
|
+
put("X-AnyRouter-Title", app.title);
|
|
26
|
+
put("X-AnyRouter-Version", app.version);
|
|
27
|
+
put("HTTP-Referer", app.url);
|
|
28
|
+
const categories = app.categories?.map((c) => c.trim()).filter(Boolean);
|
|
29
|
+
if (categories?.length) headers["X-AnyRouter-Categories"] = categories.join(",");
|
|
30
|
+
return headers;
|
|
31
|
+
}
|
|
9
32
|
function convertToAnyRouterChatMessages(prompt, fileCache) {
|
|
10
33
|
const messages = [];
|
|
11
34
|
for (const message of prompt) {
|
|
@@ -166,8 +189,6 @@ var anyRouterProviderOptionsSchema = zod.z.object({
|
|
|
166
189
|
extraBody: zod.z.record(zod.z.string(), zod.z.unknown()).optional(),
|
|
167
190
|
/** Cache this response for N seconds, forwarded as the `cf-aig-cache-ttl` header. */
|
|
168
191
|
cacheTtl: zod.z.number().optional(),
|
|
169
|
-
/** Custom cache key, forwarded as the `cf-aig-cache-key` header. */
|
|
170
|
-
cacheKey: zod.z.string().optional(),
|
|
171
192
|
/** Skip response caching for this call, forwarded as `cf-aig-skip-cache: true`. */
|
|
172
193
|
skipCache: zod.z.boolean().optional()
|
|
173
194
|
});
|
|
@@ -203,7 +224,7 @@ var toolCallDeltaSchema = zod.z.object({
|
|
|
203
224
|
var messageSchema = zod.z.object({
|
|
204
225
|
content: zod.z.string().nullish(),
|
|
205
226
|
reasoning_content: zod.z.string().nullish(),
|
|
206
|
-
tool_calls: zod.z.array(toolCallSchema).
|
|
227
|
+
tool_calls: zod.z.array(toolCallSchema).nullish()
|
|
207
228
|
});
|
|
208
229
|
var choiceSchema = zod.z.object({
|
|
209
230
|
message: messageSchema.optional(),
|
|
@@ -213,12 +234,12 @@ var generateResponseSchema = zod.z.object({
|
|
|
213
234
|
id: zod.z.string().optional(),
|
|
214
235
|
model: zod.z.string().optional(),
|
|
215
236
|
choices: zod.z.array(choiceSchema).optional(),
|
|
216
|
-
usage: completionUsageSchema.
|
|
237
|
+
usage: completionUsageSchema.nullish()
|
|
217
238
|
});
|
|
218
239
|
var deltaSchema = zod.z.object({
|
|
219
240
|
content: zod.z.string().nullish(),
|
|
220
241
|
reasoning_content: zod.z.string().nullish(),
|
|
221
|
-
tool_calls: zod.z.array(toolCallDeltaSchema).
|
|
242
|
+
tool_calls: zod.z.array(toolCallDeltaSchema).nullish()
|
|
222
243
|
});
|
|
223
244
|
var streamChoiceSchema = zod.z.object({
|
|
224
245
|
delta: deltaSchema.optional(),
|
|
@@ -228,7 +249,10 @@ var streamChunkSchema = zod.z.object({
|
|
|
228
249
|
id: zod.z.string().optional(),
|
|
229
250
|
model: zod.z.string().optional(),
|
|
230
251
|
choices: zod.z.array(streamChoiceSchema).optional(),
|
|
231
|
-
usage: completionUsageSchema.
|
|
252
|
+
usage: completionUsageSchema.nullish(),
|
|
253
|
+
// A mid-stream failure arrives as a `data: {"error":{...}}` frame on a 200
|
|
254
|
+
// response, in the same envelope the gateway uses for non-2xx bodies.
|
|
255
|
+
error: anyRouterErrorSchema.shape.error
|
|
232
256
|
});
|
|
233
257
|
function mapFinishReason(raw) {
|
|
234
258
|
switch (raw) {
|
|
@@ -242,6 +266,8 @@ function mapFinishReason(raw) {
|
|
|
242
266
|
return { unified: "tool-calls", raw };
|
|
243
267
|
case "content_filter":
|
|
244
268
|
return { unified: "content-filter", raw };
|
|
269
|
+
case "error":
|
|
270
|
+
return { unified: "error", raw };
|
|
245
271
|
default:
|
|
246
272
|
return { unified: "other", raw: raw ?? void 0 };
|
|
247
273
|
}
|
|
@@ -318,6 +344,30 @@ function emitToolCallDeltas(toolCalls, acc, controller) {
|
|
|
318
344
|
}
|
|
319
345
|
}
|
|
320
346
|
}
|
|
347
|
+
function emitDelta(delta, state, acc, controller) {
|
|
348
|
+
if (typeof delta.reasoning_content === "string" && delta.reasoning_content.length > 0) {
|
|
349
|
+
emitReasoningDelta(delta.reasoning_content, state, controller);
|
|
350
|
+
}
|
|
351
|
+
if (typeof delta.content === "string" && delta.content.length > 0) {
|
|
352
|
+
emitTextDelta(delta.content, state, controller);
|
|
353
|
+
}
|
|
354
|
+
if (delta.tool_calls) {
|
|
355
|
+
emitToolCallDeltas(delta.tool_calls, acc, controller);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
function errorFramePart(chunk, request) {
|
|
359
|
+
return {
|
|
360
|
+
type: "error",
|
|
361
|
+
error: new provider.APICallError({
|
|
362
|
+
message: chunk.error?.message ?? "AnyRouter API error",
|
|
363
|
+
url: request.url,
|
|
364
|
+
requestBodyValues: request.body,
|
|
365
|
+
responseHeaders: request.responseHeaders,
|
|
366
|
+
responseBody: JSON.stringify(chunk),
|
|
367
|
+
data: chunk
|
|
368
|
+
})
|
|
369
|
+
};
|
|
370
|
+
}
|
|
321
371
|
function emitFinish(choice, usage, state, acc, controller) {
|
|
322
372
|
closeReasoning(state, controller);
|
|
323
373
|
if (state.activeTextId !== null) {
|
|
@@ -422,11 +472,9 @@ function buildRequestBody(modelId, options, settings, stream, perCallOptions, fi
|
|
|
422
472
|
}
|
|
423
473
|
function buildCacheHeaders(settings, perCallOptions) {
|
|
424
474
|
const cacheTtl = perCallOptions.cacheTtl ?? settings.cacheTtl;
|
|
425
|
-
const cacheKey = perCallOptions.cacheKey ?? settings.cacheKey;
|
|
426
475
|
const skipCache = perCallOptions.skipCache ?? settings.skipCache;
|
|
427
476
|
const headers = {};
|
|
428
477
|
if (cacheTtl !== void 0) headers["cf-aig-cache-ttl"] = String(cacheTtl);
|
|
429
|
-
if (cacheKey !== void 0) headers["cf-aig-cache-key"] = cacheKey;
|
|
430
478
|
if (skipCache === true) headers["cf-aig-skip-cache"] = "true";
|
|
431
479
|
return headers;
|
|
432
480
|
}
|
|
@@ -441,7 +489,6 @@ var AnyRouterChatLanguageModel = class {
|
|
|
441
489
|
this.provider = config.provider;
|
|
442
490
|
this.config = config;
|
|
443
491
|
}
|
|
444
|
-
// ─── doGenerate ─────────────────────────────────────────────────────────
|
|
445
492
|
async doGenerate(options) {
|
|
446
493
|
const perCallOptions = await providerUtils.parseProviderOptions({
|
|
447
494
|
provider: "anyrouter",
|
|
@@ -507,7 +554,6 @@ var AnyRouterChatLanguageModel = class {
|
|
|
507
554
|
}
|
|
508
555
|
};
|
|
509
556
|
}
|
|
510
|
-
// ─── doStream ───────────────────────────────────────────────────────────
|
|
511
557
|
async doStream(options) {
|
|
512
558
|
const perCallOptions = await providerUtils.parseProviderOptions({
|
|
513
559
|
provider: "anyrouter",
|
|
@@ -522,8 +568,9 @@ var AnyRouterChatLanguageModel = class {
|
|
|
522
568
|
perCallOptions,
|
|
523
569
|
this.config.fileCache
|
|
524
570
|
);
|
|
571
|
+
const url = `${this.config.baseURL}/chat/completions`;
|
|
525
572
|
const { value: stream, responseHeaders } = await providerUtils.postJsonToApi({
|
|
526
|
-
url
|
|
573
|
+
url,
|
|
527
574
|
headers: providerUtils.combineHeaders(
|
|
528
575
|
this.config.headers(),
|
|
529
576
|
buildCacheHeaders(this.config.settings, perCallOptions),
|
|
@@ -558,21 +605,15 @@ var AnyRouterChatLanguageModel = class {
|
|
|
558
605
|
return;
|
|
559
606
|
}
|
|
560
607
|
const chunk = chunkResult.value;
|
|
608
|
+
if (chunk.error) {
|
|
609
|
+
controller.enqueue(errorFramePart(chunk, { url, body, responseHeaders }));
|
|
610
|
+
finishChoice = { finish_reason: "error" };
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
561
613
|
const choice = chunk.choices?.[0];
|
|
562
614
|
if (chunk.usage) streamUsage = chunk.usage;
|
|
563
615
|
emitResponseMetadata(chunk, state, selfModelId, controller);
|
|
564
|
-
|
|
565
|
-
if (delta) {
|
|
566
|
-
if (typeof delta.reasoning_content === "string" && delta.reasoning_content.length > 0) {
|
|
567
|
-
emitReasoningDelta(delta.reasoning_content, state, controller);
|
|
568
|
-
}
|
|
569
|
-
if (typeof delta.content === "string" && delta.content.length > 0) {
|
|
570
|
-
emitTextDelta(delta.content, state, controller);
|
|
571
|
-
}
|
|
572
|
-
if (delta.tool_calls) {
|
|
573
|
-
emitToolCallDeltas(delta.tool_calls, toolCallAccumulator, controller);
|
|
574
|
-
}
|
|
575
|
-
}
|
|
616
|
+
if (choice?.delta) emitDelta(choice.delta, state, toolCallAccumulator, controller);
|
|
576
617
|
if (choice?.finish_reason) {
|
|
577
618
|
finishChoice = choice;
|
|
578
619
|
}
|
|
@@ -732,101 +773,12 @@ var AnyRouterFiles = class {
|
|
|
732
773
|
};
|
|
733
774
|
}
|
|
734
775
|
};
|
|
735
|
-
var anyRouterErrorSchema3 = zod.z.object({
|
|
736
|
-
error: zod.z.object({
|
|
737
|
-
code: zod.z.string().optional(),
|
|
738
|
-
message: zod.z.string().optional()
|
|
739
|
-
}).optional()
|
|
740
|
-
});
|
|
741
|
-
var imageGenerationResponseSchema = zod.z.object({
|
|
742
|
-
created: zod.z.number().optional(),
|
|
743
|
-
data: zod.z.array(
|
|
744
|
-
zod.z.object({
|
|
745
|
-
url: zod.z.string().optional(),
|
|
746
|
-
b64_json: zod.z.string().optional(),
|
|
747
|
-
revised_prompt: zod.z.string().optional()
|
|
748
|
-
})
|
|
749
|
-
)
|
|
750
|
-
});
|
|
751
|
-
var AnyRouterImageModel = class {
|
|
752
|
-
specificationVersion = "v4";
|
|
753
|
-
provider;
|
|
754
|
-
modelId;
|
|
755
|
-
/**
|
|
756
|
-
* Most image generation APIs support only 1 image per call via the
|
|
757
|
-
* standard `/images/generations` endpoint.
|
|
758
|
-
*/
|
|
759
|
-
maxImagesPerCall = 1;
|
|
760
|
-
config;
|
|
761
|
-
constructor(modelId, config) {
|
|
762
|
-
this.modelId = modelId;
|
|
763
|
-
this.provider = config.provider;
|
|
764
|
-
this.config = config;
|
|
765
|
-
}
|
|
766
|
-
async doGenerate(options) {
|
|
767
|
-
if (options.mask) {
|
|
768
|
-
throw new provider.UnsupportedFunctionalityError({
|
|
769
|
-
functionality: "mask (inpainting) for AnyRouter image generation"
|
|
770
|
-
});
|
|
771
|
-
}
|
|
772
|
-
if (options.files && options.files.length > 0) {
|
|
773
|
-
throw new provider.UnsupportedFunctionalityError({
|
|
774
|
-
functionality: "image editing (files) for AnyRouter image generation"
|
|
775
|
-
});
|
|
776
|
-
}
|
|
777
|
-
const warnings = [];
|
|
778
|
-
if (options.n > 1) {
|
|
779
|
-
warnings.push({
|
|
780
|
-
type: "unsupported",
|
|
781
|
-
feature: `n=${options.n} (AnyRouter image endpoint supports n=1 per call)`
|
|
782
|
-
});
|
|
783
|
-
}
|
|
784
|
-
const body = {
|
|
785
|
-
model: this.modelId,
|
|
786
|
-
prompt: options.prompt ?? "",
|
|
787
|
-
n: Math.min(options.n, 1),
|
|
788
|
-
...options.size ? { size: options.size } : {},
|
|
789
|
-
...options.seed !== void 0 ? { seed: options.seed } : {},
|
|
790
|
-
response_format: "b64_json"
|
|
791
|
-
};
|
|
792
|
-
const { value: response, responseHeaders } = await providerUtils.postJsonToApi({
|
|
793
|
-
url: `${this.config.baseURL}/images/generations`,
|
|
794
|
-
headers: providerUtils.combineHeaders(this.config.headers(), options.headers),
|
|
795
|
-
body,
|
|
796
|
-
failedResponseHandler: providerUtils.createJsonErrorResponseHandler({
|
|
797
|
-
errorSchema: anyRouterErrorSchema3,
|
|
798
|
-
errorToMessage: (data) => data.error?.message ?? "AnyRouter images API error",
|
|
799
|
-
isRetryable: (res) => res.status >= 500
|
|
800
|
-
}),
|
|
801
|
-
successfulResponseHandler: providerUtils.createJsonResponseHandler(imageGenerationResponseSchema),
|
|
802
|
-
abortSignal: options.abortSignal,
|
|
803
|
-
fetch: this.config.fetch
|
|
804
|
-
});
|
|
805
|
-
const images = [];
|
|
806
|
-
for (const item of response.data) {
|
|
807
|
-
if (item.b64_json) {
|
|
808
|
-
images.push(item.b64_json);
|
|
809
|
-
} else if (item.url) {
|
|
810
|
-
images.push(item.url);
|
|
811
|
-
}
|
|
812
|
-
}
|
|
813
|
-
return {
|
|
814
|
-
images,
|
|
815
|
-
warnings,
|
|
816
|
-
response: {
|
|
817
|
-
timestamp: /* @__PURE__ */ new Date(),
|
|
818
|
-
modelId: this.modelId,
|
|
819
|
-
headers: responseHeaders
|
|
820
|
-
}
|
|
821
|
-
};
|
|
822
|
-
}
|
|
823
|
-
};
|
|
824
776
|
var PROVIDER_ID = "anyrouter";
|
|
825
777
|
function createAnyRouter(options = {}) {
|
|
826
778
|
const baseURL = providerUtils.withoutTrailingSlash(options.baseURL ?? sdk.DEFAULT_BASE_URL) ?? sdk.DEFAULT_BASE_URL;
|
|
827
779
|
const sharedFileCache = new FileReferenceCache();
|
|
828
780
|
function getHeaders() {
|
|
829
|
-
const attribution = options.app ?
|
|
781
|
+
const attribution = options.app ? buildAppAttributionHeaders(options.app) : {};
|
|
830
782
|
if (options.keyless) {
|
|
831
783
|
return providerUtils.combineHeaders(attribution, options.headers);
|
|
832
784
|
}
|
|
@@ -855,14 +807,6 @@ function createAnyRouter(options = {}) {
|
|
|
855
807
|
fetch: options.fetch
|
|
856
808
|
});
|
|
857
809
|
}
|
|
858
|
-
function imageModel(modelId) {
|
|
859
|
-
return new AnyRouterImageModel(modelId, {
|
|
860
|
-
provider: PROVIDER_ID,
|
|
861
|
-
baseURL,
|
|
862
|
-
headers: getHeaders,
|
|
863
|
-
fetch: options.fetch
|
|
864
|
-
});
|
|
865
|
-
}
|
|
866
810
|
const provider$1 = (modelId) => chatModel(modelId);
|
|
867
811
|
const providerObj = Object.assign(provider$1, {
|
|
868
812
|
// ProviderV4 required fields
|
|
@@ -874,9 +818,6 @@ function createAnyRouter(options = {}) {
|
|
|
874
818
|
embeddingModel(modelId) {
|
|
875
819
|
return embeddingModel(modelId);
|
|
876
820
|
},
|
|
877
|
-
imageModel(modelId) {
|
|
878
|
-
return imageModel(modelId);
|
|
879
|
-
},
|
|
880
821
|
// AnyRouter convenience alias
|
|
881
822
|
chat(modelId) {
|
|
882
823
|
return chatModel(modelId);
|
|
@@ -885,7 +826,11 @@ function createAnyRouter(options = {}) {
|
|
|
885
826
|
files() {
|
|
886
827
|
return new AnyRouterFiles(PROVIDER_ID, sharedFileCache);
|
|
887
828
|
},
|
|
888
|
-
// Unsupported optional model types — throw NoSuchModelError per ProviderV4 contract
|
|
829
|
+
// Unsupported optional model types — throw NoSuchModelError per ProviderV4 contract.
|
|
830
|
+
// Image/video generation is not an AnyRouter product (text + embeddings only).
|
|
831
|
+
imageModel(modelId) {
|
|
832
|
+
throw new provider.NoSuchModelError({ modelId, modelType: "imageModel" });
|
|
833
|
+
},
|
|
889
834
|
transcriptionModel(modelId) {
|
|
890
835
|
throw new provider.NoSuchModelError({ modelId, modelType: "transcriptionModel" });
|
|
891
836
|
},
|
|
@@ -901,7 +846,6 @@ function createAnyRouter(options = {}) {
|
|
|
901
846
|
apiKey: options.apiKey,
|
|
902
847
|
baseURL: options.baseURL,
|
|
903
848
|
headers: options.headers,
|
|
904
|
-
app: options.app,
|
|
905
849
|
fetch: options.fetch
|
|
906
850
|
});
|
|
907
851
|
}
|
|
@@ -913,7 +857,8 @@ var anyrouter = createAnyRouter();
|
|
|
913
857
|
exports.AnyRouterChatLanguageModel = AnyRouterChatLanguageModel;
|
|
914
858
|
exports.AnyRouterEmbeddingModel = AnyRouterEmbeddingModel;
|
|
915
859
|
exports.AnyRouterFiles = AnyRouterFiles;
|
|
916
|
-
exports.AnyRouterImageModel = AnyRouterImageModel;
|
|
917
860
|
exports.FileReferenceCache = FileReferenceCache;
|
|
861
|
+
exports.PROVIDER_ATTRIBUTION = PROVIDER_ATTRIBUTION;
|
|
918
862
|
exports.anyrouter = anyrouter;
|
|
863
|
+
exports.buildAppAttributionHeaders = buildAppAttributionHeaders;
|
|
919
864
|
exports.createAnyRouter = createAnyRouter;
|
package/dist/index.mjs
CHANGED
|
@@ -1,9 +1,32 @@
|
|
|
1
|
+
import { NoSuchModelError, APICallError, UnsupportedFunctionalityError } from '@ai-sdk/provider';
|
|
1
2
|
import { withoutTrailingSlash, parseProviderOptions, postJsonToApi, createJsonResponseHandler, createJsonErrorResponseHandler, combineHeaders, createEventSourceResponseHandler, loadApiKey, generateId } from '@ai-sdk/provider-utils';
|
|
2
3
|
import { z } from 'zod';
|
|
3
|
-
import {
|
|
4
|
-
import { DEFAULT_BASE_URL, AnyRouter, buildAppAttributionHeaders } from '@anyr/sdk';
|
|
4
|
+
import { DEFAULT_BASE_URL, AnyRouter } from '@anyr/sdk';
|
|
5
5
|
|
|
6
|
-
// src/
|
|
6
|
+
// src/app-attribution.ts
|
|
7
|
+
var APP_SOURCE = "anyr-ai-sdk-provider";
|
|
8
|
+
var APP_TITLE = "AnyRouter AI SDK Provider";
|
|
9
|
+
var APP_VERSION = "0.1.7";
|
|
10
|
+
var PROVIDER_ATTRIBUTION = {
|
|
11
|
+
source: APP_SOURCE,
|
|
12
|
+
title: APP_TITLE,
|
|
13
|
+
version: APP_VERSION
|
|
14
|
+
};
|
|
15
|
+
function buildAppAttributionHeaders(app) {
|
|
16
|
+
if (!app) return {};
|
|
17
|
+
const headers = {};
|
|
18
|
+
const put = (name, value) => {
|
|
19
|
+
const trimmed = value?.trim();
|
|
20
|
+
if (trimmed) headers[name] = trimmed;
|
|
21
|
+
};
|
|
22
|
+
put("X-AnyRouter-Source", app.source);
|
|
23
|
+
put("X-AnyRouter-Title", app.title);
|
|
24
|
+
put("X-AnyRouter-Version", app.version);
|
|
25
|
+
put("HTTP-Referer", app.url);
|
|
26
|
+
const categories = app.categories?.map((c) => c.trim()).filter(Boolean);
|
|
27
|
+
if (categories?.length) headers["X-AnyRouter-Categories"] = categories.join(",");
|
|
28
|
+
return headers;
|
|
29
|
+
}
|
|
7
30
|
function convertToAnyRouterChatMessages(prompt, fileCache) {
|
|
8
31
|
const messages = [];
|
|
9
32
|
for (const message of prompt) {
|
|
@@ -164,8 +187,6 @@ var anyRouterProviderOptionsSchema = z.object({
|
|
|
164
187
|
extraBody: z.record(z.string(), z.unknown()).optional(),
|
|
165
188
|
/** Cache this response for N seconds, forwarded as the `cf-aig-cache-ttl` header. */
|
|
166
189
|
cacheTtl: z.number().optional(),
|
|
167
|
-
/** Custom cache key, forwarded as the `cf-aig-cache-key` header. */
|
|
168
|
-
cacheKey: z.string().optional(),
|
|
169
190
|
/** Skip response caching for this call, forwarded as `cf-aig-skip-cache: true`. */
|
|
170
191
|
skipCache: z.boolean().optional()
|
|
171
192
|
});
|
|
@@ -201,7 +222,7 @@ var toolCallDeltaSchema = z.object({
|
|
|
201
222
|
var messageSchema = z.object({
|
|
202
223
|
content: z.string().nullish(),
|
|
203
224
|
reasoning_content: z.string().nullish(),
|
|
204
|
-
tool_calls: z.array(toolCallSchema).
|
|
225
|
+
tool_calls: z.array(toolCallSchema).nullish()
|
|
205
226
|
});
|
|
206
227
|
var choiceSchema = z.object({
|
|
207
228
|
message: messageSchema.optional(),
|
|
@@ -211,12 +232,12 @@ var generateResponseSchema = z.object({
|
|
|
211
232
|
id: z.string().optional(),
|
|
212
233
|
model: z.string().optional(),
|
|
213
234
|
choices: z.array(choiceSchema).optional(),
|
|
214
|
-
usage: completionUsageSchema.
|
|
235
|
+
usage: completionUsageSchema.nullish()
|
|
215
236
|
});
|
|
216
237
|
var deltaSchema = z.object({
|
|
217
238
|
content: z.string().nullish(),
|
|
218
239
|
reasoning_content: z.string().nullish(),
|
|
219
|
-
tool_calls: z.array(toolCallDeltaSchema).
|
|
240
|
+
tool_calls: z.array(toolCallDeltaSchema).nullish()
|
|
220
241
|
});
|
|
221
242
|
var streamChoiceSchema = z.object({
|
|
222
243
|
delta: deltaSchema.optional(),
|
|
@@ -226,7 +247,10 @@ var streamChunkSchema = z.object({
|
|
|
226
247
|
id: z.string().optional(),
|
|
227
248
|
model: z.string().optional(),
|
|
228
249
|
choices: z.array(streamChoiceSchema).optional(),
|
|
229
|
-
usage: completionUsageSchema.
|
|
250
|
+
usage: completionUsageSchema.nullish(),
|
|
251
|
+
// A mid-stream failure arrives as a `data: {"error":{...}}` frame on a 200
|
|
252
|
+
// response, in the same envelope the gateway uses for non-2xx bodies.
|
|
253
|
+
error: anyRouterErrorSchema.shape.error
|
|
230
254
|
});
|
|
231
255
|
function mapFinishReason(raw) {
|
|
232
256
|
switch (raw) {
|
|
@@ -240,6 +264,8 @@ function mapFinishReason(raw) {
|
|
|
240
264
|
return { unified: "tool-calls", raw };
|
|
241
265
|
case "content_filter":
|
|
242
266
|
return { unified: "content-filter", raw };
|
|
267
|
+
case "error":
|
|
268
|
+
return { unified: "error", raw };
|
|
243
269
|
default:
|
|
244
270
|
return { unified: "other", raw: raw ?? void 0 };
|
|
245
271
|
}
|
|
@@ -316,6 +342,30 @@ function emitToolCallDeltas(toolCalls, acc, controller) {
|
|
|
316
342
|
}
|
|
317
343
|
}
|
|
318
344
|
}
|
|
345
|
+
function emitDelta(delta, state, acc, controller) {
|
|
346
|
+
if (typeof delta.reasoning_content === "string" && delta.reasoning_content.length > 0) {
|
|
347
|
+
emitReasoningDelta(delta.reasoning_content, state, controller);
|
|
348
|
+
}
|
|
349
|
+
if (typeof delta.content === "string" && delta.content.length > 0) {
|
|
350
|
+
emitTextDelta(delta.content, state, controller);
|
|
351
|
+
}
|
|
352
|
+
if (delta.tool_calls) {
|
|
353
|
+
emitToolCallDeltas(delta.tool_calls, acc, controller);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
function errorFramePart(chunk, request) {
|
|
357
|
+
return {
|
|
358
|
+
type: "error",
|
|
359
|
+
error: new APICallError({
|
|
360
|
+
message: chunk.error?.message ?? "AnyRouter API error",
|
|
361
|
+
url: request.url,
|
|
362
|
+
requestBodyValues: request.body,
|
|
363
|
+
responseHeaders: request.responseHeaders,
|
|
364
|
+
responseBody: JSON.stringify(chunk),
|
|
365
|
+
data: chunk
|
|
366
|
+
})
|
|
367
|
+
};
|
|
368
|
+
}
|
|
319
369
|
function emitFinish(choice, usage, state, acc, controller) {
|
|
320
370
|
closeReasoning(state, controller);
|
|
321
371
|
if (state.activeTextId !== null) {
|
|
@@ -420,11 +470,9 @@ function buildRequestBody(modelId, options, settings, stream, perCallOptions, fi
|
|
|
420
470
|
}
|
|
421
471
|
function buildCacheHeaders(settings, perCallOptions) {
|
|
422
472
|
const cacheTtl = perCallOptions.cacheTtl ?? settings.cacheTtl;
|
|
423
|
-
const cacheKey = perCallOptions.cacheKey ?? settings.cacheKey;
|
|
424
473
|
const skipCache = perCallOptions.skipCache ?? settings.skipCache;
|
|
425
474
|
const headers = {};
|
|
426
475
|
if (cacheTtl !== void 0) headers["cf-aig-cache-ttl"] = String(cacheTtl);
|
|
427
|
-
if (cacheKey !== void 0) headers["cf-aig-cache-key"] = cacheKey;
|
|
428
476
|
if (skipCache === true) headers["cf-aig-skip-cache"] = "true";
|
|
429
477
|
return headers;
|
|
430
478
|
}
|
|
@@ -439,7 +487,6 @@ var AnyRouterChatLanguageModel = class {
|
|
|
439
487
|
this.provider = config.provider;
|
|
440
488
|
this.config = config;
|
|
441
489
|
}
|
|
442
|
-
// ─── doGenerate ─────────────────────────────────────────────────────────
|
|
443
490
|
async doGenerate(options) {
|
|
444
491
|
const perCallOptions = await parseProviderOptions({
|
|
445
492
|
provider: "anyrouter",
|
|
@@ -505,7 +552,6 @@ var AnyRouterChatLanguageModel = class {
|
|
|
505
552
|
}
|
|
506
553
|
};
|
|
507
554
|
}
|
|
508
|
-
// ─── doStream ───────────────────────────────────────────────────────────
|
|
509
555
|
async doStream(options) {
|
|
510
556
|
const perCallOptions = await parseProviderOptions({
|
|
511
557
|
provider: "anyrouter",
|
|
@@ -520,8 +566,9 @@ var AnyRouterChatLanguageModel = class {
|
|
|
520
566
|
perCallOptions,
|
|
521
567
|
this.config.fileCache
|
|
522
568
|
);
|
|
569
|
+
const url = `${this.config.baseURL}/chat/completions`;
|
|
523
570
|
const { value: stream, responseHeaders } = await postJsonToApi({
|
|
524
|
-
url
|
|
571
|
+
url,
|
|
525
572
|
headers: combineHeaders(
|
|
526
573
|
this.config.headers(),
|
|
527
574
|
buildCacheHeaders(this.config.settings, perCallOptions),
|
|
@@ -556,21 +603,15 @@ var AnyRouterChatLanguageModel = class {
|
|
|
556
603
|
return;
|
|
557
604
|
}
|
|
558
605
|
const chunk = chunkResult.value;
|
|
606
|
+
if (chunk.error) {
|
|
607
|
+
controller.enqueue(errorFramePart(chunk, { url, body, responseHeaders }));
|
|
608
|
+
finishChoice = { finish_reason: "error" };
|
|
609
|
+
return;
|
|
610
|
+
}
|
|
559
611
|
const choice = chunk.choices?.[0];
|
|
560
612
|
if (chunk.usage) streamUsage = chunk.usage;
|
|
561
613
|
emitResponseMetadata(chunk, state, selfModelId, controller);
|
|
562
|
-
|
|
563
|
-
if (delta) {
|
|
564
|
-
if (typeof delta.reasoning_content === "string" && delta.reasoning_content.length > 0) {
|
|
565
|
-
emitReasoningDelta(delta.reasoning_content, state, controller);
|
|
566
|
-
}
|
|
567
|
-
if (typeof delta.content === "string" && delta.content.length > 0) {
|
|
568
|
-
emitTextDelta(delta.content, state, controller);
|
|
569
|
-
}
|
|
570
|
-
if (delta.tool_calls) {
|
|
571
|
-
emitToolCallDeltas(delta.tool_calls, toolCallAccumulator, controller);
|
|
572
|
-
}
|
|
573
|
-
}
|
|
614
|
+
if (choice?.delta) emitDelta(choice.delta, state, toolCallAccumulator, controller);
|
|
574
615
|
if (choice?.finish_reason) {
|
|
575
616
|
finishChoice = choice;
|
|
576
617
|
}
|
|
@@ -730,95 +771,6 @@ var AnyRouterFiles = class {
|
|
|
730
771
|
};
|
|
731
772
|
}
|
|
732
773
|
};
|
|
733
|
-
var anyRouterErrorSchema3 = z.object({
|
|
734
|
-
error: z.object({
|
|
735
|
-
code: z.string().optional(),
|
|
736
|
-
message: z.string().optional()
|
|
737
|
-
}).optional()
|
|
738
|
-
});
|
|
739
|
-
var imageGenerationResponseSchema = z.object({
|
|
740
|
-
created: z.number().optional(),
|
|
741
|
-
data: z.array(
|
|
742
|
-
z.object({
|
|
743
|
-
url: z.string().optional(),
|
|
744
|
-
b64_json: z.string().optional(),
|
|
745
|
-
revised_prompt: z.string().optional()
|
|
746
|
-
})
|
|
747
|
-
)
|
|
748
|
-
});
|
|
749
|
-
var AnyRouterImageModel = class {
|
|
750
|
-
specificationVersion = "v4";
|
|
751
|
-
provider;
|
|
752
|
-
modelId;
|
|
753
|
-
/**
|
|
754
|
-
* Most image generation APIs support only 1 image per call via the
|
|
755
|
-
* standard `/images/generations` endpoint.
|
|
756
|
-
*/
|
|
757
|
-
maxImagesPerCall = 1;
|
|
758
|
-
config;
|
|
759
|
-
constructor(modelId, config) {
|
|
760
|
-
this.modelId = modelId;
|
|
761
|
-
this.provider = config.provider;
|
|
762
|
-
this.config = config;
|
|
763
|
-
}
|
|
764
|
-
async doGenerate(options) {
|
|
765
|
-
if (options.mask) {
|
|
766
|
-
throw new UnsupportedFunctionalityError({
|
|
767
|
-
functionality: "mask (inpainting) for AnyRouter image generation"
|
|
768
|
-
});
|
|
769
|
-
}
|
|
770
|
-
if (options.files && options.files.length > 0) {
|
|
771
|
-
throw new UnsupportedFunctionalityError({
|
|
772
|
-
functionality: "image editing (files) for AnyRouter image generation"
|
|
773
|
-
});
|
|
774
|
-
}
|
|
775
|
-
const warnings = [];
|
|
776
|
-
if (options.n > 1) {
|
|
777
|
-
warnings.push({
|
|
778
|
-
type: "unsupported",
|
|
779
|
-
feature: `n=${options.n} (AnyRouter image endpoint supports n=1 per call)`
|
|
780
|
-
});
|
|
781
|
-
}
|
|
782
|
-
const body = {
|
|
783
|
-
model: this.modelId,
|
|
784
|
-
prompt: options.prompt ?? "",
|
|
785
|
-
n: Math.min(options.n, 1),
|
|
786
|
-
...options.size ? { size: options.size } : {},
|
|
787
|
-
...options.seed !== void 0 ? { seed: options.seed } : {},
|
|
788
|
-
response_format: "b64_json"
|
|
789
|
-
};
|
|
790
|
-
const { value: response, responseHeaders } = await postJsonToApi({
|
|
791
|
-
url: `${this.config.baseURL}/images/generations`,
|
|
792
|
-
headers: combineHeaders(this.config.headers(), options.headers),
|
|
793
|
-
body,
|
|
794
|
-
failedResponseHandler: createJsonErrorResponseHandler({
|
|
795
|
-
errorSchema: anyRouterErrorSchema3,
|
|
796
|
-
errorToMessage: (data) => data.error?.message ?? "AnyRouter images API error",
|
|
797
|
-
isRetryable: (res) => res.status >= 500
|
|
798
|
-
}),
|
|
799
|
-
successfulResponseHandler: createJsonResponseHandler(imageGenerationResponseSchema),
|
|
800
|
-
abortSignal: options.abortSignal,
|
|
801
|
-
fetch: this.config.fetch
|
|
802
|
-
});
|
|
803
|
-
const images = [];
|
|
804
|
-
for (const item of response.data) {
|
|
805
|
-
if (item.b64_json) {
|
|
806
|
-
images.push(item.b64_json);
|
|
807
|
-
} else if (item.url) {
|
|
808
|
-
images.push(item.url);
|
|
809
|
-
}
|
|
810
|
-
}
|
|
811
|
-
return {
|
|
812
|
-
images,
|
|
813
|
-
warnings,
|
|
814
|
-
response: {
|
|
815
|
-
timestamp: /* @__PURE__ */ new Date(),
|
|
816
|
-
modelId: this.modelId,
|
|
817
|
-
headers: responseHeaders
|
|
818
|
-
}
|
|
819
|
-
};
|
|
820
|
-
}
|
|
821
|
-
};
|
|
822
774
|
var PROVIDER_ID = "anyrouter";
|
|
823
775
|
function createAnyRouter(options = {}) {
|
|
824
776
|
const baseURL = withoutTrailingSlash(options.baseURL ?? DEFAULT_BASE_URL) ?? DEFAULT_BASE_URL;
|
|
@@ -853,14 +805,6 @@ function createAnyRouter(options = {}) {
|
|
|
853
805
|
fetch: options.fetch
|
|
854
806
|
});
|
|
855
807
|
}
|
|
856
|
-
function imageModel(modelId) {
|
|
857
|
-
return new AnyRouterImageModel(modelId, {
|
|
858
|
-
provider: PROVIDER_ID,
|
|
859
|
-
baseURL,
|
|
860
|
-
headers: getHeaders,
|
|
861
|
-
fetch: options.fetch
|
|
862
|
-
});
|
|
863
|
-
}
|
|
864
808
|
const provider = (modelId) => chatModel(modelId);
|
|
865
809
|
const providerObj = Object.assign(provider, {
|
|
866
810
|
// ProviderV4 required fields
|
|
@@ -872,9 +816,6 @@ function createAnyRouter(options = {}) {
|
|
|
872
816
|
embeddingModel(modelId) {
|
|
873
817
|
return embeddingModel(modelId);
|
|
874
818
|
},
|
|
875
|
-
imageModel(modelId) {
|
|
876
|
-
return imageModel(modelId);
|
|
877
|
-
},
|
|
878
819
|
// AnyRouter convenience alias
|
|
879
820
|
chat(modelId) {
|
|
880
821
|
return chatModel(modelId);
|
|
@@ -883,7 +824,11 @@ function createAnyRouter(options = {}) {
|
|
|
883
824
|
files() {
|
|
884
825
|
return new AnyRouterFiles(PROVIDER_ID, sharedFileCache);
|
|
885
826
|
},
|
|
886
|
-
// Unsupported optional model types — throw NoSuchModelError per ProviderV4 contract
|
|
827
|
+
// Unsupported optional model types — throw NoSuchModelError per ProviderV4 contract.
|
|
828
|
+
// Image/video generation is not an AnyRouter product (text + embeddings only).
|
|
829
|
+
imageModel(modelId) {
|
|
830
|
+
throw new NoSuchModelError({ modelId, modelType: "imageModel" });
|
|
831
|
+
},
|
|
887
832
|
transcriptionModel(modelId) {
|
|
888
833
|
throw new NoSuchModelError({ modelId, modelType: "transcriptionModel" });
|
|
889
834
|
},
|
|
@@ -899,7 +844,6 @@ function createAnyRouter(options = {}) {
|
|
|
899
844
|
apiKey: options.apiKey,
|
|
900
845
|
baseURL: options.baseURL,
|
|
901
846
|
headers: options.headers,
|
|
902
|
-
app: options.app,
|
|
903
847
|
fetch: options.fetch
|
|
904
848
|
});
|
|
905
849
|
}
|
|
@@ -908,4 +852,4 @@ function createAnyRouter(options = {}) {
|
|
|
908
852
|
}
|
|
909
853
|
var anyrouter = createAnyRouter();
|
|
910
854
|
|
|
911
|
-
export { AnyRouterChatLanguageModel, AnyRouterEmbeddingModel, AnyRouterFiles,
|
|
855
|
+
export { AnyRouterChatLanguageModel, AnyRouterEmbeddingModel, AnyRouterFiles, FileReferenceCache, PROVIDER_ATTRIBUTION, anyrouter, buildAppAttributionHeaders, 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.7",
|
|
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",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"build": "tsup",
|
|
32
32
|
"dev": "tsup --watch",
|
|
33
33
|
"clean": "rm -rf dist",
|
|
34
|
-
"typecheck": "
|
|
34
|
+
"typecheck": "tsgo --noEmit",
|
|
35
35
|
"test": "vitest run",
|
|
36
36
|
"prepublishOnly": "tsup"
|
|
37
37
|
},
|
|
@@ -49,13 +49,13 @@
|
|
|
49
49
|
"homepage": "https://anyrouter.dev",
|
|
50
50
|
"repository": {
|
|
51
51
|
"type": "git",
|
|
52
|
-
"url": "git+https://github.com/
|
|
53
|
-
"directory": "packages/ai-sdk-provider"
|
|
52
|
+
"url": "git+https://github.com/AnyRouterHQ/anyrouter-ai-sdk-provider.git"
|
|
54
53
|
},
|
|
55
54
|
"bugs": {
|
|
56
|
-
"url": "https://github.com/
|
|
55
|
+
"url": "https://github.com/AnyRouterHQ/anyrouter-ai-sdk-provider/issues"
|
|
57
56
|
},
|
|
58
57
|
"author": "Duyet Le",
|
|
58
|
+
"packageManager": "pnpm@12.16.1",
|
|
59
59
|
"license": "MIT",
|
|
60
60
|
"publishConfig": {
|
|
61
61
|
"access": "public"
|
|
@@ -70,10 +70,14 @@
|
|
|
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.2",
|
|
74
|
+
"@ai-sdk/provider-utils": "5.0.5",
|
|
75
75
|
"@types/node": "^24.0.0",
|
|
76
|
-
"
|
|
77
|
-
"
|
|
76
|
+
"@typescript/native-preview": "7.0.0-dev.20260707.2",
|
|
77
|
+
"ai": "7.0.15",
|
|
78
|
+
"tsup": "^8.5.1",
|
|
79
|
+
"typescript": "^6.0.3",
|
|
80
|
+
"vitest": "^5.1.0",
|
|
81
|
+
"zod": "4.6.7"
|
|
78
82
|
}
|
|
79
83
|
}
|