@opencode/ai 2.0.22 → 2.0.24
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 +61 -1
- package/dist/cache-policy.js +13 -9
- package/dist/protocols/alibaba-chat.d.ts +3 -3
- package/dist/protocols/alibaba-messages.d.ts +3 -0
- package/dist/protocols/alibaba-responses.d.ts +19 -12
- package/dist/protocols/alibaba-responses.js +3 -5
- package/dist/protocols/anthropic-messages.d.ts +3 -0
- package/dist/protocols/anthropic-messages.js +53 -48
- package/dist/protocols/bedrock-converse.js +3 -3
- package/dist/protocols/cartesia-speech.js +3 -3
- package/dist/protocols/cohere-chat.d.ts +178 -0
- package/dist/protocols/cohere-chat.js +299 -0
- package/dist/protocols/elevenlabs-speech.js +3 -3
- package/dist/protocols/gemini.d.ts +2 -2
- package/dist/protocols/gemini.js +3 -3
- package/dist/protocols/google-interactions.d.ts +236 -0
- package/dist/protocols/google-interactions.js +478 -0
- package/dist/protocols/google-speech.js +1 -1
- package/dist/protocols/google-transcription.js +1 -1
- package/dist/protocols/index.d.ts +2 -0
- package/dist/protocols/index.js +2 -0
- package/dist/protocols/meta-messages.d.ts +3 -0
- package/dist/protocols/meta-responses.d.ts +34 -58
- package/dist/protocols/meta-responses.js +8 -27
- package/dist/protocols/mistral-chat.d.ts +24 -9
- package/dist/protocols/mistral-chat.js +22 -10
- package/dist/protocols/open-responses.d.ts +424 -103
- package/dist/protocols/open-responses.js +30 -20
- package/dist/protocols/openai-chat.d.ts +401 -5
- package/dist/protocols/openai-chat.js +18 -21
- package/dist/protocols/openai-compatible-chat.d.ts +1 -1
- package/dist/protocols/openai-compatible-responses.d.ts +16 -4
- package/dist/protocols/openai-images.js +2 -2
- package/dist/protocols/openai-responses.d.ts +90 -223
- package/dist/protocols/openai-responses.js +6 -13
- package/dist/protocols/openai-speech.js +1 -1
- package/dist/protocols/openai-transcription.js +1 -1
- package/dist/protocols/shared.js +2 -2
- package/dist/protocols/stability-images.js +1 -1
- package/dist/protocols/utils/bedrock-media.js +2 -2
- package/dist/protocols/utils/gateway-protocol.d.ts +17 -0
- package/dist/protocols/utils/gateway-protocol.js +57 -0
- package/dist/protocols/utils/responses-checkpoint.js +2 -2
- package/dist/protocols/utils/responses-hosted-tools.js +1 -1
- package/dist/protocols/utils/tool-stream.js +15 -7
- package/dist/protocols/venice-chat.d.ts +280 -0
- package/dist/protocols/venice-chat.js +283 -0
- package/dist/protocols/xai-responses.d.ts +21 -21
- package/dist/protocols/xai-responses.js +2 -8
- package/dist/protocols/zai-chat.d.ts +3 -3
- package/dist/protocols/zai-messages.d.ts +3 -0
- package/dist/provider-error.js +7 -1
- package/dist/providers/alibaba.d.ts +17 -13
- package/dist/providers/amazon-bedrock/mantle/messages.d.ts +2 -0
- package/dist/providers/amazon-bedrock/mantle/messages.js +1 -0
- package/dist/providers/amazon-bedrock-mantle.d.ts +301 -9
- package/dist/providers/amazon-bedrock-mantle.js +28 -3
- package/dist/providers/azure.d.ts +13 -61
- package/dist/providers/baseten.d.ts +2 -2
- package/dist/providers/cerebras.d.ts +2 -2
- package/dist/providers/cloudflare-ai-gateway.d.ts +14 -62
- package/dist/providers/cloudflare-workers-ai.d.ts +2 -2
- package/dist/providers/cohere/chat.d.ts +4 -0
- package/dist/providers/cohere/chat.js +8 -0
- package/dist/providers/cohere.d.ts +395 -0
- package/dist/providers/cohere.js +48 -0
- package/dist/providers/deepinfra.d.ts +2 -2
- package/dist/providers/deepseek.d.ts +2 -2
- package/dist/providers/digitalocean.d.ts +5 -5
- package/dist/providers/fireworks.d.ts +2 -2
- package/dist/providers/google/interactions.d.ts +7 -0
- package/dist/providers/google/interactions.js +8 -0
- package/dist/providers/google-vertex-chat.d.ts +1 -1
- package/dist/providers/google-vertex-messages.js +1 -0
- package/dist/providers/google-vertex-responses.d.ts +16 -4
- package/dist/providers/google-vertex.d.ts +1 -1
- package/dist/providers/google.d.ts +95 -4
- package/dist/providers/google.js +8 -1
- package/dist/providers/groq.d.ts +4 -4
- package/dist/providers/index.d.ts +2 -0
- package/dist/providers/index.js +2 -0
- package/dist/providers/meta.d.ts +15 -28
- package/dist/providers/minimax.d.ts +17 -5
- package/dist/providers/mistral.d.ts +10 -4
- package/dist/providers/moonshot.d.ts +17 -5
- package/dist/providers/openai-compatible-responses.d.ts +16 -4
- package/dist/providers/openai-compatible.d.ts +1 -1
- package/dist/providers/openai-options.d.ts +1 -1
- package/dist/providers/openai.d.ts +7 -31
- package/dist/providers/openrouter.d.ts +5 -5
- package/dist/providers/togetherai.d.ts +2 -2
- package/dist/providers/venice.d.ts +183 -0
- package/dist/providers/venice.js +38 -0
- 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/dist/providers/xai.d.ts +1 -1
- package/dist/providers/zai-coding-plan.d.ts +17 -5
- package/dist/providers/zai.d.ts +1 -1
- package/dist/route/client.js +2 -5
- package/dist/route/framing.js +23 -23
- package/package.json +3 -3
|
@@ -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/dist/providers/xai.d.ts
CHANGED
|
@@ -134,9 +134,9 @@ export declare const routes: (Route<{
|
|
|
134
134
|
readonly top_p?: number | undefined;
|
|
135
135
|
readonly frequency_penalty?: number | undefined;
|
|
136
136
|
readonly presence_penalty?: number | undefined;
|
|
137
|
+
readonly store?: boolean | undefined;
|
|
137
138
|
readonly prompt_cache_key?: string | undefined;
|
|
138
139
|
readonly reasoning_effort?: import("../schema/options.js").ReasoningEffort | undefined;
|
|
139
|
-
readonly store?: boolean | undefined;
|
|
140
140
|
readonly stream_options?: {
|
|
141
141
|
readonly include_usage: boolean;
|
|
142
142
|
} | undefined;
|
|
@@ -57,6 +57,15 @@ export declare const routes: (Route<{
|
|
|
57
57
|
readonly error?: unknown;
|
|
58
58
|
readonly arguments?: string | undefined;
|
|
59
59
|
readonly server_label?: string | undefined;
|
|
60
|
+
} | {
|
|
61
|
+
readonly type: "configuration_update";
|
|
62
|
+
readonly reasoning: {
|
|
63
|
+
readonly effort: import("../schema/options.js").ReasoningEffort;
|
|
64
|
+
};
|
|
65
|
+
} | {
|
|
66
|
+
readonly [x: string]: unknown;
|
|
67
|
+
readonly type: string;
|
|
68
|
+
readonly id: string;
|
|
60
69
|
} | {
|
|
61
70
|
readonly type: "reasoning";
|
|
62
71
|
readonly summary: readonly {
|
|
@@ -144,7 +153,10 @@ export declare const routes: (Route<{
|
|
|
144
153
|
readonly summary?: "auto" | "concise" | "detailed" | undefined;
|
|
145
154
|
readonly effort?: import("../schema/options.js").ReasoningEffort | undefined;
|
|
146
155
|
} | undefined;
|
|
147
|
-
readonly tools?: readonly {
|
|
156
|
+
readonly tools?: readonly ({
|
|
157
|
+
readonly [x: string]: unknown;
|
|
158
|
+
readonly type: string;
|
|
159
|
+
} | {
|
|
148
160
|
readonly type: "function";
|
|
149
161
|
readonly description: string;
|
|
150
162
|
readonly name: string;
|
|
@@ -152,7 +164,7 @@ export declare const routes: (Route<{
|
|
|
152
164
|
readonly [x: string]: unknown;
|
|
153
165
|
};
|
|
154
166
|
readonly strict?: boolean | undefined;
|
|
155
|
-
}[] | undefined;
|
|
167
|
+
})[] | undefined;
|
|
156
168
|
readonly text?: {
|
|
157
169
|
readonly verbosity?: import("../protocols/utils/open-responses-options.js").TextVerbosity | undefined;
|
|
158
170
|
} | undefined;
|
|
@@ -172,9 +184,10 @@ export declare const routes: (Route<{
|
|
|
172
184
|
readonly top_p?: number | undefined;
|
|
173
185
|
readonly frequency_penalty?: number | undefined;
|
|
174
186
|
readonly presence_penalty?: number | undefined;
|
|
187
|
+
readonly store?: boolean | undefined;
|
|
188
|
+
readonly max_output_tokens?: number | undefined;
|
|
175
189
|
readonly prompt_cache_key?: string | undefined;
|
|
176
190
|
readonly parallel_tool_calls?: boolean | undefined;
|
|
177
|
-
readonly store?: boolean | undefined;
|
|
178
191
|
readonly include?: readonly import("../protocols/utils/open-responses-options.js").ResponseIncludable[] | undefined;
|
|
179
192
|
readonly truncation?: "auto" | "disabled" | undefined;
|
|
180
193
|
readonly stream_options?: {
|
|
@@ -182,7 +195,6 @@ export declare const routes: (Route<{
|
|
|
182
195
|
} | undefined;
|
|
183
196
|
readonly safety_identifier?: string | undefined;
|
|
184
197
|
readonly top_logprobs?: number | undefined;
|
|
185
|
-
readonly max_output_tokens?: number | undefined;
|
|
186
198
|
readonly max_tool_calls?: number | undefined;
|
|
187
199
|
}, import("../route/transport/http.js").HttpPrepared<string>, import("../route/client.js").CompactionOperations | undefined> | Route<{
|
|
188
200
|
readonly model: string;
|
|
@@ -303,9 +315,9 @@ export declare const routes: (Route<{
|
|
|
303
315
|
readonly top_p?: number | undefined;
|
|
304
316
|
readonly frequency_penalty?: number | undefined;
|
|
305
317
|
readonly presence_penalty?: number | undefined;
|
|
318
|
+
readonly store?: boolean | undefined;
|
|
306
319
|
readonly prompt_cache_key?: string | undefined;
|
|
307
320
|
readonly reasoning_effort?: import("../schema/options.js").ReasoningEffort | undefined;
|
|
308
|
-
readonly store?: boolean | undefined;
|
|
309
321
|
readonly stream_options?: {
|
|
310
322
|
readonly include_usage: boolean;
|
|
311
323
|
} | undefined;
|
package/dist/providers/zai.d.ts
CHANGED
|
@@ -133,9 +133,9 @@ export declare const routes: Route<{
|
|
|
133
133
|
readonly top_p?: number | undefined;
|
|
134
134
|
readonly frequency_penalty?: number | undefined;
|
|
135
135
|
readonly presence_penalty?: number | undefined;
|
|
136
|
+
readonly store?: boolean | undefined;
|
|
136
137
|
readonly prompt_cache_key?: string | undefined;
|
|
137
138
|
readonly reasoning_effort?: import("../schema/options.js").ReasoningEffort | undefined;
|
|
138
|
-
readonly store?: boolean | undefined;
|
|
139
139
|
readonly stream_options?: {
|
|
140
140
|
readonly include_usage: boolean;
|
|
141
141
|
} | undefined;
|
package/dist/route/client.js
CHANGED
|
@@ -102,7 +102,6 @@ const requireTerminalEvent = (route) => (events) => Stream.suspend(() => {
|
|
|
102
102
|
});
|
|
103
103
|
function makeFromTransport(input) {
|
|
104
104
|
const protocol = input.protocol;
|
|
105
|
-
const encodeBody = Schema.encodeSync(Schema.fromJsonString(protocol.body.schema));
|
|
106
105
|
const decodeEventEffect = Schema.decodeUnknownEffect(protocol.stream.event);
|
|
107
106
|
const decodeEvent = (route) => (frame) => decodeEventEffect(frame).pipe(Effect.mapError((cause) => ProviderShared.eventError(input.id, `Invalid ${route} stream event`, typeof frame === "string" ? frame : ProviderShared.encodeJson(frame), cause)));
|
|
108
107
|
const build = (routeInput) => {
|
|
@@ -143,7 +142,7 @@ function makeFromTransport(input) {
|
|
|
143
142
|
request,
|
|
144
143
|
endpoint: routeInput.endpoint,
|
|
145
144
|
auth: routeInput.auth ?? Auth.none,
|
|
146
|
-
encodeBody,
|
|
145
|
+
encodeBody: ProviderShared.encodeJson,
|
|
147
146
|
middleware: options?.http,
|
|
148
147
|
webSocket: options?.webSocket,
|
|
149
148
|
}),
|
|
@@ -221,9 +220,7 @@ const prepareRequest = (request) => {
|
|
|
221
220
|
const compile = Effect.fn("LLM.compile")(function* (request, options) {
|
|
222
221
|
const resolved = prepareRequest(request);
|
|
223
222
|
const route = resolved.model.route;
|
|
224
|
-
const body = yield* route.body
|
|
225
|
-
.from(resolved)
|
|
226
|
-
.pipe(Effect.flatMap(ProviderShared.validateWith(Schema.decodeUnknownEffect(route.body.schema))));
|
|
223
|
+
const body = yield* route.body.from(resolved);
|
|
227
224
|
const prepared = yield* route.prepareTransport(body, resolved, options);
|
|
228
225
|
return {
|
|
229
226
|
request: resolved,
|
package/dist/route/framing.js
CHANGED
|
@@ -14,32 +14,32 @@ export const sseFraming = (bytes, events, includeDone = false) => bytes.pipe(Str
|
|
|
14
14
|
return {
|
|
15
15
|
output,
|
|
16
16
|
parser: makeParser((event) => {
|
|
17
|
-
if (event._tag === "Event"
|
|
18
|
-
|
|
17
|
+
if (event._tag === "Event" &&
|
|
18
|
+
(events === undefined || events.has(event.event)) &&
|
|
19
|
+
event.data.length > 0 &&
|
|
20
|
+
// Some OpenAI-compatible proxies serialize an empty flush as a bare
|
|
21
|
+
// `data: null`, between events or after `[DONE]`. No protocol has a
|
|
22
|
+
// null event, so it carries nothing and must not abort the stream.
|
|
23
|
+
event.data !== "null" &&
|
|
24
|
+
// Vertex AI partner models (e.g. `xai/grok-4.6`) send their SSE
|
|
25
|
+
// keepalive comment as `data: : keepalive` while reasoning.
|
|
26
|
+
event.data !== ": keepalive" &&
|
|
27
|
+
(event.data !== "[DONE]" || includeDone || (events !== undefined && event.event !== "message")))
|
|
28
|
+
output.push(event.data);
|
|
19
29
|
}),
|
|
20
30
|
};
|
|
21
|
-
}, (state, chunk) =>
|
|
31
|
+
}, (state, chunk) => {
|
|
22
32
|
const error = state.parser.feed(chunk);
|
|
23
|
-
if (error)
|
|
24
|
-
return
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
})), Stream.filter((event) => (events === undefined || events.has(event.event)) &&
|
|
34
|
-
event.data.length > 0 &&
|
|
35
|
-
// Some OpenAI-compatible proxies serialize an empty flush as a bare
|
|
36
|
-
// `data: null`, between events or after `[DONE]`. No protocol has a
|
|
37
|
-
// null event, so it carries nothing and must not abort the stream.
|
|
38
|
-
event.data !== "null" &&
|
|
39
|
-
// Vertex AI partner models (e.g. `xai/grok-4.6`) send their SSE
|
|
40
|
-
// keepalive comment as `data: : keepalive` while reasoning.
|
|
41
|
-
event.data !== ": keepalive" &&
|
|
42
|
-
(event.data !== "[DONE]" || includeDone || (events !== undefined && event.event !== "message"))), Stream.map((event) => event.data));
|
|
33
|
+
if (!error)
|
|
34
|
+
return Effect.succeed([state, state.output.splice(0)]);
|
|
35
|
+
const reason = new InvalidProviderOutputError({
|
|
36
|
+
route: "sse",
|
|
37
|
+
message: error.message,
|
|
38
|
+
body: chunk,
|
|
39
|
+
cause: error,
|
|
40
|
+
});
|
|
41
|
+
return Effect.fail(new AIError({ reason }));
|
|
42
|
+
}));
|
|
43
43
|
/** Server-Sent Events framing. Used by every JSON-streaming HTTP provider. */
|
|
44
44
|
export const sse = { id: "sse", frame: sseFraming };
|
|
45
45
|
/** Server-Sent Events framing that retains the conventional `[DONE]` sentinel. */
|
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.24",
|
|
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.24",
|
|
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.24",
|
|
48
48
|
"aws4fetch": "1.0.20",
|
|
49
49
|
"effect": "4.0.0-rc.112",
|
|
50
50
|
"google-auth-library": "10.5.0"
|