@howells/motif-sdk 0.5.1 → 0.7.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/dist/image.d.ts +197 -0
- package/dist/image.js +1525 -0
- package/dist/index.cjs +25 -11
- package/dist/index.d.cts +4 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +22 -8
- package/package.json +9 -3
package/dist/image.d.ts
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { generateImage, ImageModel } from 'ai';
|
|
2
|
+
import { Result } from 'neverthrow';
|
|
3
|
+
|
|
4
|
+
declare class MotifError extends Error {
|
|
5
|
+
readonly status: number;
|
|
6
|
+
readonly code?: string;
|
|
7
|
+
/** fal's request-correlation id (from the `x-fal-request-id` header or the
|
|
8
|
+
* error body). Ties a failure back to fal's dashboard/support. */
|
|
9
|
+
readonly requestId?: string;
|
|
10
|
+
constructor(message: string, status: number, code?: string, requestId?: string);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Public types for the provider-agnostic image generation + editing layer
|
|
15
|
+
* (`@howells/motif-sdk/image`).
|
|
16
|
+
*
|
|
17
|
+
* This layer is additive: it sits alongside the fal-specific `MotifServer`
|
|
18
|
+
* surface and reuses the SDK's Result convention (`Result<T, MotifError>` — no
|
|
19
|
+
* thrown exceptions). See docs/design/provider-agnostic-image-layer.md.
|
|
20
|
+
*/
|
|
21
|
+
|
|
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
|
+
/**
|
|
28
|
+
* Image provider id. Only `google` is implemented in Phase 1a; the type is kept
|
|
29
|
+
* an open union so later adapters (fal, openai, replicate) can slot in without a
|
|
30
|
+
* breaking type change.
|
|
31
|
+
*/
|
|
32
|
+
type ImageProviderId = "google" | (string & Record<never, never>);
|
|
33
|
+
/** Source that produced a normalized per-call cost. */
|
|
34
|
+
type ImageCostSource = "provider-metadata" | "table" | "unknown";
|
|
35
|
+
/** Normalized per-call spend attached to every result. */
|
|
36
|
+
interface ImageCost {
|
|
37
|
+
/** Total USD for the call (all images), best-effort. */
|
|
38
|
+
usd: number;
|
|
39
|
+
/** Where the figure came from: the provider's metadata, the static table, or unknown. */
|
|
40
|
+
source: ImageCostSource;
|
|
41
|
+
}
|
|
42
|
+
/** Client configuration. Provider keys fall back to environment variables. */
|
|
43
|
+
interface MotifImageConfig {
|
|
44
|
+
/** Provider used when a call does not specify one. Defaults to `google`. */
|
|
45
|
+
defaultProvider?: ImageProviderId;
|
|
46
|
+
/** Google provider overrides. `apiKey` falls back to `GOOGLE_GENERATIVE_AI_API_KEY`. */
|
|
47
|
+
google?: {
|
|
48
|
+
apiKey?: string;
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/** Options for a text→image generation. */
|
|
52
|
+
interface GenerateImageOptions {
|
|
53
|
+
/** The text prompt. */
|
|
54
|
+
prompt: string;
|
|
55
|
+
/** Quality/latency tier. Ignored when `model` is set. */
|
|
56
|
+
tier?: ImageTier;
|
|
57
|
+
/** Explicit provider model id. Overrides `tier`. */
|
|
58
|
+
model?: string;
|
|
59
|
+
/** Provider override for this call. */
|
|
60
|
+
provider?: ImageProviderId;
|
|
61
|
+
/** Aspect ratio, e.g. `"1:1"`. */
|
|
62
|
+
aspectRatio?: `${number}:${number}`;
|
|
63
|
+
/** Explicit pixel size, e.g. `"1024x1024"`. */
|
|
64
|
+
size?: `${number}x${number}`;
|
|
65
|
+
/** Number of images to generate. */
|
|
66
|
+
n?: number;
|
|
67
|
+
/**
|
|
68
|
+
* Provider-specific options, passed straight through to the underlying model
|
|
69
|
+
* as body parameters. Outer key = provider name, inner key = option name.
|
|
70
|
+
*/
|
|
71
|
+
providerOptions?: Record<string, Record<string, unknown>>;
|
|
72
|
+
}
|
|
73
|
+
/** Options for a multi-image edit (images in → image out), with an optional mask. */
|
|
74
|
+
interface EditImageOptions {
|
|
75
|
+
/** Input images. Each is raw bytes, a base64 string, or a data URL. */
|
|
76
|
+
images: (Uint8Array | string)[];
|
|
77
|
+
/** Natural-language edit instruction. */
|
|
78
|
+
instruction: string;
|
|
79
|
+
/** Optional mask (bytes, base64, or data URL) constraining the edited region. */
|
|
80
|
+
mask?: Uint8Array | string;
|
|
81
|
+
/** Quality/latency tier. Ignored when `model` is set. */
|
|
82
|
+
tier?: ImageTier;
|
|
83
|
+
/** Explicit provider model id. Overrides `tier`. */
|
|
84
|
+
model?: string;
|
|
85
|
+
/** Provider override for this call. */
|
|
86
|
+
provider?: ImageProviderId;
|
|
87
|
+
/** Number of images to generate. */
|
|
88
|
+
n?: number;
|
|
89
|
+
/** Provider-specific options (see {@link GenerateImageOptions.providerOptions}). */
|
|
90
|
+
providerOptions?: Record<string, Record<string, unknown>>;
|
|
91
|
+
}
|
|
92
|
+
/** A single generated image, mirroring the AI SDK's `GeneratedFile`. */
|
|
93
|
+
interface MotifImageFile {
|
|
94
|
+
uint8Array: Uint8Array;
|
|
95
|
+
base64: string;
|
|
96
|
+
mediaType: string;
|
|
97
|
+
}
|
|
98
|
+
/** Normalized result of a generate/edit call. */
|
|
99
|
+
interface MotifImageResult {
|
|
100
|
+
/** Generated images. */
|
|
101
|
+
images: MotifImageFile[];
|
|
102
|
+
/** Normalized per-call cost + provenance. */
|
|
103
|
+
cost: ImageCost;
|
|
104
|
+
/** Resolved provider. */
|
|
105
|
+
provider: ImageProviderId;
|
|
106
|
+
/** Resolved model id. */
|
|
107
|
+
model: string;
|
|
108
|
+
/** Provider correlation id, where the provider surfaces one. */
|
|
109
|
+
requestId?: string;
|
|
110
|
+
}
|
|
111
|
+
/** The provider-agnostic image client. Every method returns a Result — no throws. */
|
|
112
|
+
interface MotifImageClient {
|
|
113
|
+
/** Text→image generation. */
|
|
114
|
+
generate: (opts: GenerateImageOptions) => Promise<Result<MotifImageResult, MotifError>>;
|
|
115
|
+
/** Multi-image edit (with optional mask). */
|
|
116
|
+
edit: (opts: EditImageOptions) => Promise<Result<MotifImageResult, MotifError>>;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Google (Gemini) provider adapter.
|
|
121
|
+
*
|
|
122
|
+
* Builds a Vercel AI SDK `ImageModel` from `@ai-sdk/google`. Building a model
|
|
123
|
+
* performs no network I/O — the request only happens when `generateImage`
|
|
124
|
+
* invokes `model.doGenerate`. Gemini supports both text→image generation and
|
|
125
|
+
* multi-image-in → image-out editing (with an optional mask), which is the core
|
|
126
|
+
* operation this layer normalizes.
|
|
127
|
+
*/
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Tier → Gemini image model id.
|
|
131
|
+
*
|
|
132
|
+
* Seeded from Material Desk's `RENDER_IMAGE_MODEL_BY_QUALITY` (the driving
|
|
133
|
+
* consumer, see the design doc). `gemini-2.5-flash-image` is the proven-reachable
|
|
134
|
+
* floor; the preview ids may require allowlist/tier access.
|
|
135
|
+
*/
|
|
136
|
+
declare const GOOGLE_TIER_MODELS: Readonly<Record<ImageTier, string>>;
|
|
137
|
+
/** Env var read for the Google API key when `apiKey` is not supplied in config. */
|
|
138
|
+
declare const GOOGLE_API_KEY_ENV = "GOOGLE_GENERATIVE_AI_API_KEY";
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Per-call cost tracking for the image layer.
|
|
142
|
+
*
|
|
143
|
+
* Preference order:
|
|
144
|
+
* 1. A cost surfaced by the provider on `result.providerMetadata` (most image
|
|
145
|
+
* providers do NOT surface one today, so this is usually absent).
|
|
146
|
+
* 2. A static per-model table seeded from Google's published Gemini image
|
|
147
|
+
* pricing (see sources below).
|
|
148
|
+
* 3. Unknown → `{ usd: 0, source: "unknown" }`.
|
|
149
|
+
*/
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Extract a provider-reported total cost from a `generateImage` result's
|
|
153
|
+
* `providerMetadata`, if the provider surfaces a numeric `cost`. The shape is
|
|
154
|
+
* `{ [provider]: { ...; cost?: number } }`. Returns undefined otherwise.
|
|
155
|
+
*/
|
|
156
|
+
declare function costFromProviderMetadata(providerMetadata: unknown): number | undefined;
|
|
157
|
+
/**
|
|
158
|
+
* Normalized per-call cost for a generation. Prefers a provider-metadata cost,
|
|
159
|
+
* then the static table (× image count), then unknown.
|
|
160
|
+
*/
|
|
161
|
+
declare function costForImages(provider: ImageProviderId, modelId: string, providerMetadata: unknown, imageCount: number): ImageCost;
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* `@howells/motif-sdk/image` — provider-agnostic image generation + editing.
|
|
165
|
+
*
|
|
166
|
+
* ESM-only subpath export, built on the Vercel AI SDK image interface
|
|
167
|
+
* (`generateImage`, `@ai-sdk/*`). Additive to the fal-specific `MotifServer`
|
|
168
|
+
* surface; reuses the SDK's Result convention (`Result<T, MotifError>` — no
|
|
169
|
+
* thrown exceptions). Google (Gemini) is the only provider in Phase 1a.
|
|
170
|
+
*
|
|
171
|
+
* @example
|
|
172
|
+
* ```ts
|
|
173
|
+
* import { createMotifImage } from "@howells/motif-sdk/image";
|
|
174
|
+
*
|
|
175
|
+
* const img = createMotifImage({ defaultProvider: "google" });
|
|
176
|
+
* const r = await img.generate({ tier: "fast", prompt: "a bare concrete wall" });
|
|
177
|
+
* if (r.isOk()) console.log(r.value.images[0].mediaType, r.value.cost);
|
|
178
|
+
* ```
|
|
179
|
+
*/
|
|
180
|
+
|
|
181
|
+
/** A model resolver: builds an AI SDK `ImageModel` for a (provider, model, key). */
|
|
182
|
+
type ResolveImageModel = (provider: ImageProviderId, modelId: string, apiKey?: string) => ImageModel;
|
|
183
|
+
/** Internal dependency-injection seam (default: real `generateImage` + adapters). */
|
|
184
|
+
interface MotifImageDeps {
|
|
185
|
+
generateImage?: typeof generateImage;
|
|
186
|
+
resolveModel?: ResolveImageModel;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Create a provider-agnostic image client.
|
|
190
|
+
*
|
|
191
|
+
* @param config - provider selection + keys (keys fall back to env).
|
|
192
|
+
* @param deps - INTERNAL testing seam. Defaults to the real AI SDK `generateImage`
|
|
193
|
+
* and the built-in provider adapters; tests inject fakes here to run offline.
|
|
194
|
+
*/
|
|
195
|
+
declare function createMotifImage(config?: MotifImageConfig, deps?: MotifImageDeps): MotifImageClient;
|
|
196
|
+
|
|
197
|
+
export { type EditImageOptions, GOOGLE_API_KEY_ENV, GOOGLE_TIER_MODELS, type GenerateImageOptions, type ImageCost, type ImageCostSource, type ImageProviderId, type ImageTier, type MotifImageClient, type MotifImageConfig, type MotifImageDeps, type MotifImageFile, type MotifImageResult, type ResolveImageModel, costForImages, costFromProviderMetadata, createMotifImage };
|