@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.
Files changed (185) hide show
  1. package/README.md +187 -129
  2. package/dist/ai-client.d.ts +8 -0
  3. package/dist/ai-client.js +12 -0
  4. package/dist/experimental/evaluation-client.d.ts +3 -3
  5. package/dist/experimental/evaluation-client.js +1 -1
  6. package/dist/experimental/evaluation.js +1 -1
  7. package/dist/generation.d.ts +6 -10
  8. package/dist/generation.js +17 -20
  9. package/dist/image-client.d.ts +59 -24
  10. package/dist/image-client.js +16 -40
  11. package/dist/image.d.ts +15 -27
  12. package/dist/image.js +4 -15
  13. package/dist/index.d.ts +2 -1
  14. package/dist/index.js +1 -0
  15. package/dist/llm.d.ts +7 -5
  16. package/dist/llm.js +10 -4
  17. package/dist/media-client.d.ts +30 -0
  18. package/dist/media-client.js +51 -0
  19. package/dist/media-model.d.ts +9 -10
  20. package/dist/media-model.js +10 -12
  21. package/dist/media.js +2 -2
  22. package/dist/promise.d.ts +68 -30
  23. package/dist/promise.js +52 -31
  24. package/dist/protocols/alibaba-chat.js +4 -1
  25. package/dist/protocols/alibaba-messages.d.ts +1 -1
  26. package/dist/protocols/alibaba-messages.js +6 -4
  27. package/dist/protocols/anthropic-messages.d.ts +34 -34
  28. package/dist/protocols/anthropic-messages.js +14 -8
  29. package/dist/protocols/assemblyai-transcription.d.ts +2 -1
  30. package/dist/protocols/assemblyai-transcription.js +14 -16
  31. package/dist/protocols/bedrock-converse.d.ts +7 -0
  32. package/dist/protocols/bedrock-converse.js +37 -11
  33. package/dist/protocols/bfl-images.d.ts +7 -1
  34. package/dist/protocols/bfl-images.js +36 -36
  35. package/dist/protocols/cartesia-speech.d.ts +18 -2
  36. package/dist/protocols/cartesia-speech.js +10 -16
  37. package/dist/protocols/deepgram-speech.d.ts +19 -3
  38. package/dist/protocols/deepgram-speech.js +11 -12
  39. package/dist/protocols/deepgram-transcription.d.ts +2 -1
  40. package/dist/protocols/deepgram-transcription.js +9 -13
  41. package/dist/protocols/elevenlabs-speech.d.ts +19 -3
  42. package/dist/protocols/elevenlabs-speech.js +9 -13
  43. package/dist/protocols/fal-images.d.ts +2 -1
  44. package/dist/protocols/fal-images.js +30 -40
  45. package/dist/protocols/fal-video.d.ts +2 -2
  46. package/dist/protocols/fal-video.js +9 -24
  47. package/dist/protocols/gemini.d.ts +13 -13
  48. package/dist/protocols/gemini.js +16 -7
  49. package/dist/protocols/google-images.d.ts +3 -3
  50. package/dist/protocols/google-images.js +11 -21
  51. package/dist/protocols/google-speech.d.ts +16 -0
  52. package/dist/protocols/google-speech.js +20 -16
  53. package/dist/protocols/google-transcription.d.ts +2 -1
  54. package/dist/protocols/google-transcription.js +8 -20
  55. package/dist/protocols/google-video.d.ts +2 -2
  56. package/dist/protocols/google-video.js +14 -30
  57. package/dist/protocols/meta-images.d.ts +3 -4
  58. package/dist/protocols/meta-images.js +12 -21
  59. package/dist/protocols/meta-messages.d.ts +5 -5
  60. package/dist/protocols/meta-responses.js +6 -4
  61. package/dist/protocols/open-responses.d.ts +4 -3
  62. package/dist/protocols/open-responses.js +4 -8
  63. package/dist/protocols/openai-chat.js +3 -4
  64. package/dist/protocols/openai-images.d.ts +7 -5
  65. package/dist/protocols/openai-images.js +65 -66
  66. package/dist/protocols/openai-responses.d.ts +10 -10
  67. package/dist/protocols/openai-responses.js +31 -30
  68. package/dist/protocols/openai-speech.d.ts +21 -1
  69. package/dist/protocols/openai-speech.js +11 -12
  70. package/dist/protocols/openai-transcription.d.ts +4 -0
  71. package/dist/protocols/openai-transcription.js +44 -32
  72. package/dist/protocols/replicate-images.js +11 -17
  73. package/dist/protocols/runway-video.d.ts +3 -3
  74. package/dist/protocols/runway-video.js +11 -17
  75. package/dist/protocols/shared.d.ts +11 -17
  76. package/dist/protocols/shared.js +11 -40
  77. package/dist/protocols/stability-images.d.ts +2 -1
  78. package/dist/protocols/stability-images.js +24 -36
  79. package/dist/protocols/utils/fal-queue.d.ts +1 -3
  80. package/dist/protocols/utils/fal-queue.js +4 -6
  81. package/dist/protocols/utils/media-input.d.ts +15 -1
  82. package/dist/protocols/utils/media-input.js +22 -0
  83. package/dist/protocols/utils/responses-checkpoint.js +3 -7
  84. package/dist/protocols/utils/responses-compaction.d.ts +3 -1
  85. package/dist/protocols/utils/responses-compaction.js +16 -3
  86. package/dist/protocols/utils/speech-stream.d.ts +3 -3
  87. package/dist/protocols/utils/speech-stream.js +1 -4
  88. package/dist/protocols/utils/tool-schema.d.ts +2 -2
  89. package/dist/protocols/utils/tool-schema.js +29 -9
  90. package/dist/protocols/xai-images.d.ts +4 -4
  91. package/dist/protocols/xai-images.js +14 -29
  92. package/dist/protocols/xai-responses.js +1 -1
  93. package/dist/protocols/xai-video.js +12 -18
  94. package/dist/protocols/zai-images.d.ts +2 -2
  95. package/dist/protocols/zai-images.js +11 -14
  96. package/dist/protocols/zai-messages.d.ts +1 -1
  97. package/dist/provider-error.js +7 -1
  98. package/dist/providers/alibaba.d.ts +1 -1
  99. package/dist/providers/amazon-bedrock.d.ts +2 -0
  100. package/dist/providers/amazon-bedrock.js +1 -0
  101. package/dist/providers/anthropic-compatible.d.ts +5 -5
  102. package/dist/providers/anthropic.d.ts +5 -5
  103. package/dist/providers/assemblyai.d.ts +1 -1
  104. package/dist/providers/assemblyai.js +5 -10
  105. package/dist/providers/azure.d.ts +4 -4
  106. package/dist/providers/azure.js +2 -2
  107. package/dist/providers/black-forest-labs.d.ts +1 -1
  108. package/dist/providers/black-forest-labs.js +5 -10
  109. package/dist/providers/cartesia.d.ts +1 -1
  110. package/dist/providers/cartesia.js +5 -10
  111. package/dist/providers/cloudflare-ai-gateway.d.ts +14 -14
  112. package/dist/providers/deepgram.d.ts +1 -1
  113. package/dist/providers/deepgram.js +6 -12
  114. package/dist/providers/elevenlabs.d.ts +1 -1
  115. package/dist/providers/elevenlabs.js +5 -10
  116. package/dist/providers/fal.d.ts +1 -1
  117. package/dist/providers/fal.js +5 -12
  118. package/dist/providers/google-vertex-messages.d.ts +5 -5
  119. package/dist/providers/google-vertex.d.ts +3 -3
  120. package/dist/providers/google.d.ts +3 -3
  121. package/dist/providers/google.js +7 -12
  122. package/dist/providers/meta.d.ts +8 -8
  123. package/dist/providers/meta.js +4 -8
  124. package/dist/providers/minimax.d.ts +5 -5
  125. package/dist/providers/moonshot.d.ts +5 -5
  126. package/dist/providers/openai-options.d.ts +3 -9
  127. package/dist/providers/openai-options.js +4 -7
  128. package/dist/providers/openai.d.ts +9 -10
  129. package/dist/providers/openai.js +11 -12
  130. package/dist/providers/opencode-zen.js +1 -1
  131. package/dist/providers/openrouter.d.ts +6 -7
  132. package/dist/providers/openrouter.js +10 -5
  133. package/dist/providers/replicate.d.ts +1 -1
  134. package/dist/providers/replicate.js +5 -10
  135. package/dist/providers/runway.d.ts +1 -1
  136. package/dist/providers/runway.js +5 -10
  137. package/dist/providers/stability.d.ts +1 -1
  138. package/dist/providers/stability.js +6 -11
  139. package/dist/providers/typesafe-ai.js +1 -1
  140. package/dist/providers/vercel-ai-gateway.js +1 -1
  141. package/dist/providers/xai.js +5 -10
  142. package/dist/providers/zai-coding-plan.d.ts +1 -1
  143. package/dist/providers/zai.js +4 -8
  144. package/dist/route/auth.d.ts +1 -1
  145. package/dist/route/auth.js +14 -13
  146. package/dist/route/client.d.ts +9 -7
  147. package/dist/route/client.js +6 -8
  148. package/dist/route/endpoint.d.ts +1 -0
  149. package/dist/route/endpoint.js +2 -2
  150. package/dist/route/executor-service.d.ts +4 -2
  151. package/dist/route/executor-service.js +2 -1
  152. package/dist/route/executor.d.ts +3 -1
  153. package/dist/route/executor.js +7 -0
  154. package/dist/route/framing.d.ts +10 -1
  155. package/dist/route/framing.js +45 -5
  156. package/dist/route/index.d.ts +1 -1
  157. package/dist/route/media-protocol.d.ts +49 -35
  158. package/dist/route/media-protocol.js +77 -65
  159. package/dist/route/media.d.ts +10 -16
  160. package/dist/route/media.js +46 -62
  161. package/dist/route/protocol.d.ts +3 -1
  162. package/dist/schema/options.d.ts +6 -3
  163. package/dist/schema/options.js +7 -3
  164. package/dist/speech-client.d.ts +62 -17
  165. package/dist/speech-client.js +17 -21
  166. package/dist/speech.d.ts +178 -21
  167. package/dist/speech.js +13 -8
  168. package/dist/testing.d.ts +2 -2
  169. package/dist/transcription-client.d.ts +78 -24
  170. package/dist/transcription-client.js +9 -40
  171. package/dist/transcription.d.ts +15 -27
  172. package/dist/transcription.js +4 -10
  173. package/dist/utils/json.d.ts +4 -0
  174. package/dist/utils/json.js +4 -0
  175. package/dist/utils/media-type.d.ts +2 -1
  176. package/dist/utils/media-type.js +3 -1
  177. package/dist/video-client.d.ts +55 -24
  178. package/dist/video-client.js +16 -36
  179. package/dist/video.d.ts +18 -26
  180. package/dist/video.js +15 -16
  181. package/package.json +3 -3
  182. package/dist/protocols/utils/meta-image.d.ts +0 -2
  183. package/dist/protocols/utils/meta-image.js +0 -13
  184. package/dist/protocols/utils/openai-image.d.ts +0 -5
  185. package/dist/protocols/utils/openai-image.js +0 -18
