@howells/motif-sdk 2.0.0 → 4.0.0
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 +37 -97
- package/dist/image.d.ts +25 -42
- package/dist/image.js +952 -183
- package/dist/index.cjs +5022 -1282
- package/dist/index.d.cts +1122 -3181
- package/dist/index.d.ts +1122 -3181
- package/dist/index.js +5004 -1253
- package/package.json +7 -4
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @howells/motif-sdk
|
|
2
2
|
|
|
3
|
-
Public Node SDK for Motif
|
|
3
|
+
Public Node SDK for Motif: Task-first image, video and utility work on fal.ai, plus a provider-agnostic image layer.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -8,129 +8,69 @@ Public Node SDK for Motif fal.ai generation, editing, utility tools, and model m
|
|
|
8
8
|
npm install @howells/motif-sdk
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
##
|
|
11
|
+
## Run a Task
|
|
12
12
|
|
|
13
|
-
The
|
|
14
|
-
|
|
15
|
-
The examples in this section use the low-level `FalClient`, the fal-native client for fal-specific capabilities (queue, upload, upscale, background removal, video, and utility tools).
|
|
13
|
+
The Task client, `createMotif`, is the fal surface: name a Task and, optionally, a Tier, and Motif chooses the Model, builds its request and runs it on fal. `createMotifImage` (`@howells/motif-sdk/image`) is the provider-agnostic generate/edit layer across google, openai, replicate, and fal. See [Image Layer](#image-layer-howellsmotif-sdkimage) below.
|
|
16
14
|
|
|
17
15
|
```ts
|
|
18
|
-
import {
|
|
16
|
+
import { createMotif } from "@howells/motif-sdk";
|
|
19
17
|
|
|
20
|
-
const motif =
|
|
21
|
-
apiKey: process.env.FAL_KEY!,
|
|
22
|
-
retries: 3,
|
|
23
|
-
timeout: 120_000,
|
|
24
|
-
});
|
|
18
|
+
const motif = createMotif(); // reads FAL_KEY
|
|
25
19
|
|
|
26
20
|
const result = await motif.generate({
|
|
27
|
-
model: "banana2",
|
|
28
21
|
prompt: "editorial product photo",
|
|
29
22
|
resolution: "2K",
|
|
30
|
-
|
|
31
|
-
ephemeral: true,
|
|
23
|
+
tier: "quality",
|
|
32
24
|
});
|
|
33
25
|
|
|
34
26
|
if (result.isErr()) {
|
|
35
27
|
throw result.error;
|
|
36
28
|
}
|
|
37
29
|
|
|
38
|
-
console.log(result.value.
|
|
30
|
+
console.log(result.value.model, result.value.files[0]?.url, result.value.cost);
|
|
39
31
|
```
|
|
40
32
|
|
|
41
|
-
Every
|
|
33
|
+
Every Task function returns `Result<TaskOutput, MotifError>` from `neverthrow` and does not throw for fal request failures; check `isErr()` / `isOk()`.
|
|
42
34
|
|
|
43
|
-
##
|
|
35
|
+
## Plan Without Calling fal
|
|
44
36
|
|
|
45
|
-
|
|
37
|
+
`plan(task, input, { dryRun: true })` resolves the Model and returns the endpoint, body and projected cost with no I/O and no key.
|
|
46
38
|
|
|
47
39
|
```ts
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
quality: "auto",
|
|
57
|
-
syncMode: true,
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
console.log(preview.endpoint);
|
|
61
|
-
console.log(preview.body);
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
## Queue, Upload, and Cleanup
|
|
65
|
-
|
|
66
|
-
```ts
|
|
67
|
-
const job = await motif.submitGeneration({
|
|
68
|
-
model: "gpt2",
|
|
69
|
-
prompt: "gallery poster",
|
|
70
|
-
});
|
|
40
|
+
const plan = motif.plan(
|
|
41
|
+
"erase",
|
|
42
|
+
{
|
|
43
|
+
image: "https://example.com/room.png",
|
|
44
|
+
prompt: "the chair",
|
|
45
|
+
},
|
|
46
|
+
{ dryRun: true }
|
|
47
|
+
);
|
|
71
48
|
|
|
72
|
-
if (
|
|
73
|
-
|
|
74
|
-
job.value.endpoint,
|
|
75
|
-
job.value.requestId
|
|
76
|
-
);
|
|
77
|
-
const completed = await motif.getJobResult(
|
|
78
|
-
job.value.endpoint,
|
|
79
|
-
job.value.requestId
|
|
80
|
-
);
|
|
49
|
+
if (plan.isOk()) {
|
|
50
|
+
console.log(plan.value.model, plan.value.cost);
|
|
81
51
|
}
|
|
82
|
-
|
|
83
|
-
const uploaded = await motif.uploadToFalCdn(fileBytes, {
|
|
84
|
-
contentType: "image/png",
|
|
85
|
-
fileName: "reference.png",
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
const deleted = await motif.deletePayloads("fal-request-id");
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
## Utility Tools and Video
|
|
92
|
-
|
|
93
|
-
```ts
|
|
94
|
-
const mask = await motif.runTool({
|
|
95
|
-
tool: "sam3-image",
|
|
96
|
-
input: "https://example.com/input.png",
|
|
97
|
-
options: { prompt: "shoe", max_masks: 2 },
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
const videoJob = await motif.submitVideo({
|
|
101
|
-
imageUrl: "https://example.com/frame.png",
|
|
102
|
-
prompt: "slow cinematic push-in",
|
|
103
|
-
duration: 5,
|
|
104
|
-
generateAudio: false,
|
|
105
|
-
});
|
|
106
52
|
```
|
|
107
53
|
|
|
108
54
|
## Main Exports
|
|
109
55
|
|
|
110
|
-
- `
|
|
111
|
-
- `
|
|
112
|
-
- `
|
|
113
|
-
- `
|
|
114
|
-
- `
|
|
115
|
-
- `
|
|
116
|
-
- `
|
|
117
|
-
- `estimateCost`, `estimateVideoCost` - Local cost estimates used by CLI dry runs and SDK previews.
|
|
118
|
-
- `getFalKeyFromEnv` - `@howells/envy` backed `FAL_KEY` parsing.
|
|
56
|
+
- `createMotif` - the Task client: one function per Task plus `run`, `plan`, `upload` and `deletePayloads`.
|
|
57
|
+
- `TASKS`, `TASK_IDS`, `TIERS`, `resolveTask`, `modelProfile`, `tierChangesChoice` - the Task registry and Model resolution.
|
|
58
|
+
- `createMotifImage` (`@howells/motif-sdk/image`) - provider-agnostic generate/edit/best-of-N across google, openai, replicate, and fal.
|
|
59
|
+
- `ASPECT_RATIOS`, `RESOLUTIONS`, `FORMAT_PRESETS` - shared sizing metadata.
|
|
60
|
+
- `LOOKS`, `CREATIVE_TAXONOMY`, `enrichPrompt`, `validateCreativeDirection` - house looks and moods.
|
|
61
|
+
- `formatCost`, `sumCosts` - cost formatting and totals.
|
|
62
|
+
- `getFalKeyFromEnv`, `getOpenAiKeyFromEnv` - `@howells/envy` backed key parsing.
|
|
119
63
|
- Re-exported `neverthrow` helpers: `ok`, `err`, `Result`, `ResultAsync`.
|
|
120
64
|
|
|
121
65
|
## Common Types
|
|
122
66
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
- `
|
|
126
|
-
- `UpscaleOptions`, `RemoveBackgroundOptions`, `VideoOptions`, `VideoResponse`
|
|
127
|
-
- `QueuedJob`, `JobStatus`, `FalClientConfig`
|
|
128
|
-
- `ModelConfig`, `AspectRatio`, `Resolution`, `ImageSize`, `ImageQuality`, `BackgroundMode`, `ThinkingLevel`
|
|
129
|
-
- `FalToolConfig`, `FalToolId`, `FalToolRequest`, `FalToolRunOptions`
|
|
67
|
+
- `MotifClient`, `MotifClientConfig`, `TaskInput`, `TaskOutput`, `TaskPlan`, `TaskFile`
|
|
68
|
+
- `TaskId`, `Tier`, `TaskDefinition`, `RankedModel`, `TaskRequest`, `TaskResolution`, `ModelProfile`
|
|
69
|
+
- `AspectRatio`, `Resolution`, `CustomImageSize`, `ImageSizeBounds`, `MotifError`
|
|
130
70
|
|
|
131
71
|
## Image Layer (`@howells/motif-sdk/image`)
|
|
132
72
|
|
|
133
|
-
The
|
|
73
|
+
The provider-agnostic image generation + editing layer, for callers who choose the provider and model themselves. It is an ESM-only subpath export, built on the Vercel AI SDK image interface (`ai`'s `generateImage`).
|
|
134
74
|
|
|
135
75
|
```bash
|
|
136
76
|
npm install @howells/motif-sdk
|
|
@@ -143,14 +83,14 @@ const img = createMotifImage({ defaultProvider: "google" });
|
|
|
143
83
|
|
|
144
84
|
// text -> image
|
|
145
85
|
const generated = await img.generate({
|
|
146
|
-
|
|
86
|
+
model: "gemini-3.1-flash-image-preview",
|
|
147
87
|
prompt: "a plain room, bare concrete wall",
|
|
148
88
|
aspectRatio: "1:1",
|
|
149
89
|
});
|
|
150
90
|
|
|
151
91
|
// multi-image edit (images + instruction, optional mask -> image out)
|
|
152
92
|
const edited = await img.edit({
|
|
153
|
-
|
|
93
|
+
model: "gemini-3.1-flash-image-preview",
|
|
154
94
|
images: [roomBytes, tileBytes],
|
|
155
95
|
instruction: "Apply the oak texture from image 2 onto the wall in image 1.",
|
|
156
96
|
mask: surfaceMaskBytes,
|
|
@@ -171,13 +111,13 @@ Four providers are implemented, each reading its own API key from the environmen
|
|
|
171
111
|
| Provider | Env var | Notes |
|
|
172
112
|
| --- | --- | --- |
|
|
173
113
|
| `google` | `GOOGLE_GENERATIVE_AI_API_KEY` | Default provider; Gemini gen + edit |
|
|
174
|
-
| `openai` | `OPENAI_API_KEY` | GPT Image 2.5 Flare
|
|
114
|
+
| `openai` | `OPENAI_API_KEY` | GPT Image 2.5 Flare and Sunburst |
|
|
175
115
|
| `replicate` | `REPLICATE_API_TOKEN` | flux-1.1-pro-ultra |
|
|
176
116
|
| `fal` | `FAL_KEY` | fal-hosted adapter |
|
|
177
117
|
|
|
178
|
-
`generate()` and `edit()`
|
|
118
|
+
`generate()` and `edit()` take a provider model id; Task resolution chooses which model to pass, not the image layer. Every result carries a normalized per-call `cost: { usd, source }`.
|
|
179
119
|
|
|
180
|
-
|
|
120
|
+
Both `gpt-image-2.5-flare` and `gpt-image-2.5-sunburst` support generation and multi-image editing:
|
|
181
121
|
|
|
182
122
|
```ts
|
|
183
123
|
const image = createMotifImage({ defaultProvider: "openai" });
|
|
@@ -192,7 +132,7 @@ const refined = await image.edit({
|
|
|
192
132
|
});
|
|
193
133
|
```
|
|
194
134
|
|
|
195
|
-
These models use token-based billing. Motif has no static per-image estimate for them, so `cost` is `{ usd: 0, source: "unknown" }` unless the provider supplies a cost; this does not mean generation is free. See the official [Flare](https://developers.openai.com/api/docs/models/gpt-image-2.5-flare) and [Sunburst](https://developers.openai.com/api/docs/models/gpt-image-2.5-sunburst) model pages. The installed OpenAI adapter accepts `low`, `medium`, `high`, and `auto` quality; the new `xhigh` and `max` settings require a future adapter update. The
|
|
135
|
+
These models use token-based billing. Motif has no static per-image estimate for them, so `cost` is `{ usd: 0, source: "unknown" }` unless the provider supplies a cost; this does not mean generation is free. See the official [Flare](https://developers.openai.com/api/docs/models/gpt-image-2.5-flare) and [Sunburst](https://developers.openai.com/api/docs/models/gpt-image-2.5-sunburst) model pages. The installed OpenAI adapter accepts `low`, `medium`, `high`, and `auto` quality; the new `xhigh` and `max` settings require a future adapter update. The Task client and the CLI reach these models on fal as `flare` and `sunburst`. Fal supports `xhigh` and `max`, up to 16 edit references, masks and transparent backgrounds. Fal generation estimates are `null` (metered).
|
|
196
136
|
|
|
197
137
|
### Best-of-N with an injectable judge
|
|
198
138
|
|
package/dist/image.d.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { ImageModel, generateImage } from "ai";
|
|
2
2
|
import { Result } from "neverthrow";
|
|
3
|
+
//#region src/types.d.ts
|
|
4
|
+
/** ─── Configuration ──────────────────────────────────────────── */
|
|
5
|
+
/** The network seam: a `fetch`-shaped function. */
|
|
6
|
+
type FalFetch = (url: string, init: RequestInit) => Promise<Response>;
|
|
7
|
+
//#endregion
|
|
3
8
|
//#region src/errors.d.ts
|
|
4
9
|
/**
|
|
5
10
|
* `MotifError` and its coercion helper.
|
|
@@ -15,15 +20,12 @@ declare class MotifError extends Error {
|
|
|
15
20
|
/** fal's request-correlation id (from the `x-fal-request-id` header or the
|
|
16
21
|
* error body). Ties a failure back to fal's dashboard/support. */
|
|
17
22
|
readonly requestId?: string;
|
|
18
|
-
|
|
23
|
+
/** Structured context for the failure, e.g. the refused field. */
|
|
24
|
+
readonly details?: Record<string, unknown>;
|
|
25
|
+
constructor(message: string, status: number, code?: string, requestId?: string, details?: Record<string, unknown>);
|
|
19
26
|
}
|
|
20
27
|
//#endregion
|
|
21
28
|
//#region src/image/types.d.ts
|
|
22
|
-
/**
|
|
23
|
-
* Quality/latency tier. Resolves through a provider-aware tier→model map when no
|
|
24
|
-
* explicit `model` id is given. `balanced` is the default when a tier is omitted.
|
|
25
|
-
*/
|
|
26
|
-
type ImageTier = "fast" | "balanced" | "quality" | "hero";
|
|
27
29
|
/**
|
|
28
30
|
* Image provider id. All four Phase 1b adapters are implemented
|
|
29
31
|
* (`google`, `openai`, `replicate`, `fal`); the type keeps an open union tail so
|
|
@@ -63,6 +65,13 @@ interface MotifImageConfig {
|
|
|
63
65
|
replicate?: {
|
|
64
66
|
apiToken?: string;
|
|
65
67
|
};
|
|
68
|
+
/**
|
|
69
|
+
* Replaces global fetch for every provider request. Remote image URLs passed
|
|
70
|
+
* to `edit` are still downloaded by the AI SDK with global fetch.
|
|
71
|
+
*/
|
|
72
|
+
fetch?: FalFetch;
|
|
73
|
+
/** Retries per call for retryable provider failures. AI SDK default: 2. */
|
|
74
|
+
maxRetries?: number;
|
|
66
75
|
/** fal provider overrides. `apiKey` falls back to `FAL_KEY`. */
|
|
67
76
|
fal?: {
|
|
68
77
|
apiKey?: string;
|
|
@@ -72,10 +81,8 @@ interface MotifImageConfig {
|
|
|
72
81
|
interface GenerateImageOptions {
|
|
73
82
|
/** The text prompt. */
|
|
74
83
|
prompt: string;
|
|
75
|
-
/**
|
|
76
|
-
|
|
77
|
-
/** Explicit provider model id. Overrides `tier`. */
|
|
78
|
-
model?: string;
|
|
84
|
+
/** Provider model id. Task resolution chooses it; the image layer never does. */
|
|
85
|
+
model: string;
|
|
79
86
|
/** Provider override for this call. */
|
|
80
87
|
provider?: ImageProviderId;
|
|
81
88
|
/**
|
|
@@ -132,10 +139,8 @@ interface EditImageOptions {
|
|
|
132
139
|
* `images[0]`.
|
|
133
140
|
*/
|
|
134
141
|
mask?: Uint8Array | string;
|
|
135
|
-
/**
|
|
136
|
-
|
|
137
|
-
/** Explicit provider model id. Overrides `tier`. */
|
|
138
|
-
model?: string;
|
|
142
|
+
/** Provider model id. Task resolution chooses it; the image layer never does. */
|
|
143
|
+
model: string;
|
|
139
144
|
/** Provider override for this call. */
|
|
140
145
|
provider?: ImageProviderId;
|
|
141
146
|
/** Number of images to generate. */
|
|
@@ -238,7 +243,7 @@ interface MotifImageClient {
|
|
|
238
243
|
//#endregion
|
|
239
244
|
//#region src/image/deps.d.ts
|
|
240
245
|
/** A model resolver: builds an AI SDK `ImageModel` for a (provider, model, key). */
|
|
241
|
-
type ResolveImageModel = (provider: ImageProviderId, modelId: string, apiKey?: string) => ImageModel;
|
|
246
|
+
type ResolveImageModel = (provider: ImageProviderId, modelId: string, apiKey?: string, fetch?: FalFetch) => ImageModel;
|
|
242
247
|
/** Internal dependency-injection seam (default: real `generateImage` + adapters). */
|
|
243
248
|
interface MotifImageDeps {
|
|
244
249
|
generateImage?: typeof generateImage;
|
|
@@ -248,14 +253,11 @@ interface MotifImageDeps {
|
|
|
248
253
|
//#region src/image/provider.d.ts
|
|
249
254
|
/**
|
|
250
255
|
* A single image provider. A thin wrapper over the provider's `@ai-sdk/*` image
|
|
251
|
-
* model, plus the metadata the layer needs to
|
|
252
|
-
* meter spend.
|
|
256
|
+
* model, plus the metadata the layer needs to resolve keys and meter spend.
|
|
253
257
|
*/
|
|
254
258
|
interface ImageProviderAdapter {
|
|
255
259
|
/** Provider id, matching the key it is registered under in {@link PROVIDERS}. */
|
|
256
260
|
readonly id: ImageProviderId;
|
|
257
|
-
/** Tier → model id map, used when a call does not pass an explicit `model`. */
|
|
258
|
-
readonly tierModels: Readonly<Record<ImageTier, string>>;
|
|
259
261
|
/** Env var read for the API key when no key is supplied in config. */
|
|
260
262
|
readonly apiKeyEnv: string;
|
|
261
263
|
/**
|
|
@@ -264,7 +266,7 @@ interface ImageProviderAdapter {
|
|
|
264
266
|
* (callers translate this into a `Result.err`). Building a model performs no
|
|
265
267
|
* network I/O.
|
|
266
268
|
*/
|
|
267
|
-
readonly resolveModel: (modelId: string, apiKey?: string) => ImageModel;
|
|
269
|
+
readonly resolveModel: (modelId: string, apiKey?: string, fetch?: FalFetch) => ImageModel;
|
|
268
270
|
/**
|
|
269
271
|
* Static per-model USD/**image** table (best-effort; cited per adapter). This
|
|
270
272
|
* is multiplied by the returned image count to form the call total.
|
|
@@ -292,39 +294,18 @@ export declare const PROVIDERS: Record<ImageProviderId, ImageProviderAdapter>;
|
|
|
292
294
|
export declare function getProviderAdapter(provider: ImageProviderId): ImageProviderAdapter;
|
|
293
295
|
//#endregion
|
|
294
296
|
//#region src/image/google.d.ts
|
|
295
|
-
/**
|
|
296
|
-
* Tier → Gemini image model id.
|
|
297
|
-
*
|
|
298
|
-
* Seeded from Material Desk's `RENDER_IMAGE_MODEL_BY_QUALITY` (the driving
|
|
299
|
-
* consumer, see the design doc). `gemini-2.5-flash-image` is the proven-reachable
|
|
300
|
-
* floor; the preview ids may require allowlist/tier access.
|
|
301
|
-
*/
|
|
302
|
-
export declare const GOOGLE_TIER_MODELS: Readonly<Record<ImageTier, string>>;
|
|
303
297
|
/** Env var read for the Google API key when `apiKey` is not supplied in config. */
|
|
304
298
|
export declare const GOOGLE_API_KEY_ENV = "GOOGLE_GENERATIVE_AI_API_KEY";
|
|
305
299
|
//#endregion
|
|
306
300
|
//#region src/image/openai.d.ts
|
|
307
|
-
/**
|
|
308
|
-
* Flare favors speed for everyday generation; Sunburst favors editing precision.
|
|
309
|
-
* Explicit model ids still override tiers, including older GPT Image models.
|
|
310
|
-
*/
|
|
311
|
-
export declare const OPENAI_TIER_MODELS: Readonly<Record<ImageTier, string>>;
|
|
312
301
|
/** Env var read for the OpenAI API key when `apiKey` is not supplied in config. */
|
|
313
302
|
export declare const OPENAI_API_KEY_ENV = "OPENAI_API_KEY";
|
|
314
303
|
//#endregion
|
|
315
304
|
//#region src/image/replicate.d.ts
|
|
316
|
-
/** Tier → Replicate model id (all tiers → FLUX 1.1 Pro Ultra for now). */
|
|
317
|
-
export declare const REPLICATE_TIER_MODELS: Readonly<Record<ImageTier, string>>;
|
|
318
305
|
/** Env var read for the Replicate API token when `apiToken` is not in config. */
|
|
319
306
|
export declare const REPLICATE_API_KEY_ENV = "REPLICATE_API_TOKEN";
|
|
320
307
|
//#endregion
|
|
321
308
|
//#region src/image/fal.d.ts
|
|
322
|
-
/**
|
|
323
|
-
* Tier → fal model id. For fal, explicit `model:` endpoint ids are the primary
|
|
324
|
-
* path (any fal endpoint resolves via passthrough); this tier map is a
|
|
325
|
-
* convenience covering the two most common (FLUX Pro Ultra + gpt-image).
|
|
326
|
-
*/
|
|
327
|
-
export declare const FAL_TIER_MODELS: Readonly<Record<ImageTier, string>>;
|
|
328
309
|
/** Env var read for the fal key when `apiKey` is not supplied in config. */
|
|
329
310
|
export declare const FAL_API_KEY_ENV = "FAL_KEY";
|
|
330
311
|
//#endregion
|
|
@@ -335,6 +316,8 @@ export declare const FAL_API_KEY_ENV = "FAL_KEY";
|
|
|
335
316
|
* `{ [provider]: { ...; cost?: number } }`. Returns undefined otherwise.
|
|
336
317
|
*/
|
|
337
318
|
export declare function costFromProviderMetadata(providerMetadata: unknown): number | undefined;
|
|
319
|
+
/** Static per-image USD for a (provider, model), or undefined if unknown. */
|
|
320
|
+
export declare function providerPricePerImageUsd(provider: ImageProviderId, modelId: string): number | undefined;
|
|
338
321
|
/**
|
|
339
322
|
* Normalized per-call cost for a generation. Prefers a provider-metadata cost,
|
|
340
323
|
* then the static table (× image count), then unknown.
|
|
@@ -351,4 +334,4 @@ export declare function costForImages(provider: ImageProviderId, modelId: string
|
|
|
351
334
|
*/
|
|
352
335
|
export declare function createMotifImage(config?: MotifImageConfig, deps?: MotifImageDeps): MotifImageClient;
|
|
353
336
|
//#endregion
|
|
354
|
-
export type { BestOfNOptions, BestOfNResult, EditImageOptions, GenerateImageOptions, ImageCost, ImageCostSource, ImageJudge, ImageProviderAdapter, ImageProviderId,
|
|
337
|
+
export type { BestOfNOptions, BestOfNResult, EditImageOptions, GenerateImageOptions, ImageCost, ImageCostSource, ImageJudge, ImageProviderAdapter, ImageProviderId, MotifImageClient, MotifImageConfig, MotifImageFile, MotifImageResult };
|