@opencode/ai 2.0.16 → 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 +187 -129
- 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 +6 -10
- package/dist/generation.js +17 -20
- package/dist/image-client.d.ts +59 -24
- package/dist/image-client.js +16 -40
- package/dist/image.d.ts +15 -27
- package/dist/image.js +4 -15
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -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 +9 -10
- package/dist/media-model.js +10 -12
- package/dist/media.js +2 -2
- package/dist/promise.d.ts +68 -30
- package/dist/promise.js +52 -31
- 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/anthropic-messages.d.ts +34 -34
- package/dist/protocols/anthropic-messages.js +14 -8
- package/dist/protocols/assemblyai-transcription.d.ts +2 -1
- package/dist/protocols/assemblyai-transcription.js +14 -16
- package/dist/protocols/bedrock-converse.d.ts +7 -0
- package/dist/protocols/bedrock-converse.js +37 -11
- package/dist/protocols/bfl-images.d.ts +7 -1
- package/dist/protocols/bfl-images.js +36 -36
- package/dist/protocols/cartesia-speech.d.ts +18 -2
- package/dist/protocols/cartesia-speech.js +10 -16
- package/dist/protocols/deepgram-speech.d.ts +19 -3
- package/dist/protocols/deepgram-speech.js +11 -12
- package/dist/protocols/deepgram-transcription.d.ts +2 -1
- package/dist/protocols/deepgram-transcription.js +9 -13
- package/dist/protocols/elevenlabs-speech.d.ts +19 -3
- package/dist/protocols/elevenlabs-speech.js +9 -13
- package/dist/protocols/fal-images.d.ts +2 -1
- package/dist/protocols/fal-images.js +30 -40
- package/dist/protocols/fal-video.d.ts +2 -2
- package/dist/protocols/fal-video.js +9 -24
- package/dist/protocols/gemini.d.ts +13 -13
- package/dist/protocols/gemini.js +16 -7
- package/dist/protocols/google-images.d.ts +3 -3
- package/dist/protocols/google-images.js +11 -21
- package/dist/protocols/google-speech.d.ts +16 -0
- package/dist/protocols/google-speech.js +20 -16
- package/dist/protocols/google-transcription.d.ts +2 -1
- package/dist/protocols/google-transcription.js +8 -20
- package/dist/protocols/google-video.d.ts +2 -2
- package/dist/protocols/google-video.js +14 -30
- package/dist/protocols/meta-images.d.ts +3 -4
- package/dist/protocols/meta-images.js +12 -21
- package/dist/protocols/meta-messages.d.ts +5 -5
- package/dist/protocols/meta-responses.js +6 -4
- package/dist/protocols/open-responses.d.ts +4 -3
- package/dist/protocols/open-responses.js +4 -8
- package/dist/protocols/openai-chat.js +3 -4
- package/dist/protocols/openai-images.d.ts +7 -5
- package/dist/protocols/openai-images.js +65 -66
- package/dist/protocols/openai-responses.d.ts +10 -10
- package/dist/protocols/openai-responses.js +31 -30
- package/dist/protocols/openai-speech.d.ts +21 -1
- package/dist/protocols/openai-speech.js +11 -12
- package/dist/protocols/openai-transcription.d.ts +4 -0
- package/dist/protocols/openai-transcription.js +44 -32
- package/dist/protocols/replicate-images.js +11 -17
- package/dist/protocols/runway-video.d.ts +3 -3
- package/dist/protocols/runway-video.js +11 -17
- package/dist/protocols/shared.d.ts +11 -17
- package/dist/protocols/shared.js +11 -40
- package/dist/protocols/stability-images.d.ts +2 -1
- package/dist/protocols/stability-images.js +24 -36
- package/dist/protocols/utils/fal-queue.d.ts +1 -3
- package/dist/protocols/utils/fal-queue.js +4 -6
- package/dist/protocols/utils/media-input.d.ts +15 -1
- package/dist/protocols/utils/media-input.js +22 -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 +3 -3
- package/dist/protocols/utils/speech-stream.js +1 -4
- package/dist/protocols/utils/tool-schema.d.ts +2 -2
- package/dist/protocols/utils/tool-schema.js +29 -9
- package/dist/protocols/xai-images.d.ts +4 -4
- package/dist/protocols/xai-images.js +14 -29
- package/dist/protocols/xai-responses.js +1 -1
- package/dist/protocols/xai-video.js +12 -18
- 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 +7 -1
- package/dist/providers/alibaba.d.ts +1 -1
- 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 +1 -1
- package/dist/providers/assemblyai.js +5 -10
- package/dist/providers/azure.d.ts +4 -4
- package/dist/providers/azure.js +2 -2
- package/dist/providers/black-forest-labs.d.ts +1 -1
- package/dist/providers/black-forest-labs.js +5 -10
- package/dist/providers/cartesia.d.ts +1 -1
- package/dist/providers/cartesia.js +5 -10
- package/dist/providers/cloudflare-ai-gateway.d.ts +14 -14
- package/dist/providers/deepgram.d.ts +1 -1
- package/dist/providers/deepgram.js +6 -12
- package/dist/providers/elevenlabs.d.ts +1 -1
- package/dist/providers/elevenlabs.js +5 -10
- package/dist/providers/fal.d.ts +1 -1
- package/dist/providers/fal.js +5 -12
- package/dist/providers/google-vertex-messages.d.ts +5 -5
- package/dist/providers/google-vertex.d.ts +3 -3
- package/dist/providers/google.d.ts +3 -3
- package/dist/providers/google.js +7 -12
- package/dist/providers/meta.d.ts +8 -8
- package/dist/providers/meta.js +4 -8
- package/dist/providers/minimax.d.ts +5 -5
- package/dist/providers/moonshot.d.ts +5 -5
- package/dist/providers/openai-options.d.ts +3 -9
- package/dist/providers/openai-options.js +4 -7
- package/dist/providers/openai.d.ts +9 -10
- package/dist/providers/openai.js +11 -12
- package/dist/providers/opencode-zen.js +1 -1
- package/dist/providers/openrouter.d.ts +6 -7
- package/dist/providers/openrouter.js +10 -5
- package/dist/providers/replicate.d.ts +1 -1
- package/dist/providers/replicate.js +5 -10
- package/dist/providers/runway.d.ts +1 -1
- package/dist/providers/runway.js +5 -10
- package/dist/providers/stability.d.ts +1 -1
- package/dist/providers/stability.js +6 -11
- package/dist/providers/typesafe-ai.js +1 -1
- package/dist/providers/vercel-ai-gateway.js +1 -1
- package/dist/providers/xai.js +5 -10
- package/dist/providers/zai-coding-plan.d.ts +1 -1
- package/dist/providers/zai.js +4 -8
- package/dist/route/auth.d.ts +1 -1
- package/dist/route/auth.js +14 -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 +10 -1
- package/dist/route/framing.js +45 -5
- package/dist/route/index.d.ts +1 -1
- package/dist/route/media-protocol.d.ts +49 -35
- package/dist/route/media-protocol.js +77 -65
- package/dist/route/media.d.ts +10 -16
- package/dist/route/media.js +46 -62
- package/dist/route/protocol.d.ts +3 -1
- package/dist/schema/options.d.ts +6 -3
- package/dist/schema/options.js +7 -3
- package/dist/speech-client.d.ts +62 -17
- package/dist/speech-client.js +17 -21
- package/dist/speech.d.ts +178 -21
- package/dist/speech.js +13 -8
- package/dist/testing.d.ts +2 -2
- package/dist/transcription-client.d.ts +78 -24
- package/dist/transcription-client.js +9 -40
- package/dist/transcription.d.ts +15 -27
- package/dist/transcription.js +4 -10
- package/dist/utils/json.d.ts +4 -0
- package/dist/utils/json.js +4 -0
- package/dist/utils/media-type.d.ts +2 -1
- package/dist/utils/media-type.js +3 -1
- package/dist/video-client.d.ts +55 -24
- package/dist/video-client.js +16 -36
- package/dist/video.d.ts +18 -26
- package/dist/video.js +15 -16
- package/package.json +3 -3
- 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
package/dist/media-model.d.ts
CHANGED
|
@@ -5,11 +5,11 @@ import type { MediaProtocol } from "./route/media-protocol.js";
|
|
|
5
5
|
import { AIError, HttpOptions, ModelID, ProviderID } from "./schema/index.js";
|
|
6
6
|
/**
|
|
7
7
|
* What every media model carries: ids, the configured route, and deployment `http` overlays. Modality classes
|
|
8
|
-
* (`ImageModel`, `VideoModel`, `SpeechModel`) extend it with their route type and a nominal
|
|
9
|
-
* in for the other in requests.
|
|
8
|
+
* (`ImageModel`, `VideoModel`, `SpeechModel`, `TranscriptionModel`) extend it with their route type and a nominal
|
|
9
|
+
* marker so one cannot stand in for the other in requests.
|
|
10
10
|
*/
|
|
11
11
|
export declare class MediaModel<Route, Options> {
|
|
12
|
-
protected readonly _Options:
|
|
12
|
+
protected readonly _Options: Options;
|
|
13
13
|
readonly id: ModelID;
|
|
14
14
|
readonly provider: ProviderID;
|
|
15
15
|
readonly route: Route;
|
|
@@ -17,6 +17,7 @@ export declare class MediaModel<Route, Options> {
|
|
|
17
17
|
constructor(input: MediaModel.Input<Route>);
|
|
18
18
|
}
|
|
19
19
|
export declare namespace MediaModel {
|
|
20
|
+
type Options = Record<string, unknown>;
|
|
20
21
|
interface Input<Route> {
|
|
21
22
|
readonly id: string | ModelID;
|
|
22
23
|
readonly provider: string | ProviderID;
|
|
@@ -25,20 +26,18 @@ export declare namespace MediaModel {
|
|
|
25
26
|
}
|
|
26
27
|
/** A protocol plus its canonical start path; `ModelInput.baseURL` overrides `baseURL` per deployment. */
|
|
27
28
|
interface RouteInput<Request extends MediaRoute.MediaRequest, Protocol> {
|
|
28
|
-
readonly id: string;
|
|
29
|
-
readonly provider: string | ProviderID;
|
|
30
29
|
readonly protocol: Protocol;
|
|
31
30
|
readonly path: Endpoint.EndpointPart<MediaProtocol.Body, Request>;
|
|
32
31
|
readonly baseURL?: string;
|
|
33
32
|
/** Headers the protocol requires on every call, such as a pinned API version; deployment headers win. */
|
|
34
33
|
readonly headers?: Record<string, string>;
|
|
35
34
|
}
|
|
36
|
-
type
|
|
35
|
+
type InlineRouteInput<Request extends MediaRoute.MediaRequest, Response> = RouteInput<Request, MediaProtocol.Inline<Request, Response>>;
|
|
36
|
+
type StreamRouteInput<Request extends MediaRoute.MediaRequest, Event, Frame, State> = RouteInput<MediaProtocol.Addressed<Request>, MediaProtocol.Streamed<Request, Event, Frame, State>>;
|
|
37
|
+
type QueuedRouteInput<Request extends MediaRoute.MediaRequest, Response, Token> = RouteInput<Request, MediaProtocol.Queued<Request, Response, Token>>;
|
|
38
|
+
type AnyRouteInput<Request extends MediaRoute.MediaRequest, Event, Response, Frame, State, Token> = InlineRouteInput<Request, Response> | StreamRouteInput<Request, Event, Frame, State> | QueuedRouteInput<Request, Response, Token>;
|
|
37
39
|
}
|
|
38
40
|
/** Compose a protocol route input with one deployment through `MediaRoute.inline`, `queued`, or `stream`. */
|
|
39
|
-
export declare const composeRoute: <Request extends MediaRoute.MediaRequest,
|
|
40
|
-
readonly protocol: Protocol;
|
|
41
|
-
}) => Route, route: MediaModel.RouteInput<Request, Protocol>, input: MediaRoute.ModelInput) => Route;
|
|
42
|
-
export declare const composeAnyRoute: <Request extends MediaRoute.MediaRequest, Event, Response, Frame, State, Token>(route: MediaModel.AnyRouteInput<Request, Event, Response, Frame, State, Token>, input: MediaRoute.ModelInput, collect: (events: ReadonlyArray<Event>) => Effect.Effect<Response, AIError>) => MediaRoute.AnyRoute<Request, Event, Response>;
|
|
41
|
+
export declare const composeRoute: <Request extends MediaRoute.MediaRequest, Event, Response, Frame, State, Token>(route: MediaModel.AnyRouteInput<Request, Event, Response, Frame, State, Token>, input: MediaRoute.ModelInput, collect: (events: ReadonlyArray<Event>) => Effect.Effect<Response, AIError>) => MediaRoute.AnyRoute<Request, Event, Response>;
|
|
43
42
|
/** Lift a synchronous Schema-class constructor into a typed `InvalidRequest` failure. */
|
|
44
43
|
export declare const tryRequest: <A>(make: () => A) => Effect.Effect<A, AIError>;
|
package/dist/media-model.js
CHANGED
|
@@ -4,8 +4,8 @@ import { MediaRoute } from "./route/media.js";
|
|
|
4
4
|
import { AIError, HttpOptions, InvalidRequestError, ModelID, ProviderID } from "./schema/index.js";
|
|
5
5
|
/**
|
|
6
6
|
* What every media model carries: ids, the configured route, and deployment `http` overlays. Modality classes
|
|
7
|
-
* (`ImageModel`, `VideoModel`, `SpeechModel`) extend it with their route type and a nominal
|
|
8
|
-
* in for the other in requests.
|
|
7
|
+
* (`ImageModel`, `VideoModel`, `SpeechModel`, `TranscriptionModel`) extend it with their route type and a nominal
|
|
8
|
+
* marker so one cannot stand in for the other in requests.
|
|
9
9
|
*/
|
|
10
10
|
export class MediaModel {
|
|
11
11
|
id;
|
|
@@ -20,21 +20,19 @@ export class MediaModel {
|
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
/** Compose a protocol route input with one deployment through `MediaRoute.inline`, `queued`, or `stream`. */
|
|
23
|
-
export const composeRoute = (
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
export const composeRoute = (route, input, collect) => {
|
|
24
|
+
if (isStreamInput(route))
|
|
25
|
+
return MediaRoute.stream({ ...composition(route, input), collect });
|
|
26
|
+
if (isQueuedInput(route))
|
|
27
|
+
return MediaRoute.queued(composition(route, input));
|
|
28
|
+
return MediaRoute.inline(composition(route, input));
|
|
29
|
+
};
|
|
30
|
+
const composition = (route, input) => ({
|
|
26
31
|
protocol: route.protocol,
|
|
27
32
|
endpoint: Endpoint.path(route.path, { baseURL: input.baseURL ?? route.baseURL }),
|
|
28
33
|
auth: input.auth,
|
|
29
34
|
headers: route.headers === undefined && input.headers === undefined ? undefined : { ...route.headers, ...input.headers },
|
|
30
35
|
});
|
|
31
|
-
export const composeAnyRoute = (route, input, collect) => {
|
|
32
|
-
if (isStreamInput(route))
|
|
33
|
-
return composeRoute((composition) => MediaRoute.stream({ ...composition, collect }), route, input);
|
|
34
|
-
if (isQueuedInput(route))
|
|
35
|
-
return composeRoute(MediaRoute.queued, route, input);
|
|
36
|
-
return composeRoute(MediaRoute.inline, route, input);
|
|
37
|
-
};
|
|
38
36
|
const isStreamInput = (route) => route.protocol.kind === "stream";
|
|
39
37
|
const isQueuedInput = (route) => route.protocol.kind === "queued";
|
|
40
38
|
/** Lift a synchronous Schema-class constructor into a typed `InvalidRequest` failure. */
|
package/dist/media.js
CHANGED
|
@@ -5,7 +5,7 @@ import { ProviderID } from "./schema/ids.js";
|
|
|
5
5
|
import { AIError, HttpContext, InvalidProviderOutputError, InvalidRequestError } from "./schema/errors.js";
|
|
6
6
|
import { ProviderMetadata } from "./schema/options.js";
|
|
7
7
|
import { Service } from "./route/executor-service.js";
|
|
8
|
-
import { detectMediaType,
|
|
8
|
+
import { detectMediaType, fileMediaType } from "./utils/media-type.js";
|
|
9
9
|
export { detectMediaType } from "./utils/media-type.js";
|
|
10
10
|
const OCTET_STREAM = "application/octet-stream";
|
|
11
11
|
// ---------------------------------------------------------------------------
|
|
@@ -215,7 +215,7 @@ export const file = (path, options) => Effect.gen(function* () {
|
|
|
215
215
|
const data = yield* fs
|
|
216
216
|
.readFile(path)
|
|
217
217
|
.pipe(Effect.mapError((cause) => invalid(`Failed to read media file ${path}`, cause)));
|
|
218
|
-
return bytes(data,
|
|
218
|
+
return bytes(data, fileMediaType(data, path), options);
|
|
219
219
|
});
|
|
220
220
|
/** Materialize an asset and write its bytes through `FileSystem`. */
|
|
221
221
|
export const write = (asset, path) => Effect.gen(function* () {
|
package/dist/promise.d.ts
CHANGED
|
@@ -1,40 +1,53 @@
|
|
|
1
1
|
import { Effect, Layer } from "effect";
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
2
|
+
import { AIClient } from "./ai-client.js";
|
|
3
|
+
import type { AwaitOptions, Event, Snapshot } from "./generation.js";
|
|
4
|
+
import { type ImageModel, type ImageRequest, type ImageRequestInput } from "./image.js";
|
|
5
|
+
import { Media } from "./media.js";
|
|
6
6
|
import { RequestExecutor } from "./route/executor.js";
|
|
7
7
|
import { LanguageModel, LLMRequest } from "./schema/index.js";
|
|
8
8
|
import type { RequestInput } from "./llm.js";
|
|
9
|
-
import { SpeechModel, SpeechRequest, type SpeechRequestInput } from "./speech.js";
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import { TranscriptionClient } from "./transcription-client.js";
|
|
13
|
-
import { VideoModel, VideoRequest, type VideoOptions, type VideoRequestInput } from "./video.js";
|
|
14
|
-
import { VideoClient } from "./video-client.js";
|
|
9
|
+
import { type SpeechModel, type SpeechRequest, type SpeechRequestInput } from "./speech.js";
|
|
10
|
+
import { type TranscriptionModel, type TranscriptionRequest, type TranscriptionRequestInput } from "./transcription.js";
|
|
11
|
+
import { type VideoModel, type VideoRequest, type VideoRequestInput } from "./video.js";
|
|
15
12
|
/**
|
|
16
13
|
* Promise-first entrypoint for scripts and non-Effect callers. One `ManagedRuntime` hosts the LLM, image, video, speech,
|
|
17
14
|
* and transcription clients over a request executor; every method runs the corresponding Effect API and rethrows
|
|
18
|
-
* `AIError` unchanged.
|
|
15
|
+
* `AIError` unchanged. `file` and `write` load `node:fs/promises` on first use, so importing this module does not.
|
|
19
16
|
*/
|
|
20
17
|
export interface Options {
|
|
21
|
-
/** Executor layer; defaults to `RequestExecutor.fetchLayer`. Inject a recorder or middleware here. */
|
|
18
|
+
/** Executor layer; defaults to `RequestExecutor.fetchLayer`. Inject a recorder or `RequestExecutor.middleware(fn)` here. */
|
|
22
19
|
readonly layer?: Layer.Layer<RequestExecutor.Service>;
|
|
23
20
|
}
|
|
24
21
|
export interface RunOptions {
|
|
25
22
|
readonly signal?: AbortSignal;
|
|
26
23
|
}
|
|
27
|
-
export type Services =
|
|
28
|
-
/**
|
|
24
|
+
export type Services = AIClient.Services;
|
|
25
|
+
/**
|
|
26
|
+
* Promise view of a `Generation`. Its fields are a snapshot taken when the handle was created; `refresh()` resolves to a
|
|
27
|
+
* new handle rather than updating this one.
|
|
28
|
+
*/
|
|
29
29
|
export type GenerationHandle<Response> = Snapshot & {
|
|
30
30
|
/** Serializable JSON; pass it back to `resume` from another process. */
|
|
31
31
|
readonly token: unknown;
|
|
32
32
|
readonly await: (options?: AwaitOptions & RunOptions) => Promise<Response>;
|
|
33
|
+
/** Status observations until the first terminal one, polling like `await`; abort ends iteration without throwing. */
|
|
34
|
+
readonly events: (options?: AwaitOptions & RunOptions) => AsyncIterable<Event>;
|
|
35
|
+
/** The result without polling; fails when the generation has not completed. */
|
|
36
|
+
readonly result: (options?: RunOptions) => Promise<Response>;
|
|
33
37
|
readonly refresh: (options?: RunOptions) => Promise<GenerationHandle<Response>>;
|
|
34
38
|
readonly cancel: (options?: RunOptions) => Promise<void>;
|
|
35
39
|
};
|
|
36
40
|
export declare const make: (options?: Options) => {
|
|
37
41
|
run: <A, E>(effect: Effect.Effect<A, E, Services>, options?: RunOptions) => Promise<A>;
|
|
42
|
+
/** Decoded asset bytes, downloading `url` sources through the executor. */
|
|
43
|
+
bytes: (asset: Media.Asset, options?: RunOptions) => Promise<Uint8Array<ArrayBufferLike>>;
|
|
44
|
+
base64: (asset: Media.Asset, options?: RunOptions) => Promise<string>;
|
|
45
|
+
/** Pull a `url` asset into owned bytes before the provider URL expires. */
|
|
46
|
+
materialize: (asset: Media.Asset, options?: RunOptions) => Promise<Media.Asset>;
|
|
47
|
+
/** Read a file into an asset like `Media.file`: sniffed media type, then the extension's. */
|
|
48
|
+
file: (path: string, options?: Media.AssetOptions & RunOptions) => Promise<Media.Asset>;
|
|
49
|
+
/** Write an asset's bytes like `Media.write`, downloading `url` sources through the executor. */
|
|
50
|
+
write: (asset: Media.Asset, path: string, options?: RunOptions) => Promise<void>;
|
|
38
51
|
llm: {
|
|
39
52
|
request: <const SelectedLanguageModel extends LanguageModel>(input: RequestInput<SelectedLanguageModel>) => LLMRequest<SelectedLanguageModel>;
|
|
40
53
|
generate: <const Model extends LanguageModel>(input: RequestInput<Model> | LLMRequest, options?: RunOptions) => Promise<import("./index.js").LLMResponse>;
|
|
@@ -209,7 +222,7 @@ export declare const make: (options?: Options) => {
|
|
|
209
222
|
readonly namespace?: string | undefined;
|
|
210
223
|
} | {
|
|
211
224
|
readonly type: "media";
|
|
212
|
-
readonly media:
|
|
225
|
+
readonly media: Media.Asset;
|
|
213
226
|
readonly providerMetadata?: {
|
|
214
227
|
readonly [x: string]: {
|
|
215
228
|
readonly [x: string]: unknown;
|
|
@@ -265,11 +278,11 @@ export declare const make: (options?: Options) => {
|
|
|
265
278
|
} | {
|
|
266
279
|
readonly type: "image-partial";
|
|
267
280
|
readonly index: number;
|
|
268
|
-
readonly image:
|
|
281
|
+
readonly image: Media.Asset;
|
|
269
282
|
} | {
|
|
270
283
|
readonly type: "image";
|
|
271
284
|
readonly index: number;
|
|
272
|
-
readonly image:
|
|
285
|
+
readonly image: Media.Asset;
|
|
273
286
|
} | {
|
|
274
287
|
readonly type: "finish";
|
|
275
288
|
readonly providerMetadata?: {
|
|
@@ -309,13 +322,13 @@ export declare const make: (options?: Options) => {
|
|
|
309
322
|
}[] | undefined;
|
|
310
323
|
}>;
|
|
311
324
|
start: <const Model extends ImageModel>(input: ImageRequestInput<Model> | ImageRequest, options?: RunOptions) => Promise<GenerationHandle<import("./image.js").ImageResponse>>;
|
|
312
|
-
resume:
|
|
325
|
+
resume: (model: ImageModel, token: unknown, options?: RunOptions) => Promise<GenerationHandle<import("./image.js").ImageResponse>>;
|
|
313
326
|
};
|
|
314
327
|
video: {
|
|
315
328
|
request: typeof import("./video.js").request;
|
|
316
329
|
start: <const Model extends VideoModel>(input: VideoRequestInput<Model> | VideoRequest, options?: RunOptions) => Promise<GenerationHandle<import("./video.js").VideoResponse>>;
|
|
317
330
|
generate: <const Model extends VideoModel>(input: VideoRequestInput<Model> | VideoRequest, options?: AwaitOptions & RunOptions) => Promise<import("./video.js").VideoResponse>;
|
|
318
|
-
resume:
|
|
331
|
+
resume: (model: VideoModel, token: unknown, options?: RunOptions) => Promise<GenerationHandle<import("./video.js").VideoResponse>>;
|
|
319
332
|
stream: <const Model extends VideoModel>(input: VideoRequestInput<Model> | VideoRequest, options?: AwaitOptions & RunOptions) => AsyncIterable<{
|
|
320
333
|
readonly id: string;
|
|
321
334
|
readonly type: "generation-queued";
|
|
@@ -327,7 +340,7 @@ export declare const make: (options?: Options) => {
|
|
|
327
340
|
} | {
|
|
328
341
|
readonly type: "video";
|
|
329
342
|
readonly index: number;
|
|
330
|
-
readonly video:
|
|
343
|
+
readonly video: Media.Asset;
|
|
331
344
|
} | {
|
|
332
345
|
readonly type: "finish";
|
|
333
346
|
readonly providerMetadata?: {
|
|
@@ -371,6 +384,14 @@ export declare const make: (options?: Options) => {
|
|
|
371
384
|
request: typeof import("./speech.js").request;
|
|
372
385
|
generate: <const Model extends SpeechModel>(input: SpeechRequestInput<Model> | SpeechRequest, options?: RunOptions) => Promise<import("./speech.js").SpeechResponse>;
|
|
373
386
|
stream: <const Model extends SpeechModel>(input: SpeechRequestInput<Model> | SpeechRequest, options?: RunOptions) => AsyncIterable<{
|
|
387
|
+
readonly id: string;
|
|
388
|
+
readonly type: "generation-queued";
|
|
389
|
+
readonly position?: number | undefined;
|
|
390
|
+
} | {
|
|
391
|
+
readonly id: string;
|
|
392
|
+
readonly type: "generation-progress";
|
|
393
|
+
readonly progress?: number | undefined;
|
|
394
|
+
} | {
|
|
374
395
|
readonly type: "audio-delta";
|
|
375
396
|
readonly chunk: Uint8Array<ArrayBufferLike>;
|
|
376
397
|
} | {
|
|
@@ -382,7 +403,7 @@ export declare const make: (options?: Options) => {
|
|
|
382
403
|
}[];
|
|
383
404
|
} | {
|
|
384
405
|
readonly type: "finish";
|
|
385
|
-
readonly audio:
|
|
406
|
+
readonly audio: Media.Asset;
|
|
386
407
|
readonly providerMetadata?: {
|
|
387
408
|
readonly [x: string]: {
|
|
388
409
|
readonly [x: string]: unknown;
|
|
@@ -497,7 +518,7 @@ export declare const make: (options?: Options) => {
|
|
|
497
518
|
}[] | undefined;
|
|
498
519
|
}>;
|
|
499
520
|
start: <const Model extends TranscriptionModel>(input: TranscriptionRequestInput<Model> | TranscriptionRequest, options?: RunOptions) => Promise<GenerationHandle<import("./transcription.js").TranscriptionResponse>>;
|
|
500
|
-
resume:
|
|
521
|
+
resume: (model: TranscriptionModel, token: unknown, options?: RunOptions) => Promise<GenerationHandle<import("./transcription.js").TranscriptionResponse>>;
|
|
501
522
|
};
|
|
502
523
|
dispose: () => Promise<void>;
|
|
503
524
|
};
|
|
@@ -505,6 +526,15 @@ export type Client = ReturnType<typeof make>;
|
|
|
505
526
|
/** Default client over `RequestExecutor.fetchLayer` for scripts; the runtime builds its layer on first use. */
|
|
506
527
|
export declare const ai: {
|
|
507
528
|
run: <A, E>(effect: Effect.Effect<A, E, Services>, options?: RunOptions) => Promise<A>;
|
|
529
|
+
/** Decoded asset bytes, downloading `url` sources through the executor. */
|
|
530
|
+
bytes: (asset: Media.Asset, options?: RunOptions) => Promise<Uint8Array<ArrayBufferLike>>;
|
|
531
|
+
base64: (asset: Media.Asset, options?: RunOptions) => Promise<string>;
|
|
532
|
+
/** Pull a `url` asset into owned bytes before the provider URL expires. */
|
|
533
|
+
materialize: (asset: Media.Asset, options?: RunOptions) => Promise<Media.Asset>;
|
|
534
|
+
/** Read a file into an asset like `Media.file`: sniffed media type, then the extension's. */
|
|
535
|
+
file: (path: string, options?: Media.AssetOptions & RunOptions) => Promise<Media.Asset>;
|
|
536
|
+
/** Write an asset's bytes like `Media.write`, downloading `url` sources through the executor. */
|
|
537
|
+
write: (asset: Media.Asset, path: string, options?: RunOptions) => Promise<void>;
|
|
508
538
|
llm: {
|
|
509
539
|
request: <const SelectedLanguageModel extends LanguageModel>(input: RequestInput<SelectedLanguageModel>) => LLMRequest<SelectedLanguageModel>;
|
|
510
540
|
generate: <const Model extends LanguageModel>(input: RequestInput<Model> | LLMRequest, options?: RunOptions) => Promise<import("./index.js").LLMResponse>;
|
|
@@ -679,7 +709,7 @@ export declare const ai: {
|
|
|
679
709
|
readonly namespace?: string | undefined;
|
|
680
710
|
} | {
|
|
681
711
|
readonly type: "media";
|
|
682
|
-
readonly media:
|
|
712
|
+
readonly media: Media.Asset;
|
|
683
713
|
readonly providerMetadata?: {
|
|
684
714
|
readonly [x: string]: {
|
|
685
715
|
readonly [x: string]: unknown;
|
|
@@ -735,11 +765,11 @@ export declare const ai: {
|
|
|
735
765
|
} | {
|
|
736
766
|
readonly type: "image-partial";
|
|
737
767
|
readonly index: number;
|
|
738
|
-
readonly image:
|
|
768
|
+
readonly image: Media.Asset;
|
|
739
769
|
} | {
|
|
740
770
|
readonly type: "image";
|
|
741
771
|
readonly index: number;
|
|
742
|
-
readonly image:
|
|
772
|
+
readonly image: Media.Asset;
|
|
743
773
|
} | {
|
|
744
774
|
readonly type: "finish";
|
|
745
775
|
readonly providerMetadata?: {
|
|
@@ -779,13 +809,13 @@ export declare const ai: {
|
|
|
779
809
|
}[] | undefined;
|
|
780
810
|
}>;
|
|
781
811
|
start: <const Model extends ImageModel>(input: ImageRequestInput<Model> | ImageRequest, options?: RunOptions) => Promise<GenerationHandle<import("./image.js").ImageResponse>>;
|
|
782
|
-
resume:
|
|
812
|
+
resume: (model: ImageModel, token: unknown, options?: RunOptions) => Promise<GenerationHandle<import("./image.js").ImageResponse>>;
|
|
783
813
|
};
|
|
784
814
|
video: {
|
|
785
815
|
request: typeof import("./video.js").request;
|
|
786
816
|
start: <const Model extends VideoModel>(input: VideoRequestInput<Model> | VideoRequest, options?: RunOptions) => Promise<GenerationHandle<import("./video.js").VideoResponse>>;
|
|
787
817
|
generate: <const Model extends VideoModel>(input: VideoRequestInput<Model> | VideoRequest, options?: AwaitOptions & RunOptions) => Promise<import("./video.js").VideoResponse>;
|
|
788
|
-
resume:
|
|
818
|
+
resume: (model: VideoModel, token: unknown, options?: RunOptions) => Promise<GenerationHandle<import("./video.js").VideoResponse>>;
|
|
789
819
|
stream: <const Model extends VideoModel>(input: VideoRequestInput<Model> | VideoRequest, options?: AwaitOptions & RunOptions) => AsyncIterable<{
|
|
790
820
|
readonly id: string;
|
|
791
821
|
readonly type: "generation-queued";
|
|
@@ -797,7 +827,7 @@ export declare const ai: {
|
|
|
797
827
|
} | {
|
|
798
828
|
readonly type: "video";
|
|
799
829
|
readonly index: number;
|
|
800
|
-
readonly video:
|
|
830
|
+
readonly video: Media.Asset;
|
|
801
831
|
} | {
|
|
802
832
|
readonly type: "finish";
|
|
803
833
|
readonly providerMetadata?: {
|
|
@@ -841,6 +871,14 @@ export declare const ai: {
|
|
|
841
871
|
request: typeof import("./speech.js").request;
|
|
842
872
|
generate: <const Model extends SpeechModel>(input: SpeechRequestInput<Model> | SpeechRequest, options?: RunOptions) => Promise<import("./speech.js").SpeechResponse>;
|
|
843
873
|
stream: <const Model extends SpeechModel>(input: SpeechRequestInput<Model> | SpeechRequest, options?: RunOptions) => AsyncIterable<{
|
|
874
|
+
readonly id: string;
|
|
875
|
+
readonly type: "generation-queued";
|
|
876
|
+
readonly position?: number | undefined;
|
|
877
|
+
} | {
|
|
878
|
+
readonly id: string;
|
|
879
|
+
readonly type: "generation-progress";
|
|
880
|
+
readonly progress?: number | undefined;
|
|
881
|
+
} | {
|
|
844
882
|
readonly type: "audio-delta";
|
|
845
883
|
readonly chunk: Uint8Array<ArrayBufferLike>;
|
|
846
884
|
} | {
|
|
@@ -852,7 +890,7 @@ export declare const ai: {
|
|
|
852
890
|
}[];
|
|
853
891
|
} | {
|
|
854
892
|
readonly type: "finish";
|
|
855
|
-
readonly audio:
|
|
893
|
+
readonly audio: Media.Asset;
|
|
856
894
|
readonly providerMetadata?: {
|
|
857
895
|
readonly [x: string]: {
|
|
858
896
|
readonly [x: string]: unknown;
|
|
@@ -967,7 +1005,7 @@ export declare const ai: {
|
|
|
967
1005
|
}[] | undefined;
|
|
968
1006
|
}>;
|
|
969
1007
|
start: <const Model extends TranscriptionModel>(input: TranscriptionRequestInput<Model> | TranscriptionRequest, options?: RunOptions) => Promise<GenerationHandle<import("./transcription.js").TranscriptionResponse>>;
|
|
970
|
-
resume:
|
|
1008
|
+
resume: (model: TranscriptionModel, token: unknown, options?: RunOptions) => Promise<GenerationHandle<import("./transcription.js").TranscriptionResponse>>;
|
|
971
1009
|
};
|
|
972
1010
|
dispose: () => Promise<void>;
|
|
973
1011
|
};
|
package/dist/promise.js
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
import { Effect, Layer, ManagedRuntime, Stream } from "effect";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { AIClient } from "./ai-client.js";
|
|
3
|
+
import { Image } from "./image.js";
|
|
4
4
|
import { LLM } from "./index.js";
|
|
5
|
-
import {
|
|
5
|
+
import { Media } from "./media.js";
|
|
6
|
+
import { tryRequest } from "./media-model.js";
|
|
6
7
|
import { RequestExecutor } from "./route/executor.js";
|
|
7
|
-
import { LanguageModel, LLMRequest } from "./schema/index.js";
|
|
8
|
-
import { Speech
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import { Video, VideoModel, VideoRequest } from "./video.js";
|
|
13
|
-
import { VideoClient } from "./video-client.js";
|
|
8
|
+
import { AIError, InvalidRequestError, LanguageModel, LLMRequest } from "./schema/index.js";
|
|
9
|
+
import { Speech } from "./speech.js";
|
|
10
|
+
import { Transcription, } from "./transcription.js";
|
|
11
|
+
import { fileMediaType } from "./utils/media-type.js";
|
|
12
|
+
import { Video } from "./video.js";
|
|
14
13
|
const abortEffect = (signal) => signal === undefined
|
|
15
14
|
? Effect.never
|
|
16
15
|
: Effect.callback((resume) => {
|
|
@@ -23,59 +22,81 @@ const abortEffect = (signal) => signal === undefined
|
|
|
23
22
|
return Effect.sync(() => signal.removeEventListener("abort", onAbort));
|
|
24
23
|
});
|
|
25
24
|
export const make = (options = {}) => {
|
|
26
|
-
const runtime = ManagedRuntime.make(
|
|
27
|
-
/** Run any package Effect (for example `
|
|
25
|
+
const runtime = ManagedRuntime.make(AIClient.layerWith(options.layer ?? RequestExecutor.fetchLayer));
|
|
26
|
+
/** Run any package Effect (for example `LLMClient.compact(...)`) inside this runtime. */
|
|
28
27
|
const run = (effect, options) => runtime.runPromise(effect, { signal: options?.signal });
|
|
29
28
|
const iterate = (stream, options) => Stream.toAsyncIterable(Stream.unwrap(runtime.contextEffect.pipe(Effect.map((context) => stream.pipe(Stream.interruptWhen(abortEffect(options?.signal)), Stream.provideContext(context))))));
|
|
30
29
|
const handle = (generation) => ({
|
|
31
30
|
...generation.snapshot,
|
|
32
31
|
token: generation.token,
|
|
33
32
|
await: (options) => run(generation.await({ poll: options?.poll }), options),
|
|
33
|
+
events: (options) => iterate(generation.events({ poll: options?.poll }), options),
|
|
34
|
+
result: (options) => run(generation.result(), options),
|
|
34
35
|
refresh: (options) => run(generation.refresh(), options).then(handle),
|
|
35
36
|
cancel: (options) => run(generation.cancel(), options),
|
|
36
37
|
});
|
|
37
|
-
|
|
38
|
-
const llmRequest = (input) => (input instanceof LLMRequest ? input : LLM.request(input));
|
|
39
|
-
const imageRequest = (input) => input instanceof ImageRequest ? input : Image.request(input);
|
|
40
|
-
const videoRequest = (input) => input instanceof VideoRequest ? input : Video.request(input);
|
|
41
|
-
const speechRequest = (input) => input instanceof SpeechRequest ? input : Speech.request(input);
|
|
42
|
-
const transcriptionRequest = (input) => input instanceof TranscriptionRequest ? input : Transcription.request(input);
|
|
38
|
+
const llmRequest = (input) => input instanceof LLMRequest ? Effect.succeed(input) : tryRequest(() => LLM.request(input));
|
|
43
39
|
return {
|
|
44
40
|
run,
|
|
41
|
+
/** Decoded asset bytes, downloading `url` sources through the executor. */
|
|
42
|
+
bytes: (asset, options) => run(asset.bytes(), options),
|
|
43
|
+
base64: (asset, options) => run(asset.base64(), options),
|
|
44
|
+
/** Pull a `url` asset into owned bytes before the provider URL expires. */
|
|
45
|
+
materialize: (asset, options) => run(asset.materialize(), options),
|
|
46
|
+
/** Read a file into an asset like `Media.file`: sniffed media type, then the extension's. */
|
|
47
|
+
file: async (path, options) => {
|
|
48
|
+
const { readFile } = await import("node:fs/promises");
|
|
49
|
+
return run(Effect.tryPromise({
|
|
50
|
+
try: (signal) => readFile(path, { signal }),
|
|
51
|
+
catch: (cause) => fileError(`Failed to read media file ${path}`, cause),
|
|
52
|
+
}).pipe(Effect.map((buffer) => {
|
|
53
|
+
const data = new Uint8Array(buffer);
|
|
54
|
+
return Media.bytes(data, fileMediaType(data, path), options);
|
|
55
|
+
})), options);
|
|
56
|
+
},
|
|
57
|
+
/** Write an asset's bytes like `Media.write`, downloading `url` sources through the executor. */
|
|
58
|
+
write: async (asset, path, options) => {
|
|
59
|
+
const { writeFile } = await import("node:fs/promises");
|
|
60
|
+
return run(asset.bytes().pipe(Effect.flatMap((data) => Effect.tryPromise({
|
|
61
|
+
try: (signal) => writeFile(path, data, { signal }),
|
|
62
|
+
catch: (cause) => fileError(`Failed to write media file ${path}`, cause),
|
|
63
|
+
}))), options);
|
|
64
|
+
},
|
|
45
65
|
llm: {
|
|
46
66
|
request: LLM.request,
|
|
47
|
-
generate: (input, options) => run(
|
|
48
|
-
stream: (input, options) => iterate(
|
|
67
|
+
generate: (input, options) => run(Effect.flatMap(llmRequest(input), LLM.generate), options),
|
|
68
|
+
stream: (input, options) => iterate(Stream.unwrap(Effect.map(llmRequest(input), LLM.stream)), options),
|
|
49
69
|
},
|
|
50
70
|
image: {
|
|
51
71
|
request: Image.request,
|
|
52
|
-
generate: (input, options) => run(Image.generate(
|
|
53
|
-
stream: (input, options) => iterate(Image.stream(
|
|
54
|
-
start: (input, options) => run(Image.start(
|
|
72
|
+
generate: (input, options) => run(Image.generate(input, { poll: options?.poll }), options),
|
|
73
|
+
stream: (input, options) => iterate(Image.stream(input, { poll: options?.poll }), options),
|
|
74
|
+
start: (input, options) => run(Image.start(input), options).then(handle),
|
|
55
75
|
resume: (model, token, options) => run(Image.resume(model, token), options).then(handle),
|
|
56
76
|
},
|
|
57
77
|
video: {
|
|
58
78
|
request: Video.request,
|
|
59
|
-
start: (input, options) => run(Video.start(
|
|
60
|
-
generate: (input, options) => run(Video.generate(
|
|
79
|
+
start: (input, options) => run(Video.start(input), options).then(handle),
|
|
80
|
+
generate: (input, options) => run(Video.generate(input, { poll: options?.poll }), options),
|
|
61
81
|
resume: (model, token, options) => run(Video.resume(model, token), options).then(handle),
|
|
62
|
-
stream: (input, options) => iterate(Video.stream(
|
|
82
|
+
stream: (input, options) => iterate(Video.stream(input, { poll: options?.poll }), options),
|
|
63
83
|
},
|
|
64
84
|
speech: {
|
|
65
85
|
request: Speech.request,
|
|
66
|
-
generate: (input, options) => run(Speech.generate(
|
|
67
|
-
stream: (input, options) => iterate(Speech.stream(
|
|
86
|
+
generate: (input, options) => run(Speech.generate(input), options),
|
|
87
|
+
stream: (input, options) => iterate(Speech.stream(input), options),
|
|
68
88
|
},
|
|
69
89
|
transcription: {
|
|
70
90
|
request: Transcription.request,
|
|
71
|
-
generate: (input, options) => run(Transcription.generate(
|
|
72
|
-
stream: (input, options) => iterate(Transcription.stream(
|
|
73
|
-
start: (input, options) => run(Transcription.start(
|
|
91
|
+
generate: (input, options) => run(Transcription.generate(input, { poll: options?.poll }), options),
|
|
92
|
+
stream: (input, options) => iterate(Transcription.stream(input, { poll: options?.poll }), options),
|
|
93
|
+
start: (input, options) => run(Transcription.start(input), options).then(handle),
|
|
74
94
|
resume: (model, token, options) => run(Transcription.resume(model, token), options).then(handle),
|
|
75
95
|
},
|
|
76
96
|
dispose: () => runtime.dispose(),
|
|
77
97
|
};
|
|
78
98
|
};
|
|
99
|
+
const fileError = (message, cause) => new AIError({ reason: new InvalidRequestError({ message, cause }) });
|
|
79
100
|
/** Default client over `RequestExecutor.fetchLayer` for scripts; the runtime builds its layer on first use. */
|
|
80
101
|
export const ai = make();
|
|
81
102
|
export * as AI from "./promise.js";
|
|
@@ -55,7 +55,10 @@ export const protocol = Protocol.make({
|
|
|
55
55
|
return {
|
|
56
56
|
...(yield* OpenAIChat.protocol.body.from(req)),
|
|
57
57
|
enable_thinking: opts.enableThinking,
|
|
58
|
-
|
|
58
|
+
// Alibaba also rejects an explicit budget that is not below `max_completion_tokens`.
|
|
59
|
+
thinking_budget: opts.thinkingBudget === undefined
|
|
60
|
+
? undefined
|
|
61
|
+
: ProviderShared.fitThinkingBudget(opts.thinkingBudget, req.generation?.maxTokens),
|
|
59
62
|
preserve_thinking: opts.preserveThinking,
|
|
60
63
|
clear_thinking: opts.clearThinking,
|
|
61
64
|
thinking: opts.thinking,
|
|
@@ -228,7 +228,7 @@ export declare const protocol: Protocol<{
|
|
|
228
228
|
readonly type: string;
|
|
229
229
|
readonly budget_tokens?: number | undefined;
|
|
230
230
|
} | undefined;
|
|
231
|
-
readonly service_tier?: "auto" |
|
|
231
|
+
readonly service_tier?: import("../schema/options.js").OpenString<"auto" | "standard_only"> | undefined;
|
|
232
232
|
readonly container?: string | {
|
|
233
233
|
readonly id?: string | null | undefined;
|
|
234
234
|
readonly skills?: readonly {
|
|
@@ -22,15 +22,17 @@ export const protocol = Protocol.make({
|
|
|
22
22
|
from: Effect.fn("AlibabaMessages.fromRequest")(function* (req) {
|
|
23
23
|
const opts = yield* ProviderShared.validateWith(Schema.decodeUnknownEffect(Options))(req.providerOptions ?? {});
|
|
24
24
|
// Model Studio accepts enabled thinking without Anthropic's mandatory token budget.
|
|
25
|
+
const body = yield* AnthropicMessages.protocol.body.from(LLMRequest.update(req, {
|
|
26
|
+
providerOptions: { ...req.providerOptions, thinking: undefined },
|
|
27
|
+
}));
|
|
28
|
+
const budget = opts.thinking?.budgetTokens ?? opts.thinking?.budget_tokens;
|
|
25
29
|
return {
|
|
26
|
-
...
|
|
27
|
-
providerOptions: { ...req.providerOptions, thinking: undefined },
|
|
28
|
-
}))),
|
|
30
|
+
...body,
|
|
29
31
|
thinking: opts.thinking === undefined
|
|
30
32
|
? undefined
|
|
31
33
|
: {
|
|
32
34
|
type: opts.thinking.type,
|
|
33
|
-
budget_tokens:
|
|
35
|
+
budget_tokens: budget === undefined ? undefined : ProviderShared.fitThinkingBudget(budget, body.max_tokens),
|
|
34
36
|
},
|
|
35
37
|
};
|
|
36
38
|
}),
|