@opencode/ai 2.0.26 → 2.0.28
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 +8 -2
- package/dist/cache-policy.js +20 -11
- package/dist/experimental/system-one.js +1 -1
- package/dist/media.d.ts +1 -1
- package/dist/media.js +7 -6
- package/dist/protocols/alibaba-chat.d.ts +2 -2
- package/dist/protocols/alibaba-messages.d.ts +1 -1
- 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/gemini.d.ts +73 -9
- package/dist/protocols/gemini.js +111 -17
- package/dist/protocols/meta-responses.js +3 -2
- package/dist/protocols/mistral-chat.d.ts +1 -1
- package/dist/protocols/mistral-chat.js +4 -2
- package/dist/protocols/open-responses-channel.d.ts +1 -1
- package/dist/protocols/open-responses-channel.js +7 -2
- package/dist/protocols/openai-chat.js +6 -2
- package/dist/protocols/openai-responses.d.ts +5 -5
- package/dist/protocols/openai-responses.js +4 -3
- package/dist/protocols/shared.d.ts +6 -2
- package/dist/protocols/shared.js +29 -3
- 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/responses-compaction.js +6 -1
- package/dist/protocols/utils/tool-schema.js +8 -2
- package/dist/providers/alibaba.d.ts +5 -5
- 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 +3 -1
- package/dist/providers/google-vertex-shared.js +29 -3
- package/dist/providers/google-vertex.d.ts +2 -1
- package/dist/providers/google-vertex.js +4 -5
- package/dist/providers/google.d.ts +2 -1
- package/dist/providers/google.js +2 -2
- package/dist/providers/groq.js +2 -2
- package/dist/providers/index.d.ts +3 -1
- package/dist/providers/index.js +3 -1
- 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/{opencode-zen.d.ts → opencode.d.ts} +1 -1
- package/dist/providers/{opencode-zen.js → opencode.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 +5 -4
- 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/schema/options.d.ts +15 -1
- package/dist/schema/options.js +25 -5
- package/dist/tool.d.ts +10 -0
- package/dist/tool.js +21 -2
- package/package.json +5 -5
|
@@ -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";
|
|
@@ -106,7 +106,12 @@ export const transport = (options) => {
|
|
|
106
106
|
});
|
|
107
107
|
return {
|
|
108
108
|
http: {
|
|
109
|
-
request: ProviderShared.jsonPost({
|
|
109
|
+
request: ProviderShared.jsonPost({
|
|
110
|
+
url: parts.url,
|
|
111
|
+
body: parts.bodyText,
|
|
112
|
+
headers: parts.headers,
|
|
113
|
+
encoding: input.request.http?.encoding,
|
|
114
|
+
}),
|
|
110
115
|
framing: Framing.sse,
|
|
111
116
|
middleware: input.middleware,
|
|
112
117
|
},
|
|
@@ -9,6 +9,7 @@ import { Protocol } from "../route/protocol.js";
|
|
|
9
9
|
import { AIError, AIErrorReason, InvalidProviderOutputError, LLMEvent, ProviderInternalError, UnknownProviderError, Usage, } from "../schema/index.js";
|
|
10
10
|
import { classifyProviderFailure } from "../provider-error.js";
|
|
11
11
|
import { isRecord, JsonObject, optionalArray, optionalNull, ProviderShared } from "./shared.js";
|
|
12
|
+
import { cacheControl } from "./utils/cache.js";
|
|
12
13
|
import { OpenAIOptions } from "./utils/openai-options.js";
|
|
13
14
|
import { Lifecycle } from "./utils/lifecycle.js";
|
|
14
15
|
import { ToolStream } from "./utils/tool-stream.js";
|
|
@@ -646,14 +647,15 @@ export const fromRequest = Effect.fn("OpenAIChat.fromRequest")(function* (reques
|
|
|
646
647
|
const zaiToolStream = request.model.compatibility?.zaiToolStream ?? detectZaiToolStream(provider, baseURL, request.model.id);
|
|
647
648
|
const hasHistory = hasToolHistory(request.messages);
|
|
648
649
|
const hasActiveTools = flattened.tools.length > 0;
|
|
650
|
+
const lowering = { ...options, cacheControl: options.cacheControl ?? declaredCacheControl(request) };
|
|
649
651
|
return {
|
|
650
652
|
model: request.model.id,
|
|
651
|
-
messages: yield* lowerMessages(flattened.request,
|
|
653
|
+
messages: yield* lowerMessages(flattened.request, lowering),
|
|
652
654
|
tools: flattened.tools.length === 0
|
|
653
655
|
? hasHistory
|
|
654
656
|
? []
|
|
655
657
|
: undefined
|
|
656
|
-
: flattened.tools.map((tool) => lowerTool(tool,
|
|
658
|
+
: flattened.tools.map((tool) => lowerTool(tool, lowering, supportsStrictMode)),
|
|
657
659
|
tool_choice: hasActiveTools && request.toolChoice ? yield* lowerToolChoice(request.toolChoice) : undefined,
|
|
658
660
|
stream: true,
|
|
659
661
|
...(supportsUsageInStreaming ? { stream_options: { include_usage: true } } : {}),
|
|
@@ -670,6 +672,8 @@ export const fromRequest = Effect.fn("OpenAIChat.fromRequest")(function* (reques
|
|
|
670
672
|
...lowerOptions(request, supportsStore),
|
|
671
673
|
};
|
|
672
674
|
});
|
|
675
|
+
// Provider wrappers that pass their own marker writer keep it; otherwise a declared cache format adds one.
|
|
676
|
+
const declaredCacheControl = (request) => request.model.compatibility?.cacheFormat === undefined ? undefined : cacheControl();
|
|
673
677
|
// =============================================================================
|
|
674
678
|
// Stream Parsing
|
|
675
679
|
// =============================================================================
|
|
@@ -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,8 +1,8 @@
|
|
|
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
|
-
import { AIError, LLMRequest, Message, ToolDefinition, type ContentPart, type MediaPart, type OpenString, type ProviderID, type ToolEntry, type ToolResultPart } from "../schema/index.js";
|
|
5
|
+
import { AIError, LLMRequest, Message, ToolDefinition, type ContentPart, type MediaPart, type OpenString, type ProviderID, type RequestEncoding, type ToolEntry, type ToolResultPart } from "../schema/index.js";
|
|
6
6
|
import { Json, decodeJson, encodeJson } from "../utils/json.js";
|
|
7
7
|
import { isRecord } from "../utils/record.js";
|
|
8
8
|
export { Json, decodeJson, encodeJson, isRecord };
|
|
@@ -14,6 +14,7 @@ export declare const lenient: <const S extends Schema.Top>(schema: S) => Schema.
|
|
|
14
14
|
/** Provider-defined string enum: known values for autocomplete, any string accepted at runtime. */
|
|
15
15
|
export declare const knownString: <Known extends string>() => Schema.declare<OpenString<Known>, OpenString<Known>>;
|
|
16
16
|
export declare const OPENAI_PROMPT_CACHE_KEY_MAX_LENGTH = 64;
|
|
17
|
+
export declare const sendsPromptCacheKey: (request: LLMRequest) => boolean;
|
|
17
18
|
export declare const promptCacheKey: (request: LLMRequest) => string | undefined;
|
|
18
19
|
/**
|
|
19
20
|
* Streaming tool-call accumulator. Adapters that build a tool call across
|
|
@@ -192,10 +193,13 @@ export declare const validateWith: <A, I, E extends {
|
|
|
192
193
|
* send JSON with a stale content type. The body is passed pre-encoded so
|
|
193
194
|
* routes can choose between
|
|
194
195
|
* `Schema.encodeSync(payload)` and `ProviderShared.encodeJson(payload)`.
|
|
196
|
+
* A `zstd` or `gzip` encoding compresses the body and sets `content-encoding`;
|
|
197
|
+
* it falls back to plain JSON when the runtime has no zlib.
|
|
195
198
|
*/
|
|
196
199
|
export declare const jsonPost: (input: {
|
|
197
200
|
readonly url: string;
|
|
198
201
|
readonly body: string;
|
|
199
202
|
readonly headers?: Headers.Input;
|
|
203
|
+
readonly encoding?: RequestEncoding;
|
|
200
204
|
}) => HttpClientRequest.HttpClientRequest;
|
|
201
205
|
export * as ProviderShared from "./shared.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";
|
|
@@ -17,10 +17,13 @@ export const knownString = () => Schema.declare((value) => typeof value === "str
|
|
|
17
17
|
expected: "string",
|
|
18
18
|
});
|
|
19
19
|
export const OPENAI_PROMPT_CACHE_KEY_MAX_LENGTH = 64;
|
|
20
|
+
// Body-level `prompt_cache_key` is off when caching is disabled or the model
|
|
21
|
+
// explicitly rejects the field. Header-based affinity is unaffected.
|
|
22
|
+
export const sendsPromptCacheKey = (request) => request.cache !== "none" && request.model.compatibility?.supportsPromptCacheKey !== false;
|
|
20
23
|
// OpenAI limits `prompt_cache_key` to 64 chars; DeepSeek and Zai inherit the same
|
|
21
24
|
// limit via their OpenAI-compatible APIs. Clamp with unicode-aware slicing.
|
|
22
25
|
export const promptCacheKey = (request) => {
|
|
23
|
-
if (request
|
|
26
|
+
if (!sendsPromptCacheKey(request) || request.promptCacheKey === undefined)
|
|
24
27
|
return undefined;
|
|
25
28
|
const chars = Array.from(request.promptCacheKey);
|
|
26
29
|
if (chars.length <= OPENAI_PROMPT_CACHE_KEY_MAX_LENGTH)
|
|
@@ -279,6 +282,29 @@ export const validateWith = (decode) => (payload) => decode(payload).pipe(Effect
|
|
|
279
282
|
* send JSON with a stale content type. The body is passed pre-encoded so
|
|
280
283
|
* routes can choose between
|
|
281
284
|
* `Schema.encodeSync(payload)` and `ProviderShared.encodeJson(payload)`.
|
|
285
|
+
* A `zstd` or `gzip` encoding compresses the body and sets `content-encoding`;
|
|
286
|
+
* it falls back to plain JSON when the runtime has no zlib.
|
|
282
287
|
*/
|
|
283
|
-
export const jsonPost = (input) =>
|
|
288
|
+
export const jsonPost = (input) => {
|
|
289
|
+
const headers = Headers.set(Headers.fromInput(input.headers), "content-type", "application/json");
|
|
290
|
+
const compressed = compressBody(input.body, input.encoding);
|
|
291
|
+
if (!compressed)
|
|
292
|
+
return HttpClientRequest.post(input.url).pipe(HttpClientRequest.setHeaders(headers), HttpClientRequest.bodyText(input.body, "application/json"));
|
|
293
|
+
return HttpClientRequest.post(input.url).pipe(HttpClientRequest.setHeaders(Headers.set(headers, "content-encoding", compressed.encoding)), HttpClientRequest.bodyUint8Array(compressed.body, "application/json"));
|
|
294
|
+
};
|
|
295
|
+
function compressBody(text, encoding) {
|
|
296
|
+
if (encoding === undefined || encoding === "none")
|
|
297
|
+
return undefined;
|
|
298
|
+
// Looked up at call time instead of imported: a runtime without node:zlib or its zstd export
|
|
299
|
+
// (browsers, older Node, some workerd setups) sends plain JSON rather than failing to load this module.
|
|
300
|
+
const zlib = globalThis.process?.getBuiltinModule?.("node:zlib");
|
|
301
|
+
try {
|
|
302
|
+
const body = encoding === "zstd" ? zlib?.zstdCompressSync?.(text) : zlib?.gzipSync(text);
|
|
303
|
+
return body && { encoding, body };
|
|
304
|
+
}
|
|
305
|
+
catch {
|
|
306
|
+
// Compression is an optimization, so a failure sends plain JSON instead of failing the request.
|
|
307
|
+
return undefined;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
284
310
|
export * as ProviderShared from "./shared.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)
|
|
@@ -87,7 +87,12 @@ export const make = (adapter, lowerTools) => Effect.fn("ResponsesCompaction.exec
|
|
|
87
87
|
auth: route.auth,
|
|
88
88
|
encodeBody: Schema.encodeSync(Schema.fromJsonString(Body)),
|
|
89
89
|
});
|
|
90
|
-
const response = yield* executor.execute(ProviderShared.jsonPost({
|
|
90
|
+
const response = yield* executor.execute(ProviderShared.jsonPost({
|
|
91
|
+
url: parts.url,
|
|
92
|
+
body: parts.bodyText,
|
|
93
|
+
headers: parts.headers,
|
|
94
|
+
encoding: request.http?.encoding,
|
|
95
|
+
}), options?.http);
|
|
91
96
|
const text = yield* RequestExecutor.responseStream(response).pipe(Stream.decodeText(), Stream.runFold(() => "", (text, chunk) => text + chunk));
|
|
92
97
|
const invalid = (message, cause) => new AIError({
|
|
93
98
|
reason: new InvalidProviderOutputError({
|
|
@@ -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) &&
|
|
@@ -129,7 +129,7 @@ export declare const routes: (Route<{
|
|
|
129
129
|
readonly temperature?: number | undefined;
|
|
130
130
|
readonly seed?: number | undefined;
|
|
131
131
|
readonly thinking?: {
|
|
132
|
-
readonly type:
|
|
132
|
+
readonly type: (string & {}) | "disabled" | "adaptive";
|
|
133
133
|
} | undefined;
|
|
134
134
|
readonly tool_choice?: "required" | "auto" | "none" | {
|
|
135
135
|
readonly type: "function";
|
|
@@ -611,7 +611,7 @@ export declare const configure: (input: Config) => {
|
|
|
611
611
|
id: string & import("effect/Brand").Brand<"AI.ProviderID">;
|
|
612
612
|
model: (id: string | ModelID) => import("../schema/options.js").LanguageModel<{
|
|
613
613
|
readonly thinking?: {
|
|
614
|
-
readonly type:
|
|
614
|
+
readonly type: (string & {}) | "disabled" | "adaptive";
|
|
615
615
|
} | undefined;
|
|
616
616
|
readonly thinkingBudget?: number | undefined;
|
|
617
617
|
readonly parallelToolCalls?: boolean | undefined;
|
|
@@ -636,7 +636,7 @@ export declare const configure: (input: Config) => {
|
|
|
636
636
|
}, import("../route/client.js").CompactionOperations | undefined>;
|
|
637
637
|
chat: (id: string | ModelID) => import("../schema/options.js").LanguageModel<{
|
|
638
638
|
readonly thinking?: {
|
|
639
|
-
readonly type:
|
|
639
|
+
readonly type: (string & {}) | "disabled" | "adaptive";
|
|
640
640
|
} | undefined;
|
|
641
641
|
readonly thinkingBudget?: number | undefined;
|
|
642
642
|
readonly parallelToolCalls?: boolean | undefined;
|
|
@@ -675,7 +675,7 @@ export declare const provider: {
|
|
|
675
675
|
id: string & import("effect/Brand").Brand<"AI.ProviderID">;
|
|
676
676
|
model: (id: string | ModelID) => import("../schema/options.js").LanguageModel<{
|
|
677
677
|
readonly thinking?: {
|
|
678
|
-
readonly type:
|
|
678
|
+
readonly type: (string & {}) | "disabled" | "adaptive";
|
|
679
679
|
} | undefined;
|
|
680
680
|
readonly thinkingBudget?: number | undefined;
|
|
681
681
|
readonly parallelToolCalls?: boolean | undefined;
|
|
@@ -700,7 +700,7 @@ export declare const provider: {
|
|
|
700
700
|
}, import("../route/client.js").CompactionOperations | undefined>;
|
|
701
701
|
chat: (id: string | ModelID) => import("../schema/options.js").LanguageModel<{
|
|
702
702
|
readonly thinking?: {
|
|
703
|
-
readonly type:
|
|
703
|
+
readonly type: (string & {}) | "disabled" | "adaptive";
|
|
704
704
|
} | undefined;
|
|
705
705
|
readonly thinkingBudget?: number | undefined;
|
|
706
706
|
readonly parallelToolCalls?: boolean | undefined;
|
|
@@ -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,
|