@@ -1,44 +1,13 @@
1
- import { Context, Effect, Layer, Stream } from "effect";
2
- import { RequestExecutor } from "./route/executor.js";
3
- import { MediaRoute } from "./route/media.js";
4
- import { responseEvents, } from "./transcription.js";
5
- export class Service extends Context.Service()("@opencode/TranscriptionClient") {
1
+ import { Context } from "effect";
2
+ import { MediaClient } from "./media-client.js";
3
+ import { TranscriptionFinishEvent, } from "./transcription.js";
4
+ export class TranscriptionClientService extends Context.Service()("@opencode/TranscriptionClient") {
6
5
  }
7
- export const generate = (request, options) => Effect.gen(function* () {
8
- const client = yield* Service;
9
- return yield* client.generate(request, options);
10
- });
11
- export const stream = (request, options) => Stream.unwrap(Effect.gen(function* () {
12
- const client = yield* Service;
13
- return client.stream(request, options);
14
- }));
15
- export const start = (request) => Effect.gen(function* () {
16
- const client = yield* Service;
17
- return yield* client.start(request);
18
- });
19
- export const resume = (model, token) => Effect.gen(function* () {
20
- const client = yield* Service;
21
- return yield* client.resume(model, token);
22
- });
23
- export const layer = Layer.effect(Service, Effect.gen(function* () {
24
- const executor = yield* RequestExecutor.Service;
25
- const dispatch = MediaRoute.dispatch({
26
- modality: "transcription",
27
- execute: executor.execute,
28
- responseEvents,
29
- });
30
- return Service.of({
31
- start: (request) => dispatch.start(request.model.route, request),
32
- resume: (model, token) => dispatch.resume(model.route, model, token),
33
- generate: (request, options) => dispatch.generate(request.model.route, request, options),
34
- stream: (request, options) => dispatch.stream(request.model.route, request, options),
35
- });
36
- }));
6
+ export const Service = TranscriptionClientService;
37
7
  export const TranscriptionClient = {
38
8
  Service,
39
- layer,
40
- generate,
41
- stream,
42
- start,
43
- resume,
9
+ ...MediaClient.make(Service, {
10
+ modality: "transcription",
11
+ responseEvents: (response) => [TranscriptionFinishEvent.make({ ...response })],
12
+ }),
44
13
  };
@@ -3,30 +3,22 @@ import { Generation, type AwaitOptions } from "./generation.js";
3
3
  import { Media } from "./media.js";
4
4
  import { MediaModel } from "./media-model.js";
5
5
  import { MediaRoute } from "./route/media.js";
6
- import type { MediaProtocol } from "./route/media-protocol.js";
7
6
  import { AIError, HttpOptions } from "./schema/index.js";
8
7
  import { Service } from "./transcription-client.js";
9
- export type TranscriptionOptions = Record<string, unknown>;
10
- export type TranscriptionRoute<Options extends TranscriptionOptions = TranscriptionOptions> = MediaRoute.AnyRoute<TranscriptionRequestFor<Options>, TranscriptionEvent, TranscriptionResponse>;
11
- export declare class TranscriptionModel<Options extends TranscriptionOptions = TranscriptionOptions> extends MediaModel<TranscriptionRoute<Options>, Options> {
8
+ export type TranscriptionOptions = MediaModel.Options;
9
+ export type TranscriptionRoute = MediaRoute.AnyRoute<TranscriptionRequestFor, TranscriptionEvent, TranscriptionResponse>;
10
+ export declare class TranscriptionModel<Options extends TranscriptionOptions = TranscriptionOptions> extends MediaModel<TranscriptionRoute, Options> {
12
11
  protected readonly _TranscriptionModel: void;
13
- static make<Options extends TranscriptionOptions = TranscriptionOptions>(input: MediaModel.Input<TranscriptionRoute<Options>>): TranscriptionModel<Options>;
14
12
  /** The number of type arguments selects the kind: `<Options>`, `<Options, Frame, State>`, or `<Options, Token>`. */
15
- static fromRoute<Options extends TranscriptionOptions>(route: TranscriptionModel.InlineRouteInput<Options>, input: MediaRoute.ModelInput): TranscriptionModel<Options>;
16
- static fromRoute<Options extends TranscriptionOptions, Frame, State>(route: TranscriptionModel.StreamRouteInput<Options, Frame, State>, input: MediaRoute.ModelInput): TranscriptionModel<Options>;
17
- static fromRoute<Options extends TranscriptionOptions, Token>(route: TranscriptionModel.QueuedRouteInput<Options, Token>, input: MediaRoute.ModelInput): TranscriptionModel<Options>;
13
+ static fromRoute<Options extends TranscriptionOptions>(route: MediaModel.InlineRouteInput<TranscriptionRequestFor<Options>, TranscriptionResponse>, input: MediaRoute.ModelInput): TranscriptionModel<Options>;
14
+ static fromRoute<Options extends TranscriptionOptions, Frame, State>(route: MediaModel.StreamRouteInput<TranscriptionRequestFor<Options>, TranscriptionEvent, Frame, State>, input: MediaRoute.ModelInput): TranscriptionModel<Options>;
15
+ static fromRoute<Options extends TranscriptionOptions, Token>(route: MediaModel.QueuedRouteInput<TranscriptionRequestFor<Options>, TranscriptionResponse, Token>, input: MediaRoute.ModelInput): TranscriptionModel<Options>;
18
16
  }
19
- export declare namespace TranscriptionModel {
20
- type InlineRouteInput<Options extends TranscriptionOptions = TranscriptionOptions> = MediaModel.RouteInput<TranscriptionRequestFor<Options>, MediaProtocol.Inline<TranscriptionRequestFor<Options>, TranscriptionResponse>>;
21
- type StreamRouteInput<Options extends TranscriptionOptions = TranscriptionOptions, Frame = unknown, State = unknown> = MediaModel.RouteInput<MediaProtocol.Addressed<TranscriptionRequestFor<Options>>, MediaProtocol.Streamed<TranscriptionRequestFor<Options>, TranscriptionEvent, Frame, State>>;
22
- type QueuedRouteInput<Options extends TranscriptionOptions = TranscriptionOptions, Token = unknown> = MediaModel.RouteInput<TranscriptionRequestFor<Options>, MediaProtocol.Queued<TranscriptionRequestFor<Options>, TranscriptionResponse, Token>>;
23
- type RouteInput<Options extends TranscriptionOptions = TranscriptionOptions, Frame = unknown, State = unknown, Token = unknown> = MediaModel.AnyRouteInput<TranscriptionRequestFor<Options>, TranscriptionEvent, TranscriptionResponse, Frame, State, Token>;
24
- }
25
- export declare const TranscriptionModelSchema: Schema.declare<TranscriptionModel<TranscriptionOptions>, TranscriptionModel<TranscriptionOptions>>;
17
+ export declare const TranscriptionModelSchema: Schema.declare<TranscriptionModel<MediaModel.Options>, TranscriptionModel<MediaModel.Options>>;
26
18
  export declare const TranscriptionTimestamps: Schema.Literals<readonly ["none", "segment", "word"]>;
27
19
  export type TranscriptionTimestamps = Schema.Schema.Type<typeof TranscriptionTimestamps>;
28
20
  declare const TranscriptionRequest_base: Schema.Class<TranscriptionRequest, Schema.Struct<{
29
- readonly model: Schema.declare<TranscriptionModel<TranscriptionOptions>, TranscriptionModel<TranscriptionOptions>>;
21
+ readonly model: Schema.declare<TranscriptionModel<MediaModel.Options>, TranscriptionModel<MediaModel.Options>>;
30
22
  readonly audio: Schema.decodeTo<Schema.declare<Media.Asset, Media.Asset>, Schema.Struct<{
31
23
  readonly source: Schema.Union<readonly [Schema.Struct<{
32
24
  readonly type: Schema.Literal<"bytes">;
@@ -1012,7 +1004,7 @@ export declare const TranscriptionEvent: Schema.Union<readonly [Schema.Struct<{
1012
1004
  readonly confidence?: number | undefined;
1013
1005
  }[] | undefined;
1014
1006
  }) => any) | undefined;
1015
- } & { [K in Exclude<keyof Cases, "finish" | "text-delta" | "generation-queued" | "generation-progress" | "segment">]: never; }, OrElse extends (value: Exclude<{
1007
+ } & { [K in Exclude<keyof Cases, "finish" | "generation-queued" | "generation-progress" | "text-delta" | "segment">]: never; }, OrElse extends (value: Exclude<{
1016
1008
  readonly id: string;
1017
1009
  readonly type: "generation-queued";
1018
1010
  readonly position?: number | undefined;
@@ -1245,7 +1237,7 @@ export declare const TranscriptionEvent: Schema.Union<readonly [Schema.Struct<{
1245
1237
  readonly confidence?: number | undefined;
1246
1238
  }[] | undefined;
1247
1239
  }) => any) | undefined;
1248
- } & { [K in Exclude<keyof Cases, "finish" | "text-delta" | "generation-queued" | "generation-progress" | "segment">]: never; }, OrElse extends (value: Exclude<{
1240
+ } & { [K in Exclude<keyof Cases, "finish" | "generation-queued" | "generation-progress" | "text-delta" | "segment">]: never; }, OrElse extends (value: Exclude<{
1249
1241
  readonly id: string;
1250
1242
  readonly type: "generation-queued";
1251
1243
  readonly position?: number | undefined;
@@ -1483,22 +1475,18 @@ export declare const TranscriptionEvent: Schema.Union<readonly [Schema.Struct<{
1483
1475
  };
1484
1476
  };
1485
1477
  export type TranscriptionEvent = Schema.Schema.Type<typeof transcriptionEventTagged>;
1486
- export declare const responseEvents: (response: TranscriptionResponse) => ReadonlyArray<TranscriptionEvent>;
1487
1478
  export declare function request<const Model extends TranscriptionModel>(input: TranscriptionRequestInput<Model>): TranscriptionRequestFor<TranscriptionModelOptions<Model>>;
1488
1479
  export declare function request(input: TranscriptionRequest): TranscriptionRequest;
1489
- export declare function generate<const Model extends TranscriptionModel>(input: TranscriptionRequestInput<Model>, options?: AwaitOptions): Effect.Effect<TranscriptionResponse, AIError, Service>;
1490
- export declare function generate(input: TranscriptionRequest, options?: AwaitOptions): Effect.Effect<TranscriptionResponse, AIError, Service>;
1491
- export declare function stream<const Model extends TranscriptionModel>(input: TranscriptionRequestInput<Model>, options?: AwaitOptions): Stream.Stream<TranscriptionEvent, AIError, Service>;
1492
- export declare function stream(input: TranscriptionRequest, options?: AwaitOptions): Stream.Stream<TranscriptionEvent, AIError, Service>;
1480
+ export declare function generate<const Model extends TranscriptionModel>(input: TranscriptionRequest | TranscriptionRequestInput<Model>, options?: AwaitOptions): Effect.Effect<TranscriptionResponse, AIError, Service>;
1481
+ export declare function stream<const Model extends TranscriptionModel>(input: TranscriptionRequest | TranscriptionRequestInput<Model>, options?: AwaitOptions): Stream.Stream<TranscriptionEvent, AIError, Service>;
1493
1482
  /** Inline and streaming routes fail with `UnsupportedOperation`. */
1494
- export declare function start<const Model extends TranscriptionModel>(input: TranscriptionRequestInput<Model>): Effect.Effect<Generation<TranscriptionResponse>, AIError, Service>;
1495
- export declare function start(input: TranscriptionRequest): Effect.Effect<Generation<TranscriptionResponse>, AIError, Service>;
1496
- export declare const resume: <Options extends TranscriptionOptions>(model: TranscriptionModel<Options>, token: unknown) => Effect.Effect<Generation<TranscriptionResponse>, AIError, Service>;
1483
+ export declare function start<const Model extends TranscriptionModel>(input: TranscriptionRequest | TranscriptionRequestInput<Model>): Effect.Effect<Generation<TranscriptionResponse>, AIError, Service>;
1484
+ export declare const resume: (model: TranscriptionModel, token: unknown) => Effect.Effect<Generation<TranscriptionResponse>, AIError, Service>;
1497
1485
  export declare const Transcription: {
1498
1486
  readonly request: typeof request;
1499
1487
  readonly generate: typeof generate;
1500
1488
  readonly stream: typeof stream;
1501
1489
  readonly start: typeof start;
1502
- readonly resume: <Options extends TranscriptionOptions>(model: TranscriptionModel<Options>, token: unknown) => Effect.Effect<Generation<TranscriptionResponse>, AIError, Service>;
1490
+ readonly resume: (model: TranscriptionModel, token: unknown) => Effect.Effect<Generation<TranscriptionResponse>, AIError, Service>;
1503
1491
  };
1504
1492
  export {};
@@ -1,20 +1,17 @@
1
1
  import { Effect, Schema, Stream } from "effect";
2
2
  import { Generation, ProgressEvent, QueuedEvent } from "./generation.js";
3
3
  import { Media } from "./media.js";
4
- import { MediaModel, composeAnyRoute, tryRequest } from "./media-model.js";
4
+ import { MediaModel, composeRoute, tryRequest } from "./media-model.js";
5
5
  import { MediaRoute } from "./route/media.js";
6
6
  import { AIError, HttpOptions, MediaUsage, ProviderMetadata } from "./schema/index.js";
7
7
  import { TranscriptionClient, Service } from "./transcription-client.js";
8
8
  export class TranscriptionModel extends MediaModel {
9
- static make(input) {
10
- return new TranscriptionModel(input);
11
- }
12
9
  static fromRoute(route, input) {
13
10
  return new TranscriptionModel({
14
11
  id: input.id,
15
- provider: route.provider,
12
+ provider: route.protocol.provider,
16
13
  http: input.http,
17
- route: composeAnyRoute(route, input, collectResponse),
14
+ route: composeRoute(route, input, collectResponse),
18
15
  });
19
16
  }
20
17
  }
@@ -94,9 +91,6 @@ export const TranscriptionEvent = Object.assign(transcriptionEventTagged, {
94
91
  finish: transcriptionEventTagged.guards.finish,
95
92
  },
96
93
  });
97
- export const responseEvents = (response) => [
98
- TranscriptionFinishEvent.make({ ...response }),
99
- ];
100
94
  const collectResponse = (events) => {
101
95
  const finish = events.find(TranscriptionEvent.is.finish);
102
96
  // Every transcription protocol's `finish` emits the terminal event or fails, so a completed stream always has one.
@@ -110,7 +104,7 @@ export function request(input) {
110
104
  return input;
111
105
  return new TranscriptionRequest({
112
106
  ...input,
113
- http: input.http === undefined ? undefined : HttpOptions.make(input.http),
107
+ http: HttpOptions.make(input.http),
114
108
  });
115
109
  }
116
110
  const requestEffect = (input) => tryRequest(() => request(input));
@@ -0,0 +1,4 @@
1
+ import { Schema } from "effect";
2
+ export declare const Json: Schema.fromJsonString<Schema.Unknown>;
3
+ export declare const decodeJson: (input: unknown, options?: import("effect/SchemaAST").ParseOptions) => unknown;
4
+ export declare const encodeJson: (input: unknown, options?: import("effect/SchemaAST").ParseOptions) => string;
@@ -0,0 +1,4 @@
1
+ import { Schema } from "effect";
2
+ export const Json = Schema.fromJsonString(Schema.Unknown);
3
+ export const decodeJson = Schema.decodeUnknownSync(Json);
4
+ export const encodeJson = Schema.encodeSync(Json);
@@ -3,5 +3,6 @@
3
3
  * `undefined` so callers can fall back to a provider-declared type or `application/octet-stream`.
4
4
  */
5
5
  export declare const detectMediaType: (bytes: Uint8Array) => string | undefined;
6
- export declare const extensionMediaType: (path: string) => string | undefined;
6
+ /** Media type of a file's contents: sniffed magic bytes, then the path's extension. */
7
+ export declare const fileMediaType: (bytes: Uint8Array, path: string) => string | undefined;
7
8
  export declare const mediaTypeExtension: (mediaType: string) => string | undefined;
@@ -54,7 +54,9 @@ const EXTENSIONS = {
54
54
  md: "text/markdown",
55
55
  csv: "text/csv",
56
56
  };
57
- export const extensionMediaType = (path) => EXTENSIONS[path.slice(path.lastIndexOf(".") + 1).toLowerCase()];
57
+ const extensionMediaType = (path) => EXTENSIONS[path.slice(path.lastIndexOf(".") + 1).toLowerCase()];
58
+ /** Media type of a file's contents: sniffed magic bytes, then the path's extension. */
59
+ export const fileMediaType = (bytes, path) => detectMediaType(bytes) ?? extensionMediaType(path);
58
60
  const EXTENSION_ALIASES = {
59
61
  "audio/mp3": "mp3",
60
62
  "audio/m4a": "m4a",
@@ -1,28 +1,59 @@
1
- import { Context, Effect, Layer, Stream } from "effect";
2
- import { type AwaitOptions, type Generation } from "./generation.js";
3
- import { RequestExecutor } from "./route/executor.js";
4
- import type { AIError } from "./schema/index.js";
5
- import { type VideoEvent, type VideoModel, type VideoOptions, type VideoRequestFor, type VideoResponse } from "./video.js";
6
- export interface Interface {
7
- readonly start: <Options extends VideoOptions>(request: VideoRequestFor<Options>) => Effect.Effect<Generation<VideoResponse>, AIError>;
8
- readonly resume: <Options extends VideoOptions>(model: VideoModel<Options>, token: unknown) => Effect.Effect<Generation<VideoResponse>, AIError>;
9
- readonly generate: <Options extends VideoOptions>(request: VideoRequestFor<Options>, options?: AwaitOptions) => Effect.Effect<VideoResponse, AIError>;
10
- readonly stream: <Options extends VideoOptions>(request: VideoRequestFor<Options>, options?: AwaitOptions) => Stream.Stream<VideoEvent, AIError>;
1
+ import { Context } from "effect";
2
+ import { MediaClient } from "./media-client.js";
3
+ import { type VideoEvent, type VideoRequestFor, type VideoResponse } from "./video.js";
4
+ export type Interface = MediaClient.Interface<VideoRequestFor, VideoEvent, VideoResponse>;
5
+ declare const VideoClientService_base: Context.ServiceClass<VideoClientService, "@opencode/VideoClient", Interface>;
6
+ export declare class VideoClientService extends VideoClientService_base {
11
7
  }
12
- declare const Service_base: Context.ServiceClass<Service, "@opencode/VideoClient", Interface>;
13
- export declare class Service extends Service_base {
14
- }
15
- export declare const start: <Options extends VideoOptions>(request: VideoRequestFor<Options>) => Effect.Effect<Generation<VideoResponse>, AIError, Service>;
16
- export declare const resume: <Options extends VideoOptions>(model: VideoModel<Options>, token: unknown) => Effect.Effect<Generation<VideoResponse>, AIError, Service>;
17
- export declare const generate: <Options extends VideoOptions>(request: VideoRequestFor<Options>, options?: AwaitOptions) => Effect.Effect<VideoResponse, AIError, Service>;
18
- export declare const stream: <Options extends VideoOptions>(request: VideoRequestFor<Options>, options?: AwaitOptions) => Stream.Stream<VideoEvent, AIError, Service>;
19
- export declare const layer: Layer.Layer<Service, never, RequestExecutor.Service>;
8
+ export declare const Service: typeof VideoClientService;
9
+ export type Service = VideoClientService;
20
10
  export declare const VideoClient: {
21
- readonly Service: typeof Service;
22
- readonly layer: Layer.Layer<Service, never, RequestExecutor.Service>;
23
- readonly start: <Options extends VideoOptions>(request: VideoRequestFor<Options>) => Effect.Effect<Generation<VideoResponse>, AIError, Service>;
24
- readonly resume: <Options extends VideoOptions>(model: VideoModel<Options>, token: unknown) => Effect.Effect<Generation<VideoResponse>, AIError, Service>;
25
- readonly generate: <Options extends VideoOptions>(request: VideoRequestFor<Options>, options?: AwaitOptions) => Effect.Effect<VideoResponse, AIError, Service>;
26
- readonly stream: <Options extends VideoOptions>(request: VideoRequestFor<Options>, options?: AwaitOptions) => Stream.Stream<VideoEvent, AIError, Service>;
11
+ readonly layer: import("effect/Layer").Layer<VideoClientService, never, import("./route/executor-service.js").RequestExecutorService>;
12
+ readonly generate: (request: VideoRequestFor, options?: import("./generation.js").AwaitOptions) => import("effect/Effect").Effect<VideoResponse, import("./index.js").AIError, VideoClientService>;
13
+ readonly stream: (request: VideoRequestFor, options?: import("./generation.js").AwaitOptions) => import("effect/Stream").Stream<import("./generation.js").Observation | {
14
+ readonly type: "video";
15
+ readonly index: number;
16
+ readonly video: import("./media.js").Asset;
17
+ } | {
18
+ readonly type: "finish";
19
+ readonly providerMetadata?: {
20
+ readonly [x: string]: {
21
+ readonly [x: string]: unknown;
22
+ };
23
+ } | undefined;
24
+ readonly usage?: {
25
+ readonly type: "tokens";
26
+ readonly input?: number | undefined;
27
+ readonly output?: number | undefined;
28
+ readonly total?: number | undefined;
29
+ readonly details?: {
30
+ readonly [x: string]: unknown;
31
+ } | undefined;
32
+ } | {
33
+ readonly type: "seconds";
34
+ readonly seconds: number;
35
+ } | {
36
+ readonly type: "characters";
37
+ readonly characters: number;
38
+ } | {
39
+ readonly type: "credits";
40
+ readonly credits: number;
41
+ } | {
42
+ readonly type: "compute";
43
+ readonly seconds: number;
44
+ } | undefined;
45
+ readonly notices?: readonly {
46
+ readonly type: "other" | "moderated" | "filtered";
47
+ readonly message: string;
48
+ readonly providerMetadata?: {
49
+ readonly [x: string]: {
50
+ readonly [x: string]: unknown;
51
+ };
52
+ } | undefined;
53
+ }[] | undefined;
54
+ }, import("./index.js").AIError, VideoClientService>;
55
+ readonly start: (request: VideoRequestFor) => import("effect/Effect").Effect<import("./generation.js").Generation<VideoResponse>, import("./index.js").AIError, VideoClientService>;
56
+ readonly resume: (model: import("./video.js").VideoModel<import("./media-model.js").MediaModel.Options>, token: unknown) => import("effect/Effect").Effect<import("./generation.js").Generation<VideoResponse>, import("./index.js").AIError, VideoClientService>;
57
+ readonly Service: typeof VideoClientService;
27
58
  };
28
59
  export {};
@@ -1,40 +1,20 @@
1
- import { Context, Effect, Layer, Stream } from "effect";
2
- import { resultEvents } from "./generation.js";
3
- import { RequestExecutor } from "./route/executor.js";
4
- import { responseEvents, } from "./video.js";
5
- export class Service extends Context.Service()("@opencode/VideoClient") {
1
+ import { Context } from "effect";
2
+ import { MediaClient } from "./media-client.js";
3
+ import { VideoOutputEvent, VideoFinishEvent, } from "./video.js";
4
+ export class VideoClientService extends Context.Service()("@opencode/VideoClient") {
6
5
  }
7
- export const start = (request) => Effect.gen(function* () {
8
- const client = yield* Service;
9
- return yield* client.start(request);
10
- });
11
- export const resume = (model, token) => Effect.gen(function* () {
12
- const client = yield* Service;
13
- return yield* client.resume(model, token);
14
- });
15
- export const generate = (request, options) => Effect.gen(function* () {
16
- const client = yield* Service;
17
- return yield* client.generate(request, options);
18
- });
19
- export const stream = (request, options) => Stream.unwrap(Effect.gen(function* () {
20
- const client = yield* Service;
21
- return client.stream(request, options);
22
- }));
23
- export const layer = Layer.effect(Service, Effect.gen(function* () {
24
- const executor = yield* RequestExecutor.Service;
25
- const start = (request) => request.model.route.start(request, executor.execute);
26
- return Service.of({
27
- start,
28
- resume: (model, token) => model.route.resume(model, token, executor.execute),
29
- generate: (request, options) => start(request).pipe(Effect.flatMap((generation) => generation.await(options))),
30
- stream: (request, options) => Stream.unwrap(start(request).pipe(Effect.map((generation) => resultEvents(generation, responseEvents, options)))),
31
- });
32
- }));
6
+ export const Service = VideoClientService;
33
7
  export const VideoClient = {
34
8
  Service,
35
- layer,
36
- start,
37
- resume,
38
- generate,
39
- stream,
9
+ ...MediaClient.make(Service, {
10
+ modality: "video",
11
+ responseEvents: (response) => [
12
+ ...response.videos.map((video, index) => VideoOutputEvent.make({ index, video })),
13
+ VideoFinishEvent.make({
14
+ usage: response.usage,
15
+ notices: response.notices,
16
+ providerMetadata: response.providerMetadata,
17
+ }),
18
+ ],
19
+ }),
40
20
  };
package/dist/video.d.ts CHANGED
@@ -3,24 +3,21 @@ import { Generation, type AwaitOptions } from "./generation.js";
3
3
  import { Media } from "./media.js";
4
4
  import { MediaModel } from "./media-model.js";
5
5
  import { MediaRoute } from "./route/media.js";
6
- import type { MediaProtocol } from "./route/media-protocol.js";
7
- import { AIError, HttpOptions } from "./schema/index.js";
6
+ import { AIError, HttpOptions, type OpenString } from "./schema/index.js";
8
7
  import { Service } from "./video-client.js";
9
- export type VideoOptions = Record<string, unknown>;
10
- export type VideoRoute<Options extends VideoOptions = VideoOptions> = MediaRoute.QueuedRoute<VideoRequestFor<Options>, VideoResponse>;
11
- export declare class VideoModel<Options extends VideoOptions = VideoOptions> extends MediaModel<VideoRoute<Options>, Options> {
8
+ export type VideoOptions = MediaModel.Options;
9
+ export type VideoRoute = MediaRoute.AnyRoute<VideoRequestFor, VideoEvent, VideoResponse>;
10
+ export declare class VideoModel<Options extends VideoOptions = VideoOptions> extends MediaModel<VideoRoute, Options> {
12
11
  protected readonly _VideoModel: void;
13
- static make<Options extends VideoOptions = VideoOptions>(input: MediaModel.Input<VideoRoute<Options>>): VideoModel<Options>;
14
- /** Compose a queued video protocol with its canonical start path into a model for one deployment. */
15
- static fromRoute<Options extends VideoOptions = VideoOptions, Token = unknown>(route: VideoModel.RouteInput<Options, Token>, input: MediaRoute.ModelInput): VideoModel<Options>;
12
+ /** The number of type arguments selects the kind: `<Options>`, `<Options, Frame, State>`, or `<Options, Token>`. */
13
+ static fromRoute<Options extends VideoOptions>(route: MediaModel.InlineRouteInput<VideoRequestFor<Options>, VideoResponse>, input: MediaRoute.ModelInput): VideoModel<Options>;
14
+ static fromRoute<Options extends VideoOptions, Frame, State>(route: MediaModel.StreamRouteInput<VideoRequestFor<Options>, VideoEvent, Frame, State>, input: MediaRoute.ModelInput): VideoModel<Options>;
15
+ static fromRoute<Options extends VideoOptions, Token>(route: MediaModel.QueuedRouteInput<VideoRequestFor<Options>, VideoResponse, Token>, input: MediaRoute.ModelInput): VideoModel<Options>;
16
16
  }
17
- export declare namespace VideoModel {
18
- type RouteInput<Options extends VideoOptions = VideoOptions, Token = unknown> = MediaModel.RouteInput<VideoRequestFor<Options>, MediaProtocol.Queued<VideoRequestFor<Options>, VideoResponse, Token>>;
19
- }
20
- export declare const VideoModelSchema: Schema.declare<VideoModel<VideoOptions>, VideoModel<VideoOptions>>;
17
+ export declare const VideoModelSchema: Schema.declare<VideoModel<MediaModel.Options>, VideoModel<MediaModel.Options>>;
21
18
  export type VideoAspectRatio = Media.AspectRatio;
22
19
  export declare const VideoAspectRatio: Schema.declare<`${number}:${number}`, `${number}:${number}`>;
23
- export type VideoResolution = "480p" | "720p" | "1080p" | "4k" | (string & {});
20
+ export type VideoResolution = OpenString<"480p" | "720p" | "1080p" | "4k">;
24
21
  /** Pinned frames. Routes that accept only a first frame fail typed when `last` is present. */
25
22
  export declare const VideoFrames: Schema.Struct<{
26
23
  readonly first: Schema.optional<Schema.decodeTo<Schema.declare<Media.Asset, Media.Asset>, Schema.Struct<{
@@ -88,7 +85,7 @@ export declare const VideoFrames: Schema.Struct<{
88
85
  }>;
89
86
  export type VideoFrames = Schema.Schema.Type<typeof VideoFrames>;
90
87
  declare const VideoRequest_base: Schema.Class<VideoRequest, Schema.Struct<{
91
- readonly model: Schema.declare<VideoModel<VideoOptions>, VideoModel<VideoOptions>>;
88
+ readonly model: Schema.declare<VideoModel<MediaModel.Options>, VideoModel<MediaModel.Options>>;
92
89
  readonly prompt: Schema.String;
93
90
  readonly frames: Schema.optional<Schema.Struct<{
94
91
  readonly first: Schema.optional<Schema.decodeTo<Schema.declare<Media.Asset, Media.Asset>, Schema.Struct<{
@@ -1010,7 +1007,7 @@ export declare const VideoEvent: Schema.Union<readonly [Schema.Struct<{
1010
1007
  } | undefined;
1011
1008
  }[] | undefined;
1012
1009
  }) => any) | undefined;
1013
- } & { [K in Exclude<keyof Cases, "finish" | "video" | "generation-queued" | "generation-progress">]: never; }, OrElse extends (value: Exclude<{
1010
+ } & { [K in Exclude<keyof Cases, "finish" | "generation-queued" | "generation-progress" | "video">]: never; }, OrElse extends (value: Exclude<{
1014
1011
  readonly id: string;
1015
1012
  readonly type: "generation-queued";
1016
1013
  readonly position?: number | undefined;
@@ -1171,7 +1168,7 @@ export declare const VideoEvent: Schema.Union<readonly [Schema.Struct<{
1171
1168
  } | undefined;
1172
1169
  }[] | undefined;
1173
1170
  }) => any) | undefined;
1174
- } & { [K in Exclude<keyof Cases, "finish" | "video" | "generation-queued" | "generation-progress">]: never; }, OrElse extends (value: Exclude<{
1171
+ } & { [K in Exclude<keyof Cases, "finish" | "generation-queued" | "generation-progress" | "video">]: never; }, OrElse extends (value: Exclude<{
1175
1172
  readonly id: string;
1176
1173
  readonly type: "generation-queued";
1177
1174
  readonly position?: number | undefined;
@@ -1337,23 +1334,18 @@ export declare const VideoEvent: Schema.Union<readonly [Schema.Struct<{
1337
1334
  };
1338
1335
  };
1339
1336
  export type VideoEvent = Schema.Schema.Type<typeof videoEventTagged>;
1340
- /** A completed response expanded into the streaming event shape. */
1341
- export declare const responseEvents: (response: VideoResponse) => ReadonlyArray<VideoEvent>;
1342
1337
  export declare function request<const Model extends VideoModel>(input: VideoRequestInput<Model>): VideoRequestFor<VideoModelOptions<Model>>;
1343
1338
  export declare function request(input: VideoRequest): VideoRequest;
1344
- export declare function start<const Model extends VideoModel>(input: VideoRequestInput<Model>): Effect.Effect<Generation<VideoResponse>, AIError, Service>;
1345
- export declare function start(input: VideoRequest): Effect.Effect<Generation<VideoResponse>, AIError, Service>;
1346
- export declare function generate<const Model extends VideoModel>(input: VideoRequestInput<Model>, options?: AwaitOptions): Effect.Effect<VideoResponse, AIError, Service>;
1347
- export declare function generate(input: VideoRequest, options?: AwaitOptions): Effect.Effect<VideoResponse, AIError, Service>;
1339
+ export declare function start<const Model extends VideoModel>(input: VideoRequest | VideoRequestInput<Model>): Effect.Effect<Generation<VideoResponse>, AIError, Service>;
1340
+ export declare function generate<const Model extends VideoModel>(input: VideoRequest | VideoRequestInput<Model>, options?: AwaitOptions): Effect.Effect<VideoResponse, AIError, Service>;
1348
1341
  /** Rebuild a generation handle from a persisted `Generation.token`, refreshing its status once. */
1349
- export declare const resume: <Options extends VideoOptions>(model: VideoModel<Options>, token: unknown) => Effect.Effect<Generation<VideoResponse>, AIError, Service>;
1350
- export declare function stream<const Model extends VideoModel>(input: VideoRequestInput<Model>, options?: AwaitOptions): Stream.Stream<VideoEvent, AIError, Service>;
1351
- export declare function stream(input: VideoRequest, options?: AwaitOptions): Stream.Stream<VideoEvent, AIError, Service>;
1342
+ export declare const resume: (model: VideoModel, token: unknown) => Effect.Effect<Generation<VideoResponse>, AIError, Service>;
1343
+ export declare function stream<const Model extends VideoModel>(input: VideoRequest | VideoRequestInput<Model>, options?: AwaitOptions): Stream.Stream<VideoEvent, AIError, Service>;
1352
1344
  export declare const Video: {
1353
1345
  readonly request: typeof request;
1354
1346
  readonly start: typeof start;
1355
1347
  readonly generate: typeof generate;
1356
- readonly resume: <Options extends VideoOptions>(model: VideoModel<Options>, token: unknown) => Effect.Effect<Generation<VideoResponse>, AIError, Service>;
1348
+ readonly resume: (model: VideoModel, token: unknown) => Effect.Effect<Generation<VideoResponse>, AIError, Service>;
1357
1349
  readonly stream: typeof stream;
1358
1350
  };
1359
1351
  export {};
package/dist/video.js CHANGED
@@ -6,16 +6,12 @@ import { MediaRoute } from "./route/media.js";
6
6
  import { AIError, HttpOptions, MediaUsage, ProviderMetadata } from "./schema/index.js";
7
7
  import { VideoClient, Service } from "./video-client.js";
8
8
  export class VideoModel extends MediaModel {
9
- static make(input) {
10
- return new VideoModel(input);
11
- }
12
- /** Compose a queued video protocol with its canonical start path into a model for one deployment. */
13
9
  static fromRoute(route, input) {
14
10
  return new VideoModel({
15
11
  id: input.id,
16
- provider: route.provider,
12
+ provider: route.protocol.provider,
17
13
  http: input.http,
18
- route: composeRoute(MediaRoute.queued, route, input),
14
+ route: composeRoute(route, input, collectResponse),
19
15
  });
20
16
  }
21
17
  }
@@ -81,21 +77,24 @@ export const VideoEvent = Object.assign(videoEventTagged, {
81
77
  finish: videoEventTagged.guards.finish,
82
78
  },
83
79
  });
84
- /** A completed response expanded into the streaming event shape. */
85
- export const responseEvents = (response) => [
86
- ...response.videos.map((video, index) => VideoOutputEvent.make({ index, video })),
87
- VideoFinishEvent.make({
88
- usage: response.usage,
89
- notices: response.notices,
90
- providerMetadata: response.providerMetadata,
91
- }),
92
- ];
80
+ const collectResponse = (events) => {
81
+ const finish = events.find(VideoEvent.is.finish);
82
+ // A streaming video protocol's `finish` emits the terminal event or fails, so a completed stream always has one.
83
+ if (finish === undefined)
84
+ return Effect.die(new Error("The video stream completed without a finish event"));
85
+ return Effect.succeed(new VideoResponse({
86
+ videos: events.filter(VideoEvent.is.video).map((event) => event.video),
87
+ usage: finish.usage,
88
+ notices: finish.notices,
89
+ providerMetadata: finish.providerMetadata,
90
+ }));
91
+ };
93
92
  export function request(input) {
94
93
  if (input instanceof VideoRequest)
95
94
  return input;
96
95
  return new VideoRequest({
97
96
  ...input,
98
- http: input.http === undefined ? undefined : HttpOptions.make(input.http),
97
+ http: HttpOptions.make(input.http),
99
98
  });
100
99
  }
101
100
  const requestEffect = (input) => tryRequest(() => request(input));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
- "version": "2.0.16",
3
+ "version": "2.0.17",
4
4
  "name": "@opencode/ai",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -34,7 +34,7 @@
34
34
  "devDependencies": {
35
35
  "@clack/prompts": "1.0.0-alpha.1",
36
36
  "@effect/platform-node": "4.0.0-rc.112",
37
- "@opencode/http-recorder": "2.0.16",
37
+ "@opencode/http-recorder": "2.0.17",
38
38
  "@tsconfig/bun": "1.0.9",
39
39
  "@types/bun": "1.4.0",
40
40
  "@typescript/native-preview": "7.0.0-dev.20251207.1",
@@ -44,7 +44,7 @@
44
44
  "@aws-sdk/credential-providers": "3.1057.0",
45
45
  "@smithy/eventstream-codec": "4.2.14",
46
46
  "@smithy/util-utf8": "4.2.2",
47
- "@opencode/schema": "2.0.16",
47
+ "@opencode/schema": "2.0.17",
48
48
  "aws4fetch": "1.0.20",
49
49
  "effect": "4.0.0-rc.112",
50
50
  "google-auth-library": "10.5.0"
@@ -1,2 +0,0 @@
1
- export declare const mediaType: (data: Uint8Array, format?: string) => string;
2
- export * as MetaImage from "./meta-image.js";
@@ -1,13 +0,0 @@
1
- // Responses image items can omit output_format, including when PNG/JPEG was requested.
2
- export const mediaType = (data, format) => {
3
- if (format !== undefined)
4
- return `image/${format}`;
5
- if (data[0] === 137 && data[1] === 80 && data[2] === 78 && data[3] === 71)
6
- return "image/png";
7
- if (data[0] === 255 && data[1] === 216 && data[2] === 255)
8
- return "image/jpeg";
9
- if (new TextDecoder().decode(data.slice(0, 4)) === "RIFF" && new TextDecoder().decode(data.slice(8, 12)) === "WEBP")
10
- return "image/webp";
11
- return "application/octet-stream";
12
- };
13
- export * as MetaImage from "./meta-image.js";
@@ -1,5 +0,0 @@
1
- import { Schema } from "effect";
2
- export declare const Size: Schema.String;
3
- export declare const OpenAIImage: {
4
- readonly Size: Schema.String;
5
- };
@@ -1,18 +0,0 @@
1
- import { Schema } from "effect";
2
- const dimensions = (value) => {
3
- const match = /^(\d+)x(\d+)$/.exec(value);
4
- if (!match)
5
- return undefined;
6
- return { width: Number(match[1]), height: Number(match[2]) };
7
- };
8
- export const Size = Schema.String.check(Schema.makeFilter((value) => {
9
- if (value === "auto")
10
- return undefined;
11
- const parsed = dimensions(value);
12
- if (!parsed)
13
- return "image size must be `auto` or `{width}x{height}`";
14
- return parsed.width > 0 && parsed.height > 0 ? undefined : "image dimensions must be positive integers";
15
- }));
16
- export const OpenAIImage = {
17
- Size,
18
- };