@opencode/ai 2.0.23 → 2.0.25
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 +1 -1
- package/dist/cache-policy.js +12 -9
- package/dist/protocols/alibaba-messages.d.ts +3 -0
- package/dist/protocols/alibaba-responses.d.ts +3 -0
- package/dist/protocols/anthropic-messages.d.ts +8 -5
- package/dist/protocols/anthropic-messages.js +19 -16
- package/dist/protocols/bedrock-converse.js +3 -1
- package/dist/protocols/google-interactions.d.ts +1 -1
- package/dist/protocols/meta-messages.d.ts +4 -1
- package/dist/protocols/meta-responses.d.ts +3 -0
- package/dist/protocols/open-responses.d.ts +18 -12
- package/dist/protocols/open-responses.js +7 -5
- package/dist/protocols/openai-responses.d.ts +3 -0
- package/dist/protocols/utils/bedrock-auth.js +2 -1
- package/dist/protocols/utils/gateway-protocol.d.ts +17 -0
- package/dist/protocols/utils/gateway-protocol.js +57 -0
- package/dist/protocols/utils/openai-options.d.ts +1 -1
- package/dist/protocols/utils/openai-options.js +2 -1
- package/dist/protocols/utils/tool-stream.d.ts +1 -1
- package/dist/protocols/utils/tool-stream.js +5 -5
- package/dist/protocols/xai-responses.d.ts +3 -0
- package/dist/protocols/zai-messages.d.ts +3 -0
- package/dist/providers/amazon-bedrock-mantle.d.ts +1 -1
- package/dist/providers/amazon-bedrock-mantle.js +4 -3
- package/dist/providers/anthropic-compatible.d.ts +1 -1
- package/dist/providers/anthropic.d.ts +1 -1
- package/dist/providers/cloudflare-ai-gateway.d.ts +2 -2
- package/dist/providers/google-vertex-messages.d.ts +1 -1
- package/dist/providers/google-vertex-messages.js +1 -0
- package/dist/providers/google-vertex.js +1 -1
- package/dist/providers/google.d.ts +4 -4
- package/dist/providers/meta.d.ts +1 -1
- package/dist/providers/minimax.d.ts +1 -1
- package/dist/providers/moonshot.d.ts +1 -1
- package/dist/providers/vercel-ai-gateway/chat.d.ts +2 -0
- package/dist/providers/vercel-ai-gateway/chat.js +1 -0
- package/dist/providers/vercel-ai-gateway/messages.d.ts +2 -0
- package/dist/providers/vercel-ai-gateway/messages.js +1 -0
- package/dist/providers/vercel-ai-gateway/responses.d.ts +2 -0
- package/dist/providers/vercel-ai-gateway/responses.js +1 -0
- package/dist/providers/vercel-ai-gateway.d.ts +91 -9
- package/dist/providers/vercel-ai-gateway.js +161 -21
- package/package.json +3 -3
|
@@ -266,8 +266,10 @@ export declare const protocol: Protocol<{
|
|
|
266
266
|
readonly top_k?: number | undefined;
|
|
267
267
|
readonly stop_sequences?: readonly string[] | undefined;
|
|
268
268
|
}, string, {
|
|
269
|
+
readonly [x: string]: unknown;
|
|
269
270
|
readonly type: string;
|
|
270
271
|
readonly message?: {
|
|
272
|
+
readonly [x: string]: unknown;
|
|
271
273
|
readonly usage?: {
|
|
272
274
|
readonly [x: string]: unknown;
|
|
273
275
|
readonly input_tokens?: number | null | undefined;
|
|
@@ -300,6 +302,7 @@ export declare const protocol: Protocol<{
|
|
|
300
302
|
} | undefined;
|
|
301
303
|
} | undefined;
|
|
302
304
|
readonly error?: {
|
|
305
|
+
readonly [x: string]: unknown;
|
|
303
306
|
readonly type?: string | undefined;
|
|
304
307
|
readonly message?: string | undefined;
|
|
305
308
|
} | undefined;
|
|
@@ -257,7 +257,7 @@ export declare const routes: (Route<{
|
|
|
257
257
|
readonly prefix_mismatch_behavior?: import("../schema/options.js").OpenString<"error" | "drop_block"> | undefined;
|
|
258
258
|
} | undefined;
|
|
259
259
|
} | {
|
|
260
|
-
readonly type: "disabled";
|
|
260
|
+
readonly type: "disabled" | "between_tools";
|
|
261
261
|
} | undefined;
|
|
262
262
|
readonly service_tier?: import("../schema/options.js").OpenString<"auto" | "standard_only"> | undefined;
|
|
263
263
|
readonly container?: string | {
|
|
@@ -30,9 +30,10 @@ const messagesRoute = Route.make({
|
|
|
30
30
|
...AnthropicMessages.protocol,
|
|
31
31
|
// Mantle rejects mid-conversation `output_config` on Opus 5.0; support starts at 5.1+.
|
|
32
32
|
supportsEffortUpdates: (request) => {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
if (!(AnthropicMessages.protocol.supportsEffortUpdates?.(request) ?? false))
|
|
34
|
+
return false;
|
|
35
|
+
if (request.model.compatibility?.supportsEffortUpdates !== undefined)
|
|
36
|
+
return true;
|
|
36
37
|
const version = claudeVersion(request.model.id);
|
|
37
38
|
return version !== undefined && (version.major > 5 || (version.major === 5 && version.minor >= 1));
|
|
38
39
|
},
|
|
@@ -249,7 +249,7 @@ export declare const routes: import("../route/client.js").Route<{
|
|
|
249
249
|
readonly prefix_mismatch_behavior?: import("../schema/options.js").OpenString<"error" | "drop_block"> | undefined;
|
|
250
250
|
} | undefined;
|
|
251
251
|
} | {
|
|
252
|
-
readonly type: "disabled";
|
|
252
|
+
readonly type: "disabled" | "between_tools";
|
|
253
253
|
} | undefined;
|
|
254
254
|
readonly service_tier?: import("../schema/options.js").OpenString<"auto" | "standard_only"> | undefined;
|
|
255
255
|
readonly container?: string | {
|
|
@@ -234,7 +234,7 @@ export declare const routes: import("../route/client.js").Route<{
|
|
|
234
234
|
readonly prefix_mismatch_behavior?: import("../schema/options.js").OpenString<"error" | "drop_block"> | undefined;
|
|
235
235
|
} | undefined;
|
|
236
236
|
} | {
|
|
237
|
-
readonly type: "disabled";
|
|
237
|
+
readonly type: "disabled" | "between_tools";
|
|
238
238
|
} | undefined;
|
|
239
239
|
readonly service_tier?: import("../schema/options.js").OpenString<"auto" | "standard_only"> | undefined;
|
|
240
240
|
readonly container?: string | {
|
|
@@ -461,7 +461,7 @@ export declare const messagesRoute: import("../route/client.js").Route<{
|
|
|
461
461
|
readonly prefix_mismatch_behavior?: import("../schema/options.js").OpenString<"error" | "drop_block"> | undefined;
|
|
462
462
|
} | undefined;
|
|
463
463
|
} | {
|
|
464
|
-
readonly type: "disabled";
|
|
464
|
+
readonly type: "disabled" | "between_tools";
|
|
465
465
|
} | undefined;
|
|
466
466
|
readonly service_tier?: import("../schema/options.js").OpenString<"auto" | "standard_only"> | undefined;
|
|
467
467
|
readonly container?: string | {
|
|
@@ -856,7 +856,7 @@ export declare const routes: (import("../route/client.js").Route<{
|
|
|
856
856
|
readonly prefix_mismatch_behavior?: import("../schema/options.js").OpenString<"error" | "drop_block"> | undefined;
|
|
857
857
|
} | undefined;
|
|
858
858
|
} | {
|
|
859
|
-
readonly type: "disabled";
|
|
859
|
+
readonly type: "disabled" | "between_tools";
|
|
860
860
|
} | undefined;
|
|
861
861
|
readonly service_tier?: import("../schema/options.js").OpenString<"auto" | "standard_only"> | undefined;
|
|
862
862
|
readonly container?: string | {
|
|
@@ -247,7 +247,7 @@ export declare const routes: Route<{
|
|
|
247
247
|
readonly prefix_mismatch_behavior?: import("../schema/options.js").OpenString<"error" | "drop_block"> | undefined;
|
|
248
248
|
} | undefined;
|
|
249
249
|
} | {
|
|
250
|
-
readonly type: "disabled";
|
|
250
|
+
readonly type: "disabled" | "between_tools";
|
|
251
251
|
} | undefined;
|
|
252
252
|
service_tier?: import("../schema/options.js").OpenString<"auto" | "standard_only"> | undefined;
|
|
253
253
|
container?: string | {
|
|
@@ -26,6 +26,7 @@ const route = Route.make({
|
|
|
26
26
|
}))),
|
|
27
27
|
},
|
|
28
28
|
stream: AnthropicMessages.protocol.stream,
|
|
29
|
+
supportsEffortUpdates: AnthropicMessages.protocol.supportsEffortUpdates,
|
|
29
30
|
}),
|
|
30
31
|
endpoint: Endpoint.path(({ request }) => `/${request.model.id}:streamRawPredict`),
|
|
31
32
|
auth: Auth.none,
|
|
@@ -49,7 +49,7 @@ const configuredRoute = (input, modelID) => {
|
|
|
49
49
|
provider: id,
|
|
50
50
|
message: "Google Vertex tuned models do not support Express Mode API keys",
|
|
51
51
|
});
|
|
52
|
-
const location = GoogleVertexShared.location(inputLocation, "
|
|
52
|
+
const location = GoogleVertexShared.location(inputLocation, "global");
|
|
53
53
|
const project = GoogleVertexShared.project(inputProject);
|
|
54
54
|
const endpoint = baseURL ??
|
|
55
55
|
(apiKey
|
|
@@ -170,7 +170,7 @@ export declare const configure: (input?: Config) => {
|
|
|
170
170
|
id: string & import("effect/Brand").Brand<"AI.ProviderID">;
|
|
171
171
|
model: (modelID: string | ModelID) => import("../schema/options.js").LanguageModel<Gemini.OptionsInput, import("../route/client.js").CompactionOperations | undefined>;
|
|
172
172
|
interactions: (modelID: string | ModelID) => import("../schema/options.js").LanguageModel<{
|
|
173
|
-
readonly serviceTier?: import("../schema/options.js").OpenString<"standard" | "flex" | "priority"> | undefined;
|
|
173
|
+
readonly serviceTier?: import("../schema/options.js").OpenString<"standard" | "flex" | "priority" | "deferred"> | undefined;
|
|
174
174
|
readonly thinkingLevel?: import("../schema/options.js").OpenString<"minimal" | "low" | "medium" | "high"> | undefined;
|
|
175
175
|
readonly previousInteractionId?: string | undefined;
|
|
176
176
|
readonly store?: boolean | undefined;
|
|
@@ -186,7 +186,7 @@ export declare const provider: {
|
|
|
186
186
|
id: string & import("effect/Brand").Brand<"AI.ProviderID">;
|
|
187
187
|
model: (modelID: string | ModelID) => import("../schema/options.js").LanguageModel<Gemini.OptionsInput, import("../route/client.js").CompactionOperations | undefined>;
|
|
188
188
|
interactions: (modelID: string | ModelID) => import("../schema/options.js").LanguageModel<{
|
|
189
|
-
readonly serviceTier?: import("../schema/options.js").OpenString<"standard" | "flex" | "priority"> | undefined;
|
|
189
|
+
readonly serviceTier?: import("../schema/options.js").OpenString<"standard" | "flex" | "priority" | "deferred"> | undefined;
|
|
190
190
|
readonly thinkingLevel?: import("../schema/options.js").OpenString<"minimal" | "low" | "medium" | "high"> | undefined;
|
|
191
191
|
readonly previousInteractionId?: string | undefined;
|
|
192
192
|
readonly store?: boolean | undefined;
|
|
@@ -200,7 +200,7 @@ export declare const provider: {
|
|
|
200
200
|
id: string & import("effect/Brand").Brand<"AI.ProviderID">;
|
|
201
201
|
model: (modelID: string | ModelID) => import("../schema/options.js").LanguageModel<Gemini.OptionsInput, import("../route/client.js").CompactionOperations | undefined>;
|
|
202
202
|
interactions: (modelID: string | ModelID) => import("../schema/options.js").LanguageModel<{
|
|
203
|
-
readonly serviceTier?: import("../schema/options.js").OpenString<"standard" | "flex" | "priority"> | undefined;
|
|
203
|
+
readonly serviceTier?: import("../schema/options.js").OpenString<"standard" | "flex" | "priority" | "deferred"> | undefined;
|
|
204
204
|
readonly thinkingLevel?: import("../schema/options.js").OpenString<"minimal" | "low" | "medium" | "high"> | undefined;
|
|
205
205
|
readonly previousInteractionId?: string | undefined;
|
|
206
206
|
readonly store?: boolean | undefined;
|
|
@@ -216,7 +216,7 @@ export declare const provider: {
|
|
|
216
216
|
export declare const model: ProviderPackage.Definition<Settings, Gemini.ProviderOptionsInput>["model"];
|
|
217
217
|
export declare const image: (modelID: string | ModelID) => import("../image.js").ImageModel<import("../protocols/google-images.js").GoogleImageOptions>;
|
|
218
218
|
export declare const interactions: (modelID: string | ModelID) => import("../schema/options.js").LanguageModel<{
|
|
219
|
-
readonly serviceTier?: import("../schema/options.js").OpenString<"standard" | "flex" | "priority"> | undefined;
|
|
219
|
+
readonly serviceTier?: import("../schema/options.js").OpenString<"standard" | "flex" | "priority" | "deferred"> | undefined;
|
|
220
220
|
readonly thinkingLevel?: import("../schema/options.js").OpenString<"minimal" | "low" | "medium" | "high"> | undefined;
|
|
221
221
|
readonly previousInteractionId?: string | undefined;
|
|
222
222
|
readonly store?: boolean | undefined;
|
package/dist/providers/meta.d.ts
CHANGED
|
@@ -573,7 +573,7 @@ export declare const routes: (Route<{
|
|
|
573
573
|
readonly prefix_mismatch_behavior?: OpenString<"error" | "drop_block"> | undefined;
|
|
574
574
|
} | undefined;
|
|
575
575
|
} | {
|
|
576
|
-
readonly type: "disabled";
|
|
576
|
+
readonly type: "disabled" | "between_tools";
|
|
577
577
|
} | undefined;
|
|
578
578
|
readonly service_tier?: OpenString<"auto" | "standard_only"> | undefined;
|
|
579
579
|
readonly container?: string | {
|
|
@@ -260,7 +260,7 @@ export declare const routes: (Route<{
|
|
|
260
260
|
readonly prefix_mismatch_behavior?: import("../schema/options.js").OpenString<"error" | "drop_block"> | undefined;
|
|
261
261
|
} | undefined;
|
|
262
262
|
} | {
|
|
263
|
-
readonly type: "disabled";
|
|
263
|
+
readonly type: "disabled" | "between_tools";
|
|
264
264
|
} | undefined;
|
|
265
265
|
readonly service_tier?: import("../schema/options.js").OpenString<"auto" | "standard_only"> | undefined;
|
|
266
266
|
readonly container?: string | {
|
|
@@ -258,7 +258,7 @@ export declare const routes: (Route<{
|
|
|
258
258
|
readonly prefix_mismatch_behavior?: import("../schema/options.js").OpenString<"error" | "drop_block"> | undefined;
|
|
259
259
|
} | undefined;
|
|
260
260
|
} | {
|
|
261
|
-
readonly type: "disabled";
|
|
261
|
+
readonly type: "disabled" | "between_tools";
|
|
262
262
|
} | undefined;
|
|
263
263
|
readonly service_tier?: import("../schema/options.js").OpenString<"auto" | "standard_only"> | undefined;
|
|
264
264
|
readonly container?: string | {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { chatModel as model } from "../vercel-ai-gateway.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { messagesModel as model } from "../vercel-ai-gateway.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { responsesModel as model } from "../vercel-ai-gateway.js";
|
|
@@ -1,22 +1,89 @@
|
|
|
1
1
|
import { EvaluationModel } from "../experimental/evaluation.js";
|
|
2
|
+
import { AnthropicMessages } from "../protocols/anthropic-messages.js";
|
|
3
|
+
import type { ProviderPackage } from "../provider-package.js";
|
|
2
4
|
import { type ProviderAuthOption } from "../route/auth-options.js";
|
|
3
|
-
import {
|
|
5
|
+
import { Route, type RouteDefaultsInput } from "../route/client.js";
|
|
6
|
+
import { ModelID } from "../schema/index.js";
|
|
7
|
+
import type { OpenResponsesProviderOptionsInput } from "./open-responses-options.js";
|
|
4
8
|
export declare const id: string & import("effect/Brand").Brand<"AI.ProviderID">;
|
|
5
|
-
export interface
|
|
9
|
+
export interface GatewayOptions {
|
|
10
|
+
/** Service-owned options added by the Gateway without requiring an SDK update. */
|
|
6
11
|
readonly [key: string]: unknown;
|
|
7
|
-
|
|
12
|
+
/** Enables Gateway automatic prompt-cache breakpoint injection (`"auto"`). */
|
|
13
|
+
readonly caching?: "auto" | (string & {});
|
|
14
|
+
/** Provider slugs that are the only ones allowed to serve the request (e.g. `["anthropic", "vertex"]`). */
|
|
15
|
+
readonly only?: ReadonlyArray<string>;
|
|
16
|
+
/** Provider slugs specifying the order in which providers are tried (e.g. `["bedrock", "anthropic"]`). */
|
|
17
|
+
readonly order?: ReadonlyArray<string>;
|
|
18
|
+
/** Sort candidate providers by cost (`"cost"`), throughput (`"tps"`), or time-to-first-token (`"ttft"`). */
|
|
19
|
+
readonly sort?: "cost" | "tps" | "ttft" | (string & {});
|
|
20
|
+
/** Fallback models to try in order, or a conditional `{ model, when }` entry on evaluation requests. */
|
|
21
|
+
readonly models?: ReadonlyArray<string | Readonly<Record<string, unknown>>>;
|
|
22
|
+
/** Restrict routing to providers with zero data retention agreements. */
|
|
23
|
+
readonly zeroDataRetention?: boolean;
|
|
24
|
+
/** Restrict routing to providers that do not train on prompt data. */
|
|
25
|
+
readonly disallowPromptTraining?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Restrict routing to provider models that satisfy every entry: capability
|
|
28
|
+
* tags (`"implicit-caching"`, `"reasoning"`, `"structured-output"`,
|
|
29
|
+
* `"tool-use"`, `"vision"`) or weight-format filters (`"quantization:fp8"`,
|
|
30
|
+
* `"!quantization:fp8"`).
|
|
31
|
+
*/
|
|
32
|
+
readonly has?: ReadonlyArray<"implicit-caching" | "reasoning" | "structured-output" | "tool-use" | "vision" | `quantization:${string}` | `!quantization:${string}` | (string & {})>;
|
|
33
|
+
/** Entity identifier against which Gateway quota is tracked. */
|
|
34
|
+
readonly quotaEntityId?: string;
|
|
35
|
+
/** Unified service tier intent (`"flex"` or `"priority"`). */
|
|
36
|
+
readonly serviceTier?: "flex" | "priority" | (string & {});
|
|
37
|
+
/** End-user identifier for spend tracking and attribution. */
|
|
38
|
+
readonly user?: string;
|
|
39
|
+
/** User-specified tags for reporting and filtering usage. */
|
|
40
|
+
readonly tags?: ReadonlyArray<string>;
|
|
41
|
+
/** Request-scoped BYOK credentials keyed by provider slug, used instead of cached workspace credentials. */
|
|
42
|
+
readonly byok?: Readonly<Record<string, ReadonlyArray<Readonly<Record<string, unknown>>>>>;
|
|
43
|
+
/** Preferred inference region for upstream provider routing. */
|
|
44
|
+
readonly inferenceRegion?: string;
|
|
45
|
+
/** Per-provider timeouts in milliseconds (e.g. `{ byok: { anthropic: 3000 } }`). */
|
|
46
|
+
readonly providerTimeouts?: {
|
|
8
47
|
readonly [key: string]: unknown;
|
|
9
|
-
readonly
|
|
10
|
-
|
|
11
|
-
|
|
48
|
+
readonly byok?: Readonly<Record<string, number>>;
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
export type ProviderOptionsInput = OpenResponsesProviderOptionsInput & Omit<AnthropicMessages.OptionsInput, "thinking"> & {
|
|
52
|
+
/** Reasoning configuration for Messages (`thinking`) or Chat (`reasoning.enabled` + `reasoning.max_tokens`). */
|
|
53
|
+
readonly thinking?: AnthropicMessages.OptionsInput["thinking"] | {
|
|
54
|
+
readonly type: "enabled" | "adaptive" | "disabled" | (string & {});
|
|
55
|
+
readonly budgetTokens?: number;
|
|
56
|
+
readonly budget_tokens?: number;
|
|
57
|
+
};
|
|
58
|
+
/** Gateway routing, fallback, BYOK, compliance, and attribution options sent under `body.providerOptions.gateway`. */
|
|
59
|
+
readonly gateway?: GatewayOptions;
|
|
60
|
+
/** Provider-specific options forwarded under their upstream namespace in `body.providerOptions` (e.g. `{ anthropic: { ... } }`). */
|
|
61
|
+
readonly upstream?: Readonly<Record<string, Readonly<Record<string, unknown>>>>;
|
|
62
|
+
/** Responses API automatic-cache lifetime (`"5m"` or `"1h"`), sent as top-level `cache_ttl`. */
|
|
63
|
+
readonly cacheTTL?: "5m" | "1h" | (string & {});
|
|
64
|
+
/** Responses API count of stable input items to anchor for caching, sent as top-level `cache_anchor_items`. */
|
|
65
|
+
readonly cacheAnchorItems?: number;
|
|
66
|
+
};
|
|
67
|
+
export interface EvaluationOptions {
|
|
68
|
+
readonly [key: string]: unknown;
|
|
69
|
+
readonly gateway?: GatewayOptions;
|
|
12
70
|
}
|
|
13
|
-
export type Options = ProviderAuthOption<"optional"> & {
|
|
71
|
+
export type Options = Omit<RouteDefaultsInput, "providerOptions"> & ProviderAuthOption<"optional"> & {
|
|
14
72
|
readonly baseURL?: string;
|
|
15
|
-
readonly
|
|
16
|
-
|
|
73
|
+
readonly providerOptions?: ProviderOptionsInput;
|
|
74
|
+
};
|
|
75
|
+
export type Settings = ProviderPackage.Settings & ProviderOptionsInput & {
|
|
76
|
+
readonly apiKey?: string;
|
|
17
77
|
};
|
|
78
|
+
export declare const routes: Route<{
|
|
79
|
+
readonly [x: string]: unknown;
|
|
80
|
+
}, import("../route/transport/http.js").HttpPrepared<string>, import("../route/client.js").CompactionOperations | undefined>[];
|
|
18
81
|
export declare const configure: (input?: Options) => {
|
|
19
82
|
id: string & import("effect/Brand").Brand<"AI.ProviderID">;
|
|
83
|
+
model: (modelID: string | ModelID) => import("../schema/options.js").LanguageModel<ProviderOptionsInput, import("../route/client.js").CompactionOperations | undefined>;
|
|
84
|
+
messages: (modelID: string | ModelID) => import("../schema/options.js").LanguageModel<ProviderOptionsInput, import("../route/client.js").CompactionOperations | undefined>;
|
|
85
|
+
responses: (modelID: string | ModelID) => import("../schema/options.js").LanguageModel<ProviderOptionsInput, import("../route/client.js").CompactionOperations | undefined>;
|
|
86
|
+
chat: (modelID: string | ModelID) => import("../schema/options.js").LanguageModel<ProviderOptionsInput, import("../route/client.js").CompactionOperations | undefined>;
|
|
20
87
|
experimental: {
|
|
21
88
|
evaluation: (modelID: string | ModelID) => EvaluationModel<EvaluationOptions>;
|
|
22
89
|
};
|
|
@@ -24,11 +91,19 @@ export declare const configure: (input?: Options) => {
|
|
|
24
91
|
};
|
|
25
92
|
export declare const provider: {
|
|
26
93
|
id: string & import("effect/Brand").Brand<"AI.ProviderID">;
|
|
94
|
+
model: (modelID: string | ModelID) => import("../schema/options.js").LanguageModel<ProviderOptionsInput, import("../route/client.js").CompactionOperations | undefined>;
|
|
95
|
+
messages: (modelID: string | ModelID) => import("../schema/options.js").LanguageModel<ProviderOptionsInput, import("../route/client.js").CompactionOperations | undefined>;
|
|
96
|
+
responses: (modelID: string | ModelID) => import("../schema/options.js").LanguageModel<ProviderOptionsInput, import("../route/client.js").CompactionOperations | undefined>;
|
|
97
|
+
chat: (modelID: string | ModelID) => import("../schema/options.js").LanguageModel<ProviderOptionsInput, import("../route/client.js").CompactionOperations | undefined>;
|
|
27
98
|
experimental: {
|
|
28
99
|
evaluation: (modelID: string | ModelID) => EvaluationModel<EvaluationOptions>;
|
|
29
100
|
};
|
|
30
101
|
configure: (input?: Options) => {
|
|
31
102
|
id: string & import("effect/Brand").Brand<"AI.ProviderID">;
|
|
103
|
+
model: (modelID: string | ModelID) => import("../schema/options.js").LanguageModel<ProviderOptionsInput, import("../route/client.js").CompactionOperations | undefined>;
|
|
104
|
+
messages: (modelID: string | ModelID) => import("../schema/options.js").LanguageModel<ProviderOptionsInput, import("../route/client.js").CompactionOperations | undefined>;
|
|
105
|
+
responses: (modelID: string | ModelID) => import("../schema/options.js").LanguageModel<ProviderOptionsInput, import("../route/client.js").CompactionOperations | undefined>;
|
|
106
|
+
chat: (modelID: string | ModelID) => import("../schema/options.js").LanguageModel<ProviderOptionsInput, import("../route/client.js").CompactionOperations | undefined>;
|
|
32
107
|
experimental: {
|
|
33
108
|
evaluation: (modelID: string | ModelID) => EvaluationModel<EvaluationOptions>;
|
|
34
109
|
};
|
|
@@ -38,4 +113,11 @@ export declare const provider: {
|
|
|
38
113
|
export declare const experimental: {
|
|
39
114
|
evaluation: (modelID: string | ModelID) => EvaluationModel<EvaluationOptions>;
|
|
40
115
|
};
|
|
116
|
+
export declare const messages: (modelID: string | ModelID) => import("../schema/options.js").LanguageModel<ProviderOptionsInput, import("../route/client.js").CompactionOperations | undefined>;
|
|
117
|
+
export declare const responses: (modelID: string | ModelID) => import("../schema/options.js").LanguageModel<ProviderOptionsInput, import("../route/client.js").CompactionOperations | undefined>;
|
|
118
|
+
export declare const chat: (modelID: string | ModelID) => import("../schema/options.js").LanguageModel<ProviderOptionsInput, import("../route/client.js").CompactionOperations | undefined>;
|
|
119
|
+
export declare const model: ProviderPackage.Definition<Settings, ProviderOptionsInput>["model"];
|
|
120
|
+
export declare const messagesModel: ProviderPackage.Definition<Settings, ProviderOptionsInput>["model"];
|
|
121
|
+
export declare const responsesModel: ProviderPackage.Definition<Settings, ProviderOptionsInput>["model"];
|
|
122
|
+
export declare const chatModel: ProviderPackage.Definition<Settings, ProviderOptionsInput>["model"];
|
|
41
123
|
export * as VercelAIGateway from "./vercel-ai-gateway.js";
|
|
@@ -1,11 +1,111 @@
|
|
|
1
1
|
import { Effect, Schema } from "effect";
|
|
2
2
|
import { Headers, HttpClientRequest } from "effect/unstable/http";
|
|
3
3
|
import { EvaluationAnswer, EvaluationInput, EvaluationModel, EvaluationQuestion, EvaluationResponse, EvaluationRounding, } from "../experimental/evaluation.js";
|
|
4
|
+
import { AnthropicMessages } from "../protocols/anthropic-messages.js";
|
|
5
|
+
import { OpenAIChat } from "../protocols/openai-chat.js";
|
|
6
|
+
import { OpenResponses } from "../protocols/open-responses.js";
|
|
7
|
+
import { optionalNull, ProviderShared } from "../protocols/shared.js";
|
|
8
|
+
import { gatewayProtocol } from "../protocols/utils/gateway-protocol.js";
|
|
4
9
|
import { Auth } from "../route/auth.js";
|
|
5
10
|
import { AuthOptions } from "../route/auth-options.js";
|
|
6
|
-
import {
|
|
11
|
+
import { Route } from "../route/client.js";
|
|
12
|
+
import { Endpoint } from "../route/endpoint.js";
|
|
13
|
+
import { Framing } from "../route/framing.js";
|
|
14
|
+
import { AIError, HttpContext, HttpOptions, InvalidProviderOutputError, InvalidRequestError, LLMRequest, ModelID, ProviderID, ProviderMetadata, ReasoningEffort, Usage, } from "../schema/index.js";
|
|
7
15
|
export const id = ProviderID.make("vercel-ai-gateway");
|
|
8
16
|
const baseURL = "https://ai-gateway.vercel.sh/v1";
|
|
17
|
+
const GatewayOptionsSchema = Schema.Struct({
|
|
18
|
+
gateway: Schema.optional(Schema.Record(Schema.String, Schema.Unknown)),
|
|
19
|
+
upstream: Schema.optional(Schema.Record(Schema.String, Schema.Record(Schema.String, Schema.Unknown))),
|
|
20
|
+
reasoningEffort: Schema.optional(ReasoningEffort),
|
|
21
|
+
thinking: Schema.optional(Schema.Struct({
|
|
22
|
+
type: Schema.String,
|
|
23
|
+
budgetTokens: Schema.optional(Schema.Number),
|
|
24
|
+
budget_tokens: Schema.optional(Schema.Number),
|
|
25
|
+
})),
|
|
26
|
+
cacheTTL: Schema.optional(Schema.String),
|
|
27
|
+
cacheAnchorItems: Schema.optional(Schema.Number),
|
|
28
|
+
});
|
|
29
|
+
const decodeOptions = ProviderShared.validateWith(Schema.decodeUnknownEffect(GatewayOptionsSchema));
|
|
30
|
+
const prepare = (api) => Effect.fnUntraced(function* (request) {
|
|
31
|
+
const options = yield* decodeOptions(request.providerOptions ?? {});
|
|
32
|
+
const providerOptions = (() => {
|
|
33
|
+
if (!options.upstream && !options.gateway)
|
|
34
|
+
return undefined;
|
|
35
|
+
if (!options.gateway)
|
|
36
|
+
return options.upstream;
|
|
37
|
+
return { ...options.upstream, gateway: options.gateway };
|
|
38
|
+
})();
|
|
39
|
+
switch (api) {
|
|
40
|
+
case "messages": {
|
|
41
|
+
const effort = options.reasoningEffort;
|
|
42
|
+
if (effort === undefined)
|
|
43
|
+
return { request, body: { providerOptions } };
|
|
44
|
+
const enabled = effort !== "none";
|
|
45
|
+
const thinking = request.providerOptions?.thinking ?? { type: enabled ? "adaptive" : "disabled" };
|
|
46
|
+
const next = LLMRequest.update(request, {
|
|
47
|
+
providerOptions: {
|
|
48
|
+
...request.providerOptions,
|
|
49
|
+
effort: enabled ? effort : undefined,
|
|
50
|
+
thinking,
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
return { request: next, body: { providerOptions } };
|
|
54
|
+
}
|
|
55
|
+
case "responses":
|
|
56
|
+
return {
|
|
57
|
+
request,
|
|
58
|
+
body: {
|
|
59
|
+
providerOptions,
|
|
60
|
+
cache_ttl: options.cacheTTL,
|
|
61
|
+
cache_anchor_items: options.cacheAnchorItems,
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
case "chat": {
|
|
65
|
+
if (!options.thinking)
|
|
66
|
+
return { request, body: { providerOptions } };
|
|
67
|
+
const reasoning = {
|
|
68
|
+
enabled: options.thinking.type !== "disabled",
|
|
69
|
+
max_tokens: options.thinking.budgetTokens ?? options.thinking.budget_tokens,
|
|
70
|
+
};
|
|
71
|
+
return { request, body: { providerOptions, reasoning } };
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
const route = (input) => Route.make({
|
|
76
|
+
id: input.id,
|
|
77
|
+
provider: id,
|
|
78
|
+
providerMetadataKey: id,
|
|
79
|
+
protocol: gatewayProtocol(input.protocol, { id: input.id, prepare: prepare(input.api) }),
|
|
80
|
+
endpoint: Endpoint.path(input.path, { baseURL }),
|
|
81
|
+
framing: input.framing,
|
|
82
|
+
headers: ({ request }) => request.promptCacheKey ? { "x-session-affinity": request.promptCacheKey } : {},
|
|
83
|
+
defaults: input.defaults,
|
|
84
|
+
});
|
|
85
|
+
const messagesRoute = route({
|
|
86
|
+
id: "vercel-ai-gateway-messages",
|
|
87
|
+
protocol: AnthropicMessages.protocol,
|
|
88
|
+
api: "messages",
|
|
89
|
+
path: "/messages",
|
|
90
|
+
framing: AnthropicMessages.framing,
|
|
91
|
+
defaults: { headers: { "anthropic-version": "2023-06-01" } },
|
|
92
|
+
});
|
|
93
|
+
const responsesRoute = route({
|
|
94
|
+
id: "vercel-ai-gateway-responses",
|
|
95
|
+
protocol: OpenResponses.protocol,
|
|
96
|
+
api: "responses",
|
|
97
|
+
path: "/responses",
|
|
98
|
+
framing: Framing.sse,
|
|
99
|
+
defaults: { providerOptions: { store: false, include: ["reasoning.encrypted_content"] } },
|
|
100
|
+
});
|
|
101
|
+
const chatRoute = route({
|
|
102
|
+
id: "vercel-ai-gateway-chat",
|
|
103
|
+
protocol: OpenAIChat.protocol,
|
|
104
|
+
api: "chat",
|
|
105
|
+
path: "/chat/completions",
|
|
106
|
+
framing: OpenAIChat.framing,
|
|
107
|
+
});
|
|
108
|
+
export const routes = [messagesRoute, responsesRoute, chatRoute];
|
|
9
109
|
const Request = Schema.StructWithRest(Schema.Struct({
|
|
10
110
|
model: Schema.String,
|
|
11
111
|
state: EvaluationInput,
|
|
@@ -13,16 +113,39 @@ const Request = Schema.StructWithRest(Schema.Struct({
|
|
|
13
113
|
providerOptions: Schema.optional(Schema.Record(Schema.String, Schema.Unknown)),
|
|
14
114
|
}), [Schema.Record(Schema.String, Schema.Any)]);
|
|
15
115
|
const Response = Schema.Struct({
|
|
16
|
-
model:
|
|
116
|
+
model: optionalNull(Schema.String),
|
|
17
117
|
answers: Schema.Record(Schema.String, EvaluationAnswer),
|
|
18
|
-
usage:
|
|
19
|
-
inputTokens:
|
|
20
|
-
outputTokens:
|
|
118
|
+
usage: optionalNull(Schema.Struct({
|
|
119
|
+
inputTokens: optionalNull(Schema.Number),
|
|
120
|
+
outputTokens: optionalNull(Schema.Number),
|
|
21
121
|
})),
|
|
22
|
-
rounding:
|
|
23
|
-
providerMetadata:
|
|
122
|
+
rounding: optionalNull(EvaluationRounding),
|
|
123
|
+
providerMetadata: optionalNull(ProviderMetadata),
|
|
24
124
|
});
|
|
25
125
|
export const configure = (input = {}) => {
|
|
126
|
+
const { apiKey: _apiKey, auth: _auth, baseURL: endpoint, ...defaults } = input;
|
|
127
|
+
const configured = {
|
|
128
|
+
...defaults,
|
|
129
|
+
endpoint: { baseURL: endpoint ?? baseURL },
|
|
130
|
+
auth: AuthOptions.bearer(input, ["AI_GATEWAY_API_KEY", "VERCEL_OIDC_TOKEN"]),
|
|
131
|
+
};
|
|
132
|
+
const messages = (modelID) => messagesRoute.with(configured).model({
|
|
133
|
+
id: modelID,
|
|
134
|
+
// Recorded Gateway translations for non-Claude models return thinking with empty signatures.
|
|
135
|
+
compatibility: { requireSignature: modelID.startsWith("anthropic/") },
|
|
136
|
+
});
|
|
137
|
+
const responses = (modelID) => responsesRoute.with(configured).model({ id: modelID });
|
|
138
|
+
const chat = (modelID) => chatRoute
|
|
139
|
+
.with(configured)
|
|
140
|
+
.model({ id: modelID, compatibility: { reasoningField: "reasoning" } });
|
|
141
|
+
// Each family uses the API whose Gateway translation carries its reasoning state across turns.
|
|
142
|
+
const model = (modelID) => {
|
|
143
|
+
if (/^(openai\/gpt-|spacexai\/grok-)/.test(modelID))
|
|
144
|
+
return responses(modelID);
|
|
145
|
+
if (modelID.startsWith("meta/muse-"))
|
|
146
|
+
return chat(modelID);
|
|
147
|
+
return messages(modelID);
|
|
148
|
+
};
|
|
26
149
|
const evaluation = (modelID) => EvaluationModel.make({
|
|
27
150
|
id: modelID,
|
|
28
151
|
provider: id,
|
|
@@ -39,7 +162,7 @@ export const configure = (input = {}) => {
|
|
|
39
162
|
questions: req.questions,
|
|
40
163
|
providerOptions: req.options,
|
|
41
164
|
}).pipe(Effect.mapError((cause) => new AIError({ reason: new InvalidRequestError({ message: cause.message, cause }) })));
|
|
42
|
-
const headers = yield* Auth.toEffect(
|
|
165
|
+
const headers = yield* Auth.toEffect(configured.auth)({
|
|
43
166
|
request: req,
|
|
44
167
|
method: "POST",
|
|
45
168
|
url: url.toString(),
|
|
@@ -59,27 +182,44 @@ export const configure = (input = {}) => {
|
|
|
59
182
|
});
|
|
60
183
|
const text = yield* res.text.pipe(Effect.mapError((cause) => fail("Failed to read the Vercel AI Gateway evaluation response", cause)));
|
|
61
184
|
const data = yield* Schema.decodeUnknownEffect(Schema.fromJsonString(Response))(text).pipe(Effect.mapError((cause) => fail("Vercel AI Gateway returned an invalid evaluation response", cause, text)));
|
|
185
|
+
const inputTokens = data.usage?.inputTokens ?? undefined;
|
|
186
|
+
const outputTokens = data.usage?.outputTokens ?? undefined;
|
|
187
|
+
const usage = data.usage
|
|
188
|
+
? new Usage({
|
|
189
|
+
inputTokens,
|
|
190
|
+
outputTokens,
|
|
191
|
+
totalTokens: ProviderShared.totalTokens(inputTokens, outputTokens, undefined),
|
|
192
|
+
providerMetadata: { gateway: data.usage },
|
|
193
|
+
})
|
|
194
|
+
: undefined;
|
|
62
195
|
return new EvaluationResponse({
|
|
63
196
|
model: ModelID.make(data.model ?? req.model.id),
|
|
64
197
|
answers: data.answers,
|
|
65
|
-
usage
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
outputTokens: data.usage.outputTokens,
|
|
69
|
-
totalTokens: data.usage.inputTokens === undefined && data.usage.outputTokens === undefined
|
|
70
|
-
? undefined
|
|
71
|
-
: (data.usage.inputTokens ?? 0) + (data.usage.outputTokens ?? 0),
|
|
72
|
-
providerMetadata: { gateway: data.usage },
|
|
73
|
-
})
|
|
74
|
-
: undefined,
|
|
75
|
-
rounding: data.rounding,
|
|
76
|
-
providerMetadata: data.providerMetadata,
|
|
198
|
+
usage,
|
|
199
|
+
rounding: data.rounding ?? undefined,
|
|
200
|
+
providerMetadata: data.providerMetadata ?? undefined,
|
|
77
201
|
});
|
|
78
202
|
}),
|
|
79
203
|
},
|
|
80
204
|
});
|
|
81
|
-
return { id, experimental: { evaluation }, configure };
|
|
205
|
+
return { id, model, messages, responses, chat, experimental: { evaluation }, configure };
|
|
82
206
|
};
|
|
83
207
|
export const provider = configure();
|
|
84
208
|
export const experimental = provider.experimental;
|
|
209
|
+
export const messages = provider.messages;
|
|
210
|
+
export const responses = provider.responses;
|
|
211
|
+
export const chat = provider.chat;
|
|
212
|
+
export const model = (modelID, settings) => fromSettings(settings).model(modelID);
|
|
213
|
+
export const messagesModel = (modelID, settings) => fromSettings(settings).messages(modelID);
|
|
214
|
+
export const responsesModel = (modelID, settings) => fromSettings(settings).responses(modelID);
|
|
215
|
+
export const chatModel = (modelID, settings) => fromSettings(settings).chat(modelID);
|
|
216
|
+
function fromSettings({ apiKey, baseURL, headers, body, ...providerOptions }) {
|
|
217
|
+
return configure({
|
|
218
|
+
apiKey,
|
|
219
|
+
baseURL,
|
|
220
|
+
headers,
|
|
221
|
+
http: body === undefined ? undefined : { body: { ...body } },
|
|
222
|
+
providerOptions,
|
|
223
|
+
});
|
|
224
|
+
}
|
|
85
225
|
export * as VercelAIGateway from "./vercel-ai-gateway.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.25",
|
|
4
4
|
"name": "@opencode/ai",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@clack/prompts": "1.0.0-alpha.1",
|
|
36
36
|
"@effect/platform-node": "4.0.0-rc.112",
|
|
37
|
-
"@opencode/http-recorder": "2.0.
|
|
37
|
+
"@opencode/http-recorder": "2.0.25",
|
|
38
38
|
"@tsconfig/bun": "1.0.9",
|
|
39
39
|
"@types/bun": "1.4.0",
|
|
40
40
|
"@typescript/native-preview": "7.0.0-dev.20251207.1",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"@aws-sdk/credential-providers": "3.1057.0",
|
|
45
45
|
"@smithy/eventstream-codec": "4.2.14",
|
|
46
46
|
"@smithy/util-utf8": "4.2.2",
|
|
47
|
-
"@opencode/schema": "2.0.
|
|
47
|
+
"@opencode/schema": "2.0.25",
|
|
48
48
|
"aws4fetch": "1.0.20",
|
|
49
49
|
"effect": "4.0.0-rc.112",
|
|
50
50
|
"google-auth-library": "10.5.0"
|