@opencode/ai 2.0.14 → 2.0.16
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 +399 -56
- package/dist/experimental/evaluation-client.d.ts +1 -1
- package/dist/experimental/evaluation-client.js +39 -3
- package/dist/experimental/evaluation.d.ts +4 -4
- package/dist/experimental/evaluation.js +2 -2
- package/dist/experimental/system-one.d.ts +3 -3
- package/dist/experimental/system-one.js +40 -51
- package/dist/generation.d.ts +83 -0
- package/dist/generation.js +113 -0
- package/dist/image-client.d.ts +16 -7
- package/dist/image-client.js +29 -13
- package/dist/image.d.ts +1410 -81
- package/dist/image.js +97 -67
- package/dist/index.d.ts +17 -2
- package/dist/index.js +12 -1
- package/dist/llm.d.ts +9 -1
- package/dist/media-model.d.ts +44 -0
- package/dist/media-model.js +49 -0
- package/dist/media.d.ts +213 -0
- package/dist/media.js +227 -0
- package/dist/promise.d.ts +974 -0
- package/dist/promise.js +81 -0
- package/dist/protocols/alibaba-chat.d.ts +12 -0
- package/dist/protocols/alibaba-responses.d.ts +2 -2
- package/dist/protocols/anthropic-messages.js +8 -19
- package/dist/protocols/assemblyai-transcription.d.ts +40 -0
- package/dist/protocols/assemblyai-transcription.js +138 -0
- package/dist/protocols/bedrock-converse.d.ts +4 -4
- package/dist/protocols/bedrock-converse.js +6 -17
- package/dist/protocols/bfl-images.d.ts +32 -0
- package/dist/protocols/bfl-images.js +153 -0
- package/dist/protocols/cartesia-speech.d.ts +127 -0
- package/dist/protocols/cartesia-speech.js +126 -0
- package/dist/protocols/deepgram-speech.d.ts +119 -0
- package/dist/protocols/deepgram-speech.js +92 -0
- package/dist/protocols/deepgram-transcription.d.ts +25 -0
- package/dist/protocols/deepgram-transcription.js +129 -0
- package/dist/protocols/elevenlabs-speech.d.ts +122 -0
- package/dist/protocols/elevenlabs-speech.js +115 -0
- package/dist/protocols/fal-images.d.ts +24 -0
- package/dist/protocols/fal-images.js +114 -0
- package/dist/protocols/fal-video.d.ts +29 -0
- package/dist/protocols/fal-video.js +88 -0
- package/dist/protocols/gemini.d.ts +30 -9
- package/dist/protocols/gemini.js +45 -35
- package/dist/protocols/google-images.d.ts +9 -21
- package/dist/protocols/google-images.js +158 -133
- package/dist/protocols/google-speech.d.ts +130 -0
- package/dist/protocols/google-speech.js +84 -0
- package/dist/protocols/google-transcription.d.ts +173 -0
- package/dist/protocols/google-transcription.js +138 -0
- package/dist/protocols/google-video.d.ts +26 -0
- package/dist/protocols/google-video.js +158 -0
- package/dist/protocols/meta-images.d.ts +7 -12
- package/dist/protocols/meta-images.js +85 -66
- package/dist/protocols/meta-responses.d.ts +4 -4
- package/dist/protocols/meta-responses.js +1 -1
- package/dist/protocols/mistral-chat.js +7 -6
- package/dist/protocols/open-responses.d.ts +17 -9
- package/dist/protocols/open-responses.js +24 -14
- package/dist/protocols/openai-chat.d.ts +118 -1
- package/dist/protocols/openai-chat.js +125 -44
- package/dist/protocols/openai-compatible-chat.d.ts +12 -0
- package/dist/protocols/openai-compatible-responses.d.ts +2 -2
- package/dist/protocols/openai-images.d.ts +128 -18
- package/dist/protocols/openai-images.js +177 -154
- package/dist/protocols/openai-responses.d.ts +15 -15
- package/dist/protocols/openai-responses.js +5 -6
- package/dist/protocols/openai-speech.d.ts +116 -0
- package/dist/protocols/openai-speech.js +98 -0
- package/dist/protocols/openai-transcription.d.ts +207 -0
- package/dist/protocols/openai-transcription.js +190 -0
- package/dist/protocols/replicate-images.d.ts +28 -0
- package/dist/protocols/replicate-images.js +133 -0
- package/dist/protocols/runway-video.d.ts +38 -0
- package/dist/protocols/runway-video.js +146 -0
- package/dist/protocols/shared.d.ts +27 -17
- package/dist/protocols/shared.js +52 -35
- package/dist/protocols/stability-images.d.ts +38 -0
- package/dist/protocols/stability-images.js +148 -0
- package/dist/protocols/utils/bedrock-media.d.ts +2 -3
- package/dist/protocols/utils/bedrock-media.js +4 -4
- package/dist/protocols/utils/fal-queue.d.ts +28 -0
- package/dist/protocols/utils/fal-queue.js +69 -0
- package/dist/protocols/utils/gemini-generate-content.d.ts +65 -0
- package/dist/protocols/utils/gemini-generate-content.js +65 -0
- package/dist/protocols/utils/gemini-json-schema.d.ts +3 -0
- package/dist/protocols/utils/gemini-json-schema.js +76 -0
- package/dist/protocols/utils/media-input.d.ts +18 -0
- package/dist/protocols/utils/media-input.js +35 -0
- package/dist/protocols/utils/responses-compaction.js +6 -5
- package/dist/protocols/utils/speech-stream.d.ts +49 -0
- package/dist/protocols/utils/speech-stream.js +67 -0
- package/dist/protocols/utils/tool-schema.d.ts +2 -2
- package/dist/protocols/utils/tool-schema.js +40 -17
- package/dist/protocols/utils/tool-stream.d.ts +27 -3
- package/dist/protocols/xai-images.d.ts +9 -15
- package/dist/protocols/xai-images.js +75 -84
- package/dist/protocols/xai-responses.d.ts +2 -2
- package/dist/protocols/xai-video.d.ts +34 -0
- package/dist/protocols/xai-video.js +147 -0
- package/dist/protocols/zai-chat.d.ts +13 -1
- package/dist/protocols/zai-images.d.ts +9 -13
- package/dist/protocols/zai-images.js +59 -57
- package/dist/provider-error.js +3 -0
- package/dist/providers/alibaba.d.ts +14 -2
- package/dist/providers/amazon-bedrock-mantle.d.ts +14 -2
- package/dist/providers/amazon-bedrock.d.ts +2 -2
- package/dist/providers/assemblyai.d.ts +25 -0
- package/dist/providers/assemblyai.js +29 -0
- package/dist/providers/azure.d.ts +18 -6
- package/dist/providers/baseten.d.ts +24 -0
- package/dist/providers/black-forest-labs.d.ts +25 -0
- package/dist/providers/black-forest-labs.js +28 -0
- package/dist/providers/cartesia.d.ts +24 -0
- package/dist/providers/cartesia.js +22 -0
- package/dist/providers/cerebras.d.ts +24 -0
- package/dist/providers/cerebras.js +6 -1
- package/dist/providers/cloudflare-ai-gateway.d.ts +30 -6
- package/dist/providers/cloudflare-workers-ai.d.ts +24 -0
- package/dist/providers/deepgram.d.ts +29 -0
- package/dist/providers/deepgram.js +31 -0
- package/dist/providers/deepinfra.d.ts +24 -0
- package/dist/providers/deepinfra.js +6 -1
- package/dist/providers/deepseek.d.ts +24 -0
- package/dist/providers/elevenlabs.d.ts +24 -0
- package/dist/providers/elevenlabs.js +28 -0
- package/dist/providers/fal.d.ts +29 -0
- package/dist/providers/fal.js +33 -0
- package/dist/providers/fireworks.d.ts +24 -0
- package/dist/providers/google-vertex-chat.d.ts +12 -0
- package/dist/providers/google-vertex-responses.d.ts +2 -2
- package/dist/providers/google-vertex.d.ts +10 -3
- package/dist/providers/google.d.ts +25 -3
- package/dist/providers/google.js +11 -2
- package/dist/providers/groq.d.ts +24 -0
- package/dist/providers/index.d.ts +10 -0
- package/dist/providers/index.js +10 -0
- package/dist/providers/meta.d.ts +14 -2
- package/dist/providers/minimax.d.ts +14 -2
- package/dist/providers/moonshot.d.ts +14 -2
- package/dist/providers/moonshot.js +3 -3
- package/dist/providers/openai-compatible-responses.d.ts +2 -2
- package/dist/providers/openai-compatible.d.ts +12 -0
- package/dist/providers/openai.d.ts +25 -3
- package/dist/providers/openai.js +10 -1
- package/dist/providers/openrouter.d.ts +67 -0
- package/dist/providers/openrouter.js +13 -1
- package/dist/providers/replicate.d.ts +25 -0
- package/dist/providers/replicate.js +22 -0
- package/dist/providers/runway.d.ts +24 -0
- package/dist/providers/runway.js +22 -0
- package/dist/providers/stability.d.ts +28 -0
- package/dist/providers/stability.js +23 -0
- package/dist/providers/togetherai.d.ts +24 -0
- package/dist/providers/vercel-ai-gateway.d.ts +41 -0
- package/dist/providers/vercel-ai-gateway.js +85 -0
- package/dist/providers/xai.d.ts +17 -0
- package/dist/providers/xai.js +5 -2
- package/dist/providers/zai-coding-plan.d.ts +15 -3
- package/dist/providers/zai.d.ts +13 -1
- package/dist/route/auth.d.ts +4 -1
- package/dist/route/auth.js +6 -0
- package/dist/route/client.d.ts +9 -1
- package/dist/route/endpoint.d.ts +10 -10
- package/dist/route/executor-service.d.ts +12 -0
- package/dist/route/executor-service.js +3 -0
- package/dist/route/executor.d.ts +4 -9
- package/dist/route/executor.js +3 -3
- package/dist/route/framing.d.ts +5 -1
- package/dist/route/framing.js +9 -0
- package/dist/route/index.d.ts +2 -0
- package/dist/route/index.js +2 -0
- package/dist/route/media-protocol.d.ts +158 -0
- package/dist/route/media-protocol.js +96 -0
- package/dist/route/media.d.ts +97 -0
- package/dist/route/media.js +236 -0
- package/dist/schema/errors.d.ts +13 -3
- package/dist/schema/errors.js +7 -0
- package/dist/schema/events.d.ts +557 -40
- package/dist/schema/events.js +35 -2
- package/dist/schema/messages.d.ts +95 -8
- package/dist/schema/messages.js +8 -6
- package/dist/schema/options.d.ts +6 -3
- package/dist/schema/options.js +6 -2
- package/dist/speech-client.d.ts +21 -0
- package/dist/speech-client.js +25 -0
- package/dist/speech.d.ts +1150 -0
- package/dist/speech.js +119 -0
- package/dist/testing.d.ts +72 -8
- package/dist/transcription-client.d.ts +28 -0
- package/dist/transcription-client.js +44 -0
- package/dist/transcription.d.ts +1504 -0
- package/dist/transcription.js +133 -0
- package/dist/utils/bytes.d.ts +1 -0
- package/dist/utils/bytes.js +10 -0
- package/dist/utils/media-type.d.ts +7 -0
- package/dist/utils/media-type.js +70 -0
- package/dist/utils/sanitize.js +3 -1
- package/dist/video-client.d.ts +28 -0
- package/dist/video-client.js +40 -0
- package/dist/video.d.ts +1359 -0
- package/dist/video.js +119 -0
- package/package.json +7 -3
- package/dist/protocols/utils/gemini-tool-schema.d.ts +0 -2
- package/dist/protocols/utils/gemini-tool-schema.js +0 -103
- package/dist/protocols/utils/image-input.d.ts +0 -21
- package/dist/protocols/utils/image-input.js +0 -20
|
@@ -1,15 +1,23 @@
|
|
|
1
|
-
import { Effect,
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
1
|
+
import { Effect, Schema } from "effect";
|
|
2
|
+
import { ImageModel, ImageResponse } from "../image.js";
|
|
3
|
+
import { Media } from "../media.js";
|
|
4
|
+
import { MediaProtocol } from "../route/media-protocol.js";
|
|
5
|
+
import { MediaRoute } from "../route/media.js";
|
|
6
|
+
import { ProviderID, mergeJsonRecords } from "../schema/index.js";
|
|
6
7
|
import { JsonObject, ProviderShared, optionalNull } from "./shared.js";
|
|
7
|
-
import {
|
|
8
|
+
import { MediaInput } from "./utils/media-input.js";
|
|
9
|
+
const ADAPTER = "meta-images";
|
|
10
|
+
const NAME = "Meta Images";
|
|
11
|
+
const PROVIDER = ProviderID.make("meta");
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
// 2. Request body and response schemas
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
8
15
|
const Body = Schema.StructWithRest(Schema.Struct({
|
|
9
16
|
model: Schema.String,
|
|
10
17
|
prompt: Schema.String,
|
|
11
18
|
images: Schema.optional(Schema.Array(JsonObject)),
|
|
12
19
|
n: Schema.optional(Schema.Number),
|
|
20
|
+
/** Aspect ratio hint, not an exact output resolution. */
|
|
13
21
|
size: Schema.optional(Schema.String),
|
|
14
22
|
output_format: Schema.optional(Schema.String),
|
|
15
23
|
response_format: Schema.optional(Schema.String),
|
|
@@ -25,65 +33,76 @@ const Response = Schema.Struct({
|
|
|
25
33
|
total_tokens: Schema.optional(Schema.Number),
|
|
26
34
|
})),
|
|
27
35
|
});
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
const format = decoded.output_format ?? payload.output_format ?? "webp";
|
|
64
|
-
const generated = yield* Effect.forEach(decoded.data, (item, index) => {
|
|
65
|
-
if (item.b64_json)
|
|
66
|
-
return Effect.fromResult(Encoding.decodeBase64(item.b64_json)).pipe(Effect.mapError((cause) => output.invalid(`Meta Images result ${index} contains invalid base64`, cause)), Effect.map((data) => new GeneratedImage({ mediaType: `image/${format}`, data })));
|
|
67
|
-
if (item.url)
|
|
68
|
-
return Effect.succeed(new GeneratedImage({ mediaType: `image/${format}`, data: item.url }));
|
|
69
|
-
return output.invalid(`Meta Images result ${index} has neither image data nor a URL`);
|
|
70
|
-
});
|
|
71
|
-
if (generated.length === 0)
|
|
72
|
-
return yield* output.invalid("Meta Images returned no images");
|
|
73
|
-
return new ImageResponse({
|
|
74
|
-
images: generated,
|
|
75
|
-
usage: decoded.usage === undefined
|
|
76
|
-
? undefined
|
|
77
|
-
: new Usage({
|
|
78
|
-
inputTokens: decoded.usage.input_tokens,
|
|
79
|
-
outputTokens: decoded.usage.output_tokens,
|
|
80
|
-
totalTokens: decoded.usage.total_tokens,
|
|
81
|
-
providerMetadata: { meta: decoded.usage },
|
|
82
|
-
}),
|
|
83
|
-
providerMetadata: { meta: { outputFormat: format } },
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
// 5. Request body construction
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
const isEdit = (request) => (request.images?.length ?? 0) > 0;
|
|
40
|
+
// Meta has no file handles: refs are rejected even when they name this provider.
|
|
41
|
+
const reference = (asset) => ProviderShared.mediaReference(asset, undefined, NAME).pipe(Effect.map((item) => ({ image_url: item.value })));
|
|
42
|
+
const fromRequest = Effect.fn("MetaImages.fromRequest")(function* (request) {
|
|
43
|
+
const images = yield* Effect.forEach(request.images ?? [], reference);
|
|
44
|
+
const { responseFormat, reasoningStrength, toolEnablement, ...native } = request.providerOptions ?? {};
|
|
45
|
+
const payload = yield* ProviderShared.validateWith(Schema.decodeUnknownEffect(Body))(mergeJsonRecords({
|
|
46
|
+
model: request.model.id,
|
|
47
|
+
prompt: request.prompt,
|
|
48
|
+
images: images.length === 0 ? undefined : images,
|
|
49
|
+
n: request.n,
|
|
50
|
+
size: request.size,
|
|
51
|
+
output_format: request.format,
|
|
52
|
+
response_format: responseFormat,
|
|
53
|
+
reasoning_strength: reasoningStrength,
|
|
54
|
+
tool_enablement: toolEnablement,
|
|
55
|
+
}, native, request.http?.body));
|
|
56
|
+
return MediaProtocol.json(payload);
|
|
57
|
+
});
|
|
58
|
+
// ---------------------------------------------------------------------------
|
|
59
|
+
// 6. Response decoding
|
|
60
|
+
// ---------------------------------------------------------------------------
|
|
61
|
+
const decodeResponse = Effect.fn("MetaImages.decodeResponse")(function* (response, context) {
|
|
62
|
+
const output = yield* MediaProtocol.decodeJson(ADAPTER, NAME, Response)(response);
|
|
63
|
+
const decoded = output.value;
|
|
64
|
+
const requested = context.body.type === "json" ? context.body.value.output_format : undefined;
|
|
65
|
+
const format = decoded.output_format ?? (typeof requested === "string" ? requested : "webp");
|
|
66
|
+
const mediaType = `image/${format}`;
|
|
67
|
+
const images = yield* Effect.forEach(decoded.data, (item, index) => {
|
|
68
|
+
if (item.b64_json)
|
|
69
|
+
return MediaInput.decodedAsset(output.invalid, `${NAME} result ${index}`, item.b64_json, mediaType, {
|
|
70
|
+
info: { format },
|
|
84
71
|
});
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
};
|
|
72
|
+
if (item.url)
|
|
73
|
+
return Effect.succeed(Media.url(item.url, { mediaType, info: { format } }));
|
|
74
|
+
return Effect.fail(output.invalid(`${NAME} result ${index} has neither image data nor a URL`));
|
|
75
|
+
});
|
|
76
|
+
if (images.length === 0)
|
|
77
|
+
return yield* output.invalid(`${NAME} returned no images`);
|
|
78
|
+
return new ImageResponse({
|
|
79
|
+
images,
|
|
80
|
+
usage: decoded.usage === undefined
|
|
81
|
+
? undefined
|
|
82
|
+
: {
|
|
83
|
+
type: "tokens",
|
|
84
|
+
input: decoded.usage.input_tokens,
|
|
85
|
+
output: decoded.usage.output_tokens,
|
|
86
|
+
total: decoded.usage.total_tokens,
|
|
87
|
+
details: { meta: decoded.usage },
|
|
88
|
+
},
|
|
89
|
+
providerMetadata: { meta: { outputFormat: format } },
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
// ---------------------------------------------------------------------------
|
|
93
|
+
// 7. Protocol and route
|
|
94
|
+
// ---------------------------------------------------------------------------
|
|
95
|
+
export const protocol = MediaProtocol.inline({
|
|
96
|
+
id: ADAPTER,
|
|
97
|
+
name: NAME,
|
|
98
|
+
unsupported: ["mask", "aspectRatio", "seed"],
|
|
99
|
+
body: { from: fromRequest },
|
|
100
|
+
response: { decode: decodeResponse },
|
|
101
|
+
});
|
|
102
|
+
export const model = (input) => ImageModel.fromRoute({
|
|
103
|
+
id: ADAPTER,
|
|
104
|
+
provider: PROVIDER,
|
|
105
|
+
protocol,
|
|
106
|
+
path: ({ request }) => `/images/${isEdit(request) ? "edits" : "generations"}`,
|
|
107
|
+
}, input);
|
|
89
108
|
export * as MetaImages from "./meta-images.js";
|
|
@@ -92,8 +92,8 @@ export declare const protocol: Protocol<{
|
|
|
92
92
|
} | {
|
|
93
93
|
readonly type: "input_file";
|
|
94
94
|
readonly filename: string;
|
|
95
|
-
readonly detail?: string | undefined;
|
|
96
95
|
readonly file_data?: string | undefined;
|
|
96
|
+
readonly detail?: string | undefined;
|
|
97
97
|
readonly file_url?: string | undefined;
|
|
98
98
|
} | {
|
|
99
99
|
readonly type: "input_text";
|
|
@@ -129,8 +129,8 @@ export declare const protocol: Protocol<{
|
|
|
129
129
|
} | {
|
|
130
130
|
readonly type: "input_file";
|
|
131
131
|
readonly filename: string;
|
|
132
|
-
readonly detail?: string | undefined;
|
|
133
132
|
readonly file_data?: string | undefined;
|
|
133
|
+
readonly detail?: string | undefined;
|
|
134
134
|
readonly file_url?: string | undefined;
|
|
135
135
|
} | {
|
|
136
136
|
readonly type: "input_text";
|
|
@@ -338,8 +338,8 @@ export declare const httpTransport: HttpTransport.HttpJsonTransport<{
|
|
|
338
338
|
} | {
|
|
339
339
|
readonly type: "input_file";
|
|
340
340
|
readonly filename: string;
|
|
341
|
-
readonly detail?: string | undefined;
|
|
342
341
|
readonly file_data?: string | undefined;
|
|
342
|
+
readonly detail?: string | undefined;
|
|
343
343
|
readonly file_url?: string | undefined;
|
|
344
344
|
} | {
|
|
345
345
|
readonly type: "input_text";
|
|
@@ -375,8 +375,8 @@ export declare const httpTransport: HttpTransport.HttpJsonTransport<{
|
|
|
375
375
|
} | {
|
|
376
376
|
readonly type: "input_file";
|
|
377
377
|
readonly filename: string;
|
|
378
|
-
readonly detail?: string | undefined;
|
|
379
378
|
readonly file_data?: string | undefined;
|
|
379
|
+
readonly detail?: string | undefined;
|
|
380
380
|
readonly file_url?: string | undefined;
|
|
381
381
|
} | {
|
|
382
382
|
readonly type: "input_text";
|
|
@@ -82,7 +82,7 @@ const fromRequest = Effect.fn("MetaResponses.fromRequest")(function* (request) {
|
|
|
82
82
|
? undefined
|
|
83
83
|
: yield* Effect.forEach(projected.tools, (tool) => Effect.gen(function* () {
|
|
84
84
|
if (tool.native === undefined)
|
|
85
|
-
return yield* OpenResponses.lowerTool(NAME, tool, ToolSchemaProjection.modelCompatibility(tool.inputSchema, request.model
|
|
85
|
+
return yield* OpenResponses.lowerTool(NAME, tool, ToolSchemaProjection.modelCompatibility(tool.inputSchema, request.model));
|
|
86
86
|
return yield* ProviderShared.validateWith(Schema.decodeUnknownEffect(NativeTool))(tool.native.meta);
|
|
87
87
|
})),
|
|
88
88
|
tool_choice: OpenResponses.allowedToolChoice(request) ??
|
|
@@ -141,13 +141,14 @@ const MistralEvent = Schema.StructWithRest(Schema.Struct({
|
|
|
141
141
|
}), [Schema.Record(Schema.String, Schema.Unknown)]);
|
|
142
142
|
const MistralStreamEvent = Schema.Union([Schema.Literal(DONE), Protocol.jsonEvent(MistralEvent)]);
|
|
143
143
|
const lowerMedia = Effect.fn("MistralChat.lowerMedia")(function* (part) {
|
|
144
|
-
const
|
|
145
|
-
const url =
|
|
146
|
-
|
|
144
|
+
const mime = part.media.mediaType.toLowerCase();
|
|
145
|
+
const url = ProviderShared.mediaUrl(part.media) ??
|
|
146
|
+
(yield* ProviderShared.requireInlineMedia("Mistral Chat", part.media)).dataUrl;
|
|
147
|
+
if (mime.startsWith("image/"))
|
|
147
148
|
return { type: "image_url", image_url: url };
|
|
148
|
-
if (
|
|
149
|
+
if (mime === "application/pdf")
|
|
149
150
|
return { type: "document_url", document_url: url };
|
|
150
|
-
return yield* ProviderShared.invalidRequest(`Mistral Chat does not support media type ${part.mediaType}`);
|
|
151
|
+
return yield* ProviderShared.invalidRequest(`Mistral Chat does not support media type ${part.media.mediaType}`);
|
|
151
152
|
});
|
|
152
153
|
const lowerUser = Effect.fn("MistralChat.lowerUser")(function* (message) {
|
|
153
154
|
const content = [];
|
|
@@ -227,7 +228,7 @@ const lowerToolResults = Effect.fn("MistralChat.lowerToolResults")(function* (me
|
|
|
227
228
|
content.push({ type: "text", text: item.text });
|
|
228
229
|
continue;
|
|
229
230
|
}
|
|
230
|
-
content.push(yield* lowerMedia(
|
|
231
|
+
content.push(yield* lowerMedia(ProviderShared.toolFileMedia(item)));
|
|
231
232
|
}
|
|
232
233
|
output.push({
|
|
233
234
|
role: "tool",
|
|
@@ -2,7 +2,7 @@ import { Effect, Schema } from "effect";
|
|
|
2
2
|
import { HttpTransport } from "../route/transport/index.js";
|
|
3
3
|
import { Protocol } from "../route/protocol.js";
|
|
4
4
|
import { AIError, LLMEvent, Usage, type LLMRequest, type MediaPart, type ProviderMetadata, type ToolDefinition } from "../schema/index.js";
|
|
5
|
-
import {
|
|
5
|
+
import type { Media } from "../media.js";
|
|
6
6
|
import { OpenResponsesOptions } from "./utils/open-responses-options.js";
|
|
7
7
|
import { Lifecycle } from "./utils/lifecycle.js";
|
|
8
8
|
import { ToolStream } from "./utils/tool-stream.js";
|
|
@@ -689,7 +689,7 @@ export interface ProviderAdapter {
|
|
|
689
689
|
}, AIError>;
|
|
690
690
|
readonly lowerMedia?: (input: {
|
|
691
691
|
readonly part: MediaPart;
|
|
692
|
-
readonly media:
|
|
692
|
+
readonly media: Media.Inline | undefined;
|
|
693
693
|
readonly request: LLMRequest;
|
|
694
694
|
}) => MediaInput | undefined;
|
|
695
695
|
readonly restoreHostedToolItem?: (item: unknown) => HostedToolReplayItem | undefined;
|
|
@@ -895,8 +895,8 @@ export declare const fromRequest: (request: LLMRequest<import("../schema/options
|
|
|
895
895
|
} | {
|
|
896
896
|
readonly type: "input_file";
|
|
897
897
|
readonly filename: string;
|
|
898
|
-
readonly detail?: string | undefined;
|
|
899
898
|
readonly file_data?: string | undefined;
|
|
899
|
+
readonly detail?: string | undefined;
|
|
900
900
|
readonly file_url?: string | undefined;
|
|
901
901
|
} | {
|
|
902
902
|
readonly type: "input_text";
|
|
@@ -932,8 +932,8 @@ export declare const fromRequest: (request: LLMRequest<import("../schema/options
|
|
|
932
932
|
} | {
|
|
933
933
|
readonly type: "input_file";
|
|
934
934
|
readonly filename: string;
|
|
935
|
-
readonly detail?: string | undefined;
|
|
936
935
|
readonly file_data?: string | undefined;
|
|
936
|
+
readonly detail?: string | undefined;
|
|
937
937
|
readonly file_url?: string | undefined;
|
|
938
938
|
} | {
|
|
939
939
|
readonly type: "input_text";
|
|
@@ -1177,6 +1177,14 @@ export declare const step: (state: ParserState, event: NormalizedEvent) => AIErr
|
|
|
1177
1177
|
};
|
|
1178
1178
|
} | undefined;
|
|
1179
1179
|
readonly namespace?: string | undefined;
|
|
1180
|
+
} | {
|
|
1181
|
+
readonly type: "media";
|
|
1182
|
+
readonly media: Media.Asset;
|
|
1183
|
+
readonly providerMetadata?: {
|
|
1184
|
+
readonly [x: string]: {
|
|
1185
|
+
readonly [x: string]: unknown;
|
|
1186
|
+
};
|
|
1187
|
+
} | undefined;
|
|
1180
1188
|
} | {
|
|
1181
1189
|
readonly type: "step-finish";
|
|
1182
1190
|
readonly reason: {
|
|
@@ -1205,12 +1213,12 @@ export declare const step: (state: ParserState, event: NormalizedEvent) => AIErr
|
|
|
1205
1213
|
} | {
|
|
1206
1214
|
readonly type: "provider-error";
|
|
1207
1215
|
readonly message: string;
|
|
1216
|
+
readonly classification?: "context-overflow" | "payload-too-large" | undefined;
|
|
1208
1217
|
readonly providerMetadata?: {
|
|
1209
1218
|
readonly [x: string]: {
|
|
1210
1219
|
readonly [x: string]: unknown;
|
|
1211
1220
|
};
|
|
1212
1221
|
} | undefined;
|
|
1213
|
-
readonly classification?: "context-overflow" | "payload-too-large" | undefined;
|
|
1214
1222
|
})[]], AIError, never> | Effect.Effect<StepResult, never, never>;
|
|
1215
1223
|
/**
|
|
1216
1224
|
* The provider-neutral Open Responses protocol. Provider-specific Responses
|
|
@@ -1284,8 +1292,8 @@ export declare const protocol: Protocol<{
|
|
|
1284
1292
|
} | {
|
|
1285
1293
|
readonly type: "input_file";
|
|
1286
1294
|
readonly filename: string;
|
|
1287
|
-
readonly detail?: string | undefined;
|
|
1288
1295
|
readonly file_data?: string | undefined;
|
|
1296
|
+
readonly detail?: string | undefined;
|
|
1289
1297
|
readonly file_url?: string | undefined;
|
|
1290
1298
|
} | {
|
|
1291
1299
|
readonly type: "input_text";
|
|
@@ -1321,8 +1329,8 @@ export declare const protocol: Protocol<{
|
|
|
1321
1329
|
} | {
|
|
1322
1330
|
readonly type: "input_file";
|
|
1323
1331
|
readonly filename: string;
|
|
1324
|
-
readonly detail?: string | undefined;
|
|
1325
1332
|
readonly file_data?: string | undefined;
|
|
1333
|
+
readonly detail?: string | undefined;
|
|
1326
1334
|
readonly file_url?: string | undefined;
|
|
1327
1335
|
} | {
|
|
1328
1336
|
readonly type: "input_text";
|
|
@@ -1505,8 +1513,8 @@ export declare const httpTransport: HttpTransport.HttpJsonTransport<{
|
|
|
1505
1513
|
} | {
|
|
1506
1514
|
readonly type: "input_file";
|
|
1507
1515
|
readonly filename: string;
|
|
1508
|
-
readonly detail?: string | undefined;
|
|
1509
1516
|
readonly file_data?: string | undefined;
|
|
1517
|
+
readonly detail?: string | undefined;
|
|
1510
1518
|
readonly file_url?: string | undefined;
|
|
1511
1519
|
} | {
|
|
1512
1520
|
readonly type: "input_text";
|
|
@@ -1542,8 +1550,8 @@ export declare const httpTransport: HttpTransport.HttpJsonTransport<{
|
|
|
1542
1550
|
} | {
|
|
1543
1551
|
readonly type: "input_file";
|
|
1544
1552
|
readonly filename: string;
|
|
1545
|
-
readonly detail?: string | undefined;
|
|
1546
1553
|
readonly file_data?: string | undefined;
|
|
1554
|
+
readonly detail?: string | undefined;
|
|
1547
1555
|
readonly file_url?: string | undefined;
|
|
1548
1556
|
} | {
|
|
1549
1557
|
readonly type: "input_text";
|
|
@@ -335,27 +335,27 @@ const lowerReasoning = (part, providerMetadataKey) => {
|
|
|
335
335
|
};
|
|
336
336
|
};
|
|
337
337
|
const lowerMedia = Effect.fn("OpenResponses.lowerMedia")(function* (part, request, adapter, target) {
|
|
338
|
-
const media =
|
|
338
|
+
const media = part.media.inline();
|
|
339
339
|
const providerMedia = adapter.lowerMedia?.({ part, media, request });
|
|
340
340
|
if (providerMedia)
|
|
341
341
|
return providerMedia;
|
|
342
342
|
const detail = yield* ProviderShared.validateWith(Schema.decodeUnknownEffect(OpenResponsesInputImage.fields.detail))(part.providerMetadata?.[metadataKey(request.model)]?.detail);
|
|
343
|
-
const
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
if (
|
|
347
|
-
if (target === "tool-result" && media.
|
|
348
|
-
return { type: "input_video", video_url:
|
|
343
|
+
const mime = part.media.mediaType.toLowerCase();
|
|
344
|
+
const url = ProviderShared.mediaUrl(part.media);
|
|
345
|
+
const location = url ?? (yield* ProviderShared.requireInlineMedia(adapter.name, part.media)).dataUrl;
|
|
346
|
+
if (part.media.kind !== "image") {
|
|
347
|
+
if (target === "tool-result" && part.media.kind === "video")
|
|
348
|
+
return { type: "input_video", video_url: location };
|
|
349
349
|
return {
|
|
350
350
|
type: "input_file",
|
|
351
|
-
filename: part.filename ?? (
|
|
351
|
+
filename: part.filename ?? (mime === "application/pdf" ? "document.pdf" : "file"),
|
|
352
352
|
detail,
|
|
353
|
-
...(url ? { file_url: url } : { file_data:
|
|
353
|
+
...(url ? { file_url: url } : { file_data: location }),
|
|
354
354
|
};
|
|
355
355
|
}
|
|
356
356
|
return {
|
|
357
357
|
type: "input_image",
|
|
358
|
-
image_url:
|
|
358
|
+
image_url: location,
|
|
359
359
|
detail,
|
|
360
360
|
};
|
|
361
361
|
});
|
|
@@ -377,12 +377,12 @@ const lowerMessageMedia = Effect.fnUntraced(function* (part, request, adapter) {
|
|
|
377
377
|
const lowerToolResultContentItem = Effect.fnUntraced(function* (item, request, adapter) {
|
|
378
378
|
if (item.type === "text")
|
|
379
379
|
return { type: "input_text", text: item.text };
|
|
380
|
-
return yield* lowerMedia(
|
|
380
|
+
return yield* lowerMedia(ProviderShared.toolFileMedia(item), request, adapter, "tool-result");
|
|
381
381
|
});
|
|
382
382
|
const lowerHostedToolResultContentItem = Effect.fnUntraced(function* (item, request, adapter) {
|
|
383
383
|
if (item.type === "text")
|
|
384
384
|
return { type: "input_text", text: item.text };
|
|
385
|
-
return yield* lowerMessageMedia(
|
|
385
|
+
return yield* lowerMessageMedia(ProviderShared.toolFileMedia(item), request, adapter);
|
|
386
386
|
});
|
|
387
387
|
const lowerToolResultOutput = Effect.fnUntraced(function* (part, request, adapter) {
|
|
388
388
|
// Text/json/error results are encoded as a plain string for backward
|
|
@@ -513,11 +513,22 @@ const lowerMessages = Effect.fn("OpenResponses.lowerMessages")(function* (reques
|
|
|
513
513
|
});
|
|
514
514
|
continue;
|
|
515
515
|
}
|
|
516
|
+
if (part.type === "media") {
|
|
517
|
+
flushText();
|
|
518
|
+
// Responses has no assistant-authored image item; replay generated media (e.g. from Gemini) as user input.
|
|
519
|
+
input.push({
|
|
520
|
+
type: "message",
|
|
521
|
+
role: "user",
|
|
522
|
+
content: [yield* lowerMessageMedia(part, request, adapter)],
|
|
523
|
+
});
|
|
524
|
+
continue;
|
|
525
|
+
}
|
|
516
526
|
return yield* ProviderShared.unsupportedContent(adapter.name, "assistant", [
|
|
517
527
|
"text",
|
|
518
528
|
"reasoning",
|
|
519
529
|
"tool-call",
|
|
520
530
|
"tool-result",
|
|
531
|
+
"media",
|
|
521
532
|
]);
|
|
522
533
|
}
|
|
523
534
|
flushText();
|
|
@@ -592,7 +603,6 @@ export const allowedToolChoice = (request) => {
|
|
|
592
603
|
};
|
|
593
604
|
export const fromRequestWithAdapter = Effect.fn("OpenResponses.fromRequestWithAdapter")(function* (request, adapter) {
|
|
594
605
|
const projected = ProviderShared.flattenToolRequest(request);
|
|
595
|
-
const toolSchemaCompatibility = request.model.compatibility?.toolSchema;
|
|
596
606
|
return {
|
|
597
607
|
...(yield* lowerConversation(projected.request, adapter)),
|
|
598
608
|
...lowerGeneration(request),
|
|
@@ -600,7 +610,7 @@ export const fromRequestWithAdapter = Effect.fn("OpenResponses.fromRequestWithAd
|
|
|
600
610
|
? undefined
|
|
601
611
|
: yield* Effect.forEach(projected.tools, (tool) => tool.native !== undefined && adapter.nativeTool
|
|
602
612
|
? adapter.nativeTool(tool.native)
|
|
603
|
-
: lowerTool(adapter.name, tool, ToolSchemaProjection.modelCompatibility(tool.inputSchema,
|
|
613
|
+
: lowerTool(adapter.name, tool, ToolSchemaProjection.modelCompatibility(tool.inputSchema, request.model))),
|
|
604
614
|
tool_choice: allowedToolChoice(request) ??
|
|
605
615
|
(request.toolChoice ? yield* lowerToolChoice(adapter.name, request.toolChoice) : undefined),
|
|
606
616
|
};
|