@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
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { Effect, Schema } from "effect";
|
|
2
|
+
import { ImageModel, ImageResponse } from "../image.js";
|
|
3
|
+
import { MediaProtocol } from "../route/media-protocol.js";
|
|
4
|
+
import { MediaRoute } from "../route/media.js";
|
|
5
|
+
import { ProviderID, mergeJsonRecords } from "../schema/index.js";
|
|
6
|
+
import { ProviderShared } from "./shared.js";
|
|
7
|
+
import { MediaInput } from "./utils/media-input.js";
|
|
8
|
+
const ADAPTER = "stability-images";
|
|
9
|
+
const UPSCALE_ADAPTER = "stability-upscale";
|
|
10
|
+
const NAME = "Stability AI";
|
|
11
|
+
const PROVIDER = ProviderID.make("stability");
|
|
12
|
+
export const DEFAULT_BASE_URL = "https://api.stability.ai";
|
|
13
|
+
const RESULTS_PATH = "/v2beta/results";
|
|
14
|
+
const UPSCALE_MODEL = "creative";
|
|
15
|
+
/** Base64 JSON instead of raw bytes, so the seed and finish reason arrive with the image. */
|
|
16
|
+
const HEADERS = { accept: "application/json" };
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
// 2. Token and response schemas
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
export const Token = Schema.Struct({ id: Schema.String });
|
|
21
|
+
// Generate names the base64 image `image`; `/v2beta/results/{id}` names it `result`.
|
|
22
|
+
const ImageDocument = Schema.Struct({
|
|
23
|
+
image: Schema.optional(Schema.String),
|
|
24
|
+
result: Schema.optional(Schema.String),
|
|
25
|
+
seed: Schema.optional(Schema.Number),
|
|
26
|
+
finish_reason: Schema.optional(Schema.String),
|
|
27
|
+
});
|
|
28
|
+
const Started = Schema.Struct({ id: Schema.String });
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
// 5. Request body construction
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
/** `sd3.5-*` ids share the `sd3` endpoint and select the model with a form field. */
|
|
33
|
+
const endpoint = (model) => (model.startsWith("sd3") ? "sd3" : model);
|
|
34
|
+
const RESERVED_FORM_FIELDS = new Set(["image", "prompt", "mode", "model"]);
|
|
35
|
+
const unsupported = (route, operation, message) => ProviderShared.unsupportedOperation({ operation, provider: PROVIDER, route, message });
|
|
36
|
+
const form = Effect.fn("StabilityImages.form")(function* (route, fields, native, source) {
|
|
37
|
+
if ((source?.length ?? 0) > 1)
|
|
38
|
+
return yield* unsupported(route, "media.images", `${NAME} takes one source image`);
|
|
39
|
+
const body = new FormData();
|
|
40
|
+
const overlay = Object.entries(native ?? {}).filter(([key]) => !RESERVED_FORM_FIELDS.has(key));
|
|
41
|
+
Object.entries(mergeJsonRecords(fields, Object.fromEntries(overlay)) ?? {}).forEach(([key, value]) => body.append(key, typeof value === "string" ? value : ProviderShared.encodeJson(value)));
|
|
42
|
+
const image = source?.[0];
|
|
43
|
+
if (image !== undefined)
|
|
44
|
+
body.append("image", MediaInput.blob(yield* MediaInput.inlineBytes(route, image), image.mediaType), "image");
|
|
45
|
+
return MediaProtocol.multipart(body);
|
|
46
|
+
});
|
|
47
|
+
const fromRequest = Effect.fn("StabilityImages.fromRequest")(function* (request) {
|
|
48
|
+
if (request.n !== undefined && request.n > 1)
|
|
49
|
+
return yield* unsupported(ADAPTER, "media.n", `${NAME} generates one image per request; call it once per image`);
|
|
50
|
+
const target = endpoint(request.model.id);
|
|
51
|
+
const edit = (request.images?.length ?? 0) > 0;
|
|
52
|
+
if (edit && target === "core")
|
|
53
|
+
return yield* unsupported(ADAPTER, "media.images", `${NAME} core is text-to-image only; use ultra or sd3.5-*`);
|
|
54
|
+
return yield* form(ADAPTER, {
|
|
55
|
+
prompt: request.prompt,
|
|
56
|
+
aspect_ratio: request.aspectRatio,
|
|
57
|
+
seed: request.seed,
|
|
58
|
+
output_format: request.format,
|
|
59
|
+
model: target === "sd3" ? request.model.id : undefined,
|
|
60
|
+
mode: target === "sd3" && edit ? "image-to-image" : undefined,
|
|
61
|
+
}, mergeJsonRecords(request.providerOptions, request.http?.body), request.images);
|
|
62
|
+
});
|
|
63
|
+
const fromUpscaleRequest = Effect.fn("StabilityImages.fromUpscaleRequest")(function* (request) {
|
|
64
|
+
if ((request.images?.length ?? 0) === 0)
|
|
65
|
+
return yield* ProviderShared.invalidRequest(`${NAME} upscale requires the source image in images`);
|
|
66
|
+
return yield* form(UPSCALE_ADAPTER, { prompt: request.prompt, seed: request.seed, output_format: request.format }, mergeJsonRecords(request.providerOptions, request.http?.body), request.images);
|
|
67
|
+
});
|
|
68
|
+
// ---------------------------------------------------------------------------
|
|
69
|
+
// 6. Response decoding
|
|
70
|
+
// ---------------------------------------------------------------------------
|
|
71
|
+
const decodeImageDocument = (route) => {
|
|
72
|
+
const decode = MediaProtocol.decodeJson(route, NAME, ImageDocument);
|
|
73
|
+
return Effect.fn("StabilityImages.decodeImage")(function* (response) {
|
|
74
|
+
const output = yield* decode(response);
|
|
75
|
+
const document = output.value;
|
|
76
|
+
const data = document.image ?? document.result;
|
|
77
|
+
if (data === undefined)
|
|
78
|
+
return yield* output.invalid(`${NAME} returned no image`);
|
|
79
|
+
const image = yield* MediaInput.decodedAsset(output.invalid, `${NAME} result`, data, undefined);
|
|
80
|
+
return new ImageResponse({
|
|
81
|
+
images: [image],
|
|
82
|
+
notices: document.finish_reason === "CONTENT_FILTERED"
|
|
83
|
+
? [{ type: "moderated", message: `${NAME} blurred the image for violating its content policy` }]
|
|
84
|
+
: undefined,
|
|
85
|
+
providerMetadata: { stability: { seed: document.seed, finishReason: document.finish_reason } },
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
};
|
|
89
|
+
const decodeResponse = decodeImageDocument(ADAPTER);
|
|
90
|
+
const decodeUpscaleImage = decodeImageDocument(UPSCALE_ADAPTER);
|
|
91
|
+
const decodeStart = MediaProtocol.decodeStarted(UPSCALE_ADAPTER, NAME, Started, (value) => ({
|
|
92
|
+
token: { id: value.id },
|
|
93
|
+
snapshot: { id: value.id, status: "queued" },
|
|
94
|
+
}));
|
|
95
|
+
// `/v2beta/results/{id}` answers 202 while in progress and 200 with the finished image document.
|
|
96
|
+
const decodeStatus = (response, context) => Effect.succeed({
|
|
97
|
+
id: context.token.id,
|
|
98
|
+
status: response.status === 202 ? "running" : "completed",
|
|
99
|
+
});
|
|
100
|
+
const decodeUpscaleResult = Effect.fn("StabilityImages.decodeUpscaleResult")(function* (response, context) {
|
|
101
|
+
if (response.status === 202) {
|
|
102
|
+
const output = yield* MediaProtocol.text(UPSCALE_ADAPTER, NAME, response);
|
|
103
|
+
return yield* output.invalid(`${NAME} upscale ${context.token.id} has not finished`);
|
|
104
|
+
}
|
|
105
|
+
return yield* decodeUpscaleImage(response);
|
|
106
|
+
});
|
|
107
|
+
// ---------------------------------------------------------------------------
|
|
108
|
+
// 7. Protocol and route
|
|
109
|
+
// ---------------------------------------------------------------------------
|
|
110
|
+
export const protocol = MediaProtocol.inline({
|
|
111
|
+
id: ADAPTER,
|
|
112
|
+
name: NAME,
|
|
113
|
+
unsupported: ["size", "mask"],
|
|
114
|
+
body: { from: fromRequest },
|
|
115
|
+
response: { decode: decodeResponse },
|
|
116
|
+
});
|
|
117
|
+
export const upscaleProtocol = MediaProtocol.queued({
|
|
118
|
+
id: UPSCALE_ADAPTER,
|
|
119
|
+
name: NAME,
|
|
120
|
+
token: Token,
|
|
121
|
+
unsupported: ["n", "size", "aspectRatio", "mask"],
|
|
122
|
+
start: { body: { from: fromUpscaleRequest }, decode: decodeStart },
|
|
123
|
+
status: { path: (token) => `${RESULTS_PATH}/${token.id}`, decode: decodeStatus },
|
|
124
|
+
result: { path: (token) => `${RESULTS_PATH}/${token.id}`, decode: decodeUpscaleResult },
|
|
125
|
+
});
|
|
126
|
+
export const model = (input) => ImageModel.fromRoute({
|
|
127
|
+
id: ADAPTER,
|
|
128
|
+
provider: PROVIDER,
|
|
129
|
+
protocol,
|
|
130
|
+
baseURL: DEFAULT_BASE_URL,
|
|
131
|
+
headers: HEADERS,
|
|
132
|
+
path: ({ request }) => `/v2beta/stable-image/generate/${endpoint(request.model.id)}`,
|
|
133
|
+
}, input);
|
|
134
|
+
export const upscaleModel = (input) => ImageModel.fromRoute({
|
|
135
|
+
id: UPSCALE_ADAPTER,
|
|
136
|
+
provider: PROVIDER,
|
|
137
|
+
protocol: upscaleProtocol,
|
|
138
|
+
baseURL: DEFAULT_BASE_URL,
|
|
139
|
+
headers: HEADERS,
|
|
140
|
+
// Only the creative upscaler is asynchronous; fast and conservative answer inline.
|
|
141
|
+
path: `/v2beta/stable-image/upscale/${UPSCALE_MODEL}`,
|
|
142
|
+
}, { ...input, id: UPSCALE_MODEL });
|
|
143
|
+
export const StabilityImages = {
|
|
144
|
+
protocol,
|
|
145
|
+
upscaleProtocol,
|
|
146
|
+
model,
|
|
147
|
+
upscaleModel,
|
|
148
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Effect, Schema } from "effect";
|
|
2
|
+
import type { HttpClientResponse } from "effect/unstable/http";
|
|
3
|
+
import type { Media } from "../../media.js";
|
|
4
|
+
import { MediaProtocol } from "../../route/media-protocol.js";
|
|
5
|
+
import type { AIError } from "../../schema/index.js";
|
|
6
|
+
export declare const DEFAULT_BASE_URL = "https://queue.fal.run";
|
|
7
|
+
/** fal hands back absolute follow-up URLs on submit; they are authoritative for status, result, and cancel. */
|
|
8
|
+
export declare const Token: Schema.Struct<{
|
|
9
|
+
readonly requestID: Schema.String;
|
|
10
|
+
readonly statusURL: Schema.String;
|
|
11
|
+
readonly responseURL: Schema.String;
|
|
12
|
+
readonly cancelURL: Schema.String;
|
|
13
|
+
}>;
|
|
14
|
+
export type Token = Schema.Schema.Type<typeof Token>;
|
|
15
|
+
export declare const mediaUrl: (asset: Media.Asset, name: string) => Effect.Effect<string, AIError, never>;
|
|
16
|
+
export declare const protocol: <Request, Response>(input: {
|
|
17
|
+
readonly id: string;
|
|
18
|
+
readonly name: string;
|
|
19
|
+
readonly unsupported?: ReadonlyArray<keyof Request & string>;
|
|
20
|
+
readonly from: (request: Request) => Effect.Effect<MediaProtocol.Body, AIError>;
|
|
21
|
+
readonly decodeResult: (response: HttpClientResponse.HttpClientResponse, context: MediaProtocol.PollContext<Token>) => Effect.Effect<Response, AIError>;
|
|
22
|
+
}) => MediaProtocol.Queued<Request, Response, {
|
|
23
|
+
readonly requestID: string;
|
|
24
|
+
readonly statusURL: string;
|
|
25
|
+
readonly responseURL: string;
|
|
26
|
+
readonly cancelURL: string;
|
|
27
|
+
}>;
|
|
28
|
+
export * as FalQueue from "./fal-queue.js";
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { Effect, Schema } from "effect";
|
|
2
|
+
import { MediaProtocol } from "../../route/media-protocol.js";
|
|
3
|
+
import { ProviderShared, optionalNull } from "../shared.js";
|
|
4
|
+
export const DEFAULT_BASE_URL = "https://queue.fal.run";
|
|
5
|
+
/** fal hands back absolute follow-up URLs on submit; they are authoritative for status, result, and cancel. */
|
|
6
|
+
export const Token = Schema.Struct({
|
|
7
|
+
requestID: Schema.String,
|
|
8
|
+
statusURL: Schema.String,
|
|
9
|
+
responseURL: Schema.String,
|
|
10
|
+
cancelURL: Schema.String,
|
|
11
|
+
});
|
|
12
|
+
const StartResponse = Schema.Struct({
|
|
13
|
+
request_id: Schema.String,
|
|
14
|
+
status_url: Schema.String,
|
|
15
|
+
response_url: Schema.String,
|
|
16
|
+
cancel_url: Schema.String,
|
|
17
|
+
queue_position: optionalNull(Schema.Number),
|
|
18
|
+
});
|
|
19
|
+
const QueueStatus = Schema.Struct({
|
|
20
|
+
status: Schema.String,
|
|
21
|
+
queue_position: optionalNull(Schema.Number),
|
|
22
|
+
error: optionalNull(Schema.Unknown),
|
|
23
|
+
});
|
|
24
|
+
const STATUS = {
|
|
25
|
+
IN_QUEUE: "queued",
|
|
26
|
+
IN_PROGRESS: "running",
|
|
27
|
+
COMPLETED: "completed",
|
|
28
|
+
};
|
|
29
|
+
// fal accepts public URLs and data URIs; there is no provider file handle to forward.
|
|
30
|
+
export const mediaUrl = (asset, name) => ProviderShared.mediaReference(asset, undefined, name).pipe(Effect.map((reference) => reference.value));
|
|
31
|
+
export const protocol = (input) => {
|
|
32
|
+
const decodeQueueStatus = MediaProtocol.decodeJson(input.id, input.name, QueueStatus);
|
|
33
|
+
return MediaProtocol.queued({
|
|
34
|
+
id: input.id,
|
|
35
|
+
name: input.name,
|
|
36
|
+
token: Token,
|
|
37
|
+
unsupported: input.unsupported,
|
|
38
|
+
start: {
|
|
39
|
+
body: { from: input.from },
|
|
40
|
+
decode: MediaProtocol.decodeStarted(input.id, input.name, StartResponse, (value) => ({
|
|
41
|
+
token: {
|
|
42
|
+
requestID: value.request_id,
|
|
43
|
+
statusURL: value.status_url,
|
|
44
|
+
responseURL: value.response_url,
|
|
45
|
+
cancelURL: value.cancel_url,
|
|
46
|
+
},
|
|
47
|
+
snapshot: { id: value.request_id, status: "queued", position: value.queue_position ?? undefined },
|
|
48
|
+
})),
|
|
49
|
+
},
|
|
50
|
+
status: {
|
|
51
|
+
path: (token) => token.statusURL,
|
|
52
|
+
decode: Effect.fn("FalQueue.decodeStatus")(function* (response, context) {
|
|
53
|
+
const output = yield* decodeQueueStatus(response);
|
|
54
|
+
const decoded = output.value;
|
|
55
|
+
const status = yield* MediaProtocol.status(STATUS, decoded.status, output);
|
|
56
|
+
// fal reports request failures as COMPLETED with an `error`; the response endpoint carries the details.
|
|
57
|
+
const failed = status === "completed" && decoded.error !== undefined && decoded.error !== null;
|
|
58
|
+
return {
|
|
59
|
+
id: context.token.requestID,
|
|
60
|
+
status: failed ? "failed" : status,
|
|
61
|
+
position: status === "queued" ? (decoded.queue_position ?? undefined) : undefined,
|
|
62
|
+
};
|
|
63
|
+
}),
|
|
64
|
+
},
|
|
65
|
+
result: { path: (token) => token.responseURL, decode: input.decodeResult },
|
|
66
|
+
cancel: { method: "PUT", path: (token) => token.cancelURL },
|
|
67
|
+
});
|
|
68
|
+
};
|
|
69
|
+
export * as FalQueue from "./fal-queue.js";
|
|
@@ -7,6 +7,10 @@ export declare const inlineBytes: (route: string, asset: Media.Asset) => Effect.
|
|
|
7
7
|
/** Copied because `BlobPart` requires a plain `ArrayBuffer`. */
|
|
8
8
|
export declare const blob: (data: Uint8Array, mediaType: string) => Blob;
|
|
9
9
|
export declare const query: (route: string, values: Record<string, unknown>) => Effect.Effect<MediaProtocol.Query, AIError>;
|
|
10
|
+
export declare const dimensions: (size: string) => {
|
|
11
|
+
width: number;
|
|
12
|
+
height: number;
|
|
13
|
+
};
|
|
10
14
|
/** Provider file handle when the ref belongs to this provider; refs from other providers are never forwarded. */
|
|
11
15
|
export declare const refID: (asset: Media.Asset, provider: ProviderID) => string | undefined;
|
|
12
16
|
/** Decode a provider's base64 output once into an owned `bytes` asset, sniffing the type when it is not declared. */
|
|
@@ -24,6 +24,10 @@ export const query = (route, values) => {
|
|
|
24
24
|
return Effect.fail(ProviderShared.invalidRequest(`${route} cannot send "${invalid[0]}" as a query parameter`));
|
|
25
25
|
return Effect.succeed(Object.fromEntries(entries.map(([key, value]) => [key, Array.isArray(value) ? value.map(String) : String(value)])));
|
|
26
26
|
};
|
|
27
|
+
export const dimensions = (size) => {
|
|
28
|
+
const [width, height] = size.split("x").map(Number);
|
|
29
|
+
return { width, height };
|
|
30
|
+
};
|
|
27
31
|
/** Provider file handle when the ref belongs to this provider; refs from other providers are never forwarded. */
|
|
28
32
|
export const refID = (asset, provider) => asset.source.type === "ref" && asset.source.provider === provider ? asset.source.id : undefined;
|
|
29
33
|
/** Decode a provider's base64 output once into an owned `bytes` asset, sniffing the type when it is not declared. */
|
package/dist/provider-error.js
CHANGED
|
@@ -65,6 +65,7 @@ const INVALID_REQUEST_CODES = new Set(["invalid_prompt", "invalid_request_error"
|
|
|
65
65
|
// emits `image_content_policy_violation` as the native code.
|
|
66
66
|
const CONTENT_POLICY_CODES = new Set([
|
|
67
67
|
"content_filter",
|
|
68
|
+
"content_moderation",
|
|
68
69
|
"responsibleaipolicyviolation",
|
|
69
70
|
"content_policy_violation",
|
|
70
71
|
"image_content_policy_violation",
|
|
@@ -157,6 +158,8 @@ function providerCodes(value) {
|
|
|
157
158
|
const exception = isRecord(decoded.exception) ? decoded.exception : undefined;
|
|
158
159
|
return [
|
|
159
160
|
decoded.code,
|
|
161
|
+
// Stability's `{ id, name, errors }` bodies carry the code in `name`.
|
|
162
|
+
Array.isArray(decoded.errors) ? decoded.name : undefined,
|
|
160
163
|
decoded.error_type,
|
|
161
164
|
error?.code,
|
|
162
165
|
error?.type,
|
|
@@ -192,11 +192,11 @@ declare const responsesRoute: Route<{
|
|
|
192
192
|
readonly size?: string | undefined;
|
|
193
193
|
readonly action?: "generate" | "auto" | "edit" | undefined;
|
|
194
194
|
readonly output_format?: "png" | "jpeg" | "webp" | undefined;
|
|
195
|
+
readonly partial_images?: number | undefined;
|
|
195
196
|
readonly quality?: "auto" | "low" | "medium" | "high" | undefined;
|
|
196
197
|
readonly background?: "auto" | "opaque" | "transparent" | undefined;
|
|
197
198
|
readonly output_compression?: number | undefined;
|
|
198
199
|
readonly input_fidelity?: "low" | "high" | undefined;
|
|
199
|
-
readonly partial_images?: number | undefined;
|
|
200
200
|
} | {
|
|
201
201
|
readonly type: "namespace";
|
|
202
202
|
readonly name: string;
|
|
@@ -532,11 +532,11 @@ export declare const routes: (Route<{
|
|
|
532
532
|
readonly size?: string | undefined;
|
|
533
533
|
readonly action?: "generate" | "auto" | "edit" | undefined;
|
|
534
534
|
readonly output_format?: "png" | "jpeg" | "webp" | undefined;
|
|
535
|
+
readonly partial_images?: number | undefined;
|
|
535
536
|
readonly quality?: "auto" | "low" | "medium" | "high" | undefined;
|
|
536
537
|
readonly background?: "auto" | "opaque" | "transparent" | undefined;
|
|
537
538
|
readonly output_compression?: number | undefined;
|
|
538
539
|
readonly input_fidelity?: "low" | "high" | undefined;
|
|
539
|
-
readonly partial_images?: number | undefined;
|
|
540
540
|
} | {
|
|
541
541
|
readonly type: "namespace";
|
|
542
542
|
readonly name: string;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ProviderAuthOption } from "../route/auth-options.js";
|
|
2
|
+
import { HttpOptions, type ModelID } from "../schema/index.js";
|
|
3
|
+
export type { BlackForestLabsImageOptions } from "../protocols/bfl-images.js";
|
|
4
|
+
export declare const id: string & import("effect/Brand").Brand<"AI.ProviderID">;
|
|
5
|
+
export type Config = ProviderAuthOption<"optional"> & {
|
|
6
|
+
/** `https://api.eu.bfl.ai` or `https://api.us.bfl.ai` pin inference to one region. */
|
|
7
|
+
readonly baseURL?: string;
|
|
8
|
+
readonly headers?: Record<string, string>;
|
|
9
|
+
readonly http?: HttpOptions.Input;
|
|
10
|
+
};
|
|
11
|
+
export declare const configure: (input?: Config) => {
|
|
12
|
+
id: string & import("effect/Brand").Brand<"AI.ProviderID">;
|
|
13
|
+
image: (modelID: string | ModelID) => import("../image.js").ImageModel<import("../protocols/bfl-images.js").BlackForestLabsImageOptions>;
|
|
14
|
+
configure: (input?: Config) => /*elided*/ any;
|
|
15
|
+
};
|
|
16
|
+
export declare const provider: {
|
|
17
|
+
id: string & import("effect/Brand").Brand<"AI.ProviderID">;
|
|
18
|
+
image: (modelID: string | ModelID) => import("../image.js").ImageModel<import("../protocols/bfl-images.js").BlackForestLabsImageOptions>;
|
|
19
|
+
configure: (input?: Config) => {
|
|
20
|
+
id: string & import("effect/Brand").Brand<"AI.ProviderID">;
|
|
21
|
+
image: (modelID: string | ModelID) => import("../image.js").ImageModel<import("../protocols/bfl-images.js").BlackForestLabsImageOptions>;
|
|
22
|
+
configure: /*elided*/ any;
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
export declare const image: (modelID: string | ModelID) => import("../image.js").ImageModel<import("../protocols/bfl-images.js").BlackForestLabsImageOptions>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Auth } from "../route/auth.js";
|
|
2
|
+
import { HttpOptions, ProviderID } from "../schema/index.js";
|
|
3
|
+
import { BlackForestLabsImages, DEFAULT_BASE_URL } from "../protocols/bfl-images.js";
|
|
4
|
+
export const id = ProviderID.make("black-forest-labs");
|
|
5
|
+
const baseURL = DEFAULT_BASE_URL;
|
|
6
|
+
const auth = (options) => {
|
|
7
|
+
if ("auth" in options && options.auth)
|
|
8
|
+
return options.auth;
|
|
9
|
+
return Auth.optional("apiKey" in options ? options.apiKey : undefined, "apiKey")
|
|
10
|
+
.orElse(Auth.config("BFL_API_KEY"))
|
|
11
|
+
.pipe(Auth.header("x-key"));
|
|
12
|
+
};
|
|
13
|
+
export const configure = (input = {}) => {
|
|
14
|
+
const image = (modelID) => BlackForestLabsImages.model({
|
|
15
|
+
id: modelID,
|
|
16
|
+
auth: auth(input),
|
|
17
|
+
baseURL: input.baseURL ?? baseURL,
|
|
18
|
+
headers: input.headers,
|
|
19
|
+
http: input.http === undefined ? undefined : HttpOptions.make(input.http),
|
|
20
|
+
});
|
|
21
|
+
return {
|
|
22
|
+
id,
|
|
23
|
+
image,
|
|
24
|
+
configure,
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
export const provider = configure();
|
|
28
|
+
export const image = provider.image;
|
|
@@ -198,11 +198,11 @@ export declare const responsesRoute: import("../route/client.js").Route<{
|
|
|
198
198
|
readonly size?: string | undefined;
|
|
199
199
|
readonly action?: "generate" | "auto" | "edit" | undefined;
|
|
200
200
|
readonly output_format?: "png" | "jpeg" | "webp" | undefined;
|
|
201
|
+
readonly partial_images?: number | undefined;
|
|
201
202
|
readonly quality?: "auto" | "low" | "medium" | "high" | undefined;
|
|
202
203
|
readonly background?: "auto" | "opaque" | "transparent" | undefined;
|
|
203
204
|
readonly output_compression?: number | undefined;
|
|
204
205
|
readonly input_fidelity?: "low" | "high" | undefined;
|
|
205
|
-
readonly partial_images?: number | undefined;
|
|
206
206
|
} | {
|
|
207
207
|
readonly type: "namespace";
|
|
208
208
|
readonly name: string;
|
|
@@ -1195,11 +1195,11 @@ export declare const routes: (import("../route/client.js").Route<{
|
|
|
1195
1195
|
readonly size?: string | undefined;
|
|
1196
1196
|
readonly action?: "generate" | "auto" | "edit" | undefined;
|
|
1197
1197
|
readonly output_format?: "png" | "jpeg" | "webp" | undefined;
|
|
1198
|
+
readonly partial_images?: number | undefined;
|
|
1198
1199
|
readonly quality?: "auto" | "low" | "medium" | "high" | undefined;
|
|
1199
1200
|
readonly background?: "auto" | "opaque" | "transparent" | undefined;
|
|
1200
1201
|
readonly output_compression?: number | undefined;
|
|
1201
1202
|
readonly input_fidelity?: "low" | "high" | undefined;
|
|
1202
|
-
readonly partial_images?: number | undefined;
|
|
1203
1203
|
} | {
|
|
1204
1204
|
readonly type: "namespace";
|
|
1205
1205
|
readonly name: string;
|
package/dist/providers/fal.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ProviderAuthOption } from "../route/auth-options.js";
|
|
2
2
|
import { HttpOptions, type ModelID } from "../schema/index.js";
|
|
3
|
+
export type { FalImageOptions } from "../protocols/fal-images.js";
|
|
3
4
|
export type { FalVideoOptions } from "../protocols/fal-video.js";
|
|
4
5
|
export declare const id: string & import("effect/Brand").Brand<"AI.ProviderID">;
|
|
5
6
|
export type Config = ProviderAuthOption<"optional"> & {
|
|
@@ -9,16 +10,20 @@ export type Config = ProviderAuthOption<"optional"> & {
|
|
|
9
10
|
};
|
|
10
11
|
export declare const configure: (input?: Config) => {
|
|
11
12
|
id: string & import("effect/Brand").Brand<"AI.ProviderID">;
|
|
13
|
+
image: (modelID: string | ModelID) => import("../image.js").ImageModel<import("../protocols/fal-images.js").FalImageOptions>;
|
|
12
14
|
video: (modelID: string | ModelID) => import("../video.js").VideoModel<import("../protocols/fal-video.js").FalVideoOptions>;
|
|
13
15
|
configure: (input?: Config) => /*elided*/ any;
|
|
14
16
|
};
|
|
15
17
|
export declare const provider: {
|
|
16
18
|
id: string & import("effect/Brand").Brand<"AI.ProviderID">;
|
|
19
|
+
image: (modelID: string | ModelID) => import("../image.js").ImageModel<import("../protocols/fal-images.js").FalImageOptions>;
|
|
17
20
|
video: (modelID: string | ModelID) => import("../video.js").VideoModel<import("../protocols/fal-video.js").FalVideoOptions>;
|
|
18
21
|
configure: (input?: Config) => {
|
|
19
22
|
id: string & import("effect/Brand").Brand<"AI.ProviderID">;
|
|
23
|
+
image: (modelID: string | ModelID) => import("../image.js").ImageModel<import("../protocols/fal-images.js").FalImageOptions>;
|
|
20
24
|
video: (modelID: string | ModelID) => import("../video.js").VideoModel<import("../protocols/fal-video.js").FalVideoOptions>;
|
|
21
25
|
configure: /*elided*/ any;
|
|
22
26
|
};
|
|
23
27
|
};
|
|
28
|
+
export declare const image: (modelID: string | ModelID) => import("../image.js").ImageModel<import("../protocols/fal-images.js").FalImageOptions>;
|
|
24
29
|
export declare const video: (modelID: string | ModelID) => import("../video.js").VideoModel<import("../protocols/fal-video.js").FalVideoOptions>;
|
package/dist/providers/fal.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { Auth } from "../route/auth.js";
|
|
2
2
|
import { HttpOptions, ProviderID } from "../schema/index.js";
|
|
3
|
-
import {
|
|
3
|
+
import { FalImages } from "../protocols/fal-images.js";
|
|
4
|
+
import { FalVideo } from "../protocols/fal-video.js";
|
|
5
|
+
import { FalQueue } from "../protocols/utils/fal-queue.js";
|
|
4
6
|
export const id = ProviderID.make("fal");
|
|
5
|
-
const baseURL = DEFAULT_BASE_URL;
|
|
7
|
+
const baseURL = FalQueue.DEFAULT_BASE_URL;
|
|
6
8
|
// fal authenticates with `Authorization: Key <FAL_KEY>` rather than a bearer token.
|
|
7
9
|
const auth = (options) => {
|
|
8
10
|
if ("auth" in options && options.auth)
|
|
@@ -12,7 +14,7 @@ const auth = (options) => {
|
|
|
12
14
|
.pipe(Auth.scheme("Key"));
|
|
13
15
|
};
|
|
14
16
|
export const configure = (input = {}) => {
|
|
15
|
-
const
|
|
17
|
+
const media = (modelID) => ({
|
|
16
18
|
id: modelID,
|
|
17
19
|
auth: auth(input),
|
|
18
20
|
baseURL: input.baseURL ?? baseURL,
|
|
@@ -21,9 +23,11 @@ export const configure = (input = {}) => {
|
|
|
21
23
|
});
|
|
22
24
|
return {
|
|
23
25
|
id,
|
|
24
|
-
|
|
26
|
+
image: (modelID) => FalImages.model(media(modelID)),
|
|
27
|
+
video: (modelID) => FalVideo.model(media(modelID)),
|
|
25
28
|
configure,
|
|
26
29
|
};
|
|
27
30
|
};
|
|
28
31
|
export const provider = configure();
|
|
32
|
+
export const image = provider.image;
|
|
29
33
|
export const video = provider.video;
|
|
@@ -6,6 +6,7 @@ export * as AmazonBedrockMantle from "./amazon-bedrock-mantle.js";
|
|
|
6
6
|
export * as AssemblyAI from "./assemblyai.js";
|
|
7
7
|
export * as Azure from "./azure.js";
|
|
8
8
|
export * as Baseten from "./baseten.js";
|
|
9
|
+
export * as BlackForestLabs from "./black-forest-labs.js";
|
|
9
10
|
export * as Cartesia from "./cartesia.js";
|
|
10
11
|
export * as Cerebras from "./cerebras.js";
|
|
11
12
|
export * as CloudflareAIGateway from "./cloudflare-ai-gateway.js";
|
|
@@ -31,7 +32,9 @@ export * as OpenAICompatible from "./openai-compatible.js";
|
|
|
31
32
|
export * as OpenAICompatibleResponses from "./openai-compatible-responses.js";
|
|
32
33
|
export * as OpenCodeZen from "./opencode-zen.js";
|
|
33
34
|
export * as OpenRouter from "./openrouter.js";
|
|
35
|
+
export * as Replicate from "./replicate.js";
|
|
34
36
|
export * as Runway from "./runway.js";
|
|
37
|
+
export * as Stability from "./stability.js";
|
|
35
38
|
export * as TogetherAI from "./togetherai.js";
|
|
36
39
|
export * as TypeSafeAI from "./typesafe-ai.js";
|
|
37
40
|
export * as VercelAIGateway from "./vercel-ai-gateway.js";
|
package/dist/providers/index.js
CHANGED
|
@@ -6,6 +6,7 @@ export * as AmazonBedrockMantle from "./amazon-bedrock-mantle.js";
|
|
|
6
6
|
export * as AssemblyAI from "./assemblyai.js";
|
|
7
7
|
export * as Azure from "./azure.js";
|
|
8
8
|
export * as Baseten from "./baseten.js";
|
|
9
|
+
export * as BlackForestLabs from "./black-forest-labs.js";
|
|
9
10
|
export * as Cartesia from "./cartesia.js";
|
|
10
11
|
export * as Cerebras from "./cerebras.js";
|
|
11
12
|
export * as CloudflareAIGateway from "./cloudflare-ai-gateway.js";
|
|
@@ -31,7 +32,9 @@ export * as OpenAICompatible from "./openai-compatible.js";
|
|
|
31
32
|
export * as OpenAICompatibleResponses from "./openai-compatible-responses.js";
|
|
32
33
|
export * as OpenCodeZen from "./opencode-zen.js";
|
|
33
34
|
export * as OpenRouter from "./openrouter.js";
|
|
35
|
+
export * as Replicate from "./replicate.js";
|
|
34
36
|
export * as Runway from "./runway.js";
|
|
37
|
+
export * as Stability from "./stability.js";
|
|
35
38
|
export * as TogetherAI from "./togetherai.js";
|
|
36
39
|
export * as TypeSafeAI from "./typesafe-ai.js";
|
|
37
40
|
export * as VercelAIGateway from "./vercel-ai-gateway.js";
|
|
@@ -291,11 +291,11 @@ export declare const routes: (Route<{
|
|
|
291
291
|
readonly size?: string | undefined;
|
|
292
292
|
readonly action?: "generate" | "auto" | "edit" | undefined;
|
|
293
293
|
readonly output_format?: "png" | "jpeg" | "webp" | undefined;
|
|
294
|
+
readonly partial_images?: number | undefined;
|
|
294
295
|
readonly quality?: "auto" | "low" | "medium" | "high" | undefined;
|
|
295
296
|
readonly background?: "auto" | "opaque" | "transparent" | undefined;
|
|
296
297
|
readonly output_compression?: number | undefined;
|
|
297
298
|
readonly input_fidelity?: "low" | "high" | undefined;
|
|
298
|
-
readonly partial_images?: number | undefined;
|
|
299
299
|
} | {
|
|
300
300
|
readonly type: "namespace";
|
|
301
301
|
readonly name: string;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type ProviderAuthOption } from "../route/auth-options.js";
|
|
2
|
+
import { HttpOptions, type ModelID } from "../schema/index.js";
|
|
3
|
+
export type { ReplicateImageOptions } from "../protocols/replicate-images.js";
|
|
4
|
+
export declare const id: string & import("effect/Brand").Brand<"AI.ProviderID">;
|
|
5
|
+
export type Config = ProviderAuthOption<"optional"> & {
|
|
6
|
+
readonly baseURL?: string;
|
|
7
|
+
/** `{ Prefer: "wait=60" }` holds the submission open until the prediction finishes (up to 60 seconds). */
|
|
8
|
+
readonly headers?: Record<string, string>;
|
|
9
|
+
readonly http?: HttpOptions.Input;
|
|
10
|
+
};
|
|
11
|
+
export declare const configure: (input?: Config) => {
|
|
12
|
+
id: string & import("effect/Brand").Brand<"AI.ProviderID">;
|
|
13
|
+
image: (modelID: string | ModelID) => import("../image.js").ImageModel<import("../protocols/replicate-images.js").ReplicateImageOptions>;
|
|
14
|
+
configure: (input?: Config) => /*elided*/ any;
|
|
15
|
+
};
|
|
16
|
+
export declare const provider: {
|
|
17
|
+
id: string & import("effect/Brand").Brand<"AI.ProviderID">;
|
|
18
|
+
image: (modelID: string | ModelID) => import("../image.js").ImageModel<import("../protocols/replicate-images.js").ReplicateImageOptions>;
|
|
19
|
+
configure: (input?: Config) => {
|
|
20
|
+
id: string & import("effect/Brand").Brand<"AI.ProviderID">;
|
|
21
|
+
image: (modelID: string | ModelID) => import("../image.js").ImageModel<import("../protocols/replicate-images.js").ReplicateImageOptions>;
|
|
22
|
+
configure: /*elided*/ any;
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
export declare const image: (modelID: string | ModelID) => import("../image.js").ImageModel<import("../protocols/replicate-images.js").ReplicateImageOptions>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { AuthOptions } from "../route/auth-options.js";
|
|
2
|
+
import { HttpOptions, ProviderID } from "../schema/index.js";
|
|
3
|
+
import { DEFAULT_BASE_URL, ReplicateImages } from "../protocols/replicate-images.js";
|
|
4
|
+
export const id = ProviderID.make("replicate");
|
|
5
|
+
const baseURL = DEFAULT_BASE_URL;
|
|
6
|
+
const auth = (options) => AuthOptions.bearer(options, "REPLICATE_API_TOKEN");
|
|
7
|
+
export const configure = (input = {}) => {
|
|
8
|
+
const image = (modelID) => ReplicateImages.model({
|
|
9
|
+
id: modelID,
|
|
10
|
+
auth: auth(input),
|
|
11
|
+
baseURL: input.baseURL ?? baseURL,
|
|
12
|
+
headers: input.headers,
|
|
13
|
+
http: input.http === undefined ? undefined : HttpOptions.make(input.http),
|
|
14
|
+
});
|
|
15
|
+
return {
|
|
16
|
+
id,
|
|
17
|
+
image,
|
|
18
|
+
configure,
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
export const provider = configure();
|
|
22
|
+
export const image = provider.image;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type ProviderAuthOption } from "../route/auth-options.js";
|
|
2
|
+
import { HttpOptions, type ModelID } from "../schema/index.js";
|
|
3
|
+
export type { StabilityImageOptions, StabilityUpscaleOptions } from "../protocols/stability-images.js";
|
|
4
|
+
export declare const id: string & import("effect/Brand").Brand<"AI.ProviderID">;
|
|
5
|
+
export type Config = ProviderAuthOption<"optional"> & {
|
|
6
|
+
readonly baseURL?: string;
|
|
7
|
+
readonly headers?: Record<string, string>;
|
|
8
|
+
readonly http?: HttpOptions.Input;
|
|
9
|
+
};
|
|
10
|
+
export declare const configure: (input?: Config) => {
|
|
11
|
+
id: string & import("effect/Brand").Brand<"AI.ProviderID">;
|
|
12
|
+
image: (modelID: string | ModelID) => import("../image.js").ImageModel<import("../protocols/stability-images.js").StabilityImageOptions>;
|
|
13
|
+
upscale: () => import("../image.js").ImageModel<import("../protocols/stability-images.js").StabilityUpscaleOptions>;
|
|
14
|
+
configure: (input?: Config) => /*elided*/ any;
|
|
15
|
+
};
|
|
16
|
+
export declare const provider: {
|
|
17
|
+
id: string & import("effect/Brand").Brand<"AI.ProviderID">;
|
|
18
|
+
image: (modelID: string | ModelID) => import("../image.js").ImageModel<import("../protocols/stability-images.js").StabilityImageOptions>;
|
|
19
|
+
upscale: () => import("../image.js").ImageModel<import("../protocols/stability-images.js").StabilityUpscaleOptions>;
|
|
20
|
+
configure: (input?: Config) => {
|
|
21
|
+
id: string & import("effect/Brand").Brand<"AI.ProviderID">;
|
|
22
|
+
image: (modelID: string | ModelID) => import("../image.js").ImageModel<import("../protocols/stability-images.js").StabilityImageOptions>;
|
|
23
|
+
upscale: () => import("../image.js").ImageModel<import("../protocols/stability-images.js").StabilityUpscaleOptions>;
|
|
24
|
+
configure: /*elided*/ any;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
export declare const image: (modelID: string | ModelID) => import("../image.js").ImageModel<import("../protocols/stability-images.js").StabilityImageOptions>;
|
|
28
|
+
export declare const upscale: () => import("../image.js").ImageModel<import("../protocols/stability-images.js").StabilityUpscaleOptions>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { AuthOptions } from "../route/auth-options.js";
|
|
2
|
+
import { HttpOptions, ProviderID } from "../schema/index.js";
|
|
3
|
+
import { DEFAULT_BASE_URL, StabilityImages } from "../protocols/stability-images.js";
|
|
4
|
+
export const id = ProviderID.make("stability");
|
|
5
|
+
const baseURL = DEFAULT_BASE_URL;
|
|
6
|
+
const auth = (options) => AuthOptions.bearer(options, "STABILITY_API_KEY");
|
|
7
|
+
export const configure = (input = {}) => {
|
|
8
|
+
const deployment = {
|
|
9
|
+
auth: auth(input),
|
|
10
|
+
baseURL: input.baseURL ?? baseURL,
|
|
11
|
+
headers: input.headers,
|
|
12
|
+
http: input.http === undefined ? undefined : HttpOptions.make(input.http),
|
|
13
|
+
};
|
|
14
|
+
return {
|
|
15
|
+
id,
|
|
16
|
+
image: (modelID) => StabilityImages.model({ ...deployment, id: modelID }),
|
|
17
|
+
upscale: () => StabilityImages.upscaleModel(deployment),
|
|
18
|
+
configure,
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
export const provider = configure();
|
|
22
|
+
export const image = provider.image;
|
|
23
|
+
export const upscale = provider.upscale;
|
|
@@ -52,11 +52,13 @@ export interface Started<Token> {
|
|
|
52
52
|
}
|
|
53
53
|
/**
|
|
54
54
|
* A follow-up call's inputs: the decoded token and the auth headers the route sent, so a protocol can attach them
|
|
55
|
-
* to output URLs that require the same credentials to download (Veo).
|
|
55
|
+
* to output URLs that require the same credentials to download (Veo). `materialize` downloads an output through the
|
|
56
|
+
* route's executor, for URLs that expire too soon to hand back (BFL).
|
|
56
57
|
*/
|
|
57
58
|
export interface PollContext<Token> {
|
|
58
59
|
readonly token: Token;
|
|
59
60
|
readonly auth: Record<string, string>;
|
|
61
|
+
readonly materialize: (asset: Media.Asset) => Effect.Effect<Media.Asset, AIError>;
|
|
60
62
|
}
|
|
61
63
|
/**
|
|
62
64
|
* Submit, then poll. `start` posts the body to the route endpoint; `status`, `result`, and `cancel` are follow-up
|