@opencode/ai 2.0.15 → 2.0.17
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 +441 -99
- package/dist/ai-client.d.ts +8 -0
- package/dist/ai-client.js +12 -0
- package/dist/experimental/evaluation-client.d.ts +3 -3
- package/dist/experimental/evaluation-client.js +1 -1
- package/dist/experimental/evaluation.js +1 -1
- package/dist/generation.d.ts +39 -29
- package/dist/generation.js +62 -36
- package/dist/image-client.d.ts +59 -17
- package/dist/image-client.js +16 -24
- package/dist/image.d.ts +394 -55
- package/dist/image.js +48 -57
- package/dist/index.d.ts +15 -2
- package/dist/index.js +10 -0
- package/dist/llm.d.ts +7 -5
- package/dist/llm.js +10 -4
- package/dist/media-client.d.ts +30 -0
- package/dist/media-client.js +51 -0
- package/dist/media-model.d.ts +43 -0
- package/dist/media-model.js +47 -0
- package/dist/media.d.ts +10 -9
- package/dist/media.js +11 -12
- package/dist/promise.d.ts +473 -15
- package/dist/promise.js +71 -13
- package/dist/protocols/alibaba-chat.d.ts +12 -0
- package/dist/protocols/alibaba-chat.js +4 -1
- package/dist/protocols/alibaba-messages.d.ts +1 -1
- package/dist/protocols/alibaba-messages.js +6 -4
- package/dist/protocols/alibaba-responses.d.ts +2 -2
- package/dist/protocols/anthropic-messages.d.ts +34 -34
- package/dist/protocols/anthropic-messages.js +14 -9
- package/dist/protocols/assemblyai-transcription.d.ts +41 -0
- package/dist/protocols/assemblyai-transcription.js +136 -0
- package/dist/protocols/bedrock-converse.d.ts +7 -0
- package/dist/protocols/bedrock-converse.js +39 -19
- package/dist/protocols/bfl-images.d.ts +38 -0
- package/dist/protocols/bfl-images.js +153 -0
- package/dist/protocols/cartesia-speech.d.ts +143 -0
- package/dist/protocols/cartesia-speech.js +120 -0
- package/dist/protocols/deepgram-speech.d.ts +135 -0
- package/dist/protocols/deepgram-speech.js +91 -0
- package/dist/protocols/deepgram-transcription.d.ts +26 -0
- package/dist/protocols/deepgram-transcription.js +125 -0
- package/dist/protocols/elevenlabs-speech.d.ts +138 -0
- package/dist/protocols/elevenlabs-speech.js +111 -0
- package/dist/protocols/fal-images.d.ts +25 -0
- package/dist/protocols/fal-images.js +104 -0
- package/dist/protocols/fal-video.d.ts +29 -0
- package/dist/protocols/fal-video.js +73 -0
- package/dist/protocols/gemini.d.ts +22 -22
- package/dist/protocols/gemini.js +19 -36
- package/dist/protocols/google-images.d.ts +3 -3
- package/dist/protocols/google-images.js +12 -34
- package/dist/protocols/google-speech.d.ts +146 -0
- package/dist/protocols/google-speech.js +88 -0
- package/dist/protocols/google-transcription.d.ts +174 -0
- package/dist/protocols/google-transcription.js +126 -0
- package/dist/protocols/google-video.d.ts +26 -0
- package/dist/protocols/google-video.js +142 -0
- package/dist/protocols/meta-images.d.ts +3 -4
- package/dist/protocols/meta-images.js +13 -29
- package/dist/protocols/meta-messages.d.ts +5 -5
- package/dist/protocols/meta-responses.d.ts +4 -4
- package/dist/protocols/meta-responses.js +6 -4
- package/dist/protocols/open-responses.d.ts +10 -9
- package/dist/protocols/open-responses.js +4 -9
- package/dist/protocols/openai-chat.d.ts +84 -0
- package/dist/protocols/openai-chat.js +28 -17
- 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 +130 -7
- package/dist/protocols/openai-images.js +143 -91
- package/dist/protocols/openai-responses.d.ts +20 -20
- package/dist/protocols/openai-responses.js +31 -31
- package/dist/protocols/openai-speech.d.ts +136 -0
- package/dist/protocols/openai-speech.js +97 -0
- package/dist/protocols/openai-transcription.d.ts +211 -0
- package/dist/protocols/openai-transcription.js +202 -0
- package/dist/protocols/replicate-images.d.ts +28 -0
- package/dist/protocols/replicate-images.js +127 -0
- package/dist/protocols/runway-video.d.ts +38 -0
- package/dist/protocols/runway-video.js +140 -0
- package/dist/protocols/shared.d.ts +21 -17
- package/dist/protocols/shared.js +27 -36
- package/dist/protocols/stability-images.d.ts +39 -0
- package/dist/protocols/stability-images.js +136 -0
- package/dist/protocols/utils/fal-queue.d.ts +26 -0
- package/dist/protocols/utils/fal-queue.js +67 -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 +23 -1
- package/dist/protocols/utils/media-input.js +40 -0
- package/dist/protocols/utils/responses-checkpoint.js +3 -7
- package/dist/protocols/utils/responses-compaction.d.ts +3 -1
- package/dist/protocols/utils/responses-compaction.js +16 -3
- package/dist/protocols/utils/speech-stream.d.ts +49 -0
- package/dist/protocols/utils/speech-stream.js +64 -0
- package/dist/protocols/utils/tool-schema.d.ts +2 -2
- package/dist/protocols/utils/tool-schema.js +62 -19
- package/dist/protocols/xai-images.d.ts +4 -4
- package/dist/protocols/xai-images.js +14 -40
- package/dist/protocols/xai-responses.d.ts +2 -2
- package/dist/protocols/xai-responses.js +1 -1
- package/dist/protocols/xai-video.d.ts +34 -0
- package/dist/protocols/xai-video.js +141 -0
- package/dist/protocols/zai-chat.d.ts +13 -1
- package/dist/protocols/zai-images.d.ts +2 -2
- package/dist/protocols/zai-images.js +11 -14
- package/dist/protocols/zai-messages.d.ts +1 -1
- package/dist/provider-error.js +10 -1
- package/dist/providers/alibaba.d.ts +15 -3
- package/dist/providers/amazon-bedrock-mantle.d.ts +14 -2
- package/dist/providers/amazon-bedrock.d.ts +2 -0
- package/dist/providers/amazon-bedrock.js +1 -0
- package/dist/providers/anthropic-compatible.d.ts +5 -5
- package/dist/providers/anthropic.d.ts +5 -5
- package/dist/providers/assemblyai.d.ts +25 -0
- package/dist/providers/assemblyai.js +24 -0
- package/dist/providers/azure.d.ts +20 -8
- package/dist/providers/azure.js +2 -2
- 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 +23 -0
- package/dist/providers/cartesia.d.ts +24 -0
- package/dist/providers/cartesia.js +17 -0
- package/dist/providers/cerebras.d.ts +24 -0
- package/dist/providers/cloudflare-ai-gateway.d.ts +42 -18
- package/dist/providers/cloudflare-workers-ai.d.ts +24 -0
- package/dist/providers/deepgram.d.ts +29 -0
- package/dist/providers/deepgram.js +25 -0
- package/dist/providers/deepinfra.d.ts +24 -0
- package/dist/providers/deepseek.d.ts +24 -0
- package/dist/providers/elevenlabs.d.ts +24 -0
- package/dist/providers/elevenlabs.js +23 -0
- package/dist/providers/fal.d.ts +29 -0
- package/dist/providers/fal.js +26 -0
- package/dist/providers/fireworks.d.ts +24 -0
- package/dist/providers/google-vertex-chat.d.ts +12 -0
- package/dist/providers/google-vertex-messages.d.ts +5 -5
- package/dist/providers/google-vertex-responses.d.ts +2 -2
- package/dist/providers/google-vertex.d.ts +6 -6
- package/dist/providers/google.d.ts +21 -6
- package/dist/providers/google.js +13 -9
- package/dist/providers/groq.d.ts +24 -0
- package/dist/providers/index.d.ts +9 -0
- package/dist/providers/index.js +9 -0
- package/dist/providers/meta.d.ts +22 -10
- package/dist/providers/meta.js +4 -8
- package/dist/providers/minimax.d.ts +19 -7
- package/dist/providers/moonshot.d.ts +19 -7
- 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-options.d.ts +3 -9
- package/dist/providers/openai-options.js +4 -7
- package/dist/providers/openai.d.ts +33 -12
- package/dist/providers/openai.js +17 -9
- package/dist/providers/opencode-zen.js +1 -1
- package/dist/providers/openrouter.d.ts +54 -7
- package/dist/providers/openrouter.js +10 -5
- package/dist/providers/replicate.d.ts +25 -0
- package/dist/providers/replicate.js +17 -0
- package/dist/providers/runway.d.ts +24 -0
- package/dist/providers/runway.js +17 -0
- package/dist/providers/stability.d.ts +28 -0
- package/dist/providers/stability.js +18 -0
- package/dist/providers/togetherai.d.ts +24 -0
- package/dist/providers/typesafe-ai.js +1 -1
- package/dist/providers/vercel-ai-gateway.js +1 -1
- package/dist/providers/xai.d.ts +17 -0
- package/dist/providers/xai.js +7 -9
- package/dist/providers/zai-coding-plan.d.ts +16 -4
- package/dist/providers/zai.d.ts +13 -1
- package/dist/providers/zai.js +4 -8
- package/dist/route/auth.d.ts +5 -2
- package/dist/route/auth.js +20 -13
- package/dist/route/client.d.ts +9 -7
- package/dist/route/client.js +6 -8
- package/dist/route/endpoint.d.ts +1 -0
- package/dist/route/endpoint.js +2 -2
- package/dist/route/executor-service.d.ts +4 -2
- package/dist/route/executor-service.js +2 -1
- package/dist/route/executor.d.ts +3 -1
- package/dist/route/executor.js +7 -0
- package/dist/route/framing.d.ts +15 -2
- package/dist/route/framing.js +53 -4
- package/dist/route/index.d.ts +1 -1
- package/dist/route/media-protocol.d.ts +145 -18
- package/dist/route/media-protocol.js +96 -28
- package/dist/route/media.d.ts +54 -9
- package/dist/route/media.js +194 -38
- package/dist/route/protocol.d.ts +3 -1
- package/dist/schema/events.d.ts +0 -6
- package/dist/schema/messages.d.ts +0 -3
- package/dist/schema/options.d.ts +10 -6
- package/dist/schema/options.js +10 -5
- package/dist/speech-client.d.ts +66 -0
- package/dist/speech-client.js +21 -0
- package/dist/speech.d.ts +1307 -0
- package/dist/speech.js +124 -0
- package/dist/testing.d.ts +2 -2
- package/dist/transcription-client.d.ts +82 -0
- package/dist/transcription-client.js +13 -0
- package/dist/transcription.d.ts +1492 -0
- package/dist/transcription.js +127 -0
- package/dist/utils/bytes.d.ts +1 -0
- package/dist/utils/bytes.js +10 -0
- package/dist/utils/json.d.ts +4 -0
- package/dist/utils/json.js +4 -0
- package/dist/utils/media-type.d.ts +3 -1
- package/dist/utils/media-type.js +25 -2
- package/dist/video-client.d.ts +59 -0
- package/dist/video-client.js +20 -0
- package/dist/video.d.ts +1351 -0
- package/dist/video.js +118 -0
- package/package.json +3 -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/meta-image.d.ts +0 -2
- package/dist/protocols/utils/meta-image.js +0 -13
- package/dist/protocols/utils/openai-image.d.ts +0 -5
- package/dist/protocols/utils/openai-image.js +0 -18
|
@@ -1,40 +1,108 @@
|
|
|
1
|
-
import { Effect, Schema } from "effect";
|
|
1
|
+
import { Clock, Duration, Effect, Schema } from "effect";
|
|
2
2
|
import { HttpClientResponse } from "effect/unstable/http";
|
|
3
|
-
import {
|
|
4
|
-
|
|
3
|
+
import { Media } from "../media.js";
|
|
4
|
+
import { AIError, ContentPolicyError, HttpContext, InvalidProviderOutputError, InvalidRequestError, ProviderID, ProviderInternalError, UnsupportedOperationError, } from "../schema/index.js";
|
|
5
|
+
export const json = (value, query) => ({
|
|
6
|
+
type: "json",
|
|
7
|
+
value,
|
|
8
|
+
query,
|
|
9
|
+
});
|
|
5
10
|
export const multipart = (value) => ({ type: "multipart", value });
|
|
6
|
-
export const
|
|
7
|
-
|
|
8
|
-
|
|
11
|
+
export const binary = (value, contentType, query) => ({
|
|
12
|
+
type: "binary",
|
|
13
|
+
value,
|
|
14
|
+
contentType,
|
|
15
|
+
query,
|
|
9
16
|
});
|
|
17
|
+
export const inline = (route, input) => ({ kind: "inline", id: route.id, provider: route.provider, ...input });
|
|
18
|
+
export const queued = (route, input) => ({ kind: "queued", id: route.id, provider: route.provider, ...input });
|
|
19
|
+
export const stream = (route, input) => ({ kind: "stream", id: route.id, provider: route.provider, ...input });
|
|
10
20
|
// ---------------------------------------------------------------------------
|
|
11
21
|
// Response helpers
|
|
12
22
|
// ---------------------------------------------------------------------------
|
|
13
23
|
const context = (response) => new HttpContext({ url: response.request.url, status: response.status, headers: response.headers });
|
|
14
|
-
/**
|
|
15
|
-
export const
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
24
|
+
/** One protocol's route id, display name, and provider, with the decoders and errors that carry them. */
|
|
25
|
+
export const identity = (input) => {
|
|
26
|
+
const provider = ProviderID.make(input.provider);
|
|
27
|
+
const frameError = (message, body, cause) => new AIError({ reason: new InvalidProviderOutputError({ route: input.id, message, body, cause }) });
|
|
28
|
+
/**
|
|
29
|
+
* Read a text body while retaining the original payload and HTTP context on every downstream error. `invalid` is a
|
|
30
|
+
* malformed provider document; `ended` is a generation that reached a terminal status without output (`failed` is
|
|
31
|
+
* provider-side, `cancelled`/`expired` mean the result will never exist); `pending` is a `result()` read before the
|
|
32
|
+
* generation finished, which is caller misuse; `contentPolicy` is a moderated result.
|
|
33
|
+
*/
|
|
34
|
+
const text = Effect.fn("MediaProtocol.text")(function* (response) {
|
|
35
|
+
const http = context(response);
|
|
36
|
+
const body = yield* response.text.pipe(Effect.mapError((cause) => new AIError({
|
|
37
|
+
reason: new InvalidProviderOutputError({
|
|
38
|
+
route: input.id,
|
|
39
|
+
message: `Failed to read the ${input.name} response`,
|
|
40
|
+
http,
|
|
41
|
+
cause,
|
|
42
|
+
}),
|
|
43
|
+
})));
|
|
44
|
+
return {
|
|
45
|
+
body,
|
|
21
46
|
http,
|
|
22
|
-
cause,
|
|
23
|
-
|
|
24
|
-
|
|
47
|
+
invalid: (message, cause) => new AIError({ reason: new InvalidProviderOutputError({ route: input.id, message, body, http, cause }) }),
|
|
48
|
+
ended: (status, message) => new AIError({
|
|
49
|
+
reason: status === "failed"
|
|
50
|
+
? new ProviderInternalError({ message, body, http })
|
|
51
|
+
: new InvalidRequestError({ message, body, http }),
|
|
52
|
+
}),
|
|
53
|
+
pending: (id) => new AIError({
|
|
54
|
+
reason: new InvalidRequestError({
|
|
55
|
+
message: `${input.name} generation ${id} has not finished; await it before reading the result`,
|
|
56
|
+
body,
|
|
57
|
+
http,
|
|
58
|
+
}),
|
|
59
|
+
}),
|
|
60
|
+
contentPolicy: (message) => new AIError({ reason: new ContentPolicyError({ message, body, http }) }),
|
|
61
|
+
};
|
|
62
|
+
});
|
|
63
|
+
/** Read and Schema-decode a JSON body. Decode failures keep the raw body as `reason.body`. */
|
|
64
|
+
const decodeJson = (schema) => {
|
|
65
|
+
const decode = Schema.decodeUnknownEffect(Schema.fromJsonString(schema));
|
|
66
|
+
return Effect.fn("MediaProtocol.decodeJson")(function* (response) {
|
|
67
|
+
const output = yield* text(response);
|
|
68
|
+
const value = yield* decode(output.body).pipe(Effect.mapError((cause) => output.invalid(`${input.name} returned an invalid response`, cause)));
|
|
69
|
+
return { ...output, value };
|
|
70
|
+
});
|
|
71
|
+
};
|
|
25
72
|
return {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
73
|
+
id: input.id,
|
|
74
|
+
name: input.name,
|
|
75
|
+
provider,
|
|
76
|
+
text,
|
|
77
|
+
decodeJson,
|
|
78
|
+
/** Decode a submission response into the token and first snapshot. */
|
|
79
|
+
decodeStarted: (schema, started) => {
|
|
80
|
+
const decode = decodeJson(schema);
|
|
81
|
+
return (response) => decode(response).pipe(Effect.map((output) => started(output.value)));
|
|
82
|
+
},
|
|
83
|
+
/** Schema-decode one JSON stream frame. Decode failures keep the frame as `reason.body`. */
|
|
84
|
+
decodeFrame: (schema) => {
|
|
85
|
+
const decode = Schema.decodeUnknownEffect(Schema.fromJsonString(schema));
|
|
86
|
+
return (frame) => decode(frame).pipe(Effect.mapError((cause) => frameError(`${input.name} sent an invalid stream event`, frame, cause)));
|
|
87
|
+
},
|
|
88
|
+
/** A stream-time failure; the frame stays on `reason.body`. */
|
|
89
|
+
frameError,
|
|
90
|
+
incomplete: () => new AIError({
|
|
91
|
+
reason: new InvalidProviderOutputError({
|
|
92
|
+
route: input.id,
|
|
93
|
+
message: "The provider response ended unexpectedly.",
|
|
94
|
+
classification: "incomplete-stream",
|
|
95
|
+
}),
|
|
96
|
+
}),
|
|
97
|
+
unsupported: (operation, message) => new AIError({ reason: new UnsupportedOperationError({ operation, provider, route: input.id, message }) }),
|
|
29
98
|
};
|
|
30
|
-
});
|
|
31
|
-
/** Read and Schema-decode a JSON body. Decode failures keep the raw body as `reason.body`. */
|
|
32
|
-
export const decodeJson = (route, name, schema) => {
|
|
33
|
-
const decode = Schema.decodeUnknownEffect(Schema.fromJsonString(schema));
|
|
34
|
-
return Effect.fn("MediaProtocol.decodeJson")(function* (response) {
|
|
35
|
-
const output = yield* text(route, name, response);
|
|
36
|
-
const value = yield* decode(output.body).pipe(Effect.mapError((cause) => output.invalid(`${name} returned an invalid response`, cause)));
|
|
37
|
-
return { ...output, value };
|
|
38
|
-
});
|
|
39
99
|
};
|
|
100
|
+
/** Map a provider status string through the protocol's table; unknown values are an invalid provider document. */
|
|
101
|
+
export const status = (table, raw, output) => {
|
|
102
|
+
if (!Object.hasOwn(table, raw))
|
|
103
|
+
return Effect.fail(output.invalid(`Unknown generation status "${raw}"`));
|
|
104
|
+
return Effect.succeed(table[raw]);
|
|
105
|
+
};
|
|
106
|
+
/** A `url` asset whose provider-declared retention window starts now. */
|
|
107
|
+
export const expiringUrl = (url, retention, options) => Clock.currentTimeMillis.pipe(Effect.map((now) => Media.url(url, { ...options, expiresAt: now + Duration.toMillis(retention) })));
|
|
40
108
|
export * as MediaProtocol from "./media-protocol.js";
|
package/dist/route/media.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { Effect } from "effect";
|
|
1
|
+
import { Effect, Stream } from "effect";
|
|
2
2
|
import { Auth } from "./auth.js";
|
|
3
3
|
import { Endpoint } from "./endpoint.js";
|
|
4
|
-
import type
|
|
4
|
+
import { type Interface } from "./executor-service.js";
|
|
5
5
|
import { MediaProtocol } from "./media-protocol.js";
|
|
6
|
+
import { Generation } from "../generation.js";
|
|
6
7
|
import { AIError, HttpOptions, ProviderID } from "../schema/index.js";
|
|
7
8
|
export type Execute = Interface["execute"];
|
|
8
9
|
/** The minimum a media request must carry for the route to build a transport request. */
|
|
@@ -22,25 +23,69 @@ export interface ModelInput {
|
|
|
22
23
|
readonly headers?: Record<string, string>;
|
|
23
24
|
readonly http?: HttpOptions;
|
|
24
25
|
}
|
|
25
|
-
|
|
26
|
+
/** A provider facade's `configure(...)` input as the `ModelInput` every media selector shares, minus the model id. */
|
|
27
|
+
export declare const deployment: (input: {
|
|
28
|
+
readonly baseURL?: string;
|
|
29
|
+
readonly headers?: Record<string, string>;
|
|
30
|
+
readonly http?: HttpOptions.Input;
|
|
31
|
+
}, auth: Auth.Definition) => Omit<ModelInput, "id">;
|
|
32
|
+
/** One request, one response. */
|
|
33
|
+
export interface InlineRoute<Request extends MediaRequest, Response> {
|
|
34
|
+
readonly kind: "inline";
|
|
26
35
|
readonly id: string;
|
|
27
36
|
readonly provider: ProviderID;
|
|
28
37
|
readonly protocol: string;
|
|
29
38
|
readonly generate: (request: Request, execute: Execute) => Effect.Effect<Response, AIError>;
|
|
30
39
|
}
|
|
31
|
-
|
|
40
|
+
/** Submit, then poll through the returned `Generation`. */
|
|
41
|
+
export interface QueuedRoute<Request extends MediaRequest, Response> {
|
|
42
|
+
readonly kind: "queued";
|
|
32
43
|
readonly id: string;
|
|
33
|
-
readonly provider:
|
|
34
|
-
readonly protocol:
|
|
44
|
+
readonly provider: ProviderID;
|
|
45
|
+
readonly protocol: string;
|
|
46
|
+
readonly start: (request: Request, execute: Execute) => Effect.Effect<Generation<Response>, AIError>;
|
|
47
|
+
/** Rebuild a handle from a persisted `Generation.token`; fails typed when the token is not this route's. */
|
|
48
|
+
readonly resume: (model: MediaRequest["model"], token: unknown, execute: Execute) => Effect.Effect<Generation<Response>, AIError>;
|
|
49
|
+
}
|
|
50
|
+
/** One request whose response parses into events; `generate` runs the same stream and collects it. */
|
|
51
|
+
export interface StreamRoute<Request extends MediaRequest, Event, Response> {
|
|
52
|
+
readonly kind: "stream";
|
|
53
|
+
readonly id: string;
|
|
54
|
+
readonly provider: ProviderID;
|
|
55
|
+
readonly protocol: string;
|
|
56
|
+
readonly stream: (request: Request, execute: Execute) => Stream.Stream<Event, AIError>;
|
|
57
|
+
readonly generate: (request: Request, execute: Execute) => Effect.Effect<Response, AIError>;
|
|
58
|
+
}
|
|
59
|
+
export type AnyRoute<Request extends MediaRequest, Event, Response> = InlineRoute<Request, Response> | StreamRoute<Request, Event, Response> | QueuedRoute<Request, Response>;
|
|
60
|
+
export interface Composition<Request extends MediaRequest> {
|
|
35
61
|
readonly endpoint: Endpoint.Definition<MediaProtocol.Body, Request>;
|
|
36
62
|
readonly auth: Auth.Definition;
|
|
37
63
|
/** Deployment headers applied before transport authentication. */
|
|
38
64
|
readonly headers?: Record<string, string>;
|
|
39
65
|
}
|
|
66
|
+
export interface InlineInput<Request extends MediaRequest, Response> extends Composition<Request> {
|
|
67
|
+
readonly protocol: MediaProtocol.Inline<Request, Response>;
|
|
68
|
+
}
|
|
69
|
+
export interface QueuedInput<Request extends MediaRequest, Response, Token> extends Composition<Request> {
|
|
70
|
+
readonly protocol: MediaProtocol.Queued<Request, Response, Token>;
|
|
71
|
+
}
|
|
72
|
+
export interface StreamInput<Request extends MediaRequest, Event, Response, Frame, State> extends Composition<MediaProtocol.Addressed<Request>> {
|
|
73
|
+
readonly protocol: MediaProtocol.Streamed<Request, Event, Frame, State>;
|
|
74
|
+
readonly collect: (events: ReadonlyArray<Event>) => Effect.Effect<Response, AIError>;
|
|
75
|
+
}
|
|
40
76
|
/**
|
|
41
77
|
* Compose an inline media protocol with an endpoint and auth into a runnable route. The route owns the transport
|
|
42
|
-
* plumbing every media protocol would otherwise duplicate: option merging, surrogate sanitizing, unsupported-field
|
|
43
|
-
* rendering, auth headers, JSON
|
|
78
|
+
* plumbing every media protocol would otherwise duplicate: option merging, surrogate sanitizing, unsupported-field
|
|
79
|
+
* rejection, URL and query rendering, auth headers, JSON, multipart, or binary encoding, and handing responses back
|
|
80
|
+
* to the protocol.
|
|
81
|
+
*/
|
|
82
|
+
export declare const inline: <Request extends MediaRequest, Response>(input: InlineInput<Request, Response>) => InlineRoute<Request, Response>;
|
|
83
|
+
/**
|
|
84
|
+
* Compose a queued media protocol the same way, adding `start`/`resume` handles whose polls reuse the route's auth,
|
|
85
|
+
* deployment headers, and (for `start`) the request's `http` overlay. The token is decoded once at the boundary and
|
|
86
|
+
* closed over by the resulting `Generation.Route`.
|
|
44
87
|
*/
|
|
45
|
-
export declare const
|
|
88
|
+
export declare const queued: <Request extends MediaRequest, Response, Token>(input: QueuedInput<Request, Response, Token>) => QueuedRoute<Request, Response>;
|
|
89
|
+
/** Compose a streaming media protocol; `generate` runs the same stream in `generate` mode and folds it with `collect`. */
|
|
90
|
+
export declare const stream: <Request extends MediaRequest, Event, Response, Frame, State>(input: StreamInput<Request, Event, Response, Frame, State>) => StreamRoute<Request, Event, Response>;
|
|
46
91
|
export * as MediaRoute from "./media.js";
|
package/dist/route/media.js
CHANGED
|
@@ -1,52 +1,206 @@
|
|
|
1
|
-
import { Effect } from "effect";
|
|
1
|
+
import { Effect, Schema, Stream } from "effect";
|
|
2
2
|
import { Headers, HttpClientRequest } from "effect/unstable/http";
|
|
3
3
|
import { Auth } from "./auth.js";
|
|
4
4
|
import { Endpoint } from "./endpoint.js";
|
|
5
|
+
import { RequestExecutorService } from "./executor-service.js";
|
|
6
|
+
import { RequestExecutor } from "./executor.js";
|
|
5
7
|
import { MediaProtocol } from "./media-protocol.js";
|
|
6
|
-
import {
|
|
7
|
-
import { AIError, HttpOptions, ProviderID, mergeHttpOptions } from "../schema/index.js";
|
|
8
|
+
import { Generation, isTerminal } from "../generation.js";
|
|
9
|
+
import { AIError, AIErrorReason, HttpOptions, InvalidRequestError, ProviderID, UnsupportedOperationError, mergeHttpOptions, } from "../schema/index.js";
|
|
10
|
+
import { encodeJson } from "../utils/json.js";
|
|
8
11
|
import { sanitizeSurrogates } from "../utils/sanitize.js";
|
|
12
|
+
/** A provider facade's `configure(...)` input as the `ModelInput` every media selector shares, minus the model id. */
|
|
13
|
+
export const deployment = (input, auth) => ({
|
|
14
|
+
auth,
|
|
15
|
+
baseURL: input.baseURL,
|
|
16
|
+
headers: input.headers,
|
|
17
|
+
http: HttpOptions.make(input.http),
|
|
18
|
+
});
|
|
9
19
|
/**
|
|
10
20
|
* Compose an inline media protocol with an endpoint and auth into a runnable route. The route owns the transport
|
|
11
|
-
* plumbing every media protocol would otherwise duplicate: option merging, surrogate sanitizing, unsupported-field
|
|
12
|
-
* rendering, auth headers, JSON
|
|
21
|
+
* plumbing every media protocol would otherwise duplicate: option merging, surrogate sanitizing, unsupported-field
|
|
22
|
+
* rejection, URL and query rendering, auth headers, JSON, multipart, or binary encoding, and handing responses back
|
|
23
|
+
* to the protocol.
|
|
13
24
|
*/
|
|
14
|
-
export const
|
|
15
|
-
const
|
|
16
|
-
const routeHttp = input.headers === undefined ? undefined : new HttpOptions({ headers: input.headers });
|
|
17
|
-
const authorize = Auth.toEffect(input.auth);
|
|
25
|
+
export const inline = (input) => {
|
|
26
|
+
const transport = makeTransport(input);
|
|
18
27
|
return {
|
|
19
|
-
|
|
20
|
-
|
|
28
|
+
kind: "inline",
|
|
29
|
+
id: input.protocol.id,
|
|
30
|
+
provider: input.protocol.provider,
|
|
21
31
|
protocol: input.protocol.id,
|
|
22
32
|
generate: Effect.fn(`MediaRoute.generate`)(function* (request, execute) {
|
|
23
|
-
yield*
|
|
33
|
+
const submitted = yield* transport.submit(request, { unsupported: input.protocol.unsupported, from: input.protocol.body.from }, execute);
|
|
34
|
+
return yield* input.protocol.response.decode(submitted.response, submitted.context);
|
|
35
|
+
}),
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Compose a queued media protocol the same way, adding `start`/`resume` handles whose polls reuse the route's auth,
|
|
40
|
+
* deployment headers, and (for `start`) the request's `http` overlay. The token is decoded once at the boundary and
|
|
41
|
+
* closed over by the resulting `Generation.Route`.
|
|
42
|
+
*/
|
|
43
|
+
export const queued = (input) => {
|
|
44
|
+
const transport = makeTransport(input);
|
|
45
|
+
const protocol = input.protocol;
|
|
46
|
+
const decodeToken = Schema.decodeUnknownEffect(protocol.token);
|
|
47
|
+
// A protocol producing a token its own codec rejects is a programmer defect, not a provider error.
|
|
48
|
+
const encodeToken = Schema.encodeSync(protocol.token);
|
|
49
|
+
const generationRoute = (token, http, execute) => {
|
|
50
|
+
const materialize = (asset) => asset.materialize().pipe(Effect.provideService(RequestExecutorService, { execute }));
|
|
51
|
+
const poll = (operation) => transport
|
|
52
|
+
.call("GET", operation.path(token), http, execute)
|
|
53
|
+
.pipe(Effect.flatMap((sent) => operation.decode(sent.response, { token, auth: sent.auth, materialize })));
|
|
54
|
+
const status = poll(protocol.status);
|
|
55
|
+
const cancel = protocol.cancel;
|
|
56
|
+
const send = cancel === undefined
|
|
57
|
+
? undefined
|
|
58
|
+
: transport.call(cancel.method, cancel.path(token), http, execute).pipe(Effect.asVoid);
|
|
59
|
+
return {
|
|
60
|
+
status,
|
|
61
|
+
result: poll(protocol.result),
|
|
62
|
+
cancel: send !== undefined && cancel?.activeOnly
|
|
63
|
+
? status.pipe(Effect.flatMap((snapshot) => (isTerminal(snapshot.status) ? Effect.void : send)))
|
|
64
|
+
: send,
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
const start = Effect.fn("MediaRoute.start")(function* (request, execute) {
|
|
68
|
+
const submitted = yield* transport.submit(request, { unsupported: protocol.unsupported, prepare: protocol.start.prepare, from: protocol.start.body.from }, execute);
|
|
69
|
+
const started = yield* protocol.start.decode(submitted.response, submitted.context);
|
|
70
|
+
const route = generationRoute(started.token, submitted.context.request.http, execute);
|
|
71
|
+
return new Generation(route, encodeToken(started.token), started.snapshot);
|
|
72
|
+
});
|
|
73
|
+
const resume = Effect.fn("MediaRoute.resume")(function* (model, raw, execute) {
|
|
74
|
+
const token = yield* decodeToken(raw).pipe(Effect.mapError((cause) => new AIError({
|
|
75
|
+
reason: new InvalidRequestError({
|
|
76
|
+
message: `${protocol.id} cannot resume a generation from this token`,
|
|
77
|
+
cause,
|
|
78
|
+
}),
|
|
79
|
+
})));
|
|
80
|
+
const route = generationRoute(token, transport.http(model), execute);
|
|
81
|
+
return new Generation(route, encodeToken(token), yield* route.status);
|
|
82
|
+
});
|
|
83
|
+
return { kind: "queued", id: protocol.id, provider: protocol.provider, protocol: protocol.id, start, resume };
|
|
84
|
+
};
|
|
85
|
+
/** Compose a streaming media protocol; `generate` runs the same stream in `generate` mode and folds it with `collect`. */
|
|
86
|
+
export const stream = (input) => {
|
|
87
|
+
const transport = makeTransport(input);
|
|
88
|
+
const protocol = input.protocol;
|
|
89
|
+
const events = (request, execute, mode) => Stream.unwrap(Effect.gen(function* () {
|
|
90
|
+
const submitted = yield* transport.submit({ ...request, mode }, { unsupported: protocol.unsupported, from: protocol.body.from }, execute);
|
|
91
|
+
const http = RequestExecutor.responseHttp(submitted.response);
|
|
92
|
+
return Stream.suspend(() => {
|
|
93
|
+
// Parser state is local to one response, exactly like `Route.make`'s LLM stream loop.
|
|
94
|
+
let state = protocol.initial();
|
|
95
|
+
return protocol.frames(RequestExecutor.responseStream(submitted.response), submitted.context).pipe(Stream.mapEffect((frame) => protocol.step(state, frame).pipe(Effect.map(([next, output]) => {
|
|
96
|
+
state = next;
|
|
97
|
+
return output;
|
|
98
|
+
}))), Stream.flattenIterable, Stream.concat(Stream.suspend(() => Stream.fromIterableEffect(protocol.finish(state, { ...submitted.context, http })))), Stream.mapError((error) => error.reason.http !== undefined
|
|
99
|
+
? error
|
|
100
|
+
: new AIError({
|
|
101
|
+
reason: AIErrorReason.make({
|
|
102
|
+
...error.reason,
|
|
103
|
+
message: error.reason.message,
|
|
104
|
+
cause: error.reason.cause,
|
|
105
|
+
http,
|
|
106
|
+
}),
|
|
107
|
+
})));
|
|
108
|
+
});
|
|
109
|
+
}));
|
|
110
|
+
return {
|
|
111
|
+
kind: "stream",
|
|
112
|
+
id: protocol.id,
|
|
113
|
+
provider: protocol.provider,
|
|
114
|
+
protocol: protocol.id,
|
|
115
|
+
stream: (request, execute) => events(request, execute, "stream"),
|
|
116
|
+
generate: (request, execute) => events(request, execute, "generate").pipe(Stream.runCollect, Effect.flatMap(input.collect)),
|
|
117
|
+
};
|
|
118
|
+
};
|
|
119
|
+
// ---------------------------------------------------------------------------
|
|
120
|
+
// Transport plumbing shared by every kind
|
|
121
|
+
// ---------------------------------------------------------------------------
|
|
122
|
+
const makeTransport = (input) => {
|
|
123
|
+
const routeHttp = input.headers === undefined ? undefined : new HttpOptions({ headers: input.headers });
|
|
124
|
+
const authorize = Auth.toEffect(input.auth);
|
|
125
|
+
const baseURL = (path) => new URL(`${Endpoint.trimBaseUrl(input.endpoint.baseURL ?? "")}${path}`);
|
|
126
|
+
/** `auth` is only what `Auth` added or changed, never untouched deployment headers. */
|
|
127
|
+
const send = Effect.fn("MediaRoute.send")(function* (call, execute) {
|
|
128
|
+
const encoded = encode(call.body, call.headers);
|
|
129
|
+
const url = call.url.toString();
|
|
130
|
+
const headers = yield* authorize({
|
|
131
|
+
request: call.request,
|
|
132
|
+
method: call.method,
|
|
133
|
+
url,
|
|
134
|
+
body: encoded.text,
|
|
135
|
+
headers: encoded.headers,
|
|
136
|
+
});
|
|
137
|
+
const response = yield* execute(encoded.apply(HttpClientRequest.make(call.method)(url).pipe(HttpClientRequest.setHeaders(headers))));
|
|
138
|
+
return {
|
|
139
|
+
response,
|
|
140
|
+
auth: Object.fromEntries(Object.entries(headers).filter(([key, value]) => encoded.headers[key] !== value)),
|
|
141
|
+
};
|
|
142
|
+
});
|
|
143
|
+
return {
|
|
144
|
+
/** Route and model overlays; `start` additionally merges the request's own `http`. */
|
|
145
|
+
http: (model) => mergeHttpOptions(routeHttp, model.http),
|
|
146
|
+
/** POST the protocol body to the route endpoint. */
|
|
147
|
+
submit: Effect.fn("MediaRoute.submit")(function* (request, protocol, execute) {
|
|
148
|
+
yield* rejectUnsupported(input.protocol.id, input.protocol.provider, request, protocol.unsupported);
|
|
24
149
|
const http = mergeHttpOptions(routeHttp, request.model.http, request.http);
|
|
150
|
+
const headers = Headers.fromInput(http?.headers);
|
|
151
|
+
const prepared = protocol.prepare === undefined
|
|
152
|
+
? request
|
|
153
|
+
: yield* protocol.prepare(request, (path, body) => send({ method: "POST", url: baseURL(path), headers, request, body }, execute).pipe(Effect.map((sent) => sent.response)));
|
|
25
154
|
// Sanitize after merging so model-level overlays are covered; the model value is restored, not sanitized.
|
|
26
|
-
const resolved = { ...sanitizeSurrogates({ ...
|
|
27
|
-
const body = yield*
|
|
28
|
-
const url = Endpoint.render(input.endpoint, { request: resolved, body });
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const encoded = body.type === "json" ? ProviderShared.encodeJson(body.value) : "[multipart/form-data]";
|
|
32
|
-
const baseHeaders = Headers.fromInput(http?.headers);
|
|
33
|
-
const headers = yield* authorize({
|
|
34
|
-
request: resolved,
|
|
35
|
-
method: "POST",
|
|
36
|
-
url: url.toString(),
|
|
37
|
-
body: encoded,
|
|
38
|
-
// The HTTP client sets the multipart boundary; a caller-supplied content-type would corrupt it.
|
|
39
|
-
headers: body.type === "multipart" ? Headers.remove(baseHeaders, "content-type") : baseHeaders,
|
|
40
|
-
});
|
|
41
|
-
const transport = HttpClientRequest.post(url.toString()).pipe(HttpClientRequest.setHeaders(headers), body.type === "json"
|
|
42
|
-
? HttpClientRequest.bodyText(encoded, "application/json")
|
|
43
|
-
: HttpClientRequest.bodyFormData(body.value));
|
|
44
|
-
const response = yield* execute(transport);
|
|
45
|
-
return yield* input.protocol.response.decode(response, { request: resolved, body });
|
|
155
|
+
const resolved = { ...sanitizeSurrogates({ ...prepared, http }), model: request.model };
|
|
156
|
+
const body = yield* protocol.from(resolved);
|
|
157
|
+
const url = withQuery(withQuery(Endpoint.render(input.endpoint, { request: resolved, body }), body.type === "multipart" ? undefined : body.query), http?.query);
|
|
158
|
+
const sent = yield* send({ method: "POST", url, headers, request: resolved, body }, execute);
|
|
159
|
+
return { response: sent.response, context: { request: resolved, body } };
|
|
46
160
|
}),
|
|
161
|
+
/** Bodiless follow-up call (status, result, cancel) with the same auth and headers as `submit`. */
|
|
162
|
+
call: (method, path, http, execute) => {
|
|
163
|
+
// Provider-issued absolute URLs (fal `status_url`) are used as-is; everything else resolves against the base.
|
|
164
|
+
const url = withQuery(/^https?:\/\//.test(path) ? new URL(path) : baseURL(path), http?.query);
|
|
165
|
+
for (const [key, value] of Object.entries(input.endpoint.query ?? {}))
|
|
166
|
+
url.searchParams.set(key, value);
|
|
167
|
+
return send({ method, url, headers: Headers.fromInput(http?.headers), request: { http } }, execute);
|
|
168
|
+
},
|
|
47
169
|
};
|
|
48
170
|
};
|
|
49
|
-
|
|
171
|
+
const withQuery = (url, query) => {
|
|
172
|
+
for (const [key, value] of Object.entries(query ?? {})) {
|
|
173
|
+
url.searchParams.delete(key);
|
|
174
|
+
for (const item of typeof value === "string" ? [value] : value)
|
|
175
|
+
url.searchParams.append(key, item);
|
|
176
|
+
}
|
|
177
|
+
return url;
|
|
178
|
+
};
|
|
179
|
+
const encode = (body, headers) => {
|
|
180
|
+
if (body === undefined)
|
|
181
|
+
return { text: "", headers, apply: (request) => request };
|
|
182
|
+
if (body.type === "json") {
|
|
183
|
+
const text = encodeJson(body.value);
|
|
184
|
+
return { text, headers, apply: HttpClientRequest.bodyText(text, "application/json") };
|
|
185
|
+
}
|
|
186
|
+
if (body.type === "binary")
|
|
187
|
+
return {
|
|
188
|
+
text: `[${body.contentType}]`,
|
|
189
|
+
headers,
|
|
190
|
+
apply: HttpClientRequest.bodyUint8Array(body.value, body.contentType),
|
|
191
|
+
};
|
|
192
|
+
return {
|
|
193
|
+
text: "[multipart/form-data]",
|
|
194
|
+
// The HTTP client sets the multipart boundary; a caller-supplied content-type would corrupt it.
|
|
195
|
+
headers: Headers.remove(headers, "content-type"),
|
|
196
|
+
apply: HttpClientRequest.bodyFormData(body.value),
|
|
197
|
+
};
|
|
198
|
+
};
|
|
199
|
+
/**
|
|
200
|
+
* Common fields are never silently dropped: a present field the protocol declared unsupported fails typed. `false`
|
|
201
|
+
* counts as present because some booleans mean something when false (video `audio`); protocols reject opt-in
|
|
202
|
+
* booleans such as speech `timestamps` with `=== true` in `body.from` instead of listing them.
|
|
203
|
+
*/
|
|
50
204
|
const rejectUnsupported = (route, provider, request, unsupported) => {
|
|
51
205
|
const present = (unsupported ?? []).filter((field) => {
|
|
52
206
|
const value = request[field];
|
|
@@ -54,11 +208,13 @@ const rejectUnsupported = (route, provider, request, unsupported) => {
|
|
|
54
208
|
});
|
|
55
209
|
if (present.length === 0)
|
|
56
210
|
return Effect.void;
|
|
57
|
-
return Effect.fail(
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
211
|
+
return Effect.fail(new AIError({
|
|
212
|
+
reason: new UnsupportedOperationError({
|
|
213
|
+
operation: `media.${present[0]}`,
|
|
214
|
+
provider,
|
|
215
|
+
route,
|
|
216
|
+
message: `${provider}/${route} does not support ${present.join(", ")}`,
|
|
217
|
+
}),
|
|
62
218
|
}));
|
|
63
219
|
};
|
|
64
220
|
export * as MediaRoute from "./media.js";
|
package/dist/route/protocol.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Schema, type Effect } from "effect";
|
|
2
|
-
import type { AIError, LLMEvent, LLMRequest, ProtocolID } from "../schema/index.js";
|
|
2
|
+
import type { AIError, LanguageModelSanitizerCompatibility, LLMEvent, LLMRequest, ProtocolID } from "../schema/index.js";
|
|
3
3
|
/**
|
|
4
4
|
* The semantic API contract of one model server family.
|
|
5
5
|
*
|
|
@@ -42,6 +42,8 @@ export interface Protocol<Body, Frame, Event, State> {
|
|
|
42
42
|
readonly stream: ProtocolStream<Frame, Event, State>;
|
|
43
43
|
/** Whether `body.from` lowers `Message.effort(...)` markers; wrappers around another `body.from` must forward it. */
|
|
44
44
|
readonly supportsEffortUpdates?: (request: LLMRequest) => boolean;
|
|
45
|
+
/** Tool schema sanitizer for every model on this protocol unless the model's compatibility sets one; wrappers around another `body.from` must forward it. */
|
|
46
|
+
readonly sanitizer?: LanguageModelSanitizerCompatibility;
|
|
45
47
|
}
|
|
46
48
|
export interface ProtocolBody<Body> {
|
|
47
49
|
/** Schema for the validated provider-native body sent as the JSON request. */
|
package/dist/schema/events.d.ts
CHANGED
|
@@ -365,7 +365,6 @@ export declare const MediaEvent: Schema.Struct<{
|
|
|
365
365
|
readonly url: Schema.String;
|
|
366
366
|
readonly mediaType: Schema.optional<Schema.String>;
|
|
367
367
|
readonly expiresAt: Schema.optional<Schema.Number>;
|
|
368
|
-
readonly headers: Schema.optional<Schema.$Record<Schema.String, Schema.String>>;
|
|
369
368
|
}>, Schema.Struct<{
|
|
370
369
|
readonly type: Schema.Literal<"ref">;
|
|
371
370
|
readonly provider: Schema.brand<Schema.String, "AI.ProviderID">;
|
|
@@ -578,7 +577,6 @@ declare const llmEventTagged: Schema.toTaggedUnion<"type", readonly [Schema.refi
|
|
|
578
577
|
readonly url: Schema.String;
|
|
579
578
|
readonly mediaType: Schema.optional<Schema.String>;
|
|
580
579
|
readonly expiresAt: Schema.optional<Schema.Number>;
|
|
581
|
-
readonly headers: Schema.optional<Schema.$Record<Schema.String, Schema.String>>;
|
|
582
580
|
}>, Schema.Struct<{
|
|
583
581
|
readonly type: Schema.Literal<"ref">;
|
|
584
582
|
readonly provider: Schema.brand<Schema.String, "AI.ProviderID">;
|
|
@@ -820,7 +818,6 @@ export declare const LLMEvent: Schema.Union<readonly [Schema.refine<{
|
|
|
820
818
|
readonly url: Schema.String;
|
|
821
819
|
readonly mediaType: Schema.optional<Schema.String>;
|
|
822
820
|
readonly expiresAt: Schema.optional<Schema.Number>;
|
|
823
|
-
readonly headers: Schema.optional<Schema.$Record<Schema.String, Schema.String>>;
|
|
824
821
|
}>, Schema.Struct<{
|
|
825
822
|
readonly type: Schema.Literal<"ref">;
|
|
826
823
|
readonly provider: Schema.brand<Schema.String, "AI.ProviderID">;
|
|
@@ -1064,7 +1061,6 @@ export declare const LLMEvent: Schema.Union<readonly [Schema.refine<{
|
|
|
1064
1061
|
readonly url: Schema.String;
|
|
1065
1062
|
readonly mediaType: Schema.optional<Schema.String>;
|
|
1066
1063
|
readonly expiresAt: Schema.optional<Schema.Number>;
|
|
1067
|
-
readonly headers: Schema.optional<Schema.$Record<Schema.String, Schema.String>>;
|
|
1068
1064
|
}>, Schema.Struct<{
|
|
1069
1065
|
readonly type: Schema.Literal<"ref">;
|
|
1070
1066
|
readonly provider: Schema.brand<Schema.String, "AI.ProviderID">;
|
|
@@ -4805,7 +4801,6 @@ declare const LLMResponse_base: Schema.Class<LLMResponse, Schema.Struct<{
|
|
|
4805
4801
|
readonly url: Schema.String;
|
|
4806
4802
|
readonly mediaType: Schema.optional<Schema.String>;
|
|
4807
4803
|
readonly expiresAt: Schema.optional<Schema.Number>;
|
|
4808
|
-
readonly headers: Schema.optional<Schema.$Record<Schema.String, Schema.String>>;
|
|
4809
4804
|
}>, Schema.Struct<{
|
|
4810
4805
|
readonly type: Schema.Literal<"ref">;
|
|
4811
4806
|
readonly provider: Schema.brand<Schema.String, "AI.ProviderID">;
|
|
@@ -5049,7 +5044,6 @@ declare const LLMResponse_base: Schema.Class<LLMResponse, Schema.Struct<{
|
|
|
5049
5044
|
readonly url: Schema.String;
|
|
5050
5045
|
readonly mediaType: Schema.optional<Schema.String>;
|
|
5051
5046
|
readonly expiresAt: Schema.optional<Schema.Number>;
|
|
5052
|
-
readonly headers: Schema.optional<Schema.$Record<Schema.String, Schema.String>>;
|
|
5053
5047
|
}>, Schema.Struct<{
|
|
5054
5048
|
readonly type: Schema.Literal<"ref">;
|
|
5055
5049
|
readonly provider: Schema.brand<Schema.String, "AI.ProviderID">;
|
|
@@ -44,7 +44,6 @@ export declare const MediaPart: Schema.Struct<{
|
|
|
44
44
|
readonly url: Schema.String;
|
|
45
45
|
readonly mediaType: Schema.optional<Schema.String>;
|
|
46
46
|
readonly expiresAt: Schema.optional<Schema.Number>;
|
|
47
|
-
readonly headers: Schema.optional<Schema.$Record<Schema.String, Schema.String>>;
|
|
48
47
|
}>, Schema.Struct<{
|
|
49
48
|
readonly type: Schema.Literal<"ref">;
|
|
50
49
|
readonly provider: Schema.brand<Schema.String, "AI.ProviderID">;
|
|
@@ -305,7 +304,6 @@ export declare const ContentPart: Schema.toTaggedUnion<"type", readonly [Schema.
|
|
|
305
304
|
readonly url: Schema.String;
|
|
306
305
|
readonly mediaType: Schema.optional<Schema.String>;
|
|
307
306
|
readonly expiresAt: Schema.optional<Schema.Number>;
|
|
308
|
-
readonly headers: Schema.optional<Schema.$Record<Schema.String, Schema.String>>;
|
|
309
307
|
}>, Schema.Struct<{
|
|
310
308
|
readonly type: Schema.Literal<"ref">;
|
|
311
309
|
readonly provider: Schema.brand<Schema.String, "AI.ProviderID">;
|
|
@@ -450,7 +448,6 @@ declare const Message_base: Schema.Class<Message, Schema.Struct<{
|
|
|
450
448
|
readonly url: Schema.String;
|
|
451
449
|
readonly mediaType: Schema.optional<Schema.String>;
|
|
452
450
|
readonly expiresAt: Schema.optional<Schema.Number>;
|
|
453
|
-
readonly headers: Schema.optional<Schema.$Record<Schema.String, Schema.String>>;
|
|
454
451
|
}>, Schema.Struct<{
|
|
455
452
|
readonly type: Schema.Literal<"ref">;
|
|
456
453
|
readonly provider: Schema.brand<Schema.String, "AI.ProviderID">;
|
package/dist/schema/options.d.ts
CHANGED
|
@@ -18,8 +18,9 @@ export declare class HttpOptions extends HttpOptions_base {
|
|
|
18
18
|
}
|
|
19
19
|
export declare namespace HttpOptions {
|
|
20
20
|
type Input = HttpOptions | ConstructorParameters<typeof HttpOptions>[0];
|
|
21
|
-
/** Normalize HTTP option input into the canonical `HttpOptions` class
|
|
22
|
-
|
|
21
|
+
/** Normalize HTTP option input into the canonical `HttpOptions` class; `undefined` stays `undefined`. */
|
|
22
|
+
function make(input: Input): HttpOptions;
|
|
23
|
+
function make(input: Input | undefined): HttpOptions | undefined;
|
|
23
24
|
}
|
|
24
25
|
export declare const mergeHttpOptions: (...items: ReadonlyArray<HttpOptions | undefined>) => HttpOptions | undefined;
|
|
25
26
|
declare const GenerationOptions_base: Schema.Class<GenerationOptions, Schema.Struct<{
|
|
@@ -67,15 +68,18 @@ export declare namespace LanguageModelDefaults {
|
|
|
67
68
|
/** Normalize selected-model request defaults without applying precedence. */
|
|
68
69
|
const make: (input: Input) => LanguageModelDefaults;
|
|
69
70
|
}
|
|
71
|
+
/** Provider-defined string enum: known values for autocomplete, any string accepted. */
|
|
72
|
+
export type OpenString<Known extends string> = Known | (string & {});
|
|
70
73
|
export declare const ReasoningEfforts: readonly ["none", "minimal", "low", "medium", "high", "xhigh", "max"];
|
|
71
|
-
export type ReasoningEffort = (typeof ReasoningEfforts)[number]
|
|
74
|
+
export type ReasoningEffort = OpenString<(typeof ReasoningEfforts)[number]>;
|
|
72
75
|
export declare const ReasoningEffort: Schema.declare<ReasoningEffort, ReasoningEffort>;
|
|
73
|
-
|
|
74
|
-
export
|
|
76
|
+
/** Tool schema sanitizer for a model family. `none` opts out of the protocol and model-name defaults. */
|
|
77
|
+
export declare const LanguageModelSanitizerCompatibility: Schema.Literals<readonly ["gemini", "moonshot", "none"]>;
|
|
78
|
+
export type LanguageModelSanitizerCompatibility = Schema.Schema.Type<typeof LanguageModelSanitizerCompatibility>;
|
|
75
79
|
export declare const LanguageModelMaxTokensFieldCompatibility: Schema.Literals<readonly ["max_completion_tokens", "max_tokens"]>;
|
|
76
80
|
export type LanguageModelMaxTokensFieldCompatibility = Schema.Schema.Type<typeof LanguageModelMaxTokensFieldCompatibility>;
|
|
77
81
|
declare const LanguageModelCompatibility_base: Schema.Class<LanguageModelCompatibility, Schema.Struct<{
|
|
78
|
-
readonly
|
|
82
|
+
readonly sanitizer: Schema.optional<Schema.Literals<readonly ["gemini", "moonshot", "none"]>>;
|
|
79
83
|
readonly reasoningField: Schema.optional<Schema.String>;
|
|
80
84
|
/** Require every assistant message to include its reasoning field, even when empty. */
|
|
81
85
|
readonly requireReasoning: Schema.optional<Schema.Boolean>;
|