@opencode/ai 0.0.0-dev-20061 → 0.0.0-dev-20065
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 +56 -1
- package/dist/image-client.d.ts +14 -7
- package/dist/image-client.js +24 -8
- package/dist/image.d.ts +392 -12
- package/dist/image.js +41 -9
- package/dist/media-model.d.ts +3 -1
- package/dist/media-model.js +10 -0
- package/dist/promise.d.ts +33 -5
- package/dist/promise.js +4 -2
- package/dist/protocols/bfl-images.d.ts +32 -0
- package/dist/protocols/bfl-images.js +153 -0
- package/dist/protocols/fal-images.d.ts +24 -0
- package/dist/protocols/fal-images.js +114 -0
- package/dist/protocols/fal-video.d.ts +0 -10
- package/dist/protocols/fal-video.js +8 -59
- package/dist/protocols/openai-images.d.ts +124 -3
- package/dist/protocols/openai-images.js +102 -35
- package/dist/protocols/openai-responses.d.ts +5 -5
- package/dist/protocols/replicate-images.d.ts +28 -0
- package/dist/protocols/replicate-images.js +133 -0
- package/dist/protocols/stability-images.d.ts +38 -0
- package/dist/protocols/stability-images.js +148 -0
- package/dist/protocols/utils/fal-queue.d.ts +28 -0
- package/dist/protocols/utils/fal-queue.js +69 -0
- package/dist/protocols/utils/media-input.d.ts +4 -0
- package/dist/protocols/utils/media-input.js +4 -0
- package/dist/provider-error.js +3 -0
- package/dist/providers/azure.d.ts +2 -2
- package/dist/providers/black-forest-labs.d.ts +25 -0
- package/dist/providers/black-forest-labs.js +28 -0
- package/dist/providers/cloudflare-ai-gateway.d.ts +2 -2
- package/dist/providers/fal.d.ts +5 -0
- package/dist/providers/fal.js +8 -4
- package/dist/providers/index.d.ts +3 -0
- package/dist/providers/index.js +3 -0
- package/dist/providers/openai.d.ts +1 -1
- package/dist/providers/replicate.d.ts +25 -0
- package/dist/providers/replicate.js +22 -0
- package/dist/providers/stability.d.ts +28 -0
- package/dist/providers/stability.js +23 -0
- package/dist/route/media-protocol.d.ts +3 -1
- package/dist/route/media.d.ts +13 -2
- package/dist/route/media.js +37 -2
- package/dist/transcription-client.d.ts +1 -1
- package/dist/transcription-client.js +10 -35
- package/dist/transcription.d.ts +2 -2
- package/dist/transcription.js +2 -9
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -584,6 +584,61 @@ Z.ai does not include trustworthy MIME metadata for output URLs, so generated im
|
|
|
584
584
|
`application/octet-stream` until materialized. Output URLs expire after 30 days; call `asset.materialize()` and
|
|
585
585
|
persist the bytes promptly if they must remain available.
|
|
586
586
|
|
|
587
|
+
### Partial images
|
|
588
|
+
|
|
589
|
+
OpenAI's GPT image models stream previews. `Image.stream` sends `stream: true` with `partialImages` (0–3, default 2)
|
|
590
|
+
and emits `image-partial` events before each final `image`; `Image.generate` keeps the plain JSON request.
|
|
591
|
+
`dall-e-*` models do not stream and fail typed:
|
|
592
|
+
|
|
593
|
+
```ts
|
|
594
|
+
yield *
|
|
595
|
+
Image.stream({
|
|
596
|
+
model: openai.image("gpt-image-2"),
|
|
597
|
+
prompt: "A lighthouse at dusk",
|
|
598
|
+
providerOptions: { partialImages: 2 },
|
|
599
|
+
}).pipe(Stream.runForEach((event) => (ImageEvent.is.imagePartial(event) ? showPreview(event.image) : Effect.void)))
|
|
600
|
+
```
|
|
601
|
+
|
|
602
|
+
The provider may send fewer previews than requested when the final image is ready first.
|
|
603
|
+
|
|
604
|
+
### Queued image providers
|
|
605
|
+
|
|
606
|
+
Black Forest Labs, fal, Replicate, and Stability's creative upscaler are submit-then-poll routes. `Image.generate`
|
|
607
|
+
and `Image.stream` poll for you (pass `{ poll }` to tune the interval and timeout); `Image.start` returns a
|
|
608
|
+
`Generation` whose `token` is serializable JSON for `Image.resume` in another process:
|
|
609
|
+
|
|
610
|
+
```ts
|
|
611
|
+
import { BlackForestLabs, Stability } from "@opencode/ai/providers"
|
|
612
|
+
|
|
613
|
+
const bfl = BlackForestLabs.configure({ apiKey: process.env.BFL_API_KEY })
|
|
614
|
+
|
|
615
|
+
const generation = yield * Image.start({ model: bfl.image("flux-2-pro"), prompt, size: "1024x768" })
|
|
616
|
+
persist(generation.token)
|
|
617
|
+
|
|
618
|
+
const resumed = yield * Image.resume(bfl.image("flux-2-pro"), loadToken())
|
|
619
|
+
const response = yield * resumed.await({ poll: { interval: "2 seconds" } })
|
|
620
|
+
```
|
|
621
|
+
|
|
622
|
+
- **Black Forest Labs** — results are downloaded before returning, because `result.sample` expires in 10 minutes.
|
|
623
|
+
- **Replicate** — inputs are model-defined, so only `prompt` lowers: sizing, count, seed, format, and files go in
|
|
624
|
+
`providerOptions` under the model's names, with files as `Media.Asset` (data URLs up to 256 KB, larger by URL).
|
|
625
|
+
Outputs are removed an hour after the prediction completes. `Prefer: wait=60` in `headers` or `http.headers` holds
|
|
626
|
+
the submission open so a fast prediction costs one result read.
|
|
627
|
+
- **Stability** — `stability.image(id)` generates inline; `stability.upscale()` is the creative upscaler, queued:
|
|
628
|
+
|
|
629
|
+
```ts
|
|
630
|
+
const stability = Stability.configure({ apiKey: process.env.STABILITY_API_KEY })
|
|
631
|
+
const upscaled =
|
|
632
|
+
yield *
|
|
633
|
+
Image.generate(
|
|
634
|
+
{ model: stability.upscale(), prompt: "A lighthouse", images: [yield * Media.file("./small.png")] },
|
|
635
|
+
{ poll: { interval: "5 seconds" } },
|
|
636
|
+
)
|
|
637
|
+
```
|
|
638
|
+
|
|
639
|
+
Imagen is not available: Google shut it down on the Gemini API, and Vertex discontinued the Imagen 4 models on
|
|
640
|
+
2026-06-30. `Google.image(...)` uses Gemini-native image models.
|
|
641
|
+
|
|
587
642
|
Conversational image generation remains part of the LLM interaction. OpenAI Responses exposes it through its hosted image tool:
|
|
588
643
|
|
|
589
644
|
```ts
|
|
@@ -836,7 +891,7 @@ const transcript = await generation.await({ poll: { interval: 3_000 } })
|
|
|
836
891
|
- **`Message.user(...)` / `Message.assistant(...)` / `Message.tool(...)`** — message constructors from the canonical schema model.
|
|
837
892
|
- **`LanguageModel.make(...)` / `ToolCallPart.make(...)` / `ToolResultPart.make(...)` / `ToolDefinition.make(...)`** — model and tool-related constructors from the canonical schema model.
|
|
838
893
|
- **`LLMEvent.is.*`** — typed guards (`is.textDelta`, `is.toolCall`, `is.finish`, …) for filtering streams.
|
|
839
|
-
- **`Image.request` / `
|
|
894
|
+
- **`Image.request` / `generate` / `stream` / `start` / `resume`** — images over inline, streaming (partial previews), and queued routes through a provider-neutral request and response model.
|
|
840
895
|
- **`ImageClient`** — Effect service and layer for image execution, parallel to `LLMClient`.
|
|
841
896
|
- **`Media`** — the shared asset type (`Media.Asset`, `Media.Source`) and constructors used by messages, tool results, and media requests.
|
|
842
897
|
- **`Generation`** — provider-neutral handle for an in-flight media generation (`await`, `refresh`, `cancel`, `events`) used by queued media routes.
|
package/dist/image-client.d.ts
CHANGED
|
@@ -1,21 +1,28 @@
|
|
|
1
1
|
import { Context, Effect, Layer, Stream } from "effect";
|
|
2
|
+
import type { AwaitOptions, Generation } from "./generation.js";
|
|
2
3
|
import { RequestExecutor } from "./route/executor.js";
|
|
3
4
|
import type { AIError } from "./schema/index.js";
|
|
4
|
-
import { type ImageEvent, type ImageOptions, type ImageRequestFor, type ImageResponse } from "./image.js";
|
|
5
|
+
import { type ImageEvent, type ImageModel, type ImageOptions, type ImageRequestFor, type ImageResponse } from "./image.js";
|
|
5
6
|
export interface Interface {
|
|
6
|
-
readonly generate: <Options extends ImageOptions>(request: ImageRequestFor<Options
|
|
7
|
-
readonly stream: <Options extends ImageOptions>(request: ImageRequestFor<Options
|
|
7
|
+
readonly generate: <Options extends ImageOptions>(request: ImageRequestFor<Options>, options?: AwaitOptions) => Effect.Effect<ImageResponse, AIError>;
|
|
8
|
+
readonly stream: <Options extends ImageOptions>(request: ImageRequestFor<Options>, options?: AwaitOptions) => Stream.Stream<ImageEvent, AIError>;
|
|
9
|
+
readonly start: <Options extends ImageOptions>(request: ImageRequestFor<Options>) => Effect.Effect<Generation<ImageResponse>, AIError>;
|
|
10
|
+
readonly resume: <Options extends ImageOptions>(model: ImageModel<Options>, token: unknown) => Effect.Effect<Generation<ImageResponse>, AIError>;
|
|
8
11
|
}
|
|
9
12
|
declare const Service_base: Context.ServiceClass<Service, "@opencode/ImageClient", Interface>;
|
|
10
13
|
export declare class Service extends Service_base {
|
|
11
14
|
}
|
|
12
|
-
export declare const generate: <Options extends ImageOptions>(request: ImageRequestFor<Options
|
|
13
|
-
export declare const stream: <Options extends ImageOptions>(request: ImageRequestFor<Options
|
|
15
|
+
export declare const generate: <Options extends ImageOptions>(request: ImageRequestFor<Options>, options?: AwaitOptions) => Effect.Effect<ImageResponse, AIError, Service>;
|
|
16
|
+
export declare const stream: <Options extends ImageOptions>(request: ImageRequestFor<Options>, options?: AwaitOptions) => Stream.Stream<ImageEvent, AIError, Service>;
|
|
17
|
+
export declare const start: <Options extends ImageOptions>(request: ImageRequestFor<Options>) => Effect.Effect<Generation<ImageResponse>, AIError, Service>;
|
|
18
|
+
export declare const resume: <Options extends ImageOptions>(model: ImageModel<Options>, token: unknown) => Effect.Effect<Generation<ImageResponse>, AIError, Service>;
|
|
14
19
|
export declare const layer: Layer.Layer<Service, never, RequestExecutor.Service>;
|
|
15
20
|
export declare const ImageClient: {
|
|
16
21
|
readonly Service: typeof Service;
|
|
17
22
|
readonly layer: Layer.Layer<Service, never, RequestExecutor.Service>;
|
|
18
|
-
readonly generate: <Options extends ImageOptions>(request: ImageRequestFor<Options
|
|
19
|
-
readonly stream: <Options extends ImageOptions>(request: ImageRequestFor<Options
|
|
23
|
+
readonly generate: <Options extends ImageOptions>(request: ImageRequestFor<Options>, options?: AwaitOptions) => Effect.Effect<ImageResponse, AIError, Service>;
|
|
24
|
+
readonly stream: <Options extends ImageOptions>(request: ImageRequestFor<Options>, options?: AwaitOptions) => Stream.Stream<ImageEvent, AIError, Service>;
|
|
25
|
+
readonly start: <Options extends ImageOptions>(request: ImageRequestFor<Options>) => Effect.Effect<Generation<ImageResponse>, AIError, Service>;
|
|
26
|
+
readonly resume: <Options extends ImageOptions>(model: ImageModel<Options>, token: unknown) => Effect.Effect<Generation<ImageResponse>, AIError, Service>;
|
|
20
27
|
};
|
|
21
28
|
export {};
|
package/dist/image-client.js
CHANGED
|
@@ -1,23 +1,37 @@
|
|
|
1
1
|
import { Context, Effect, Layer, Stream } from "effect";
|
|
2
2
|
import { RequestExecutor } from "./route/executor.js";
|
|
3
|
+
import { MediaRoute } from "./route/media.js";
|
|
3
4
|
import { responseEvents, } from "./image.js";
|
|
4
5
|
export class Service extends Context.Service()("@opencode/ImageClient") {
|
|
5
6
|
}
|
|
6
|
-
export const generate = (request) => Effect.gen(function* () {
|
|
7
|
+
export const generate = (request, options) => Effect.gen(function* () {
|
|
7
8
|
const client = yield* Service;
|
|
8
|
-
return yield* client.generate(request);
|
|
9
|
+
return yield* client.generate(request, options);
|
|
9
10
|
});
|
|
10
|
-
export const stream = (request) => Stream.unwrap(Effect.gen(function* () {
|
|
11
|
+
export const stream = (request, options) => Stream.unwrap(Effect.gen(function* () {
|
|
11
12
|
const client = yield* Service;
|
|
12
|
-
return client.stream(request);
|
|
13
|
+
return client.stream(request, options);
|
|
13
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
|
+
});
|
|
14
23
|
export const layer = Layer.effect(Service, Effect.gen(function* () {
|
|
15
24
|
const executor = yield* RequestExecutor.Service;
|
|
16
|
-
const
|
|
25
|
+
const dispatch = MediaRoute.dispatch({
|
|
26
|
+
modality: "image",
|
|
27
|
+
execute: executor.execute,
|
|
28
|
+
responseEvents,
|
|
29
|
+
});
|
|
17
30
|
return Service.of({
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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),
|
|
21
35
|
});
|
|
22
36
|
}));
|
|
23
37
|
export const ImageClient = {
|
|
@@ -25,4 +39,6 @@ export const ImageClient = {
|
|
|
25
39
|
layer,
|
|
26
40
|
generate,
|
|
27
41
|
stream,
|
|
42
|
+
start,
|
|
43
|
+
resume,
|
|
28
44
|
};
|