@howells/motif-sdk 7.2.0 → 7.3.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 +5 -3
- package/dist/image.d.ts +3 -10
- package/dist/image.js +116 -1709
- package/dist/index.cjs +6471 -6072
- package/dist/index.d.cts +132 -36
- package/dist/index.d.ts +132 -36
- package/dist/index.js +6469 -6073
- package/dist/registry.d.ts +253 -183
- package/dist/registry.js +149 -65
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -253,6 +253,11 @@ export declare function validateCreativeDirection(creative: CreativeDirection |
|
|
|
253
253
|
* are joined with `". "` and closed with a period. With no clauses the sanitized prompt is returned unchanged.
|
|
254
254
|
*/
|
|
255
255
|
export declare function enrichPrompt(options: EnrichPromptOptions): CreativePromptResult;
|
|
256
|
+
/** The upscale factors an endpoint takes, from its fal OpenAPI schema. */
|
|
257
|
+
interface ScaleRange {
|
|
258
|
+
max: number;
|
|
259
|
+
min: number;
|
|
260
|
+
}
|
|
256
261
|
/** ─── Model Types ─────────────────────────────────────────────── */
|
|
257
262
|
type AspectRatio = "auto" | "8:1" | "4:1" | "21:9" | "16:9" | "3:2" | "4:3" | "5:4" | "1:1" | "4:5" | "3:4" | "2:3" | "9:16" | "1:4" | "1:8";
|
|
258
263
|
type Resolution = "0.5K" | "1K" | "2K" | "4K";
|
|
@@ -273,6 +278,7 @@ interface ImageSizeBounds {
|
|
|
273
278
|
/** Both edges must be multiples of this. Motif uses 16 when absent. */
|
|
274
279
|
multipleOf?: number;
|
|
275
280
|
}
|
|
281
|
+
/** ─── Queue Types ────────────────────────────────────────────── */
|
|
276
282
|
interface JobStatus {
|
|
277
283
|
error?: string;
|
|
278
284
|
logs?: {
|
|
@@ -298,20 +304,20 @@ export declare class ImageSizeBoundsError extends Error {
|
|
|
298
304
|
readonly bounds: ImageSizeBounds;
|
|
299
305
|
constructor(model: string, aspect: AspectRatio, bounds: ImageSizeBounds);
|
|
300
306
|
}
|
|
301
|
-
/**
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
*/
|
|
307
|
+
/** A named output format: an aspect, and a resolution when the format needs one. */
|
|
308
|
+
interface FormatPreset {
|
|
309
|
+
readonly aspect: AspectRatio;
|
|
310
|
+
/** What the format is for, in a few words. */
|
|
311
|
+
readonly description: string;
|
|
312
|
+
/** Short title for pickers. */
|
|
313
|
+
readonly label: string;
|
|
314
|
+
readonly resolution?: Resolution;
|
|
315
|
+
/** The platform's pixel spec, such as "1080×1920", when it publishes one. */
|
|
316
|
+
readonly size?: string;
|
|
317
|
+
}
|
|
318
|
+
/** Format presets that set aspect + resolution in one click, in display order. */
|
|
319
|
+
export declare const FORMAT_PRESETS: Record<string, FormatPreset>;
|
|
320
|
+
/** `MotifError` and the fal HTTP error mapping. */
|
|
315
321
|
export declare class MotifError extends Error {
|
|
316
322
|
readonly status: number;
|
|
317
323
|
readonly code?: string;
|
|
@@ -324,6 +330,14 @@ export declare class MotifError extends Error {
|
|
|
324
330
|
}
|
|
325
331
|
/** Error code for a fal account that is locked, usually for lack of credit. */
|
|
326
332
|
export declare const ACCOUNT_LOCKED = "ACCOUNT_LOCKED";
|
|
333
|
+
/**
|
|
334
|
+
* Error code for a request that can bill a job and got no clear answer (a
|
|
335
|
+
* connection error, a timeout, a 5xx, or an unreadable acceptance). fal may
|
|
336
|
+
* have accepted it, so the caller must not blindly submit it again.
|
|
337
|
+
*/
|
|
338
|
+
export declare const SUBMISSION_UNCERTAIN = "SUBMISSION_UNCERTAIN";
|
|
339
|
+
/** Error code for a fal response whose body was not the JSON it should be. */
|
|
340
|
+
export declare const INVALID_RESPONSE = "INVALID_RESPONSE";
|
|
327
341
|
/**
|
|
328
342
|
* Whether a fal HTTP failure means the account is locked.
|
|
329
343
|
*
|
|
@@ -331,6 +345,12 @@ export declare const ACCOUNT_LOCKED = "ACCOUNT_LOCKED";
|
|
|
331
345
|
* account has run out of credit. Retrying cannot help, and the key is valid.
|
|
332
346
|
*/
|
|
333
347
|
export declare function isFalAccountLocked(status: number, body: string): boolean;
|
|
348
|
+
/**
|
|
349
|
+
* The option a refused request was stopped on, from either refusal shape: an
|
|
350
|
+
* `INVALID_OPTION` names it as `details.field`, a `NO_MODEL_AVAILABLE` as
|
|
351
|
+
* `details.blockedBy`. Undefined when the error names no option.
|
|
352
|
+
*/
|
|
353
|
+
export declare function refusedOption(error: MotifError): string | undefined;
|
|
334
354
|
/**
|
|
335
355
|
* Arena image scores captured for MOT-72 on October 29, 2026. Flare and
|
|
336
356
|
* Sunburst route to GPT Image 2.6 but keep 2.5's scores until 2.6 is
|
|
@@ -398,6 +418,23 @@ interface TaskDefinition {
|
|
|
398
418
|
readonly modes?: readonly TaskMode[];
|
|
399
419
|
/** Best first. Order within a Tier is the order tried at that Tier. */
|
|
400
420
|
readonly models: readonly RankedModel[];
|
|
421
|
+
/**
|
|
422
|
+
* Its ranked Models are generation Models: a Look can fix one.
|
|
423
|
+
*/
|
|
424
|
+
readonly generationModels?: true;
|
|
425
|
+
/** Refuses a request with no prompt. */
|
|
426
|
+
readonly needsPrompt?: true;
|
|
427
|
+
/** Takes its Source and exactly one Reference. */
|
|
428
|
+
readonly oneReference?: true;
|
|
429
|
+
/** The ranking used when the request carries References, in place of `models`. */
|
|
430
|
+
readonly referenceModels?: readonly RankedModel[];
|
|
431
|
+
/** Makes a new image, so there is no Source to ask for. */
|
|
432
|
+
readonly sourceless?: true;
|
|
433
|
+
/**
|
|
434
|
+
* A Mood is joined to the prompt on its tool Models, and the plain job needs
|
|
435
|
+
* a prompt or a Mood to say what light to make.
|
|
436
|
+
*/
|
|
437
|
+
readonly takesMood?: true;
|
|
401
438
|
}
|
|
402
439
|
/** Every Task with a Model. A Task is absent here until it has at least one Model. */
|
|
403
440
|
export declare const TASKS: {
|
|
@@ -538,10 +575,14 @@ export declare const TASKS: {
|
|
|
538
575
|
};
|
|
539
576
|
readonly generate: {
|
|
540
577
|
readonly basis: "Order follows Arena text-to-image (https://arena.ai/leaderboard/image/text-to-image), read 2026-10-29. Sunburst and Flare lead quality at the benchmarked max setting. Balanced starts with Nano Banana 2.1 on preliminary Arena evidence, then Grok Image 2 and Muse Image. Models not yet on the board follow the ranked ones in their Tier, in their previous order. The Artificial Analysis v2 snapshot of 2026-10-07 stays as recorded benchmark data. Fast keeps Nano Banana 2 Lite, budget Grok and Seedream 5 Lite, and FLUX.2 Turbo. Design, transparency and tuned Look routes are capability exceptions. Generation with References uses the separate editing ranking. Older routes are explicit/pin/Look-only.";
|
|
578
|
+
readonly generationModels: true;
|
|
541
579
|
readonly models: readonly RankedModel[];
|
|
580
|
+
readonly needsPrompt: true;
|
|
542
581
|
readonly notFor: "Variations of an image you already have (vary), or a consistent set of images (series run).";
|
|
543
582
|
readonly rankedAt: "2026-10-29";
|
|
544
583
|
readonly rankedFrom: "hand";
|
|
584
|
+
readonly referenceModels: readonly RankedModel[];
|
|
585
|
+
readonly sourceless: true;
|
|
545
586
|
readonly summary: "Make an image from a prompt, or change an image you pass as a reference.";
|
|
546
587
|
};
|
|
547
588
|
readonly layers: {
|
|
@@ -754,6 +795,7 @@ export declare const TASKS: {
|
|
|
754
795
|
readonly rankedAt: "2026-09-16";
|
|
755
796
|
readonly rankedFrom: "hand";
|
|
756
797
|
readonly summary: "Change the light in a photo without regenerating it.";
|
|
798
|
+
readonly takesMood: true;
|
|
757
799
|
};
|
|
758
800
|
readonly restore: {
|
|
759
801
|
readonly basis: "Hand-ranked. Each mode names what is wrong and has the Model that fixes it; the plain job is Topaz's general restoration. Control Light, a FLUX.2 klein fine-tune at $0.03/MP, brightens dark photos.";
|
|
@@ -816,6 +858,7 @@ export declare const TASKS: {
|
|
|
816
858
|
readonly tier: "balanced";
|
|
817
859
|
}];
|
|
818
860
|
readonly notFor: "A house style kept across images (generate with a look).";
|
|
861
|
+
readonly oneReference: true;
|
|
819
862
|
readonly rankedAt: "2026-09-16";
|
|
820
863
|
readonly rankedFrom: "hand";
|
|
821
864
|
readonly summary: "Redraw an image in the style of a reference image.";
|
|
@@ -886,6 +929,7 @@ export declare const TASKS: {
|
|
|
886
929
|
readonly tier: "balanced";
|
|
887
930
|
}];
|
|
888
931
|
readonly notFor: "Changing clothes by description (generate with a reference).";
|
|
932
|
+
readonly oneReference: true;
|
|
889
933
|
readonly rankedAt: "2026-09-16";
|
|
890
934
|
readonly rankedFrom: "hand";
|
|
891
935
|
readonly summary: "Dress a person in a garment from another image.";
|
|
@@ -951,6 +995,7 @@ export declare const TASKS: {
|
|
|
951
995
|
};
|
|
952
996
|
readonly vary: {
|
|
953
997
|
readonly basis: "Order follows Arena image edit, single image (https://arena.ai/leaderboard/image/image-edit/single-image), read 2026-10-29. Editing order differs from generation: Grok Image 2 leads balanced, ahead of Nano Banana 2.1, and Seedream 5 Pro outranks GPT Image 1.5. Arena scores Krea 3 only at its Ultra setting, which costs $0.27 to $0.35 an edit and ignores the requested size, so krea3, which runs fal's default setting, is ranked as unscored. Models not yet on the board follow the ranked ones in their Tier, in their previous order. The Artificial Analysis v2 snapshot of 2026-10-07 stays as recorded benchmark data. Sunburst and Flare use max quality. vary reuses a previously chosen Model when explicitly supplied, including retained legacy routes.";
|
|
998
|
+
readonly generationModels: true;
|
|
954
999
|
readonly models: readonly RankedModel[];
|
|
955
1000
|
readonly notFor: "A specific change to an image described in words (generate with a reference), or a set of different scenes in one style (series run).";
|
|
956
1001
|
readonly rankedAt: "2026-10-29";
|
|
@@ -999,6 +1044,13 @@ interface TaskEnvironment {
|
|
|
999
1044
|
readonly keys: readonly string[];
|
|
1000
1045
|
/** Models pinned per Task in config (`tasks.<task>.model`). */
|
|
1001
1046
|
readonly pins?: Readonly<Partial<Record<TaskId, string>>>;
|
|
1047
|
+
/**
|
|
1048
|
+
* Whether the Model can carry the whole request: the refusal when it cannot.
|
|
1049
|
+
* The planner supplies it, so a ranked Model it would refuse is skipped
|
|
1050
|
+
* rather than chosen and then refused. Absent when only the capability
|
|
1051
|
+
* profiles are asked, as in `--describe`.
|
|
1052
|
+
*/
|
|
1053
|
+
readonly refusal?: (model: string) => MotifError | undefined;
|
|
1002
1054
|
}
|
|
1003
1055
|
/** Which rule fixed the Model. */
|
|
1004
1056
|
type ChosenBy = "look" | "model" | "pin" | "ranking";
|
|
@@ -1027,29 +1079,13 @@ interface TaskUnresolved {
|
|
|
1027
1079
|
readonly unblockedBy: readonly Unblocker[];
|
|
1028
1080
|
/** The key variable that would unblock a Model, when one would. */
|
|
1029
1081
|
readonly missingKey?: string;
|
|
1082
|
+
/** The values the Model takes, when it refused an aspect, resolution or output format. */
|
|
1083
|
+
readonly accepts?: readonly string[];
|
|
1084
|
+
/** The most images the Model makes, when it refused a count. */
|
|
1085
|
+
readonly limit?: number;
|
|
1030
1086
|
readonly message: string;
|
|
1031
1087
|
}
|
|
1032
1088
|
type TaskResolution = TaskResolved | TaskUnresolved;
|
|
1033
|
-
interface ModelProfile {
|
|
1034
|
-
/** The Model's display name, e.g. "GPT Image 2.6 Sunburst". */
|
|
1035
|
-
readonly name: string;
|
|
1036
|
-
readonly capabilities: ReadonlySet<Capability>;
|
|
1037
|
-
/** Key variables the Model needs for any request. */
|
|
1038
|
-
readonly keys: readonly string[];
|
|
1039
|
-
readonly maxReferences: number;
|
|
1040
|
-
/** Aspect ratios the Model accepts. Absent means any. */
|
|
1041
|
-
readonly aspects?: readonly string[];
|
|
1042
|
-
/** Resolutions the Model accepts. Absent means any. */
|
|
1043
|
-
readonly resolutions?: readonly string[];
|
|
1044
|
-
/** Output formats the Model returns, for a text request and an edit.
|
|
1045
|
-
* Absent means any. */
|
|
1046
|
-
readonly outputFormats?: {
|
|
1047
|
-
readonly edit: readonly string[];
|
|
1048
|
-
readonly text: readonly string[];
|
|
1049
|
-
};
|
|
1050
|
-
}
|
|
1051
|
-
/** The profile for a Model id, or undefined when no registry knows it. */
|
|
1052
|
-
export declare function modelProfile(model: string): ModelProfile | undefined;
|
|
1053
1089
|
/**
|
|
1054
1090
|
* Choose the Model for a Task. Pure: no I/O, and the prompt is never read.
|
|
1055
1091
|
*
|
|
@@ -1250,13 +1286,23 @@ interface TaskPlan {
|
|
|
1250
1286
|
body: Record<string, unknown>;
|
|
1251
1287
|
/** Prompt after Look and Mood enrichment, when the Task takes one. */
|
|
1252
1288
|
prompt?: string;
|
|
1289
|
+
/**
|
|
1290
|
+
* The exact pixel size the request asks for. Null when the size is the
|
|
1291
|
+
* Model's own to decide (a ratio with a resolution tier), the source's
|
|
1292
|
+
* (`auto`), or not set by the request.
|
|
1293
|
+
*/
|
|
1294
|
+
size: CustomImageSize | null;
|
|
1295
|
+
/**
|
|
1296
|
+
* The Model always runs through fal's queue. `run` also queues a run whose
|
|
1297
|
+
* caller passes `onSubmitted`, or `onProgress` on a generation Model.
|
|
1298
|
+
*/
|
|
1253
1299
|
queued: boolean;
|
|
1254
1300
|
/** Projected: before the call. */
|
|
1255
1301
|
cost: ResolvedCost;
|
|
1256
1302
|
/** The provider carrying the request. */
|
|
1257
1303
|
provider: "fal";
|
|
1258
1304
|
}
|
|
1259
|
-
interface TaskOutput extends Omit<TaskPlan, "body" | "cost" | "queued"> {
|
|
1305
|
+
interface TaskOutput extends Omit<TaskPlan, "body" | "cost" | "queued" | "size"> {
|
|
1260
1306
|
files: TaskFile[];
|
|
1261
1307
|
/** Non-file result fields: answer, reasoning, boxes, scores, points, rle, text... */
|
|
1262
1308
|
data: Record<string, unknown>;
|
|
@@ -1350,4 +1396,54 @@ export declare const motifEnvSchema: import("@howells/envy").EnvSchema<{
|
|
|
1350
1396
|
type MotifEnv = ReturnType<typeof motifEnvSchema.parse>;
|
|
1351
1397
|
export declare function parseMotifEnv(input?: Record<string, unknown>): MotifEnv;
|
|
1352
1398
|
export declare function getFalKeyFromEnv(input?: Record<string, unknown>): string | undefined;
|
|
1353
|
-
|
|
1399
|
+
/**
|
|
1400
|
+
* How a Model is sized:
|
|
1401
|
+
* - `exact`: Motif asks for an exact width and height from the ratio and tier.
|
|
1402
|
+
* - `preset`: a fal named size (about 1024 px on the long edge); no tier.
|
|
1403
|
+
* - `fixed`: a few fixed sizes chosen by ratio; no tier.
|
|
1404
|
+
* - `model`: Motif sends the ratio and tier and the Model decides the pixels.
|
|
1405
|
+
* - `source`: the output keeps the source's size, scaled by the tier where the
|
|
1406
|
+
* endpoint takes one.
|
|
1407
|
+
* - `none`: the Model takes no size.
|
|
1408
|
+
*/
|
|
1409
|
+
type SizingKind = "exact" | "preset" | "fixed" | "model" | "source" | "none";
|
|
1410
|
+
interface ModelSizing {
|
|
1411
|
+
readonly kind: SizingKind;
|
|
1412
|
+
/** Tiers the Model accepts. Empty when it takes none. */
|
|
1413
|
+
readonly resolutions: readonly Resolution[];
|
|
1414
|
+
/** The tier sent when none is asked for, where the Model takes tiers. */
|
|
1415
|
+
readonly defaultResolution?: Resolution;
|
|
1416
|
+
/** At ratio 1:1, the size each tier asks for (`exact` Models). */
|
|
1417
|
+
readonly tierSizes?: Readonly<Partial<Record<Resolution, CustomImageSize>>>;
|
|
1418
|
+
/** At ratio 1:1, the size asked for with no tier (`preset` and `fixed`). */
|
|
1419
|
+
readonly size?: CustomImageSize;
|
|
1420
|
+
}
|
|
1421
|
+
interface ModelProfile {
|
|
1422
|
+
/** The Model's display name, e.g. "GPT Image 2.6 Sunburst". */
|
|
1423
|
+
readonly name: string;
|
|
1424
|
+
readonly capabilities: ReadonlySet<Capability>;
|
|
1425
|
+
/** Key variables the Model needs for any request. */
|
|
1426
|
+
readonly keys: readonly string[];
|
|
1427
|
+
/** Most images one request makes. Absent where no maximum is known. */
|
|
1428
|
+
readonly maxCount?: number;
|
|
1429
|
+
readonly maxReferences: number;
|
|
1430
|
+
/** Aspect ratios the Model accepts. Absent means any. */
|
|
1431
|
+
readonly aspects?: readonly string[];
|
|
1432
|
+
/** Resolutions the Model accepts. Absent means any. */
|
|
1433
|
+
readonly resolutions?: readonly string[];
|
|
1434
|
+
/** Upscale factors the Model takes. Absent where its endpoint states no range. */
|
|
1435
|
+
readonly scaleRange?: ScaleRange;
|
|
1436
|
+
/** Output formats that make one image whatever the count. */
|
|
1437
|
+
readonly singleImageFormats?: readonly string[];
|
|
1438
|
+
/** What a resolution tier means for the Model, in pixels where known. */
|
|
1439
|
+
readonly sizing: ModelSizing;
|
|
1440
|
+
/** Output formats the Model returns, for a text request and an edit.
|
|
1441
|
+
* Absent means any. */
|
|
1442
|
+
readonly outputFormats?: {
|
|
1443
|
+
readonly edit: readonly string[];
|
|
1444
|
+
readonly text: readonly string[];
|
|
1445
|
+
};
|
|
1446
|
+
}
|
|
1447
|
+
/** The profile for a Model id, or undefined when no registry knows it. */
|
|
1448
|
+
export declare function modelProfile(model: string): ModelProfile | undefined;
|
|
1449
|
+
export { type AspectRatio, type Blocker, type Capability, type ChosenBy, type CreativeDirection, type CreativeField, type CreativeOption, type CreativeOptionErrorDetails, type CreativePromptResult, type CustomImageSize, type EnrichPromptOptions, type FalFetch, type FormatPreset, type ImageSizeBounds, type LookId, type LookOption, type ModelProfile, type ModelSizing, type MoodId, type MotifClient, type MotifClientConfig, type MotifEnv, type OutputDimensions, type PlanOptions, type PromptWarning, type PromptWarningRule, type RankedFrom, type RankedModel, type Resolution, type ResolvedCost, type Result, type ResultAsync, type SizingKind, type TaskDefinition, type TaskEnvironment, type TaskFile, type TaskFunction, type TaskId, type TaskInput, type TaskMode, type TaskOutput, type TaskPlan, type TaskRequest, type TaskResolution, type TaskResolved, type TaskStream, type TaskStreamEvent, type TaskStreamOptions, type TaskUnresolved, type Tier, type Unblocker, err, ok };
|
package/dist/index.d.ts
CHANGED
|
@@ -253,6 +253,11 @@ export declare function validateCreativeDirection(creative: CreativeDirection |
|
|
|
253
253
|
* are joined with `". "` and closed with a period. With no clauses the sanitized prompt is returned unchanged.
|
|
254
254
|
*/
|
|
255
255
|
export declare function enrichPrompt(options: EnrichPromptOptions): CreativePromptResult;
|
|
256
|
+
/** The upscale factors an endpoint takes, from its fal OpenAPI schema. */
|
|
257
|
+
interface ScaleRange {
|
|
258
|
+
max: number;
|
|
259
|
+
min: number;
|
|
260
|
+
}
|
|
256
261
|
/** ─── Model Types ─────────────────────────────────────────────── */
|
|
257
262
|
type AspectRatio = "auto" | "8:1" | "4:1" | "21:9" | "16:9" | "3:2" | "4:3" | "5:4" | "1:1" | "4:5" | "3:4" | "2:3" | "9:16" | "1:4" | "1:8";
|
|
258
263
|
type Resolution = "0.5K" | "1K" | "2K" | "4K";
|
|
@@ -273,6 +278,7 @@ interface ImageSizeBounds {
|
|
|
273
278
|
/** Both edges must be multiples of this. Motif uses 16 when absent. */
|
|
274
279
|
multipleOf?: number;
|
|
275
280
|
}
|
|
281
|
+
/** ─── Queue Types ────────────────────────────────────────────── */
|
|
276
282
|
interface JobStatus {
|
|
277
283
|
error?: string;
|
|
278
284
|
logs?: {
|
|
@@ -298,20 +304,20 @@ export declare class ImageSizeBoundsError extends Error {
|
|
|
298
304
|
readonly bounds: ImageSizeBounds;
|
|
299
305
|
constructor(model: string, aspect: AspectRatio, bounds: ImageSizeBounds);
|
|
300
306
|
}
|
|
301
|
-
/**
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
*/
|
|
307
|
+
/** A named output format: an aspect, and a resolution when the format needs one. */
|
|
308
|
+
interface FormatPreset {
|
|
309
|
+
readonly aspect: AspectRatio;
|
|
310
|
+
/** What the format is for, in a few words. */
|
|
311
|
+
readonly description: string;
|
|
312
|
+
/** Short title for pickers. */
|
|
313
|
+
readonly label: string;
|
|
314
|
+
readonly resolution?: Resolution;
|
|
315
|
+
/** The platform's pixel spec, such as "1080×1920", when it publishes one. */
|
|
316
|
+
readonly size?: string;
|
|
317
|
+
}
|
|
318
|
+
/** Format presets that set aspect + resolution in one click, in display order. */
|
|
319
|
+
export declare const FORMAT_PRESETS: Record<string, FormatPreset>;
|
|
320
|
+
/** `MotifError` and the fal HTTP error mapping. */
|
|
315
321
|
export declare class MotifError extends Error {
|
|
316
322
|
readonly status: number;
|
|
317
323
|
readonly code?: string;
|
|
@@ -324,6 +330,14 @@ export declare class MotifError extends Error {
|
|
|
324
330
|
}
|
|
325
331
|
/** Error code for a fal account that is locked, usually for lack of credit. */
|
|
326
332
|
export declare const ACCOUNT_LOCKED = "ACCOUNT_LOCKED";
|
|
333
|
+
/**
|
|
334
|
+
* Error code for a request that can bill a job and got no clear answer (a
|
|
335
|
+
* connection error, a timeout, a 5xx, or an unreadable acceptance). fal may
|
|
336
|
+
* have accepted it, so the caller must not blindly submit it again.
|
|
337
|
+
*/
|
|
338
|
+
export declare const SUBMISSION_UNCERTAIN = "SUBMISSION_UNCERTAIN";
|
|
339
|
+
/** Error code for a fal response whose body was not the JSON it should be. */
|
|
340
|
+
export declare const INVALID_RESPONSE = "INVALID_RESPONSE";
|
|
327
341
|
/**
|
|
328
342
|
* Whether a fal HTTP failure means the account is locked.
|
|
329
343
|
*
|
|
@@ -331,6 +345,12 @@ export declare const ACCOUNT_LOCKED = "ACCOUNT_LOCKED";
|
|
|
331
345
|
* account has run out of credit. Retrying cannot help, and the key is valid.
|
|
332
346
|
*/
|
|
333
347
|
export declare function isFalAccountLocked(status: number, body: string): boolean;
|
|
348
|
+
/**
|
|
349
|
+
* The option a refused request was stopped on, from either refusal shape: an
|
|
350
|
+
* `INVALID_OPTION` names it as `details.field`, a `NO_MODEL_AVAILABLE` as
|
|
351
|
+
* `details.blockedBy`. Undefined when the error names no option.
|
|
352
|
+
*/
|
|
353
|
+
export declare function refusedOption(error: MotifError): string | undefined;
|
|
334
354
|
/**
|
|
335
355
|
* Arena image scores captured for MOT-72 on October 29, 2026. Flare and
|
|
336
356
|
* Sunburst route to GPT Image 2.6 but keep 2.5's scores until 2.6 is
|
|
@@ -398,6 +418,23 @@ interface TaskDefinition {
|
|
|
398
418
|
readonly modes?: readonly TaskMode[];
|
|
399
419
|
/** Best first. Order within a Tier is the order tried at that Tier. */
|
|
400
420
|
readonly models: readonly RankedModel[];
|
|
421
|
+
/**
|
|
422
|
+
* Its ranked Models are generation Models: a Look can fix one.
|
|
423
|
+
*/
|
|
424
|
+
readonly generationModels?: true;
|
|
425
|
+
/** Refuses a request with no prompt. */
|
|
426
|
+
readonly needsPrompt?: true;
|
|
427
|
+
/** Takes its Source and exactly one Reference. */
|
|
428
|
+
readonly oneReference?: true;
|
|
429
|
+
/** The ranking used when the request carries References, in place of `models`. */
|
|
430
|
+
readonly referenceModels?: readonly RankedModel[];
|
|
431
|
+
/** Makes a new image, so there is no Source to ask for. */
|
|
432
|
+
readonly sourceless?: true;
|
|
433
|
+
/**
|
|
434
|
+
* A Mood is joined to the prompt on its tool Models, and the plain job needs
|
|
435
|
+
* a prompt or a Mood to say what light to make.
|
|
436
|
+
*/
|
|
437
|
+
readonly takesMood?: true;
|
|
401
438
|
}
|
|
402
439
|
/** Every Task with a Model. A Task is absent here until it has at least one Model. */
|
|
403
440
|
export declare const TASKS: {
|
|
@@ -538,10 +575,14 @@ export declare const TASKS: {
|
|
|
538
575
|
};
|
|
539
576
|
readonly generate: {
|
|
540
577
|
readonly basis: "Order follows Arena text-to-image (https://arena.ai/leaderboard/image/text-to-image), read 2026-10-29. Sunburst and Flare lead quality at the benchmarked max setting. Balanced starts with Nano Banana 2.1 on preliminary Arena evidence, then Grok Image 2 and Muse Image. Models not yet on the board follow the ranked ones in their Tier, in their previous order. The Artificial Analysis v2 snapshot of 2026-10-07 stays as recorded benchmark data. Fast keeps Nano Banana 2 Lite, budget Grok and Seedream 5 Lite, and FLUX.2 Turbo. Design, transparency and tuned Look routes are capability exceptions. Generation with References uses the separate editing ranking. Older routes are explicit/pin/Look-only.";
|
|
578
|
+
readonly generationModels: true;
|
|
541
579
|
readonly models: readonly RankedModel[];
|
|
580
|
+
readonly needsPrompt: true;
|
|
542
581
|
readonly notFor: "Variations of an image you already have (vary), or a consistent set of images (series run).";
|
|
543
582
|
readonly rankedAt: "2026-10-29";
|
|
544
583
|
readonly rankedFrom: "hand";
|
|
584
|
+
readonly referenceModels: readonly RankedModel[];
|
|
585
|
+
readonly sourceless: true;
|
|
545
586
|
readonly summary: "Make an image from a prompt, or change an image you pass as a reference.";
|
|
546
587
|
};
|
|
547
588
|
readonly layers: {
|
|
@@ -754,6 +795,7 @@ export declare const TASKS: {
|
|
|
754
795
|
readonly rankedAt: "2026-09-16";
|
|
755
796
|
readonly rankedFrom: "hand";
|
|
756
797
|
readonly summary: "Change the light in a photo without regenerating it.";
|
|
798
|
+
readonly takesMood: true;
|
|
757
799
|
};
|
|
758
800
|
readonly restore: {
|
|
759
801
|
readonly basis: "Hand-ranked. Each mode names what is wrong and has the Model that fixes it; the plain job is Topaz's general restoration. Control Light, a FLUX.2 klein fine-tune at $0.03/MP, brightens dark photos.";
|
|
@@ -816,6 +858,7 @@ export declare const TASKS: {
|
|
|
816
858
|
readonly tier: "balanced";
|
|
817
859
|
}];
|
|
818
860
|
readonly notFor: "A house style kept across images (generate with a look).";
|
|
861
|
+
readonly oneReference: true;
|
|
819
862
|
readonly rankedAt: "2026-09-16";
|
|
820
863
|
readonly rankedFrom: "hand";
|
|
821
864
|
readonly summary: "Redraw an image in the style of a reference image.";
|
|
@@ -886,6 +929,7 @@ export declare const TASKS: {
|
|
|
886
929
|
readonly tier: "balanced";
|
|
887
930
|
}];
|
|
888
931
|
readonly notFor: "Changing clothes by description (generate with a reference).";
|
|
932
|
+
readonly oneReference: true;
|
|
889
933
|
readonly rankedAt: "2026-09-16";
|
|
890
934
|
readonly rankedFrom: "hand";
|
|
891
935
|
readonly summary: "Dress a person in a garment from another image.";
|
|
@@ -951,6 +995,7 @@ export declare const TASKS: {
|
|
|
951
995
|
};
|
|
952
996
|
readonly vary: {
|
|
953
997
|
readonly basis: "Order follows Arena image edit, single image (https://arena.ai/leaderboard/image/image-edit/single-image), read 2026-10-29. Editing order differs from generation: Grok Image 2 leads balanced, ahead of Nano Banana 2.1, and Seedream 5 Pro outranks GPT Image 1.5. Arena scores Krea 3 only at its Ultra setting, which costs $0.27 to $0.35 an edit and ignores the requested size, so krea3, which runs fal's default setting, is ranked as unscored. Models not yet on the board follow the ranked ones in their Tier, in their previous order. The Artificial Analysis v2 snapshot of 2026-10-07 stays as recorded benchmark data. Sunburst and Flare use max quality. vary reuses a previously chosen Model when explicitly supplied, including retained legacy routes.";
|
|
998
|
+
readonly generationModels: true;
|
|
954
999
|
readonly models: readonly RankedModel[];
|
|
955
1000
|
readonly notFor: "A specific change to an image described in words (generate with a reference), or a set of different scenes in one style (series run).";
|
|
956
1001
|
readonly rankedAt: "2026-10-29";
|
|
@@ -999,6 +1044,13 @@ interface TaskEnvironment {
|
|
|
999
1044
|
readonly keys: readonly string[];
|
|
1000
1045
|
/** Models pinned per Task in config (`tasks.<task>.model`). */
|
|
1001
1046
|
readonly pins?: Readonly<Partial<Record<TaskId, string>>>;
|
|
1047
|
+
/**
|
|
1048
|
+
* Whether the Model can carry the whole request: the refusal when it cannot.
|
|
1049
|
+
* The planner supplies it, so a ranked Model it would refuse is skipped
|
|
1050
|
+
* rather than chosen and then refused. Absent when only the capability
|
|
1051
|
+
* profiles are asked, as in `--describe`.
|
|
1052
|
+
*/
|
|
1053
|
+
readonly refusal?: (model: string) => MotifError | undefined;
|
|
1002
1054
|
}
|
|
1003
1055
|
/** Which rule fixed the Model. */
|
|
1004
1056
|
type ChosenBy = "look" | "model" | "pin" | "ranking";
|
|
@@ -1027,29 +1079,13 @@ interface TaskUnresolved {
|
|
|
1027
1079
|
readonly unblockedBy: readonly Unblocker[];
|
|
1028
1080
|
/** The key variable that would unblock a Model, when one would. */
|
|
1029
1081
|
readonly missingKey?: string;
|
|
1082
|
+
/** The values the Model takes, when it refused an aspect, resolution or output format. */
|
|
1083
|
+
readonly accepts?: readonly string[];
|
|
1084
|
+
/** The most images the Model makes, when it refused a count. */
|
|
1085
|
+
readonly limit?: number;
|
|
1030
1086
|
readonly message: string;
|
|
1031
1087
|
}
|
|
1032
1088
|
type TaskResolution = TaskResolved | TaskUnresolved;
|
|
1033
|
-
interface ModelProfile {
|
|
1034
|
-
/** The Model's display name, e.g. "GPT Image 2.6 Sunburst". */
|
|
1035
|
-
readonly name: string;
|
|
1036
|
-
readonly capabilities: ReadonlySet<Capability>;
|
|
1037
|
-
/** Key variables the Model needs for any request. */
|
|
1038
|
-
readonly keys: readonly string[];
|
|
1039
|
-
readonly maxReferences: number;
|
|
1040
|
-
/** Aspect ratios the Model accepts. Absent means any. */
|
|
1041
|
-
readonly aspects?: readonly string[];
|
|
1042
|
-
/** Resolutions the Model accepts. Absent means any. */
|
|
1043
|
-
readonly resolutions?: readonly string[];
|
|
1044
|
-
/** Output formats the Model returns, for a text request and an edit.
|
|
1045
|
-
* Absent means any. */
|
|
1046
|
-
readonly outputFormats?: {
|
|
1047
|
-
readonly edit: readonly string[];
|
|
1048
|
-
readonly text: readonly string[];
|
|
1049
|
-
};
|
|
1050
|
-
}
|
|
1051
|
-
/** The profile for a Model id, or undefined when no registry knows it. */
|
|
1052
|
-
export declare function modelProfile(model: string): ModelProfile | undefined;
|
|
1053
1089
|
/**
|
|
1054
1090
|
* Choose the Model for a Task. Pure: no I/O, and the prompt is never read.
|
|
1055
1091
|
*
|
|
@@ -1250,13 +1286,23 @@ interface TaskPlan {
|
|
|
1250
1286
|
body: Record<string, unknown>;
|
|
1251
1287
|
/** Prompt after Look and Mood enrichment, when the Task takes one. */
|
|
1252
1288
|
prompt?: string;
|
|
1289
|
+
/**
|
|
1290
|
+
* The exact pixel size the request asks for. Null when the size is the
|
|
1291
|
+
* Model's own to decide (a ratio with a resolution tier), the source's
|
|
1292
|
+
* (`auto`), or not set by the request.
|
|
1293
|
+
*/
|
|
1294
|
+
size: CustomImageSize | null;
|
|
1295
|
+
/**
|
|
1296
|
+
* The Model always runs through fal's queue. `run` also queues a run whose
|
|
1297
|
+
* caller passes `onSubmitted`, or `onProgress` on a generation Model.
|
|
1298
|
+
*/
|
|
1253
1299
|
queued: boolean;
|
|
1254
1300
|
/** Projected: before the call. */
|
|
1255
1301
|
cost: ResolvedCost;
|
|
1256
1302
|
/** The provider carrying the request. */
|
|
1257
1303
|
provider: "fal";
|
|
1258
1304
|
}
|
|
1259
|
-
interface TaskOutput extends Omit<TaskPlan, "body" | "cost" | "queued"> {
|
|
1305
|
+
interface TaskOutput extends Omit<TaskPlan, "body" | "cost" | "queued" | "size"> {
|
|
1260
1306
|
files: TaskFile[];
|
|
1261
1307
|
/** Non-file result fields: answer, reasoning, boxes, scores, points, rle, text... */
|
|
1262
1308
|
data: Record<string, unknown>;
|
|
@@ -1350,4 +1396,54 @@ export declare const motifEnvSchema: import("@howells/envy").EnvSchema<{
|
|
|
1350
1396
|
type MotifEnv = ReturnType<typeof motifEnvSchema.parse>;
|
|
1351
1397
|
export declare function parseMotifEnv(input?: Record<string, unknown>): MotifEnv;
|
|
1352
1398
|
export declare function getFalKeyFromEnv(input?: Record<string, unknown>): string | undefined;
|
|
1353
|
-
|
|
1399
|
+
/**
|
|
1400
|
+
* How a Model is sized:
|
|
1401
|
+
* - `exact`: Motif asks for an exact width and height from the ratio and tier.
|
|
1402
|
+
* - `preset`: a fal named size (about 1024 px on the long edge); no tier.
|
|
1403
|
+
* - `fixed`: a few fixed sizes chosen by ratio; no tier.
|
|
1404
|
+
* - `model`: Motif sends the ratio and tier and the Model decides the pixels.
|
|
1405
|
+
* - `source`: the output keeps the source's size, scaled by the tier where the
|
|
1406
|
+
* endpoint takes one.
|
|
1407
|
+
* - `none`: the Model takes no size.
|
|
1408
|
+
*/
|
|
1409
|
+
type SizingKind = "exact" | "preset" | "fixed" | "model" | "source" | "none";
|
|
1410
|
+
interface ModelSizing {
|
|
1411
|
+
readonly kind: SizingKind;
|
|
1412
|
+
/** Tiers the Model accepts. Empty when it takes none. */
|
|
1413
|
+
readonly resolutions: readonly Resolution[];
|
|
1414
|
+
/** The tier sent when none is asked for, where the Model takes tiers. */
|
|
1415
|
+
readonly defaultResolution?: Resolution;
|
|
1416
|
+
/** At ratio 1:1, the size each tier asks for (`exact` Models). */
|
|
1417
|
+
readonly tierSizes?: Readonly<Partial<Record<Resolution, CustomImageSize>>>;
|
|
1418
|
+
/** At ratio 1:1, the size asked for with no tier (`preset` and `fixed`). */
|
|
1419
|
+
readonly size?: CustomImageSize;
|
|
1420
|
+
}
|
|
1421
|
+
interface ModelProfile {
|
|
1422
|
+
/** The Model's display name, e.g. "GPT Image 2.6 Sunburst". */
|
|
1423
|
+
readonly name: string;
|
|
1424
|
+
readonly capabilities: ReadonlySet<Capability>;
|
|
1425
|
+
/** Key variables the Model needs for any request. */
|
|
1426
|
+
readonly keys: readonly string[];
|
|
1427
|
+
/** Most images one request makes. Absent where no maximum is known. */
|
|
1428
|
+
readonly maxCount?: number;
|
|
1429
|
+
readonly maxReferences: number;
|
|
1430
|
+
/** Aspect ratios the Model accepts. Absent means any. */
|
|
1431
|
+
readonly aspects?: readonly string[];
|
|
1432
|
+
/** Resolutions the Model accepts. Absent means any. */
|
|
1433
|
+
readonly resolutions?: readonly string[];
|
|
1434
|
+
/** Upscale factors the Model takes. Absent where its endpoint states no range. */
|
|
1435
|
+
readonly scaleRange?: ScaleRange;
|
|
1436
|
+
/** Output formats that make one image whatever the count. */
|
|
1437
|
+
readonly singleImageFormats?: readonly string[];
|
|
1438
|
+
/** What a resolution tier means for the Model, in pixels where known. */
|
|
1439
|
+
readonly sizing: ModelSizing;
|
|
1440
|
+
/** Output formats the Model returns, for a text request and an edit.
|
|
1441
|
+
* Absent means any. */
|
|
1442
|
+
readonly outputFormats?: {
|
|
1443
|
+
readonly edit: readonly string[];
|
|
1444
|
+
readonly text: readonly string[];
|
|
1445
|
+
};
|
|
1446
|
+
}
|
|
1447
|
+
/** The profile for a Model id, or undefined when no registry knows it. */
|
|
1448
|
+
export declare function modelProfile(model: string): ModelProfile | undefined;
|
|
1449
|
+
export { type AspectRatio, type Blocker, type Capability, type ChosenBy, type CreativeDirection, type CreativeField, type CreativeOption, type CreativeOptionErrorDetails, type CreativePromptResult, type CustomImageSize, type EnrichPromptOptions, type FalFetch, type FormatPreset, type ImageSizeBounds, type LookId, type LookOption, type ModelProfile, type ModelSizing, type MoodId, type MotifClient, type MotifClientConfig, type MotifEnv, type OutputDimensions, type PlanOptions, type PromptWarning, type PromptWarningRule, type RankedFrom, type RankedModel, type Resolution, type ResolvedCost, type Result, type ResultAsync, type SizingKind, type TaskDefinition, type TaskEnvironment, type TaskFile, type TaskFunction, type TaskId, type TaskInput, type TaskMode, type TaskOutput, type TaskPlan, type TaskRequest, type TaskResolution, type TaskResolved, type TaskStream, type TaskStreamEvent, type TaskStreamOptions, type TaskUnresolved, type Tier, type Unblocker, err, ok };
|