@opencode/ai 2.0.25 → 2.0.27
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 +7 -1
- package/dist/experimental/system-one.js +1 -1
- package/dist/media.js +7 -6
- package/dist/protocols/anthropic-messages.js +1 -1
- package/dist/protocols/bedrock-converse.js +4 -3
- package/dist/protocols/bedrock-event-stream.js +4 -3
- package/dist/protocols/meta-responses.js +3 -2
- package/dist/protocols/mistral-chat.d.ts +1 -1
- package/dist/protocols/mistral-chat.js +1 -1
- package/dist/protocols/open-responses-channel.d.ts +1 -1
- package/dist/protocols/open-responses-channel.js +1 -1
- package/dist/protocols/openai-responses.d.ts +5 -5
- package/dist/protocols/openai-responses.js +4 -3
- package/dist/protocols/shared.d.ts +1 -1
- package/dist/protocols/shared.js +1 -1
- package/dist/protocols/utils/bedrock-auth.js +1 -1
- package/dist/protocols/utils/bedrock-media.js +4 -3
- package/dist/protocols/utils/fal-queue.d.ts +1 -1
- package/dist/protocols/utils/media-input.js +4 -3
- package/dist/protocols/utils/tool-schema.js +8 -2
- package/dist/providers/amazon-bedrock-mantle.js +2 -2
- package/dist/providers/anthropic-compatible.js +2 -2
- package/dist/providers/anthropic.js +2 -2
- package/dist/providers/azure.d.ts +2 -2
- package/dist/providers/azure.js +3 -3
- package/dist/providers/baseten.js +2 -2
- package/dist/providers/cerebras.js +2 -2
- package/dist/providers/cloudflare-ai-gateway.d.ts +2 -2
- package/dist/providers/cloudflare-ai-gateway.js +2 -2
- package/dist/providers/cloudflare-workers-ai.js +2 -2
- package/dist/providers/cohere/chat.js +1 -1
- package/dist/providers/cohere.js +1 -1
- package/dist/providers/deepinfra.js +2 -2
- package/dist/providers/deepseek.js +2 -2
- package/dist/providers/fireworks.js +2 -2
- package/dist/providers/google/interactions.js +2 -2
- package/dist/providers/google-vertex/interactions.d.ts +2 -0
- package/dist/providers/google-vertex/interactions.js +1 -0
- package/dist/providers/google-vertex/mistral.d.ts +2 -0
- package/dist/providers/google-vertex/mistral.js +1 -0
- package/dist/providers/google-vertex-chat.js +3 -3
- package/dist/providers/google-vertex-interactions.d.ts +112 -0
- package/dist/providers/google-vertex-interactions.js +64 -0
- package/dist/providers/google-vertex-messages.js +3 -3
- package/dist/providers/google-vertex-mistral.d.ts +124 -0
- package/dist/providers/google-vertex-mistral.js +69 -0
- package/dist/providers/google-vertex-responses.js +3 -3
- package/dist/providers/google-vertex-shared.d.ts +7 -2
- package/dist/providers/google-vertex-shared.js +36 -4
- package/dist/providers/google-vertex.js +3 -3
- package/dist/providers/google.js +2 -2
- package/dist/providers/groq.js +2 -2
- package/dist/providers/index.d.ts +2 -0
- package/dist/providers/index.js +2 -0
- package/dist/providers/meta.js +1 -1
- package/dist/providers/minimax/chat.js +1 -1
- package/dist/providers/minimax/responses.js +1 -1
- package/dist/providers/minimax.js +1 -1
- package/dist/providers/mistral.js +2 -2
- package/dist/providers/moonshot/messages.js +1 -1
- package/dist/providers/moonshot/responses.js +1 -1
- package/dist/providers/moonshot.js +1 -1
- package/dist/providers/openai-compatible-responses.js +2 -2
- package/dist/providers/openai-compatible.js +2 -2
- package/dist/providers/openai.d.ts +1 -1
- package/dist/providers/openai.js +2 -2
- package/dist/providers/openrouter.js +1 -1
- package/dist/providers/togetherai.js +2 -2
- package/dist/providers/venice.js +1 -1
- package/dist/providers/vercel-ai-gateway.js +2 -2
- package/dist/providers/xai.js +1 -1
- package/dist/providers/zai-coding-plan/messages.js +1 -1
- package/dist/providers/zai-coding-plan/responses.js +1 -1
- package/dist/providers/zai-coding-plan.js +1 -1
- package/dist/providers/zai.js +1 -1
- package/dist/route/auth.d.ts +1 -1
- package/dist/route/auth.js +2 -2
- package/dist/route/executor-service.d.ts +1 -1
- package/dist/route/executor.d.ts +1 -1
- package/dist/route/executor.js +1 -1
- package/dist/route/framing.js +1 -1
- package/dist/route/media-protocol.d.ts +1 -1
- package/dist/route/media-protocol.js +1 -1
- package/dist/route/media.js +1 -1
- package/dist/route/transport/http.d.ts +1 -1
- package/dist/route/transport/http.js +1 -1
- package/dist/route/transport/websocket-channel.d.ts +1 -1
- package/dist/route/transport/websocket.d.ts +4 -4
- package/dist/route/transport/websocket.js +4 -9
- package/dist/schema/messages.js +9 -8
- package/dist/tool.d.ts +10 -0
- package/dist/tool.js +21 -2
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -32,6 +32,11 @@ Anthropic Messages, Gemini, Bedrock Converse, and any OpenAI-compatible deployme
|
|
|
32
32
|
`Google.configure({ apiKey }).interactions(modelID)` selects the Interactions API; `.model(modelID)` still selects
|
|
33
33
|
GenerateContent. The package entrypoint is `@opencode/ai/providers/google/interactions`.
|
|
34
34
|
|
|
35
|
+
For Vertex AI, use `GoogleVertexInteractions.configure({ project, location: "global" }).model(modelID)` or
|
|
36
|
+
`@opencode/ai/providers/google-vertex/interactions`. It uses Application Default Credentials by default, accepts
|
|
37
|
+
an explicit `accessToken` or `auth` override, and supports Express mode with `apiKey`. Vertex metadata and raw usage
|
|
38
|
+
live under `providerMetadata.vertex`. The default is still full-history replay with `store: false`.
|
|
39
|
+
|
|
35
40
|
```ts
|
|
36
41
|
const model = Google.configure({ apiKey }).interactions("gemini-3.8-flash")
|
|
37
42
|
const response = yield* LLM.generate({
|
|
@@ -1316,13 +1321,14 @@ APIs have separate entrypoints:
|
|
|
1316
1321
|
- `@opencode/ai/providers/openai-compatible/responses`
|
|
1317
1322
|
- `@opencode/ai/providers/anthropic-compatible`
|
|
1318
1323
|
- `@opencode/ai/providers/google-vertex/gemini`
|
|
1324
|
+
- `@opencode/ai/providers/google-vertex/interactions`
|
|
1319
1325
|
- `@opencode/ai/providers/google-vertex/chat`
|
|
1320
1326
|
- `@opencode/ai/providers/google-vertex/responses`
|
|
1321
1327
|
- `@opencode/ai/providers/google-vertex/messages`
|
|
1322
1328
|
|
|
1323
1329
|
OpenAI Responses has one semantic route and uses HTTP by default. Advanced callers may supply a per-call WebSocket channel executor through `StreamOptions`; transport policy does not change provider settings, model identity, or route identity. The provider-neutral Open Responses implementation owns the reusable WebSocket request and event contract, while each provider opts in with its own handshake and connection policy. Azure follows the same Chat/Responses split at `providers/azure/chat` and `providers/azure/responses`. Generic OpenAI-compatible Chat remains at `providers/openai-compatible`; the Responses adapter at `providers/openai-compatible/responses` uses the provider-neutral Open Responses protocol. OpenAI Responses extends that baseline with OpenAI tools, event variants, metadata, and defaults. Generic Anthropic Messages-compatible providers use `providers/anthropic-compatible`, which the named Anthropic provider composes. Google Gemini and Amazon Bedrock expose their single native API through their existing provider paths.
|
|
1324
1330
|
|
|
1325
|
-
Vertex Gemini, Vertex Chat, Vertex Responses, and Vertex Messages are separate API entrypoints. All accept `project`, `location`, and an optional `accessToken`; when no explicit token or auth override is supplied they lazily use Google Application Default Credentials. Vertex Gemini instead
|
|
1331
|
+
Vertex Gemini, Vertex Interactions, Vertex Chat, Vertex Responses, and Vertex Messages are separate API entrypoints. All accept `project`, `location`, and an optional `accessToken`; when no explicit token or auth override is supplied they lazily use Google Application Default Credentials. Vertex Gemini and Interactions instead select express mode when `apiKey` or `GOOGLE_VERTEX_API_KEY` is present (explicit `project` or `location` selects ADC over an ambient key). Vertex Chat targets MaaS models through the OpenAI-compatible Chat Completions endpoint, while Vertex Responses targets Grok models and defaults `store` to `false` as required by Vertex. `providers/google-vertex` remains the default alias for `providers/google-vertex/gemini`.
|
|
1326
1332
|
|
|
1327
1333
|
Tuned Vertex Gemini deployments use model ids shaped like `endpoints/1234567890` and require OAuth or ADC; Vertex express-mode API keys support publisher models only.
|
|
1328
1334
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Effect, Schema } from "effect";
|
|
2
|
-
import { Headers, HttpClientRequest } from "effect/
|
|
2
|
+
import { Headers, HttpClientRequest } from "effect/http";
|
|
3
3
|
import { ChoiceQuestion, EvaluationInput, EvaluationModel, EvaluationResponse, EvaluationRounding, ScoreQuestion, } from "./evaluation.js";
|
|
4
4
|
import { Auth } from "../route/auth.js";
|
|
5
5
|
import { AIError, HttpContext, HttpOptions, InvalidProviderOutputError, InvalidRequestError, ModelID, Usage, mergeJsonRecords, } from "../schema/index.js";
|
package/dist/media.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export * as Media from "./media.js";
|
|
2
|
-
import { Effect,
|
|
3
|
-
import {
|
|
2
|
+
import { Effect, FileSystem, Schema, SchemaGetter } from "effect";
|
|
3
|
+
import { Base64 } from "effect/encoding";
|
|
4
|
+
import { HttpClientRequest } from "effect/http";
|
|
4
5
|
import { ProviderID } from "./schema/ids.js";
|
|
5
6
|
import { AIError, HttpContext, InvalidProviderOutputError, InvalidRequestError } from "./schema/errors.js";
|
|
6
7
|
import { ProviderMetadata } from "./schema/options.js";
|
|
@@ -105,7 +106,7 @@ export class Asset {
|
|
|
105
106
|
const source = this.source;
|
|
106
107
|
if (source.type !== "bytes" && source.type !== "base64")
|
|
107
108
|
return undefined;
|
|
108
|
-
const base64 = source.type === "base64" ? source.data : (this.#base64 ??=
|
|
109
|
+
const base64 = source.type === "base64" ? source.data : (this.#base64 ??= Base64.encode(source.data));
|
|
109
110
|
const mime = this.mediaType.toLowerCase();
|
|
110
111
|
return { mime, base64, dataUrl: `data:${mime};base64,${base64}` };
|
|
111
112
|
}
|
|
@@ -120,7 +121,7 @@ export class Asset {
|
|
|
120
121
|
if (source.type === "ref")
|
|
121
122
|
return Effect.fail(invalid(`Cannot materialize provider ref ${source.provider}:${source.id}`));
|
|
122
123
|
const decoded = source.type === "base64"
|
|
123
|
-
? Effect.fromResult(
|
|
124
|
+
? Effect.fromResult(Base64.decode(source.data)).pipe(Effect.mapError((cause) => invalid(`Media asset contains invalid base64 data`, cause)))
|
|
124
125
|
: download(source, this.headers);
|
|
125
126
|
return decoded.pipe(Effect.tap((data) => Effect.sync(() => (this.#bytes = data))));
|
|
126
127
|
});
|
|
@@ -132,7 +133,7 @@ export class Asset {
|
|
|
132
133
|
return Effect.succeed(source.data);
|
|
133
134
|
if (this.#base64 !== undefined)
|
|
134
135
|
return Effect.succeed(this.#base64);
|
|
135
|
-
return this.bytes().pipe(Effect.map((data) => (this.#base64 =
|
|
136
|
+
return this.bytes().pipe(Effect.map((data) => (this.#base64 = Base64.encode(data))));
|
|
136
137
|
});
|
|
137
138
|
}
|
|
138
139
|
dataUrl() {
|
|
@@ -145,7 +146,7 @@ export class Asset {
|
|
|
145
146
|
toJSON() {
|
|
146
147
|
const source = this.source;
|
|
147
148
|
return {
|
|
148
|
-
source: source.type === "bytes" ? { ...source, data:
|
|
149
|
+
source: source.type === "bytes" ? { ...source, data: Base64.encode(source.data) } : source,
|
|
149
150
|
info: this.info,
|
|
150
151
|
providerMetadata: this.providerMetadata,
|
|
151
152
|
};
|
|
@@ -6,7 +6,7 @@ import { Auth } from "../route/auth.js";
|
|
|
6
6
|
import { Endpoint } from "../route/endpoint.js";
|
|
7
7
|
import { Framing } from "../route/framing.js";
|
|
8
8
|
import { Protocol } from "../route/protocol.js";
|
|
9
|
-
import { Headers } from "effect/
|
|
9
|
+
import { Headers } from "effect/http";
|
|
10
10
|
import { HttpTransport } from "../route/transport/index.js";
|
|
11
11
|
import { AIError, HttpOptions, LLMRequest, LLMEvent, mergeJsonRecords, Usage, } from "../schema/index.js";
|
|
12
12
|
import { JsonObject, knownString, optionalArray, optionalNull, ProviderShared } from "./shared.js";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { Effect,
|
|
1
|
+
import { Effect, Schema } from "effect";
|
|
2
|
+
import { Base64 } from "effect/encoding";
|
|
2
3
|
import { Route } from "../route/client.js";
|
|
3
4
|
import { Endpoint } from "../route/endpoint.js";
|
|
4
5
|
import { Protocol } from "../route/protocol.js";
|
|
@@ -489,7 +490,7 @@ const mapUsage = (usage, providerMetadataKey) => {
|
|
|
489
490
|
providerMetadata: { [providerMetadataKey]: usage },
|
|
490
491
|
});
|
|
491
492
|
};
|
|
492
|
-
const encodeRedactedContent = (chunks) =>
|
|
493
|
+
const encodeRedactedContent = (chunks) => Base64.encode(concatBytes(chunks));
|
|
493
494
|
const step = (state, event) => Effect.gen(function* () {
|
|
494
495
|
if (event.contentBlockStart?.start?.toolUse) {
|
|
495
496
|
const index = event.contentBlockStart.contentBlockIndex;
|
|
@@ -530,7 +531,7 @@ const step = (state, event) => Effect.gen(function* () {
|
|
|
530
531
|
const redactedChunk = yield* (() => {
|
|
531
532
|
if (reasoning.redactedContent === undefined)
|
|
532
533
|
return Effect.succeed(undefined);
|
|
533
|
-
return Effect.fromResult(
|
|
534
|
+
return Effect.fromResult(Base64.decode(reasoning.redactedContent)).pipe(Effect.mapError((cause) => ProviderShared.eventError(ADAPTER, "Bedrock Converse reasoningContent.redactedContent contains invalid base64 data", undefined, cause)));
|
|
534
535
|
})();
|
|
535
536
|
const redactedChunks = state.reasoningRedactedContent[index] ?? [];
|
|
536
537
|
if (redactedChunk !== undefined)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { EventStreamCodec } from "@smithy/eventstream-codec";
|
|
2
2
|
import { fromUtf8, toUtf8 } from "@smithy/util-utf8";
|
|
3
|
-
import { Effect,
|
|
3
|
+
import { Effect, Stream } from "effect";
|
|
4
|
+
import { Base64 } from "effect/encoding";
|
|
4
5
|
import { AIError, AIErrorReason, InvalidProviderOutputError } from "../schema/index.js";
|
|
5
6
|
import { Framing } from "../route/framing.js";
|
|
6
7
|
import { ProviderShared } from "./shared.js";
|
|
@@ -31,7 +32,7 @@ const consumeFrames = (route) => (state, input) => Effect.gen(function* () {
|
|
|
31
32
|
route,
|
|
32
33
|
classification: "incomplete-stream",
|
|
33
34
|
message: `Incomplete Bedrock Converse event-stream frame: ${remaining.length} buffered bytes remain at end of stream`,
|
|
34
|
-
body:
|
|
35
|
+
body: Base64.encode(remaining),
|
|
35
36
|
}),
|
|
36
37
|
});
|
|
37
38
|
return [state, []];
|
|
@@ -45,7 +46,7 @@ const consumeFrames = (route) => (state, input) => Effect.gen(function* () {
|
|
|
45
46
|
break;
|
|
46
47
|
const decoded = yield* Effect.try({
|
|
47
48
|
try: () => eventCodec.decode(view.subarray(0, totalLength)),
|
|
48
|
-
catch: (error) => ProviderShared.eventError(route, `Failed to decode Bedrock Converse event-stream frame: ${error instanceof Error ? error.message : String(error)}`,
|
|
49
|
+
catch: (error) => ProviderShared.eventError(route, `Failed to decode Bedrock Converse event-stream frame: ${error instanceof Error ? error.message : String(error)}`, Base64.encode(view.subarray(0, totalLength)), error),
|
|
49
50
|
});
|
|
50
51
|
cursor = { buffer: cursor.buffer, offset: cursor.offset + totalLength };
|
|
51
52
|
const payload = utf8.decode(decoded.body);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { Effect,
|
|
1
|
+
import { Effect, Schema } from "effect";
|
|
2
|
+
import { Base64 } from "effect/encoding";
|
|
2
3
|
import { Protocol } from "../route/protocol.js";
|
|
3
4
|
import { LLMEvent, LLMRequest, Message, ToolResultPart } from "../schema/index.js";
|
|
4
5
|
import { OpenResponses } from "./open-responses.js";
|
|
@@ -80,7 +81,7 @@ const HOSTED_TOOLS = {
|
|
|
80
81
|
return { type: "error", value: item.error };
|
|
81
82
|
if (!item.result)
|
|
82
83
|
return yield* ProviderShared.eventError(ADAPTER, "Meta returned an image without data", ProviderShared.encodeJson(raw));
|
|
83
|
-
const data = yield* Effect.fromResult(
|
|
84
|
+
const data = yield* Effect.fromResult(Base64.decode(item.result)).pipe(Effect.mapError((cause) => ProviderShared.eventError(ADAPTER, "Meta returned invalid image base64", ProviderShared.encodeJson(raw), cause)));
|
|
84
85
|
// Responses image items can omit output_format, including when PNG/JPEG was requested.
|
|
85
86
|
const mime = item.output_format === undefined
|
|
86
87
|
? (detectMediaType(data) ?? "application/octet-stream")
|
|
@@ -32,7 +32,7 @@ export type ProviderOptionsInput = {
|
|
|
32
32
|
readonly promptCacheKey?: string;
|
|
33
33
|
readonly [key: string]: unknown;
|
|
34
34
|
};
|
|
35
|
-
declare const MistralBody: Schema.Struct<{
|
|
35
|
+
export declare const MistralBody: Schema.Struct<{
|
|
36
36
|
readonly model: Schema.String;
|
|
37
37
|
readonly messages: Schema.$Array<Schema.toTaggedUnion<"role", readonly [Schema.Struct<{
|
|
38
38
|
readonly role: Schema.Literal<"system">;
|
|
@@ -78,7 +78,7 @@ const MistralOptions = Schema.Struct({
|
|
|
78
78
|
promptMode: Schema.optional(Schema.Literal("reasoning")),
|
|
79
79
|
promptCacheKey: Schema.optional(Schema.String),
|
|
80
80
|
});
|
|
81
|
-
const MistralBody = Schema.Struct({
|
|
81
|
+
export const MistralBody = Schema.Struct({
|
|
82
82
|
model: Schema.String,
|
|
83
83
|
messages: Schema.Array(MistralMessage),
|
|
84
84
|
tools: optionalArray(MistralTool),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Headers } from "effect/
|
|
1
|
+
import { Headers } from "effect/http";
|
|
2
2
|
import { HttpTransport, type Transport, type WebSocketChannelDriver } from "../route/transport/index.js";
|
|
3
3
|
import { OpenResponsesContinuation } from "./open-responses-continuation.js";
|
|
4
4
|
export interface Options {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Effect, Schema, Stream } from "effect";
|
|
2
|
-
import { Headers } from "effect/
|
|
2
|
+
import { Headers } from "effect/http";
|
|
3
3
|
import { Framing } from "../route/framing.js";
|
|
4
4
|
import { HttpTransport, WebSocketTransport, } from "../route/transport/index.js";
|
|
5
5
|
import * as ProviderShared from "./shared.js";
|
|
@@ -348,7 +348,7 @@ export declare const protocol: Protocol<{
|
|
|
348
348
|
} | {
|
|
349
349
|
readonly type: "image_generation";
|
|
350
350
|
readonly size?: string | undefined;
|
|
351
|
-
readonly action?: "
|
|
351
|
+
readonly action?: "auto" | "generate" | "edit" | undefined;
|
|
352
352
|
readonly output_format?: "png" | "jpeg" | "webp" | undefined;
|
|
353
353
|
readonly quality?: "auto" | "low" | "medium" | "high" | undefined;
|
|
354
354
|
readonly background?: "auto" | "opaque" | "transparent" | undefined;
|
|
@@ -610,7 +610,7 @@ export declare const httpTransport: HttpTransport.HttpJsonTransport<{
|
|
|
610
610
|
} | {
|
|
611
611
|
readonly type: "image_generation";
|
|
612
612
|
readonly size?: string | undefined;
|
|
613
|
-
readonly action?: "
|
|
613
|
+
readonly action?: "auto" | "generate" | "edit" | undefined;
|
|
614
614
|
readonly output_format?: "png" | "jpeg" | "webp" | undefined;
|
|
615
615
|
readonly quality?: "auto" | "low" | "medium" | "high" | undefined;
|
|
616
616
|
readonly background?: "auto" | "opaque" | "transparent" | undefined;
|
|
@@ -814,7 +814,7 @@ export declare const channelTransport: (options: import("./open-responses-channe
|
|
|
814
814
|
} | {
|
|
815
815
|
readonly type: "image_generation";
|
|
816
816
|
readonly size?: string | undefined;
|
|
817
|
-
readonly action?: "
|
|
817
|
+
readonly action?: "auto" | "generate" | "edit" | undefined;
|
|
818
818
|
readonly output_format?: "png" | "jpeg" | "webp" | undefined;
|
|
819
819
|
readonly quality?: "auto" | "low" | "medium" | "high" | undefined;
|
|
820
820
|
readonly background?: "auto" | "opaque" | "transparent" | undefined;
|
|
@@ -1018,7 +1018,7 @@ export declare const transport: import("../route/transport/index.js").Transport<
|
|
|
1018
1018
|
} | {
|
|
1019
1019
|
readonly type: "image_generation";
|
|
1020
1020
|
readonly size?: string | undefined;
|
|
1021
|
-
readonly action?: "
|
|
1021
|
+
readonly action?: "auto" | "generate" | "edit" | undefined;
|
|
1022
1022
|
readonly output_format?: "png" | "jpeg" | "webp" | undefined;
|
|
1023
1023
|
readonly quality?: "auto" | "low" | "medium" | "high" | undefined;
|
|
1024
1024
|
readonly background?: "auto" | "opaque" | "transparent" | undefined;
|
|
@@ -1222,7 +1222,7 @@ export declare const route: Route<{
|
|
|
1222
1222
|
} | {
|
|
1223
1223
|
readonly type: "image_generation";
|
|
1224
1224
|
readonly size?: string | undefined;
|
|
1225
|
-
readonly action?: "
|
|
1225
|
+
readonly action?: "auto" | "generate" | "edit" | undefined;
|
|
1226
1226
|
readonly output_format?: "png" | "jpeg" | "webp" | undefined;
|
|
1227
1227
|
readonly quality?: "auto" | "low" | "medium" | "high" | undefined;
|
|
1228
1228
|
readonly background?: "auto" | "opaque" | "transparent" | undefined;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { Effect,
|
|
2
|
-
import {
|
|
1
|
+
import { Effect, Schema } from "effect";
|
|
2
|
+
import { Base64 } from "effect/encoding";
|
|
3
|
+
import { Headers } from "effect/http";
|
|
3
4
|
import { Route } from "../route/client.js";
|
|
4
5
|
import { Auth } from "../route/auth.js";
|
|
5
6
|
import { Endpoint } from "../route/endpoint.js";
|
|
@@ -194,7 +195,7 @@ const checkpointBody = {
|
|
|
194
195
|
const hostedToolResult = Effect.fnUntraced(function* (item) {
|
|
195
196
|
const isError = item.error !== undefined && item.error !== null;
|
|
196
197
|
if (item.type === "image_generation_call" && item.result) {
|
|
197
|
-
yield* Effect.fromResult(
|
|
198
|
+
yield* Effect.fromResult(Base64.decode(item.result)).pipe(Effect.mapError((cause) => ProviderShared.eventError(ADAPTER, "OpenAI Responses returned invalid image base64", undefined, cause)));
|
|
198
199
|
const format = item.output_format ?? "png";
|
|
199
200
|
return {
|
|
200
201
|
type: "content",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Tool } from "@opencode/schema/tool";
|
|
2
2
|
import { Effect, Schema } from "effect";
|
|
3
|
-
import { Headers, HttpClientRequest } from "effect/
|
|
3
|
+
import { Headers, HttpClientRequest } from "effect/http";
|
|
4
4
|
import { Media } from "../media.js";
|
|
5
5
|
import { AIError, LLMRequest, Message, ToolDefinition, type ContentPart, type MediaPart, type OpenString, type ProviderID, type ToolEntry, type ToolResultPart } from "../schema/index.js";
|
|
6
6
|
import { Json, decodeJson, encodeJson } from "../utils/json.js";
|
package/dist/protocols/shared.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Tool } from "@opencode/schema/tool";
|
|
2
2
|
import { Effect, Option, Schema } from "effect";
|
|
3
|
-
import { Headers, HttpClientRequest } from "effect/
|
|
3
|
+
import { Headers, HttpClientRequest } from "effect/http";
|
|
4
4
|
import { Media } from "../media.js";
|
|
5
5
|
import { InvalidProviderOutputError, InvalidRequestError, UnsupportedOperationError, AIError, LLMRequest, Message, ToolDefinition, } from "../schema/index.js";
|
|
6
6
|
import { Json, decodeJson, encodeJson } from "../utils/json.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AwsV4Signer } from "aws4fetch";
|
|
2
2
|
import { Effect } from "effect";
|
|
3
|
-
import { Headers } from "effect/
|
|
3
|
+
import { Headers } from "effect/http";
|
|
4
4
|
import { Auth } from "../../route/auth.js";
|
|
5
5
|
import { AIError, AuthenticationError } from "../../schema/index.js";
|
|
6
6
|
import { ProviderShared } from "../shared.js";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { Effect,
|
|
1
|
+
import { Effect, Schema } from "effect";
|
|
2
|
+
import { Base64 } from "effect/encoding";
|
|
2
3
|
import { ProviderShared } from "../shared.js";
|
|
3
4
|
// Bedrock Converse accepts image `format` as the file extension and
|
|
4
5
|
// `source.bytes` as base64 in the JSON wire format.
|
|
@@ -63,8 +64,8 @@ function documentName(filename, names) {
|
|
|
63
64
|
}
|
|
64
65
|
const mediaBase64 = Effect.fnUntraced(function* (part) {
|
|
65
66
|
const media = yield* ProviderShared.requireInlineMedia("Bedrock Converse", part.media);
|
|
66
|
-
const bytes = yield* Effect.fromResult(
|
|
67
|
-
return
|
|
67
|
+
const bytes = yield* Effect.fromResult(Base64.decode(media.base64)).pipe(Effect.mapError((cause) => ProviderShared.invalidRequest("Bedrock Converse media data must be valid base64", cause)));
|
|
68
|
+
return Base64.encode(bytes);
|
|
68
69
|
});
|
|
69
70
|
// Route by MIME. Known image/document formats lower into a typed block; anything
|
|
70
71
|
// else fails with a clear error instead of silently degrading to a malformed
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Effect, Schema } from "effect";
|
|
2
|
-
import type { HttpClientResponse } from "effect/
|
|
2
|
+
import type { HttpClientResponse } from "effect/http";
|
|
3
3
|
import type { Media } from "../../media.js";
|
|
4
4
|
import { MediaProtocol } from "../../route/media-protocol.js";
|
|
5
5
|
import type { AIError } from "../../schema/index.js";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { Effect
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { Base64 } from "effect/encoding";
|
|
2
3
|
import { Media } from "../../media.js";
|
|
3
4
|
import { mergeJsonRecords } from "../../schema/index.js";
|
|
4
5
|
import { encodeJson } from "../../utils/json.js";
|
|
@@ -10,7 +11,7 @@ export const inlineBytes = (route, asset) => {
|
|
|
10
11
|
const inline = asset.inline();
|
|
11
12
|
if (!inline)
|
|
12
13
|
return Effect.fail(ProviderShared.inlineRequired(route, asset));
|
|
13
|
-
return Effect.fromResult(
|
|
14
|
+
return Effect.fromResult(Base64.decode(inline.base64)).pipe(Effect.mapError((cause) => ProviderShared.invalidRequest(`${route} media contains invalid base64 data`, cause)));
|
|
14
15
|
};
|
|
15
16
|
/** Copied because `BlobPart` requires a plain `ArrayBuffer`. */
|
|
16
17
|
export const blob = (data, mediaType) => {
|
|
@@ -33,7 +34,7 @@ export const dimensions = (size) => {
|
|
|
33
34
|
/** Provider file handle when the ref belongs to this provider; refs from other providers are never forwarded. */
|
|
34
35
|
export const refID = (asset, provider) => asset.source.type === "ref" && asset.source.provider === provider ? asset.source.id : undefined;
|
|
35
36
|
/** Decode a provider's base64 output once into an owned `bytes` asset, sniffing the type when it is not declared. */
|
|
36
|
-
export const decodedAsset = (invalid, label, data, mediaType, options) => Effect.fromResult(
|
|
37
|
+
export const decodedAsset = (invalid, label, data, mediaType, options) => Effect.fromResult(Base64.decode(data)).pipe(Effect.mapError((cause) => invalid(`${label} contains invalid base64 data`, cause)), Effect.map((bytes) => Media.bytes(bytes, mediaType, options)));
|
|
37
38
|
/** One image of an OpenAI-shaped `data` array, which carries either `b64_json` or a `url`. */
|
|
38
39
|
export const imageOutput = (invalid, label, item, mediaType, options) => {
|
|
39
40
|
if (item.b64_json)
|
|
@@ -56,9 +56,15 @@ const MODEL_NAMES = [
|
|
|
56
56
|
[/kimi/i, "moonshot"],
|
|
57
57
|
];
|
|
58
58
|
// Tool arguments are always a JSON object, and most providers reject a tool schema whose root does not
|
|
59
|
-
// declare `type: "object"`, such as `{}` or a bare `properties` map.
|
|
60
|
-
//
|
|
59
|
+
// declare `type: "object"`, such as `{}` or a bare `properties` map. An object root makes Effect's
|
|
60
|
+
// empty-struct markers redundant: `{ not: { type: "null" } }`, and `anyOf` object or array from older
|
|
61
|
+
// releases. Both are dropped so the root is a plain object schema.
|
|
61
62
|
const objectRoot = (schema) => {
|
|
63
|
+
if ((schema.type === undefined || schema.type === "object") &&
|
|
64
|
+
isRecord(schema.not) &&
|
|
65
|
+
schema.not.type === "null" &&
|
|
66
|
+
Object.keys(schema.not).length === 1)
|
|
67
|
+
return { type: "object", ...Object.fromEntries(Object.entries(schema).filter(([key]) => key !== "not")) };
|
|
62
68
|
if (schema.type !== undefined)
|
|
63
69
|
return schema;
|
|
64
70
|
if (Array.isArray(schema.anyOf) &&
|
|
@@ -93,8 +93,8 @@ const fromSettings = ({ apiKey, auth, baseURL, body, credentials, headers, profi
|
|
|
93
93
|
baseURL,
|
|
94
94
|
credentials,
|
|
95
95
|
generation: topP === undefined ? undefined : { topP },
|
|
96
|
-
headers
|
|
97
|
-
http: body === undefined ? undefined : { body
|
|
96
|
+
headers,
|
|
97
|
+
http: body === undefined ? undefined : { body },
|
|
98
98
|
profile,
|
|
99
99
|
providerOptions,
|
|
100
100
|
region,
|
|
@@ -42,8 +42,8 @@ export const model = (modelID, { apiKey, authToken, baseURL, body, headers, prov
|
|
|
42
42
|
return configure({
|
|
43
43
|
...(authToken === undefined ? { apiKey: apiKey } : { auth: Auth.bearer(authToken) }),
|
|
44
44
|
baseURL,
|
|
45
|
-
headers
|
|
46
|
-
http: body === undefined ? undefined : { body
|
|
45
|
+
headers,
|
|
46
|
+
http: body === undefined ? undefined : { body },
|
|
47
47
|
provider,
|
|
48
48
|
providerOptions,
|
|
49
49
|
}).model(modelID);
|
|
@@ -35,8 +35,8 @@ export const model = (modelID, { apiKey, authToken, baseURL, body, headers, ...p
|
|
|
35
35
|
return configure({
|
|
36
36
|
...(authToken === undefined ? { apiKey: apiKey } : { auth: Auth.bearer(authToken) }),
|
|
37
37
|
baseURL,
|
|
38
|
-
headers
|
|
39
|
-
http: body === undefined ? undefined : { body
|
|
38
|
+
headers,
|
|
39
|
+
http: body === undefined ? undefined : { body },
|
|
40
40
|
providerOptions,
|
|
41
41
|
}).model(modelID);
|
|
42
42
|
};
|
|
@@ -166,7 +166,7 @@ declare const responsesRoute: Route<{
|
|
|
166
166
|
} | {
|
|
167
167
|
readonly type: "image_generation";
|
|
168
168
|
readonly size?: string | undefined;
|
|
169
|
-
readonly action?: "
|
|
169
|
+
readonly action?: "auto" | "generate" | "edit" | undefined;
|
|
170
170
|
readonly output_format?: "png" | "jpeg" | "webp" | undefined;
|
|
171
171
|
readonly quality?: "auto" | "low" | "medium" | "high" | undefined;
|
|
172
172
|
readonly background?: "auto" | "opaque" | "transparent" | undefined;
|
|
@@ -493,7 +493,7 @@ export declare const routes: (Route<{
|
|
|
493
493
|
} | {
|
|
494
494
|
readonly type: "image_generation";
|
|
495
495
|
readonly size?: string | undefined;
|
|
496
|
-
readonly action?: "
|
|
496
|
+
readonly action?: "auto" | "generate" | "edit" | undefined;
|
|
497
497
|
readonly output_format?: "png" | "jpeg" | "webp" | undefined;
|
|
498
498
|
readonly quality?: "auto" | "low" | "medium" | "high" | undefined;
|
|
499
499
|
readonly background?: "auto" | "opaque" | "transparent" | undefined;
|
package/dist/providers/azure.js
CHANGED
|
@@ -91,10 +91,10 @@ const config = ({ apiKey, apiVersion, baseURL, body, headers, queryParams, resou
|
|
|
91
91
|
const common = {
|
|
92
92
|
apiKey,
|
|
93
93
|
apiVersion,
|
|
94
|
-
headers
|
|
95
|
-
http: body === undefined ? undefined : { body
|
|
94
|
+
headers,
|
|
95
|
+
http: body === undefined ? undefined : { body },
|
|
96
96
|
providerOptions,
|
|
97
|
-
queryParams
|
|
97
|
+
queryParams,
|
|
98
98
|
useDeploymentBasedUrls,
|
|
99
99
|
};
|
|
100
100
|
if (baseURL !== undefined)
|
|
@@ -31,8 +31,8 @@ export const provider = configure();
|
|
|
31
31
|
export const model = (modelID, { apiKey, baseURL, body, headers, ...providerOptions }) => configure({
|
|
32
32
|
apiKey,
|
|
33
33
|
baseURL,
|
|
34
|
-
headers
|
|
35
|
-
http: body === undefined ? undefined : { body
|
|
34
|
+
headers,
|
|
35
|
+
http: body === undefined ? undefined : { body },
|
|
36
36
|
providerOptions,
|
|
37
37
|
}).model(modelID);
|
|
38
38
|
export * as Baseten from "./baseten.js";
|
|
@@ -39,7 +39,7 @@ export const provider = configure();
|
|
|
39
39
|
export const model = (modelID, { apiKey, baseURL, body, headers, ...providerOptions }) => configure({
|
|
40
40
|
apiKey,
|
|
41
41
|
baseURL,
|
|
42
|
-
headers
|
|
43
|
-
http: body === undefined ? undefined : { body
|
|
42
|
+
headers,
|
|
43
|
+
http: body === undefined ? undefined : { body },
|
|
44
44
|
providerOptions,
|
|
45
45
|
}).model(modelID);
|
|
@@ -172,7 +172,7 @@ export declare const responsesRoute: import("../route/client.js").Route<{
|
|
|
172
172
|
} | {
|
|
173
173
|
readonly type: "image_generation";
|
|
174
174
|
readonly size?: string | undefined;
|
|
175
|
-
readonly action?: "
|
|
175
|
+
readonly action?: "auto" | "generate" | "edit" | undefined;
|
|
176
176
|
readonly output_format?: "png" | "jpeg" | "webp" | undefined;
|
|
177
177
|
readonly quality?: "auto" | "low" | "medium" | "high" | undefined;
|
|
178
178
|
readonly background?: "auto" | "opaque" | "transparent" | undefined;
|
|
@@ -1167,7 +1167,7 @@ export declare const routes: (import("../route/client.js").Route<{
|
|
|
1167
1167
|
} | {
|
|
1168
1168
|
readonly type: "image_generation";
|
|
1169
1169
|
readonly size?: string | undefined;
|
|
1170
|
-
readonly action?: "
|
|
1170
|
+
readonly action?: "auto" | "generate" | "edit" | undefined;
|
|
1171
1171
|
readonly output_format?: "png" | "jpeg" | "webp" | undefined;
|
|
1172
1172
|
readonly quality?: "auto" | "low" | "medium" | "high" | undefined;
|
|
1173
1173
|
readonly background?: "auto" | "opaque" | "transparent" | undefined;
|
|
@@ -100,8 +100,8 @@ export const model = (modelID, { accountId, apiKey, baseURL: configuredBaseURL,
|
|
|
100
100
|
collectLog,
|
|
101
101
|
gatewayApiKey,
|
|
102
102
|
gatewayId,
|
|
103
|
-
headers
|
|
104
|
-
http: body === undefined ? undefined : { body
|
|
103
|
+
headers,
|
|
104
|
+
http: body === undefined ? undefined : { body },
|
|
105
105
|
metadata,
|
|
106
106
|
providerOptions,
|
|
107
107
|
skipCache,
|
|
@@ -43,8 +43,8 @@ export const model = (modelID, settings) => {
|
|
|
43
43
|
return configure({
|
|
44
44
|
apiKey,
|
|
45
45
|
baseURL: baseURL(settings),
|
|
46
|
-
headers
|
|
47
|
-
http: body === undefined ? undefined : { body
|
|
46
|
+
headers,
|
|
47
|
+
http: body === undefined ? undefined : { body },
|
|
48
48
|
providerOptions,
|
|
49
49
|
}).model(modelID);
|
|
50
50
|
};
|
package/dist/providers/cohere.js
CHANGED
|
@@ -42,7 +42,7 @@ export const model = (modelID, { apiKey, baseURL, body, headers, ...providerOpti
|
|
|
42
42
|
apiKey,
|
|
43
43
|
baseURL,
|
|
44
44
|
headers,
|
|
45
|
-
http: body === undefined ? undefined : { body
|
|
45
|
+
http: body === undefined ? undefined : { body },
|
|
46
46
|
providerOptions,
|
|
47
47
|
}).model(modelID);
|
|
48
48
|
export * as Cohere from "./cohere.js";
|
|
@@ -42,7 +42,7 @@ export const provider = configure();
|
|
|
42
42
|
export const model = (modelID, { apiKey, baseURL, body, headers, ...providerOptions }) => configure({
|
|
43
43
|
apiKey,
|
|
44
44
|
baseURL,
|
|
45
|
-
headers
|
|
46
|
-
http: body === undefined ? undefined : { body
|
|
45
|
+
headers,
|
|
46
|
+
http: body === undefined ? undefined : { body },
|
|
47
47
|
providerOptions,
|
|
48
48
|
}).model(modelID);
|
|
@@ -34,8 +34,8 @@ export const provider = configure();
|
|
|
34
34
|
export const model = (modelID, { apiKey, baseURL, body, headers, ...providerOptions }) => configure({
|
|
35
35
|
apiKey,
|
|
36
36
|
baseURL,
|
|
37
|
-
headers
|
|
38
|
-
http: body === undefined ? undefined : { body
|
|
37
|
+
headers,
|
|
38
|
+
http: body === undefined ? undefined : { body },
|
|
39
39
|
providerOptions,
|
|
40
40
|
}).model(modelID);
|
|
41
41
|
export * as DeepSeek from "./deepseek.js";
|
|
@@ -31,8 +31,8 @@ export const provider = configure();
|
|
|
31
31
|
export const model = (modelID, { apiKey, baseURL, body, headers, ...providerOptions }) => configure({
|
|
32
32
|
apiKey,
|
|
33
33
|
baseURL,
|
|
34
|
-
headers
|
|
35
|
-
http: body === undefined ? undefined : { body
|
|
34
|
+
headers,
|
|
35
|
+
http: body === undefined ? undefined : { body },
|
|
36
36
|
providerOptions,
|
|
37
37
|
}).model(modelID);
|
|
38
38
|
export * as Fireworks from "./fireworks.js";
|
|
@@ -2,7 +2,7 @@ import { configure } from "../google.js";
|
|
|
2
2
|
export const model = (modelID, { apiKey, baseURL, body, headers, ...providerOptions }) => configure({
|
|
3
3
|
apiKey,
|
|
4
4
|
baseURL,
|
|
5
|
-
headers
|
|
6
|
-
http: body === undefined ? undefined : { body
|
|
5
|
+
headers,
|
|
6
|
+
http: body === undefined ? undefined : { body },
|
|
7
7
|
providerOptions,
|
|
8
8
|
}).interactions(modelID);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { model } from "../google-vertex-interactions.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { model } from "../google-vertex-mistral.js";
|
|
@@ -17,7 +17,7 @@ const configuredRoute = (input) => {
|
|
|
17
17
|
if ("apiKey" in input && input.apiKey !== undefined)
|
|
18
18
|
throw new ProviderConfigurationError({ provider: id, message: "Google Vertex Chat does not support API keys" });
|
|
19
19
|
const { accessToken: _accessToken, auth: _auth, baseURL, location: inputLocation, project: inputProject, ...rest } = input;
|
|
20
|
-
const location = GoogleVertexShared.location(inputLocation
|
|
20
|
+
const location = GoogleVertexShared.location(inputLocation);
|
|
21
21
|
const project = GoogleVertexShared.project(inputProject);
|
|
22
22
|
return route.with({
|
|
23
23
|
...rest,
|
|
@@ -46,8 +46,8 @@ export const model = (modelID, { accessToken, apiKey, baseURL, body, headers, lo
|
|
|
46
46
|
return configure({
|
|
47
47
|
accessToken,
|
|
48
48
|
baseURL,
|
|
49
|
-
headers
|
|
50
|
-
http: body === undefined ? undefined : { body
|
|
49
|
+
headers,
|
|
50
|
+
http: body === undefined ? undefined : { body },
|
|
51
51
|
location,
|
|
52
52
|
project,
|
|
53
53
|
providerOptions,
|