getaiapi 0.1.2 → 0.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 CHANGED
@@ -78,7 +78,9 @@ const cutout = await generate({
78
78
 
79
79
  ## Configuration
80
80
 
81
- Set API keys as environment variables for the providers you want to use. You only need keys for the providers you plan to call.
81
+ ### Option 1: Environment Variables
82
+
83
+ Set API keys as environment variables. You only need keys for the providers you plan to call.
82
84
 
83
85
  ```bash
84
86
  # fal-ai (1,199 models)
@@ -91,6 +93,52 @@ export REPLICATE_API_TOKEN="your-replicate-token"
91
93
  export WAVESPEED_API_KEY="your-wavespeed-key"
92
94
  ```
93
95
 
96
+ ### Option 2: Programmatic Configuration
97
+
98
+ Use `configure()` to set keys in code -- useful when your env vars have different names or keys come from a secrets manager.
99
+
100
+ ```typescript
101
+ import { configure } from 'getaiapi'
102
+
103
+ configure({
104
+ keys: {
105
+ 'fal-ai': process.env.MY_FAL_TOKEN,
106
+ 'replicate': process.env.MY_REPLICATE_TOKEN,
107
+ 'wavespeed': process.env.MY_WAVESPEED_TOKEN,
108
+ },
109
+ })
110
+ ```
111
+
112
+ You can also set keys and storage together:
113
+
114
+ ```typescript
115
+ configure({
116
+ keys: {
117
+ 'fal-ai': 'your-fal-key',
118
+ },
119
+ storage: {
120
+ accountId: 'your-r2-account',
121
+ bucketName: 'your-bucket',
122
+ accessKeyId: 'your-r2-key',
123
+ secretAccessKey: 'your-r2-secret',
124
+ publicUrlBase: 'https://cdn.example.com',
125
+ },
126
+ })
127
+ ```
128
+
129
+ Or set just provider keys with `configureAuth()`:
130
+
131
+ ```typescript
132
+ import { configureAuth } from 'getaiapi'
133
+
134
+ configureAuth({
135
+ 'fal-ai': myKeyVault.get('fal'),
136
+ 'replicate': myKeyVault.get('replicate'),
137
+ })
138
+ ```
139
+
140
+ Programmatic keys take priority over environment variables. Any provider not set programmatically falls back to its default env var.
141
+
94
142
  Models are automatically filtered to only show providers where you have a valid key configured.
95
143
 
96
144
  ## Model Discovery
@@ -212,6 +260,175 @@ Returns all models the caller has API keys for. Accepts optional filters:
212
260
 
213
261
  Resolves a model by name. Accepts canonical names, aliases, and normalized variants. Throws `ModelNotFoundError` if no match is found.
214
262
 
263
+ ## R2 Storage (Asset Uploads)
264
+
265
+ getaiapi includes built-in Cloudflare R2 storage support that automatically uploads binary assets before sending them to providers. Two modes are supported:
266
+
267
+ - **`public`** (default) — requires a publicly readable bucket; returns public URLs (via `publicUrlBase` or the R2 endpoint)
268
+ - **`presigned`** — works with private buckets; returns time-limited presigned GET URLs signed with S3 Signature V4 (no public access needed, `publicUrlBase` is not required)
269
+
270
+ ### Setup
271
+
272
+ Set these environment variables:
273
+
274
+ ```bash
275
+ # Required
276
+ export R2_ACCOUNT_ID="your-cloudflare-account-id"
277
+ export R2_BUCKET_NAME="your-bucket-name"
278
+ export R2_ACCESS_KEY_ID="your-r2-access-key"
279
+ export R2_SECRET_ACCESS_KEY="your-r2-secret-key"
280
+
281
+ # Optional - custom public URL (only needed for mode: 'public')
282
+ export R2_PUBLIC_URL="https://cdn.example.com"
283
+
284
+ # Optional - use presigned URLs for private buckets (default: 'public')
285
+ export R2_STORAGE_MODE="presigned"
286
+ export R2_PRESIGN_EXPIRES_IN="3600" # seconds, default: 3600, max: 604800 (7 days)
287
+ ```
288
+
289
+ #### How to get your R2 Public URL (public mode only)
290
+
291
+ If using `mode: 'presigned'`, you can skip this — no public bucket access is needed.
292
+
293
+ 1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com)
294
+ 2. Go to **R2 Object Storage** in the left sidebar
295
+ 3. Click on your bucket
296
+ 4. Go to the **Settings** tab
297
+ 5. Under **Public access**, click **Allow Access**
298
+ 6. Cloudflare will provide a public URL like `https://<bucket>.<account-id>.r2.dev` — use this as your `R2_PUBLIC_URL`
299
+ 7. (Optional) You can also connect a **Custom Domain** under the same section for a cleaner URL like `https://cdn.yourdomain.com`
300
+
301
+ Then call `configureStorage()` once at startup:
302
+
303
+ ```typescript
304
+ import { configureStorage } from 'getaiapi'
305
+
306
+ // Read from environment variables
307
+ configureStorage()
308
+
309
+ // Or pass config directly
310
+ configureStorage({
311
+ accountId: 'your-account-id',
312
+ bucketName: 'your-bucket',
313
+ accessKeyId: 'your-key',
314
+ secretAccessKey: 'your-secret',
315
+ publicUrlBase: 'https://cdn.example.com', // optional
316
+ autoUpload: false, // optional
317
+ mode: 'public', // 'public' | 'presigned' (default: 'public')
318
+ presignExpiresIn: 3600, // presigned URL TTL in seconds (default: 3600)
319
+ })
320
+ ```
321
+
322
+ ### Automatic Uploads in `generate()`
323
+
324
+ Once storage is configured, any `Buffer`, `Blob`, `File`, or `ArrayBuffer` values in provider params are automatically uploaded to R2 and replaced with public URLs before the request is sent to the provider. This works recursively -- nested objects and arrays are traversed, so params like Kling's `elements[].frontal_image_url` are handled automatically. No code changes needed -- it just works.
325
+
326
+ ```typescript
327
+ import { generate, configureStorage } from 'getaiapi'
328
+ import { readFileSync } from 'fs'
329
+
330
+ configureStorage()
331
+
332
+ const result = await generate({
333
+ model: 'gpt-image-1.5-edit',
334
+ image: readFileSync('./photo.jpg'), // Buffer uploaded to R2 automatically
335
+ prompt: 'add a rainbow in the sky',
336
+ })
337
+ ```
338
+
339
+ To also re-upload URL strings through R2 (useful when providers can't access the original URL), pass `reupload: true` per-call:
340
+
341
+ ```typescript
342
+ const result = await generate({
343
+ model: 'kling-video-pro',
344
+ image: 'https://private-server.com/img.jpg',
345
+ prompt: 'animate this image',
346
+ options: { reupload: true },
347
+ })
348
+ ```
349
+
350
+ Or enable it globally with `autoUpload: true` in the storage config.
351
+
352
+ ### Cleanup / Lifecycle
353
+
354
+ Assets uploaded automatically via `generate()` use the `getaiapi-tmp/` key prefix. You can set a [Cloudflare R2 lifecycle rule](https://developers.cloudflare.com/r2/buckets/object-lifecycles/) to auto-expire objects under that prefix (e.g. delete after 24 hours) so ephemeral generation assets don't accumulate.
355
+
356
+ ### Standalone Upload / Delete
357
+
358
+ You can also use R2 storage directly:
359
+
360
+ ```typescript
361
+ import { uploadAsset, deleteAsset, configureStorage } from 'getaiapi'
362
+
363
+ configureStorage()
364
+
365
+ // Upload a buffer
366
+ const { url, key, size_bytes, content_type } = await uploadAsset(
367
+ Buffer.from('hello world'),
368
+ { contentType: 'text/plain', prefix: 'uploads' }
369
+ )
370
+ console.log(url) // https://cdn.example.com/uploads/a1b2c3d4-...
371
+
372
+ // Delete by key
373
+ await deleteAsset(key)
374
+ ```
375
+
376
+ ### Presigned URLs (Private Buckets)
377
+
378
+ If your R2 bucket doesn't have public read access, use presigned mode. Instead of returning a public URL, `uploadAsset` will return a time-limited presigned GET URL signed with S3 Signature V4.
379
+
380
+ ```typescript
381
+ configureStorage({
382
+ accountId: 'your-account-id',
383
+ bucketName: 'private-bucket',
384
+ accessKeyId: 'your-key',
385
+ secretAccessKey: 'your-secret',
386
+ mode: 'presigned', // uploadAsset returns presigned URLs
387
+ presignExpiresIn: 1800, // URLs expire after 30 minutes
388
+ })
389
+
390
+ const { url } = await uploadAsset(Buffer.from('secret data'), {
391
+ contentType: 'application/octet-stream',
392
+ })
393
+ // url is a presigned GET URL, valid for 30 minutes
394
+ ```
395
+
396
+ You can also generate presigned URLs for existing objects:
397
+
398
+ ```typescript
399
+ import { presignAsset } from 'getaiapi'
400
+
401
+ const url = presignAsset('uploads/my-file.png')
402
+ // => https://<account>.r2.cloudflarestorage.com/<bucket>/uploads/my-file.png?X-Amz-Algorithm=...
403
+
404
+ // Custom expiry per-call (overrides config default)
405
+ const shortUrl = presignAsset('uploads/my-file.png', { expiresIn: 300 }) // 5 minutes
406
+ ```
407
+
408
+ **UploadOptions**
409
+
410
+ | Option | Type | Description |
411
+ |---|---|---|
412
+ | `key` | `string` | Custom object key (default: auto-generated UUID) |
413
+ | `contentType` | `string` | MIME type (default: detected from input or `application/octet-stream`) |
414
+ | `prefix` | `string` | Key prefix / folder (e.g. `"uploads"`) |
415
+ | `maxBytes` | `number` | Max upload size in bytes (default: 500 MB) |
416
+
417
+ ### Storage Errors
418
+
419
+ ```typescript
420
+ import { StorageError } from 'getaiapi'
421
+
422
+ try {
423
+ await uploadAsset(buffer)
424
+ } catch (err) {
425
+ if (err instanceof StorageError) {
426
+ console.error(err.operation) // 'upload' | 'delete' | 'config'
427
+ console.error(err.statusCode) // HTTP status from R2, if applicable
428
+ }
429
+ }
430
+ ```
431
+
215
432
  ## Error Handling
216
433
 
217
434
  All errors extend `GetAIApiError` and can be caught uniformly or by type:
@@ -224,6 +441,7 @@ All errors extend `GetAIApiError` and can be caught uniformly or by type:
224
441
  | `ProviderError` | Provider returned an error response |
225
442
  | `TimeoutError` | Generation exceeded the timeout |
226
443
  | `RateLimitError` | Provider returned HTTP 429 |
444
+ | `StorageError` | R2 upload, delete, or config failure |
227
445
 
228
446
  ```typescript
229
447
  import { generate, AuthError, ModelNotFoundError } from 'getaiapi'
@@ -1,5 +1,5 @@
1
1
  // src/gateway.ts
2
- import { randomUUID } from "crypto";
2
+ import { randomUUID as randomUUID2 } from "crypto";
3
3
 
4
4
  // src/errors.ts
5
5
  var GetAIApiError = class extends Error {
@@ -79,6 +79,16 @@ var RateLimitError = class extends GetAIApiError {
79
79
  this.retryAfterMs = retryAfterMs;
80
80
  }
81
81
  };
82
+ var StorageError = class extends GetAIApiError {
83
+ operation;
84
+ statusCode;
85
+ constructor(operation, message, statusCode) {
86
+ super(`Storage ${operation} failed: ${message}`);
87
+ this.name = "StorageError";
88
+ this.operation = operation;
89
+ this.statusCode = statusCode;
90
+ }
91
+ };
82
92
 
83
93
  // src/auth.ts
84
94
  var ENV_MAP = {
@@ -86,13 +96,26 @@ var ENV_MAP = {
86
96
  replicate: "REPLICATE_API_TOKEN",
87
97
  wavespeed: "WAVESPEED_API_KEY"
88
98
  };
99
+ var keyOverrides = /* @__PURE__ */ new Map();
100
+ function configureAuth(keys) {
101
+ for (const [provider, key] of Object.entries(keys)) {
102
+ if (key?.trim()) {
103
+ keyOverrides.set(provider, key.trim());
104
+ }
105
+ }
106
+ }
89
107
  var AuthManager = class {
90
108
  keys;
91
109
  constructor() {
92
110
  this.keys = /* @__PURE__ */ new Map();
111
+ for (const [provider, key] of keyOverrides) {
112
+ this.keys.set(provider, key);
113
+ }
93
114
  for (const [provider, envVar] of Object.entries(ENV_MAP)) {
94
- const key = process.env[envVar]?.trim();
95
- if (key) this.keys.set(provider, key);
115
+ if (!this.keys.has(provider)) {
116
+ const key = process.env[envVar]?.trim();
117
+ if (key) this.keys.set(provider, key);
118
+ }
96
119
  }
97
120
  }
98
121
  availableProviders() {
@@ -1263,6 +1286,330 @@ async function withRetry(fn, options) {
1263
1286
  throw lastError;
1264
1287
  }
1265
1288
 
1289
+ // src/storage.ts
1290
+ import { randomUUID } from "crypto";
1291
+
1292
+ // src/s3-signer.ts
1293
+ import { createHmac, createHash } from "crypto";
1294
+ function sha256(data) {
1295
+ return createHash("sha256").update(data).digest("hex");
1296
+ }
1297
+ function hmacSha256(key, data) {
1298
+ return createHmac("sha256", key).update(data).digest();
1299
+ }
1300
+ function getSigningKey(secretKey, dateStamp, region, service) {
1301
+ const kDate = hmacSha256(`AWS4${secretKey}`, dateStamp);
1302
+ const kRegion = hmacSha256(kDate, region);
1303
+ const kService = hmacSha256(kRegion, service);
1304
+ return hmacSha256(kService, "aws4_request");
1305
+ }
1306
+ function toAmzDate(date) {
1307
+ const iso = date.toISOString().replace(/[-:]/g, "").replace(/\.\d{3}Z$/, "Z");
1308
+ return {
1309
+ amzDate: iso,
1310
+ dateStamp: iso.slice(0, 8)
1311
+ };
1312
+ }
1313
+ function signS3Request(method, url, headers, body, credentials) {
1314
+ const region = credentials.region ?? "auto";
1315
+ const service = "s3";
1316
+ const parsedUrl = new URL(url);
1317
+ const now = /* @__PURE__ */ new Date();
1318
+ const { amzDate, dateStamp } = toAmzDate(now);
1319
+ const payloadHash = body ? sha256(body) : sha256("");
1320
+ const allHeaders = {
1321
+ ...headers,
1322
+ host: parsedUrl.host,
1323
+ "x-amz-date": amzDate,
1324
+ "x-amz-content-sha256": payloadHash
1325
+ };
1326
+ const lcHeaders = Object.fromEntries(
1327
+ Object.entries(allHeaders).map(([k, v]) => [k.toLowerCase(), v.trim()])
1328
+ );
1329
+ const sortedKeys = Object.keys(lcHeaders).sort();
1330
+ const canonicalHeaders = sortedKeys.map((k) => `${k}:${lcHeaders[k]}`).join("\n") + "\n";
1331
+ const signedHeaders = sortedKeys.join(";");
1332
+ const canonicalRequest = [
1333
+ method,
1334
+ parsedUrl.pathname,
1335
+ parsedUrl.searchParams.toString(),
1336
+ canonicalHeaders,
1337
+ signedHeaders,
1338
+ payloadHash
1339
+ ].join("\n");
1340
+ const scope = `${dateStamp}/${region}/${service}/aws4_request`;
1341
+ const stringToSign = [
1342
+ "AWS4-HMAC-SHA256",
1343
+ amzDate,
1344
+ scope,
1345
+ sha256(canonicalRequest)
1346
+ ].join("\n");
1347
+ const signingKey = getSigningKey(credentials.secretAccessKey, dateStamp, region, service);
1348
+ const signature = createHmac("sha256", signingKey).update(stringToSign).digest("hex");
1349
+ const authorization = `AWS4-HMAC-SHA256 Credential=${credentials.accessKeyId}/${scope}, SignedHeaders=${signedHeaders}, Signature=${signature}`;
1350
+ return {
1351
+ url,
1352
+ headers: {
1353
+ ...lcHeaders,
1354
+ authorization
1355
+ }
1356
+ };
1357
+ }
1358
+ function presignS3Url(url, credentials, options) {
1359
+ const region = credentials.region ?? "auto";
1360
+ const service = "s3";
1361
+ const parsedUrl = new URL(url);
1362
+ const now = /* @__PURE__ */ new Date();
1363
+ const { amzDate, dateStamp } = toAmzDate(now);
1364
+ const expiresIn = options?.expiresIn ?? 3600;
1365
+ const host = parsedUrl.host;
1366
+ const signedHeaders = "host";
1367
+ const scope = `${dateStamp}/${region}/${service}/aws4_request`;
1368
+ const credential = `${credentials.accessKeyId}/${scope}`;
1369
+ const queryParams = new URLSearchParams({
1370
+ "X-Amz-Algorithm": "AWS4-HMAC-SHA256",
1371
+ "X-Amz-Credential": credential,
1372
+ "X-Amz-Date": amzDate,
1373
+ "X-Amz-Expires": String(expiresIn),
1374
+ "X-Amz-SignedHeaders": signedHeaders
1375
+ });
1376
+ const canonicalRequest = [
1377
+ "GET",
1378
+ parsedUrl.pathname,
1379
+ queryParams.toString(),
1380
+ `host:${host}
1381
+ `,
1382
+ signedHeaders,
1383
+ "UNSIGNED-PAYLOAD"
1384
+ ].join("\n");
1385
+ const stringToSign = [
1386
+ "AWS4-HMAC-SHA256",
1387
+ amzDate,
1388
+ scope,
1389
+ sha256(canonicalRequest)
1390
+ ].join("\n");
1391
+ const signingKey = getSigningKey(credentials.secretAccessKey, dateStamp, region, service);
1392
+ const signature = createHmac("sha256", signingKey).update(stringToSign).digest("hex");
1393
+ queryParams.set("X-Amz-Signature", signature);
1394
+ return `${parsedUrl.origin}${parsedUrl.pathname}?${queryParams.toString()}`;
1395
+ }
1396
+
1397
+ // src/storage.ts
1398
+ var MAX_PRESIGN_EXPIRES = 604800;
1399
+ var storageConfig = null;
1400
+ function parseExpiresIn(value) {
1401
+ if (!value) return void 0;
1402
+ const parsed = parseInt(value, 10);
1403
+ if (Number.isNaN(parsed) || parsed <= 0) {
1404
+ throw new StorageError("config", `Invalid R2_PRESIGN_EXPIRES_IN: "${value}". Must be a positive integer.`);
1405
+ }
1406
+ return parsed;
1407
+ }
1408
+ function configureStorage(config) {
1409
+ if (config) {
1410
+ storageConfig = config;
1411
+ return;
1412
+ }
1413
+ const accountId = process.env.R2_ACCOUNT_ID;
1414
+ const bucketName = process.env.R2_BUCKET_NAME;
1415
+ const accessKeyId = process.env.R2_ACCESS_KEY_ID;
1416
+ const secretAccessKey = process.env.R2_SECRET_ACCESS_KEY;
1417
+ if (!accountId || !bucketName || !accessKeyId || !secretAccessKey) {
1418
+ throw new StorageError(
1419
+ "config",
1420
+ "Missing R2 credentials. Provide a config object or set R2_ACCOUNT_ID, R2_BUCKET_NAME, R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY environment variables."
1421
+ );
1422
+ }
1423
+ storageConfig = {
1424
+ accountId,
1425
+ bucketName,
1426
+ accessKeyId,
1427
+ secretAccessKey,
1428
+ publicUrlBase: process.env.R2_PUBLIC_URL,
1429
+ autoUpload: false,
1430
+ mode: process.env.R2_STORAGE_MODE === "presigned" ? "presigned" : void 0,
1431
+ presignExpiresIn: parseExpiresIn(process.env.R2_PRESIGN_EXPIRES_IN)
1432
+ };
1433
+ }
1434
+ function getStorageConfig() {
1435
+ return storageConfig;
1436
+ }
1437
+ function getConfig() {
1438
+ if (!storageConfig) {
1439
+ throw new StorageError("config", "Storage not configured. Call configureStorage() first.");
1440
+ }
1441
+ return storageConfig;
1442
+ }
1443
+ function buildR2Url(config, key) {
1444
+ return `https://${config.accountId}.r2.cloudflarestorage.com/${config.bucketName}/${key}`;
1445
+ }
1446
+ function buildPublicUrl(config, key) {
1447
+ if (config.publicUrlBase) {
1448
+ const base = config.publicUrlBase.replace(/\/$/, "");
1449
+ return `${base}/${key}`;
1450
+ }
1451
+ return buildR2Url(config, key);
1452
+ }
1453
+ function detectContentType(input) {
1454
+ if (input instanceof File) return input.type || "application/octet-stream";
1455
+ if (input instanceof Blob) return input.type || "application/octet-stream";
1456
+ return "application/octet-stream";
1457
+ }
1458
+ async function toBuffer(input) {
1459
+ if (Buffer.isBuffer(input)) return input;
1460
+ if (input instanceof ArrayBuffer) return Buffer.from(input);
1461
+ if (input instanceof Blob) return Buffer.from(await input.arrayBuffer());
1462
+ return Buffer.from(input);
1463
+ }
1464
+ async function uploadAsset(input, options) {
1465
+ const config = getConfig();
1466
+ const buffer = await toBuffer(input);
1467
+ const maxBytes = options?.maxBytes ?? DEFAULT_MAX_BYTES;
1468
+ if (buffer.length > maxBytes) {
1469
+ throw new StorageError(
1470
+ "upload",
1471
+ `Asset too large (${buffer.length} bytes, max ${maxBytes})`
1472
+ );
1473
+ }
1474
+ const contentType = options?.contentType ?? detectContentType(input);
1475
+ const prefix = options?.prefix ? `${options.prefix.replace(/\/$/, "")}/` : "";
1476
+ const key = options?.key ?? `${prefix}${randomUUID()}`;
1477
+ const r2Url = buildR2Url(config, key);
1478
+ const signed = signS3Request(
1479
+ "PUT",
1480
+ r2Url,
1481
+ { "Content-Type": contentType, "Content-Length": String(buffer.length) },
1482
+ buffer,
1483
+ {
1484
+ accessKeyId: config.accessKeyId,
1485
+ secretAccessKey: config.secretAccessKey
1486
+ }
1487
+ );
1488
+ const response = await fetch(signed.url, {
1489
+ method: "PUT",
1490
+ headers: signed.headers,
1491
+ body: new Uint8Array(buffer)
1492
+ });
1493
+ if (!response.ok) {
1494
+ const body = await response.text().catch(() => "");
1495
+ throw new StorageError("upload", `R2 returned ${response.status}: ${body}`, response.status);
1496
+ }
1497
+ const url = config.mode === "presigned" ? validatedPresign(config, key) : buildPublicUrl(config, key);
1498
+ return {
1499
+ url,
1500
+ key,
1501
+ size_bytes: buffer.length,
1502
+ content_type: contentType
1503
+ };
1504
+ }
1505
+ function validatedPresign(config, key, expiresIn) {
1506
+ const ttl = expiresIn ?? config.presignExpiresIn ?? 3600;
1507
+ if (ttl > MAX_PRESIGN_EXPIRES) {
1508
+ throw new StorageError(
1509
+ "config",
1510
+ `Presign expiry ${ttl}s exceeds maximum of ${MAX_PRESIGN_EXPIRES}s (7 days).`
1511
+ );
1512
+ }
1513
+ return presignS3Url(buildR2Url(config, key), {
1514
+ accessKeyId: config.accessKeyId,
1515
+ secretAccessKey: config.secretAccessKey
1516
+ }, { expiresIn: ttl });
1517
+ }
1518
+ function presignAsset(key, options) {
1519
+ const config = getConfig();
1520
+ return validatedPresign(config, key, options?.expiresIn);
1521
+ }
1522
+ async function deleteAsset(key) {
1523
+ const config = getConfig();
1524
+ const r2Url = buildR2Url(config, key);
1525
+ const signed = signS3Request(
1526
+ "DELETE",
1527
+ r2Url,
1528
+ {},
1529
+ null,
1530
+ {
1531
+ accessKeyId: config.accessKeyId,
1532
+ secretAccessKey: config.secretAccessKey
1533
+ }
1534
+ );
1535
+ const response = await fetch(signed.url, {
1536
+ method: "DELETE",
1537
+ headers: signed.headers
1538
+ });
1539
+ if (!response.ok && response.status !== 404) {
1540
+ const body = await response.text().catch(() => "");
1541
+ throw new StorageError("delete", `R2 returned ${response.status}: ${body}`, response.status);
1542
+ }
1543
+ }
1544
+ var DEFAULT_PREFIX = "getaiapi-tmp";
1545
+ var DEFAULT_MAX_BYTES = 500 * 1024 * 1024;
1546
+ function isBinaryValue(value) {
1547
+ return Buffer.isBuffer(value) || value instanceof File || value instanceof Blob || value instanceof ArrayBuffer;
1548
+ }
1549
+ function isUrl(value) {
1550
+ return typeof value === "string" && (value.startsWith("http://") || value.startsWith("https://"));
1551
+ }
1552
+ async function fetchAndReupload(url, maxBytes) {
1553
+ const response = await fetch(url);
1554
+ if (!response.ok) {
1555
+ throw new StorageError("upload", `Failed to fetch URL for re-upload: ${url}`);
1556
+ }
1557
+ const contentLength = response.headers.get("content-length");
1558
+ if (contentLength && parseInt(contentLength, 10) > maxBytes) {
1559
+ throw new StorageError(
1560
+ "upload",
1561
+ `URL content too large (${contentLength} bytes, max ${maxBytes}): ${url}`
1562
+ );
1563
+ }
1564
+ const buffer = Buffer.from(await response.arrayBuffer());
1565
+ if (buffer.length > maxBytes) {
1566
+ throw new StorageError(
1567
+ "upload",
1568
+ `URL content too large (${buffer.length} bytes, max ${maxBytes}): ${url}`
1569
+ );
1570
+ }
1571
+ const contentType = response.headers.get("content-type") ?? "application/octet-stream";
1572
+ const uploaded = await uploadAsset(buffer, { contentType, prefix: DEFAULT_PREFIX });
1573
+ return uploaded.url;
1574
+ }
1575
+ async function processValue(value, shouldReupload, maxBytes) {
1576
+ if (isBinaryValue(value)) {
1577
+ const uploaded = await uploadAsset(value, { prefix: DEFAULT_PREFIX });
1578
+ return uploaded.url;
1579
+ }
1580
+ if (isUrl(value) && shouldReupload) {
1581
+ return fetchAndReupload(value, maxBytes);
1582
+ }
1583
+ if (Array.isArray(value)) {
1584
+ const results = await Promise.all(
1585
+ value.map((item) => processValue(item, shouldReupload, maxBytes))
1586
+ );
1587
+ return results;
1588
+ }
1589
+ if (value !== null && typeof value === "object" && !(value instanceof Date)) {
1590
+ return processRecord(
1591
+ value,
1592
+ shouldReupload,
1593
+ maxBytes
1594
+ );
1595
+ }
1596
+ return value;
1597
+ }
1598
+ async function processRecord(obj, shouldReupload, maxBytes) {
1599
+ const result = {};
1600
+ for (const [key, value] of Object.entries(obj)) {
1601
+ result[key] = await processValue(value, shouldReupload, maxBytes);
1602
+ }
1603
+ return result;
1604
+ }
1605
+ async function processParamsForUpload(params, options) {
1606
+ const config = getStorageConfig();
1607
+ if (!config) return params;
1608
+ const shouldReupload = options?.reupload || config.autoUpload || false;
1609
+ const maxBytes = options?.maxBytes ?? DEFAULT_MAX_BYTES;
1610
+ return processRecord(params, shouldReupload, maxBytes);
1611
+ }
1612
+
1266
1613
  // src/gateway.ts
1267
1614
  var adapters = {
1268
1615
  "fal-ai": falAiAdapter,
@@ -1289,11 +1636,14 @@ async function generate(request) {
1289
1636
  throw new ValidationError("model", `No category template for "${model.category}" yet`);
1290
1637
  }
1291
1638
  const providerParams = mapInput(request, binding, template);
1639
+ const finalParams = await processParamsForUpload(providerParams, {
1640
+ reupload: request.options?.reupload
1641
+ });
1292
1642
  const adapter = adapters[binding.provider];
1293
1643
  const apiKey = auth.getKey(binding.provider);
1294
1644
  const timeoutMs = request.options?.timeout ?? template.default_timeout_ms;
1295
1645
  const submitted = await withRetry(
1296
- () => adapter.submit(binding.endpoint, providerParams, apiKey),
1646
+ () => adapter.submit(binding.endpoint, finalParams, apiKey),
1297
1647
  { timeoutMs }
1298
1648
  );
1299
1649
  let result = submitted;
@@ -1311,7 +1661,7 @@ async function generate(request) {
1311
1661
  }
1312
1662
  const outputs = mapOutput(result.output, binding.output_map);
1313
1663
  return {
1314
- id: randomUUID(),
1664
+ id: randomUUID2(),
1315
1665
  model: model.canonical_name,
1316
1666
  provider: binding.provider,
1317
1667
  status: "completed",
@@ -1324,6 +1674,16 @@ async function generate(request) {
1324
1674
  };
1325
1675
  }
1326
1676
 
1677
+ // src/configure.ts
1678
+ function configure(options) {
1679
+ if (options.keys) {
1680
+ configureAuth(options.keys);
1681
+ }
1682
+ if (options.storage) {
1683
+ configureStorage(options.storage);
1684
+ }
1685
+ }
1686
+
1327
1687
  // src/discovery.ts
1328
1688
  function listModels(filters) {
1329
1689
  let models = loadRegistry();
@@ -1359,8 +1719,15 @@ export {
1359
1719
  ProviderError,
1360
1720
  TimeoutError,
1361
1721
  RateLimitError,
1722
+ StorageError,
1723
+ configureAuth,
1724
+ configureStorage,
1725
+ uploadAsset,
1726
+ presignAsset,
1727
+ deleteAsset,
1362
1728
  generate,
1729
+ configure,
1363
1730
  listModels,
1364
1731
  getModel
1365
1732
  };
1366
- //# sourceMappingURL=chunk-DXIDQGB2.js.map
1733
+ //# sourceMappingURL=chunk-RC2KZLI2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/gateway.ts","../src/errors.ts","../src/auth.ts","../src/resolver.ts","../src/mapper.ts","../src/categories/text-to-image.ts","../src/categories/image-edit.ts","../src/categories/text-to-video.ts","../src/categories/image-to-video.ts","../src/categories/upscale-image.ts","../src/categories/text-to-audio.ts","../src/categories/audio-to-text.ts","../src/categories/remove-background.ts","../src/categories/index.ts","../src/adapters/fal-ai.ts","../src/adapters/replicate.ts","../src/adapters/wavespeed.ts","../src/retry.ts","../src/storage.ts","../src/s3-signer.ts","../src/configure.ts","../src/discovery.ts"],"sourcesContent":["import { randomUUID } from 'crypto'\nimport { AuthManager } from './auth.js'\nimport { resolveModel } from './resolver.js'\nimport { mapInput, mapOutput } from './mapper.js'\nimport { getCategoryTemplate } from './categories/index.js'\nimport { falAiAdapter } from './adapters/fal-ai.js'\nimport { replicateAdapter } from './adapters/replicate.js'\nimport { wavespeedAdapter } from './adapters/wavespeed.js'\nimport type { GenerateRequest, GenerateResponse, ProviderAdapter, ProviderName } from './types.js'\nimport { ValidationError, ProviderError } from './errors.js'\nimport { withRetry } from './retry.js'\nimport { processParamsForUpload } from './storage.js'\n\n// Adapter registry\nconst adapters: Record<string, ProviderAdapter> = {\n 'fal-ai': falAiAdapter,\n 'replicate': replicateAdapter,\n 'wavespeed': wavespeedAdapter,\n}\n\nexport async function generate(request: GenerateRequest): Promise<GenerateResponse> {\n const startTime = Date.now()\n\n // 1. Validate request\n if (!request.model) throw new ValidationError('model', 'model is required')\n\n // 2. Auth - check available providers\n const auth = new AuthManager()\n\n // 3. Resolve model\n const model = resolveModel(request.model, auth.availableProviders())\n\n // 4. Pick provider (first available)\n const availableBindings = model.providers.filter(p =>\n auth.availableProviders().includes(p.provider) && adapters[p.provider]\n )\n if (availableBindings.length === 0) {\n throw new ValidationError(\n 'model',\n `No adapter available for model \"${model.canonical_name}\". Available providers: ${model.providers.map(p => p.provider).join(', ')}`,\n )\n }\n const binding = availableBindings[0]\n\n // 5. Get category template\n const template = getCategoryTemplate(model.category)\n if (!template) {\n throw new ValidationError('model', `No category template for \"${model.category}\" yet`)\n }\n\n // 6. Map input\n const providerParams = mapInput(request, binding, template)\n\n // 6.5 Upload binary params to R2 (no-op if storage not configured)\n const finalParams = await processParamsForUpload(providerParams, {\n reupload: request.options?.reupload as boolean | undefined,\n })\n\n // 7. Get adapter and auth key\n const adapter = adapters[binding.provider]\n const apiKey = auth.getKey(binding.provider)\n\n // 8. Submit with retry, then poll\n const timeoutMs = (request.options?.timeout as number | undefined) ?? template.default_timeout_ms\n const submitted = await withRetry(\n () => adapter.submit(binding.endpoint, finalParams, apiKey),\n { timeoutMs },\n )\n\n let result = submitted\n while (result.status === 'processing' || result.status === 'pending') {\n await new Promise(resolve => setTimeout(resolve, 1000))\n result = await adapter.poll(submitted.id, apiKey, binding.endpoint)\n }\n\n if (result.status === 'failed') {\n throw new ProviderError(\n binding.provider,\n model.canonical_name,\n 0,\n result.error || 'Generation failed',\n )\n }\n\n // 9. Map output\n const outputs = mapOutput(result.output, binding.output_map)\n\n // 10. Build response\n return {\n id: randomUUID(),\n model: model.canonical_name,\n provider: binding.provider,\n status: 'completed',\n outputs,\n metadata: {\n inference_time_ms: Date.now() - startTime,\n seed: typeof result.output === 'object' && result.output !== null\n ? (result.output as Record<string, unknown>).seed as number | undefined\n : undefined,\n safety_flagged: typeof result.output === 'object' && result.output !== null\n ? (\n Array.isArray((result.output as Record<string, unknown>).has_nsfw_concepts)\n ? ((result.output as Record<string, unknown>).has_nsfw_concepts as boolean[]).some((v: boolean) => v)\n : undefined\n )\n : undefined,\n },\n }\n}\n","import type { ProviderName } from \"./types.js\";\n\nexport class GetAIApiError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"GetAIApiError\";\n }\n}\n\nexport class AuthError extends GetAIApiError {\n readonly provider: ProviderName;\n readonly envVar: string;\n\n constructor(provider: ProviderName, envVar: string) {\n super(`Missing or invalid API key for ${provider}. Set the ${envVar} environment variable.`);\n this.name = \"AuthError\";\n this.provider = provider;\n this.envVar = envVar;\n }\n}\n\nexport class ModelNotFoundError extends GetAIApiError {\n readonly query: string;\n readonly suggestions: string[];\n\n constructor(query: string, suggestions: string[] = []) {\n const hint =\n suggestions.length > 0\n ? ` Did you mean: ${suggestions.join(\", \")}?`\n : \"\";\n super(`Model \"${query}\" not found.${hint}`);\n this.name = \"ModelNotFoundError\";\n this.query = query;\n this.suggestions = suggestions;\n }\n}\n\nexport class ValidationError extends GetAIApiError {\n readonly field: string;\n\n constructor(field: string, message: string) {\n super(`Validation error on \"${field}\": ${message}`);\n this.name = \"ValidationError\";\n this.field = field;\n }\n}\n\nexport class ProviderError extends GetAIApiError {\n readonly provider: ProviderName;\n readonly model: string;\n readonly statusCode: number;\n readonly raw: unknown;\n\n constructor(\n provider: ProviderName,\n model: string,\n statusCode: number,\n raw: unknown,\n ) {\n super(\n `Provider ${provider} returned status ${statusCode} for model \"${model}\".`,\n );\n this.name = \"ProviderError\";\n this.provider = provider;\n this.model = model;\n this.statusCode = statusCode;\n this.raw = raw;\n }\n}\n\nexport class TimeoutError extends GetAIApiError {\n readonly provider: ProviderName;\n readonly model: string;\n readonly timeoutMs: number;\n\n constructor(provider: ProviderName, model: string, timeoutMs: number) {\n super(\n `Generation timed out after ${timeoutMs}ms for model \"${model}\" on ${provider}.`,\n );\n this.name = \"TimeoutError\";\n this.provider = provider;\n this.model = model;\n this.timeoutMs = timeoutMs;\n }\n}\n\nexport class RateLimitError extends GetAIApiError {\n readonly provider: ProviderName;\n readonly retryAfterMs: number;\n\n constructor(provider: ProviderName, retryAfterMs: number) {\n super(\n `Rate limited by ${provider}. Retry after ${retryAfterMs}ms.`,\n );\n this.name = \"RateLimitError\";\n this.provider = provider;\n this.retryAfterMs = retryAfterMs;\n }\n}\n\nexport type StorageOperation = \"upload\" | \"delete\" | \"config\";\n\nexport class StorageError extends GetAIApiError {\n readonly operation: StorageOperation;\n readonly statusCode?: number;\n\n constructor(operation: StorageOperation, message: string, statusCode?: number) {\n super(`Storage ${operation} failed: ${message}`);\n this.name = \"StorageError\";\n this.operation = operation;\n this.statusCode = statusCode;\n }\n}\n","import type { ProviderName, ModelEntry } from \"./types.js\";\nimport { AuthError } from \"./errors.js\";\n\nconst ENV_MAP: Record<ProviderName, string> = {\n \"fal-ai\": \"FAL_KEY\",\n replicate: \"REPLICATE_API_TOKEN\",\n wavespeed: \"WAVESPEED_API_KEY\",\n};\n\n// Module-level overrides set via configureAuth()\nconst keyOverrides = new Map<string, string>();\n\nexport function configureAuth(keys: Partial<Record<ProviderName, string>>): void {\n for (const [provider, key] of Object.entries(keys)) {\n if (key?.trim()) {\n keyOverrides.set(provider, key.trim());\n }\n }\n}\n\nexport function resetAuth(): void {\n keyOverrides.clear();\n}\n\nexport class AuthManager {\n private keys: Map<string, string>;\n\n constructor() {\n this.keys = new Map();\n // Overrides take priority over env vars\n for (const [provider, key] of keyOverrides) {\n this.keys.set(provider, key);\n }\n for (const [provider, envVar] of Object.entries(ENV_MAP)) {\n if (!this.keys.has(provider)) {\n const key = process.env[envVar]?.trim();\n if (key) this.keys.set(provider, key);\n }\n }\n }\n\n availableProviders(): ProviderName[] {\n return [...this.keys.keys()] as ProviderName[];\n }\n\n getKey(provider: ProviderName): string {\n const key = this.keys.get(provider);\n if (!key) {\n throw new AuthError(provider, ENV_MAP[provider]);\n }\n return key;\n }\n\n canAccess(model: ModelEntry): boolean {\n return model.providers.some((p) => this.keys.has(p.provider));\n }\n\n listAvailableModels(registry: ModelEntry[]): ModelEntry[] {\n return registry.filter((m) => this.canAccess(m));\n }\n}\n","import { readFileSync } from \"fs\";\nimport { resolve, dirname } from \"path\";\nimport { fileURLToPath } from \"url\";\nimport type { ModelEntry, ProviderName } from \"./types.js\";\nimport { ModelNotFoundError } from \"./errors.js\";\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nlet registryCache: ModelEntry[] | null = null;\n\n/**\n * Reads and parses registry/registry.json.\n * Caches the result so the file is only loaded once.\n */\nexport function loadRegistry(): ModelEntry[] {\n if (registryCache) {\n return registryCache;\n }\n\n // Try resolving from project root (works both from src/ and dist/)\n // Walk up from current file to find the registry directory\n let dir = __dirname;\n for (let i = 0; i < 5; i++) {\n const candidate = resolve(dir, \"registry\", \"registry.json\");\n try {\n const raw = readFileSync(candidate, \"utf-8\");\n registryCache = JSON.parse(raw) as ModelEntry[];\n return registryCache;\n } catch {\n dir = dirname(dir);\n }\n }\n\n throw new Error(\n \"Could not find registry/registry.json. Searched upward from: \" + __dirname,\n );\n}\n\n/**\n * Normalizes a model name for fuzzy matching.\n * - Lowercase\n * - Strip all non-alphanumeric characters\n * - Strip leading 'v' from version numbers (e.g., \"v4.5\" -> \"45\")\n */\nexport function normalizeModelName(input: string): string {\n return input\n .toLowerCase()\n .replace(/[^a-z0-9]/g, \"\")\n .replace(/(?<=\\d)v(?=\\d)/g, \"\") // v between digits (unlikely but safe)\n .replace(/v(?=\\d)/g, \"\"); // v before digits\n}\n\n/**\n * Resolves a user's model name query to a matching ModelEntry.\n *\n * Resolution order:\n * 1. Exact canonical match\n * 2. Exact alias match\n * 3. Normalized canonical match\n * 4. Normalized alias match\n * 5. No match -> throw ModelNotFoundError with suggestions\n */\nexport function resolveModel(\n query: string,\n availableProviders?: ProviderName[],\n): ModelEntry {\n if (!query || typeof query !== \"string\" || query.trim() === \"\") {\n throw new ModelNotFoundError(\"Model name is required\");\n }\n\n const trimmedQuery = query.trim();\n const registry = loadRegistry();\n\n let matched: ModelEntry | undefined;\n\n // 1. Exact canonical match\n matched = registry.find((e) => e.canonical_name === trimmedQuery);\n\n // 2. Exact alias match\n if (!matched) {\n matched = registry.find((e) =>\n e.aliases.some((a) => a === trimmedQuery),\n );\n }\n\n // 3. Normalized canonical match\n if (!matched) {\n const normalizedQuery = normalizeModelName(trimmedQuery);\n matched = registry.find(\n (e) => normalizeModelName(e.canonical_name) === normalizedQuery,\n );\n\n // 4. Normalized alias match\n if (!matched) {\n matched = registry.find((e) =>\n e.aliases.some((a) => normalizeModelName(a) === normalizedQuery),\n );\n }\n }\n\n if (!matched) {\n const suggestions = findSuggestions(trimmedQuery, registry);\n throw new ModelNotFoundError(trimmedQuery, suggestions);\n }\n\n // Apply provider filtering after matching\n if (availableProviders && availableProviders.length > 0) {\n const filteredProviders = matched.providers.filter((p) =>\n availableProviders.includes(p.provider),\n );\n\n if (filteredProviders.length === 0) {\n const suggestions = findSuggestions(trimmedQuery, registry);\n throw new ModelNotFoundError(trimmedQuery, suggestions);\n }\n\n return { ...matched, providers: filteredProviders };\n }\n\n return matched;\n}\n\n/**\n * Find up to 5 suggestions for a failed query.\n * Uses prefix and substring matching on normalized names.\n * Sorted by canonical_name length (shorter = more likely intended).\n */\nfunction findSuggestions(\n query: string,\n registry: ModelEntry[],\n): string[] {\n const normalizedQuery = normalizeModelName(query);\n\n if (normalizedQuery === \"\") {\n return [];\n }\n\n const matches = registry.filter((e) => {\n const normalizedCanonical = normalizeModelName(e.canonical_name);\n // Check if either is a prefix/substring of the other\n if (\n normalizedCanonical.startsWith(normalizedQuery) ||\n normalizedCanonical.includes(normalizedQuery) ||\n normalizedQuery.startsWith(normalizedCanonical)\n ) {\n return true;\n }\n // Check for a meaningful shared prefix (at least 3 chars)\n const minLen = Math.min(normalizedQuery.length, normalizedCanonical.length);\n let shared = 0;\n for (let i = 0; i < minLen; i++) {\n if (normalizedQuery[i] === normalizedCanonical[i]) {\n shared++;\n } else {\n break;\n }\n }\n return shared >= 3 && shared >= normalizedQuery.length * 0.3;\n });\n\n return matches\n .sort((a, b) => a.canonical_name.length - b.canonical_name.length)\n .slice(0, 5)\n .map((e) => e.canonical_name);\n}\n\n/**\n * Clears the registry cache. Useful for testing.\n */\nexport function clearRegistryCache(): void {\n registryCache = null;\n}\n","import type {\n GenerateRequest,\n ProviderBinding,\n CategoryTemplate,\n ParamMapping,\n OutputItem,\n OutputMapping,\n ProviderName,\n} from './types.js'\nimport { ValidationError } from './errors.js'\n\n/**\n * Maps a universal GenerateRequest to provider-specific params\n * using the category template's input_mappings.\n */\nexport function mapInput(\n request: GenerateRequest,\n binding: ProviderBinding,\n template: CategoryTemplate,\n): Record<string, unknown> {\n const result: Record<string, unknown> = {}\n const provider = binding.provider\n\n for (const mapping of template.input_mappings) {\n const value = getUniversalValue(request, mapping.universal)\n\n if (value === undefined || value === null) {\n if (mapping.required) {\n throw new ValidationError(\n mapping.universal,\n `\"${mapping.universal}\" is required but was not provided.`,\n )\n }\n continue\n }\n\n const providerKey = mapping.providers[provider]\n if (providerKey === undefined) {\n // Provider doesn't support this param — silently drop\n continue\n }\n\n const transformed = applyTransform(value, mapping, provider)\n\n if (Array.isArray(providerKey)) {\n // Spread into multiple params (e.g., Replicate's [\"width\", \"height\"])\n if (typeof transformed === 'object' && transformed !== null && !Array.isArray(transformed)) {\n const obj = transformed as Record<string, unknown>\n for (const key of providerKey) {\n if (obj[key] !== undefined) {\n result[key] = obj[key]\n }\n }\n }\n } else {\n result[providerKey] = transformed\n }\n }\n\n // Merge options passthrough — options wins on conflict\n if (request.options) {\n for (const [key, val] of Object.entries(request.options)) {\n result[key] = val\n }\n }\n\n return result\n}\n\n/**\n * Extracts a universal field value from the GenerateRequest.\n */\nfunction getUniversalValue(request: GenerateRequest, field: string): unknown {\n return (request as unknown as Record<string, unknown>)[field]\n}\n\n/**\n * Applies the specified transform to the value.\n */\nfunction applyTransform(\n value: unknown,\n mapping: ParamMapping,\n provider: ProviderName,\n): unknown {\n const transform = mapping.transform\n\n if (!transform || transform === 'none') {\n return value\n }\n\n if (transform === 'flip_boolean') {\n if (provider === 'replicate') {\n return !value\n }\n return value\n }\n\n if (transform === 'parse_size') {\n return parseSizeForProvider(value, mapping, provider)\n }\n\n return value\n}\n\n/**\n * Converts a size value to the provider-specific format.\n */\nfunction parseSizeForProvider(\n value: unknown,\n mapping: ParamMapping,\n provider: ProviderName,\n): unknown {\n if (provider === 'fal-ai') {\n if (typeof value === 'string') {\n const [w, h] = value.split('x').map(Number)\n return { width: w, height: h }\n }\n // Object passthrough\n return value\n }\n\n if (provider === 'replicate') {\n if (typeof value === 'string') {\n const [w, h] = value.split('x').map(Number)\n return { width: w, height: h }\n }\n if (typeof value === 'object' && value !== null) {\n return value\n }\n return value\n }\n\n // wavespeed and others: pass through as-is\n return value\n}\n\n/**\n * Maps raw provider response to OutputItem[] using the output mapping.\n */\nexport function mapOutput(raw: unknown, outputMapping: OutputMapping): OutputItem[] {\n const { type, extract_path, content_type } = outputMapping\n const defaultContentType = content_type || 'image/jpeg'\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const data = raw as any\n\n if (extract_path === 'images[].url') {\n const images: unknown[] = data?.images ?? []\n return images.map((img: any) => ({\n type,\n url: img.url as string,\n content_type: (img.content_type as string) || defaultContentType,\n }))\n }\n\n if (extract_path === 'output[]') {\n const arr: unknown[] = Array.isArray(data) ? data : data?.output ?? []\n return arr.map((url: unknown) => ({\n type,\n url: url as string,\n content_type: defaultContentType,\n }))\n }\n\n if (extract_path === 'data.outputs[]') {\n const outputs: unknown[] = data?.data?.outputs ?? []\n return outputs.map((url: unknown) => ({\n type,\n url: url as string,\n content_type: defaultContentType,\n }))\n }\n\n if (extract_path === 'video.url') {\n return [{\n type: 'video',\n url: data?.video?.url as string,\n content_type: 'video/mp4',\n }]\n }\n\n if (extract_path === 'audio.url') {\n return [{\n type: 'audio',\n url: data?.audio?.url as string,\n content_type: 'audio/mpeg',\n }]\n }\n\n // Generic dot-notation traversal for unknown paths\n return genericExtract(data, extract_path, type, defaultContentType)\n}\n\n/**\n * Generic dot-notation traversal for unknown extract paths.\n * Supports paths like \"foo.bar[].baz\".\n */\nfunction genericExtract(\n data: unknown,\n path: string,\n type: OutputMapping['type'],\n contentType: string,\n): OutputItem[] {\n const segments = path.split('.')\n let current: unknown = data\n\n for (const seg of segments) {\n if (current === null || current === undefined) return []\n\n const arrayMatch = seg.match(/^(.+)\\[\\]$/)\n if (arrayMatch) {\n const key = arrayMatch[1]\n current = (current as Record<string, unknown>)[key]\n if (Array.isArray(current)) {\n // If there are more segments after this, we'd need to map deeper\n // For now, treat as final array\n const remaining = segments.slice(segments.indexOf(seg) + 1).join('.')\n if (remaining) {\n return (current as unknown[]).map((item: any) => ({\n type,\n url: getNestedValue(item, remaining) as string,\n content_type: contentType,\n }))\n }\n return (current as unknown[]).map((item: unknown) => ({\n type,\n url: (typeof item === 'string' ? item : (item as any)?.url) as string,\n content_type: contentType,\n }))\n }\n return []\n }\n\n current = (current as Record<string, unknown>)[seg]\n }\n\n // Single value at end of path\n if (typeof current === 'string') {\n return [{ type, url: current, content_type: contentType }]\n }\n\n return []\n}\n\nfunction getNestedValue(obj: unknown, path: string): unknown {\n let current = obj\n for (const key of path.split('.')) {\n if (current === null || current === undefined) return undefined\n current = (current as Record<string, unknown>)[key]\n }\n return current\n}\n","import type { CategoryTemplate } from '../types.js'\n\nexport const textToImageTemplate: CategoryTemplate = {\n category: 'text-to-image',\n input_mappings: [\n {\n universal: 'prompt',\n providers: {\n 'fal-ai': 'prompt',\n 'replicate': 'prompt',\n 'wavespeed': 'prompt',\n },\n required: true,\n },\n {\n universal: 'negative_prompt',\n providers: {\n 'fal-ai': 'negative_prompt',\n 'replicate': 'negative_prompt',\n 'wavespeed': 'negative_prompt',\n },\n },\n {\n universal: 'count',\n providers: {\n 'fal-ai': 'num_images',\n 'replicate': 'num_outputs',\n 'wavespeed': 'num_outputs',\n },\n },\n {\n universal: 'size',\n providers: {\n 'fal-ai': 'image_size',\n 'replicate': ['width', 'height'],\n 'wavespeed': 'resolution',\n },\n transform: 'parse_size',\n },\n {\n universal: 'guidance',\n providers: {\n 'fal-ai': 'guidance_scale',\n 'replicate': 'guidance',\n 'wavespeed': 'guidance_scale',\n },\n },\n {\n universal: 'steps',\n providers: {\n 'fal-ai': 'num_inference_steps',\n 'replicate': 'num_inference_steps',\n 'wavespeed': 'num_inference_steps',\n },\n },\n {\n universal: 'seed',\n providers: {\n 'fal-ai': 'seed',\n 'replicate': 'seed',\n 'wavespeed': 'seed',\n },\n },\n {\n universal: 'format',\n providers: {\n 'fal-ai': 'output_format',\n 'replicate': 'output_format',\n 'wavespeed': 'output_format',\n },\n },\n {\n universal: 'quality',\n providers: {\n 'fal-ai': 'quality',\n 'replicate': 'output_quality',\n 'wavespeed': 'quality',\n },\n },\n {\n universal: 'safety',\n providers: {\n 'fal-ai': 'enable_safety_checker',\n 'replicate': 'disable_safety_checker',\n 'wavespeed': 'enable_safety_checker',\n },\n transform: 'flip_boolean',\n },\n ],\n output_type: 'image',\n output_extract: {\n 'fal-ai': 'images[].url',\n 'replicate': 'output[]',\n 'wavespeed': 'data.outputs[]',\n },\n default_timeout_ms: 60000,\n}\n","import type { CategoryTemplate } from '../types.js'\n\nexport const imageEditTemplate: CategoryTemplate = {\n category: 'image-edit',\n input_mappings: [\n {\n universal: 'image',\n providers: {\n 'fal-ai': 'image_url',\n 'replicate': 'image',\n 'wavespeed': 'image_url',\n },\n required: true,\n },\n {\n universal: 'prompt',\n providers: {\n 'fal-ai': 'prompt',\n 'replicate': 'prompt',\n 'wavespeed': 'prompt',\n },\n required: true,\n },\n {\n universal: 'strength',\n providers: {\n 'fal-ai': 'strength',\n 'replicate': 'strength',\n 'wavespeed': 'strength',\n },\n },\n {\n universal: 'mask',\n providers: {\n 'fal-ai': 'mask_url',\n 'replicate': 'mask',\n 'wavespeed': 'mask_url',\n },\n },\n {\n universal: 'seed',\n providers: {\n 'fal-ai': 'seed',\n 'replicate': 'seed',\n 'wavespeed': 'seed',\n },\n },\n {\n universal: 'format',\n providers: {\n 'fal-ai': 'output_format',\n 'replicate': 'output_format',\n 'wavespeed': 'output_format',\n },\n },\n {\n universal: 'quality',\n providers: {\n 'fal-ai': 'quality',\n 'replicate': 'output_quality',\n 'wavespeed': 'quality',\n },\n },\n {\n universal: 'safety',\n providers: {\n 'fal-ai': 'enable_safety_checker',\n 'replicate': 'disable_safety_checker',\n 'wavespeed': 'enable_safety_checker',\n },\n transform: 'flip_boolean',\n },\n ],\n output_type: 'image',\n output_extract: {\n 'fal-ai': 'images[].url',\n 'replicate': 'output[]',\n 'wavespeed': 'data.outputs[]',\n },\n default_timeout_ms: 60000,\n}\n","import type { CategoryTemplate } from '../types.js'\n\nexport const textToVideoTemplate: CategoryTemplate = {\n category: 'text-to-video',\n input_mappings: [\n {\n universal: 'prompt',\n providers: {\n 'fal-ai': 'prompt',\n 'replicate': 'prompt',\n 'wavespeed': 'prompt',\n },\n required: true,\n },\n {\n universal: 'negative_prompt',\n providers: {\n 'fal-ai': 'negative_prompt',\n 'replicate': 'negative_prompt',\n 'wavespeed': 'negative_prompt',\n },\n },\n {\n universal: 'count',\n providers: {\n 'fal-ai': 'num_videos',\n 'replicate': 'num_outputs',\n 'wavespeed': 'num_outputs',\n },\n },\n {\n universal: 'size',\n providers: {\n 'fal-ai': 'video_size',\n 'replicate': ['width', 'height'],\n 'wavespeed': 'resolution',\n },\n transform: 'parse_size',\n },\n {\n universal: 'guidance',\n providers: {\n 'fal-ai': 'guidance_scale',\n 'replicate': 'guidance',\n 'wavespeed': 'guidance_scale',\n },\n },\n {\n universal: 'steps',\n providers: {\n 'fal-ai': 'num_inference_steps',\n 'replicate': 'num_inference_steps',\n 'wavespeed': 'num_inference_steps',\n },\n },\n {\n universal: 'seed',\n providers: {\n 'fal-ai': 'seed',\n 'replicate': 'seed',\n 'wavespeed': 'seed',\n },\n },\n {\n universal: 'format',\n providers: {\n 'fal-ai': 'output_format',\n 'replicate': 'output_format',\n 'wavespeed': 'output_format',\n },\n },\n {\n universal: 'safety',\n providers: {\n 'fal-ai': 'enable_safety_checker',\n 'replicate': 'disable_safety_checker',\n 'wavespeed': 'enable_safety_checker',\n },\n transform: 'flip_boolean',\n },\n ],\n output_type: 'video',\n output_extract: {\n 'fal-ai': 'video.url',\n 'replicate': 'output',\n 'wavespeed': 'data.outputs[]',\n },\n default_timeout_ms: 300000,\n}\n","import type { CategoryTemplate } from '../types.js'\n\nexport const imageToVideoTemplate: CategoryTemplate = {\n category: 'image-to-video',\n input_mappings: [\n {\n universal: 'image',\n providers: {\n 'fal-ai': 'image_url',\n 'replicate': 'image',\n 'wavespeed': 'image_url',\n },\n required: true,\n },\n {\n universal: 'prompt',\n providers: {\n 'fal-ai': 'prompt',\n 'replicate': 'prompt',\n 'wavespeed': 'prompt',\n },\n },\n {\n universal: 'negative_prompt',\n providers: {\n 'fal-ai': 'negative_prompt',\n 'replicate': 'negative_prompt',\n 'wavespeed': 'negative_prompt',\n },\n },\n {\n universal: 'seed',\n providers: {\n 'fal-ai': 'seed',\n 'replicate': 'seed',\n 'wavespeed': 'seed',\n },\n },\n {\n universal: 'guidance',\n providers: {\n 'fal-ai': 'guidance_scale',\n 'replicate': 'guidance',\n 'wavespeed': 'guidance_scale',\n },\n },\n {\n universal: 'steps',\n providers: {\n 'fal-ai': 'num_inference_steps',\n 'replicate': 'num_inference_steps',\n 'wavespeed': 'num_inference_steps',\n },\n },\n {\n universal: 'format',\n providers: {\n 'fal-ai': 'output_format',\n 'replicate': 'output_format',\n 'wavespeed': 'output_format',\n },\n },\n {\n universal: 'safety',\n providers: {\n 'fal-ai': 'enable_safety_checker',\n 'replicate': 'disable_safety_checker',\n 'wavespeed': 'enable_safety_checker',\n },\n transform: 'flip_boolean',\n },\n ],\n output_type: 'video',\n output_extract: {\n 'fal-ai': 'video.url',\n 'replicate': 'output',\n 'wavespeed': 'data.outputs[]',\n },\n default_timeout_ms: 300000,\n}\n","import type { CategoryTemplate } from '../types.js'\n\nexport const upscaleImageTemplate: CategoryTemplate = {\n category: 'upscale-image',\n input_mappings: [\n {\n universal: 'image',\n providers: {\n 'fal-ai': 'image_url',\n 'replicate': 'image',\n 'wavespeed': 'image_url',\n },\n required: true,\n },\n {\n universal: 'strength',\n providers: {\n 'fal-ai': 'scale',\n 'replicate': 'scale',\n 'wavespeed': 'scale',\n },\n },\n {\n universal: 'format',\n providers: {\n 'fal-ai': 'output_format',\n 'replicate': 'output_format',\n 'wavespeed': 'output_format',\n },\n },\n {\n universal: 'quality',\n providers: {\n 'fal-ai': 'quality',\n 'replicate': 'output_quality',\n 'wavespeed': 'quality',\n },\n },\n ],\n output_type: 'image',\n output_extract: {\n 'fal-ai': 'images[].url',\n 'replicate': 'output[]',\n 'wavespeed': 'data.outputs[]',\n },\n default_timeout_ms: 120000,\n}\n","import type { CategoryTemplate } from '../types.js'\n\nexport const textToAudioTemplate: CategoryTemplate = {\n category: 'text-to-audio',\n input_mappings: [\n {\n universal: 'prompt',\n providers: {\n 'fal-ai': 'text',\n 'replicate': 'prompt',\n 'wavespeed': 'prompt',\n },\n required: true,\n },\n {\n universal: 'count',\n providers: {\n 'fal-ai': 'num_outputs',\n 'replicate': 'num_outputs',\n 'wavespeed': 'num_outputs',\n },\n },\n {\n universal: 'format',\n providers: {\n 'fal-ai': 'output_format',\n 'replicate': 'output_format',\n 'wavespeed': 'output_format',\n },\n },\n {\n universal: 'seed',\n providers: {\n 'fal-ai': 'seed',\n 'replicate': 'seed',\n 'wavespeed': 'seed',\n },\n },\n ],\n output_type: 'audio',\n output_extract: {\n 'fal-ai': 'audio.url',\n 'replicate': 'output',\n 'wavespeed': 'data.outputs[]',\n },\n default_timeout_ms: 60000,\n}\n","import type { CategoryTemplate } from '../types.js'\n\nexport const audioToTextTemplate: CategoryTemplate = {\n category: 'audio-to-text',\n input_mappings: [\n {\n universal: 'audio',\n providers: {\n 'fal-ai': 'audio_url',\n 'replicate': 'audio',\n 'wavespeed': 'audio_url',\n },\n required: true,\n },\n ],\n output_type: 'text',\n output_extract: {\n 'fal-ai': 'text',\n 'replicate': 'output.text',\n 'wavespeed': 'data.outputs[]',\n },\n default_timeout_ms: 120000,\n}\n","import type { CategoryTemplate } from '../types.js'\n\nexport const removeBackgroundTemplate: CategoryTemplate = {\n category: 'remove-background',\n input_mappings: [\n {\n universal: 'image',\n providers: {\n 'fal-ai': 'image_url',\n 'replicate': 'image',\n 'wavespeed': 'image_url',\n },\n required: true,\n },\n {\n universal: 'format',\n providers: {\n 'fal-ai': 'output_format',\n 'replicate': 'output_format',\n 'wavespeed': 'output_format',\n },\n },\n {\n universal: 'quality',\n providers: {\n 'fal-ai': 'quality',\n 'replicate': 'output_quality',\n 'wavespeed': 'quality',\n },\n },\n ],\n output_type: 'image',\n output_extract: {\n 'fal-ai': 'images[].url',\n 'replicate': 'output[]',\n 'wavespeed': 'data.outputs[]',\n },\n default_timeout_ms: 60000,\n}\n","import { textToImageTemplate } from './text-to-image.js'\nimport { imageEditTemplate } from './image-edit.js'\nimport { textToVideoTemplate } from './text-to-video.js'\nimport { imageToVideoTemplate } from './image-to-video.js'\nimport { upscaleImageTemplate } from './upscale-image.js'\nimport { textToAudioTemplate } from './text-to-audio.js'\nimport { audioToTextTemplate } from './audio-to-text.js'\nimport { removeBackgroundTemplate } from './remove-background.js'\nimport type { CategoryTemplate, ModelCategory } from '../types.js'\n\nconst templates: Partial<Record<ModelCategory, CategoryTemplate>> = {\n 'text-to-image': textToImageTemplate,\n 'image-edit': imageEditTemplate,\n 'text-to-video': textToVideoTemplate,\n 'image-to-video': imageToVideoTemplate,\n 'upscale-image': upscaleImageTemplate,\n 'text-to-audio': textToAudioTemplate,\n 'audio-to-text': audioToTextTemplate,\n 'remove-background': removeBackgroundTemplate,\n}\n\nexport function getCategoryTemplate(category: ModelCategory): CategoryTemplate | undefined {\n return templates[category]\n}\n\nexport {\n textToImageTemplate,\n imageEditTemplate,\n textToVideoTemplate,\n imageToVideoTemplate,\n upscaleImageTemplate,\n textToAudioTemplate,\n audioToTextTemplate,\n removeBackgroundTemplate,\n}\n","import type { ProviderAdapter, ProviderResponse, OutputItem, OutputMapping } from \"./base.js\";\nimport { AuthError, RateLimitError, ProviderError, TimeoutError } from \"../errors.js\";\n\nconst BASE_URL = \"https://queue.fal.run\";\n\nasync function handleHttpErrors(\n response: Response,\n endpoint: string,\n): Promise<void> {\n if (response.ok) return;\n\n const status = response.status;\n\n if (status === 401) {\n throw new AuthError(\"fal-ai\", \"FAL_KEY\");\n }\n\n if (status === 429) {\n const retryAfter = response.headers.get(\"retry-after\");\n const retryMs = retryAfter ? parseInt(retryAfter, 10) * 1000 : 60000;\n throw new RateLimitError(\"fal-ai\", retryMs);\n }\n\n let raw: unknown;\n try {\n raw = await response.json();\n } catch {\n raw = await response.text().catch(() => null);\n }\n\n throw new ProviderError(\"fal-ai\", endpoint, status, raw);\n}\n\nfunction authHeaders(auth: string): Record<string, string> {\n return {\n Authorization: `Key ${auth}`,\n \"Content-Type\": \"application/json\",\n };\n}\n\nexport const falAiAdapter: ProviderAdapter = {\n name: \"fal-ai\",\n\n async submit(\n endpoint: string,\n params: Record<string, unknown>,\n auth: string,\n ): Promise<ProviderResponse> {\n const url = `${BASE_URL}/${endpoint}`;\n const response = await fetch(url, {\n method: \"POST\",\n headers: authHeaders(auth),\n body: JSON.stringify(params),\n });\n\n await handleHttpErrors(response, endpoint);\n\n const data = (await response.json()) as { request_id: string };\n\n return {\n id: data.request_id,\n status: \"pending\",\n };\n },\n\n async poll(\n taskId: string,\n auth: string,\n endpoint?: string,\n ): Promise<ProviderResponse> {\n if (!endpoint) {\n throw new ProviderError(\"fal-ai\", \"unknown\", 400, \"endpoint is required for polling\");\n }\n\n // Check status\n const statusUrl = `${BASE_URL}/${endpoint}/requests/${taskId}/status`;\n const statusResponse = await fetch(statusUrl, {\n headers: { Authorization: `Key ${auth}` },\n });\n\n await handleHttpErrors(statusResponse, endpoint);\n\n const statusData = (await statusResponse.json()) as {\n status: \"IN_QUEUE\" | \"IN_PROGRESS\" | \"COMPLETED\" | \"FAILED\";\n error?: string;\n };\n\n if (statusData.status === \"FAILED\") {\n return {\n id: taskId,\n status: \"failed\",\n error: statusData.error ?? \"Unknown error\",\n };\n }\n\n if (statusData.status !== \"COMPLETED\") {\n return {\n id: taskId,\n status: \"processing\",\n };\n }\n\n // Fetch result\n const resultUrl = `${BASE_URL}/${endpoint}/requests/${taskId}`;\n const resultResponse = await fetch(resultUrl, {\n headers: { Authorization: `Key ${auth}` },\n });\n\n await handleHttpErrors(resultResponse, endpoint);\n\n const output = await resultResponse.json();\n\n return {\n id: taskId,\n status: \"completed\",\n output,\n };\n },\n\n parseOutput(raw: unknown, outputMapping: OutputMapping): OutputItem[] {\n const data = raw as Record<string, unknown>;\n const path = outputMapping.extract_path;\n\n if (path === \"images[].url\") {\n const images = data.images as Array<{\n url: string;\n content_type?: string;\n }>;\n if (!Array.isArray(images)) return [];\n return images.map((img) => ({\n type: outputMapping.type,\n url: img.url,\n content_type: img.content_type ?? outputMapping.content_type ?? \"image/jpeg\",\n }));\n }\n\n if (path === \"video.url\") {\n const video = data.video as { url: string; content_type?: string } | undefined;\n if (!video?.url) return [];\n return [\n {\n type: outputMapping.type,\n url: video.url,\n content_type: video.content_type ?? outputMapping.content_type ?? \"video/mp4\",\n },\n ];\n }\n\n if (path === \"audio.url\") {\n const audio = data.audio as { url: string; content_type?: string } | undefined;\n if (!audio?.url) return [];\n return [\n {\n type: outputMapping.type,\n url: audio.url,\n content_type: audio.content_type ?? outputMapping.content_type ?? \"audio/mpeg\",\n },\n ];\n }\n\n return [];\n },\n};\n\n/**\n * Submit a request and poll until completion or timeout.\n */\nexport async function submitAndPoll(\n endpoint: string,\n params: Record<string, unknown>,\n auth: string,\n options?: {\n timeoutMs?: number;\n intervalMs?: number;\n maxIntervalMs?: number;\n },\n): Promise<ProviderResponse> {\n const timeoutMs = options?.timeoutMs ?? 300_000;\n const startInterval = options?.intervalMs ?? 1000;\n const maxInterval = options?.maxIntervalMs ?? 5000;\n\n const submitted = await falAiAdapter.submit(endpoint, params, auth);\n const taskId = submitted.id;\n\n const start = Date.now();\n let interval = startInterval;\n\n while (Date.now() - start < timeoutMs) {\n await sleep(interval);\n\n const result = await falAiAdapter.poll(taskId, auth, endpoint);\n\n if (result.status === \"completed\" || result.status === \"failed\") {\n return result;\n }\n\n interval = Math.min(interval + 500, maxInterval);\n }\n\n throw new TimeoutError(\"fal-ai\", endpoint, timeoutMs);\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import type { ProviderAdapter, ProviderResponse, OutputItem, OutputMapping } from \"./base.js\";\nimport { AuthError, RateLimitError, ProviderError } from \"../errors.js\";\n\nconst BASE_URL = \"https://api.replicate.com/v1\";\n\nasync function handleHttpErrors(\n response: Response,\n endpoint: string,\n): Promise<void> {\n if (response.ok) return;\n\n const status = response.status;\n\n if (status === 401) {\n throw new AuthError(\"replicate\", \"REPLICATE_API_TOKEN\");\n }\n\n if (status === 429) {\n const retryAfter = response.headers.get(\"retry-after\");\n const retryMs = retryAfter ? parseInt(retryAfter, 10) * 1000 : 60000;\n throw new RateLimitError(\"replicate\", retryMs);\n }\n\n let raw: unknown;\n try {\n raw = await response.json();\n } catch {\n raw = await response.text().catch(() => null);\n }\n\n throw new ProviderError(\"replicate\", endpoint, status, raw);\n}\n\nfunction authHeaders(auth: string): Record<string, string> {\n return {\n Authorization: `Bearer ${auth}`,\n \"Content-Type\": \"application/json\",\n };\n}\n\nfunction inferContentType(url: string): string {\n const lower = url.toLowerCase();\n if (lower.includes(\".png\")) return \"image/png\";\n if (lower.includes(\".jpg\") || lower.includes(\".jpeg\")) return \"image/jpeg\";\n if (lower.includes(\".webp\")) return \"image/webp\";\n if (lower.includes(\".mp4\")) return \"video/mp4\";\n if (lower.includes(\".mp3\")) return \"audio/mpeg\";\n if (lower.includes(\".wav\")) return \"audio/wav\";\n return \"image/jpeg\";\n}\n\nexport const replicateAdapter: ProviderAdapter = {\n name: \"replicate\",\n\n async submit(\n endpoint: string,\n params: Record<string, unknown>,\n auth: string,\n ): Promise<ProviderResponse> {\n const url = `${BASE_URL}/models/${endpoint}/predictions`;\n const response = await fetch(url, {\n method: \"POST\",\n headers: authHeaders(auth),\n body: JSON.stringify({ input: params }),\n });\n\n await handleHttpErrors(response, endpoint);\n\n const data = (await response.json()) as { id: string };\n\n return {\n id: data.id,\n status: \"pending\",\n };\n },\n\n async poll(\n taskId: string,\n auth: string,\n ): Promise<ProviderResponse> {\n const url = `${BASE_URL}/predictions/${taskId}`;\n const response = await fetch(url, {\n headers: { Authorization: `Bearer ${auth}` },\n });\n\n await handleHttpErrors(response, taskId);\n\n const data = (await response.json()) as {\n id: string;\n status: \"starting\" | \"processing\" | \"succeeded\" | \"failed\" | \"canceled\";\n output?: unknown;\n error?: string;\n };\n\n if (data.status === \"succeeded\") {\n return {\n id: data.id,\n status: \"completed\",\n output: data.output,\n };\n }\n\n if (data.status === \"failed\" || data.status === \"canceled\") {\n return {\n id: data.id,\n status: \"failed\",\n error: data.error ?? `Prediction ${data.status}`,\n };\n }\n\n // starting or processing\n return {\n id: data.id,\n status: \"processing\",\n };\n },\n\n parseOutput(raw: unknown, outputMapping: OutputMapping): OutputItem[] {\n // Replicate output is typically string[] (URLs)\n if (!Array.isArray(raw)) return [];\n\n return (raw as string[]).map((url) => ({\n type: outputMapping.type,\n url,\n content_type: outputMapping.content_type ?? inferContentType(url),\n }));\n },\n};\n","import type { ProviderAdapter, ProviderResponse, OutputItem, OutputMapping } from \"./base.js\";\nimport { AuthError, RateLimitError, ProviderError } from \"../errors.js\";\n\nconst BASE_URL = \"https://api.wavespeed.ai/api/v3\";\n\nasync function handleHttpErrors(\n response: Response,\n endpoint: string,\n): Promise<void> {\n if (response.ok) return;\n\n const status = response.status;\n\n if (status === 401) {\n throw new AuthError(\"wavespeed\", \"WAVESPEED_API_KEY\");\n }\n\n if (status === 429) {\n const retryAfter = response.headers.get(\"retry-after\");\n const retryMs = retryAfter ? parseInt(retryAfter, 10) * 1000 : 60000;\n throw new RateLimitError(\"wavespeed\", retryMs);\n }\n\n let raw: unknown;\n try {\n raw = await response.json();\n } catch {\n raw = await response.text().catch(() => null);\n }\n\n throw new ProviderError(\"wavespeed\", endpoint, status, raw);\n}\n\nfunction authHeaders(auth: string): Record<string, string> {\n return {\n Authorization: `Bearer ${auth}`,\n \"Content-Type\": \"application/json\",\n };\n}\n\nfunction inferContentType(url: string): string {\n const ext = url.split(\".\").pop()?.toLowerCase()?.split(\"?\")[0];\n switch (ext) {\n case \"png\":\n return \"image/png\";\n case \"jpg\":\n case \"jpeg\":\n return \"image/jpeg\";\n case \"webp\":\n return \"image/webp\";\n case \"gif\":\n return \"image/gif\";\n case \"mp4\":\n return \"video/mp4\";\n case \"mp3\":\n return \"audio/mpeg\";\n case \"wav\":\n return \"audio/wav\";\n default:\n return \"application/octet-stream\";\n }\n}\n\nexport const wavespeedAdapter: ProviderAdapter = {\n name: \"wavespeed\",\n\n async submit(\n endpoint: string,\n params: Record<string, unknown>,\n auth: string,\n ): Promise<ProviderResponse> {\n const url = `${BASE_URL}/${endpoint}`;\n const response = await fetch(url, {\n method: \"POST\",\n headers: authHeaders(auth),\n body: JSON.stringify(params),\n });\n\n await handleHttpErrors(response, endpoint);\n\n const json = (await response.json()) as {\n data: { id: string; status: string };\n };\n\n return {\n id: json.data.id,\n status: \"pending\",\n };\n },\n\n async poll(\n taskId: string,\n auth: string,\n ): Promise<ProviderResponse> {\n const url = `${BASE_URL}/predictions/${taskId}/result`;\n const response = await fetch(url, {\n headers: { Authorization: `Bearer ${auth}` },\n });\n\n await handleHttpErrors(response, `predictions/${taskId}/result`);\n\n const json = (await response.json()) as {\n data: {\n id: string;\n status: string;\n outputs?: string[];\n error?: string;\n };\n };\n\n const { data } = json;\n\n if (data.status === \"failed\") {\n return {\n id: taskId,\n status: \"failed\",\n error: data.error ?? \"Unknown error\",\n };\n }\n\n if (data.status === \"completed\") {\n return {\n id: taskId,\n status: \"completed\",\n output: data,\n };\n }\n\n // created or processing\n return {\n id: taskId,\n status: \"processing\",\n };\n },\n\n parseOutput(raw: unknown, outputMapping: OutputMapping): OutputItem[] {\n const data = raw as Record<string, unknown>;\n const outputs = data.outputs as string[] | undefined;\n\n if (!Array.isArray(outputs)) return [];\n\n return outputs.map((url) => ({\n type: outputMapping.type,\n url,\n content_type: outputMapping.content_type ?? inferContentType(url),\n }));\n },\n};\n","import {\n AuthError,\n ValidationError,\n ModelNotFoundError,\n ProviderError,\n RateLimitError,\n TimeoutError,\n} from './errors.js'\n\nexport interface RetryOptions {\n maxRetries: number\n initialDelayMs: number\n maxDelayMs: number\n timeoutMs: number\n}\n\nconst DEFAULT_OPTIONS: RetryOptions = {\n maxRetries: 3,\n initialDelayMs: 1000,\n maxDelayMs: 10000,\n timeoutMs: 300_000,\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\nfunction isRetryable(error: unknown): boolean {\n // Never retry auth, validation, or model-not-found errors\n if (\n error instanceof AuthError ||\n error instanceof ValidationError ||\n error instanceof ModelNotFoundError\n ) {\n return false\n }\n\n // Retry rate limit errors (429)\n if (error instanceof RateLimitError) {\n return true\n }\n\n // ProviderError: only retry 5xx, not 4xx\n if (error instanceof ProviderError) {\n return error.statusCode >= 500\n }\n\n // Network errors (TypeError from fetch, etc.) are retryable\n if (error instanceof TypeError) {\n return true\n }\n\n return false\n}\n\nfunction getDelayMs(\n error: unknown,\n attempt: number,\n options: RetryOptions,\n): number {\n // RateLimitError has its own retry-after\n if (error instanceof RateLimitError) {\n return error.retryAfterMs\n }\n\n // Exponential backoff with jitter\n const jitter = Math.random() * options.initialDelayMs * 0.5\n const delay = options.initialDelayMs * Math.pow(2, attempt) + jitter\n return Math.min(delay, options.maxDelayMs)\n}\n\nexport async function withRetry<T>(\n fn: () => Promise<T>,\n options?: Partial<RetryOptions>,\n): Promise<T> {\n const opts: RetryOptions = { ...DEFAULT_OPTIONS, ...options }\n const startTime = Date.now()\n let lastError: unknown\n\n for (let attempt = 0; attempt <= opts.maxRetries; attempt++) {\n // Check total timeout before attempting\n if (attempt > 0) {\n const elapsed = Date.now() - startTime\n if (elapsed >= opts.timeoutMs) {\n throw new TimeoutError('unknown', 'unknown', opts.timeoutMs)\n }\n }\n\n try {\n return await fn()\n } catch (error) {\n lastError = error\n\n // If not retryable, throw immediately\n if (!isRetryable(error)) {\n throw error\n }\n\n // If we've exhausted retries, throw\n if (attempt >= opts.maxRetries) {\n throw error\n }\n\n const delay = getDelayMs(error, attempt, opts)\n\n // Check if waiting would exceed timeout\n const elapsed = Date.now() - startTime\n if (elapsed + delay >= opts.timeoutMs) {\n throw new TimeoutError('unknown', 'unknown', opts.timeoutMs)\n }\n\n await sleep(delay)\n }\n }\n\n /* v8 ignore next 3 */\n // Unreachable: the for loop always returns or throws\n throw lastError as Error\n}\n","import { randomUUID } from \"node:crypto\";\nimport { signS3Request, presignS3Url } from \"./s3-signer.js\";\nimport { StorageError } from \"./errors.js\";\nimport type { StorageConfig, UploadResult, UploadOptions } from \"./types.js\";\n\nconst MAX_PRESIGN_EXPIRES = 604800; // 7 days in seconds (S3/R2 limit)\n\nlet storageConfig: StorageConfig | null = null;\n\nfunction parseExpiresIn(value: string | undefined): number | undefined {\n if (!value) return undefined;\n const parsed = parseInt(value, 10);\n if (Number.isNaN(parsed) || parsed <= 0) {\n throw new StorageError(\"config\", `Invalid R2_PRESIGN_EXPIRES_IN: \"${value}\". Must be a positive integer.`);\n }\n return parsed;\n}\n\nexport function configureStorage(config?: StorageConfig): void {\n if (config) {\n storageConfig = config;\n return;\n }\n\n // Fall back to environment variables\n const accountId = process.env.R2_ACCOUNT_ID;\n const bucketName = process.env.R2_BUCKET_NAME;\n const accessKeyId = process.env.R2_ACCESS_KEY_ID;\n const secretAccessKey = process.env.R2_SECRET_ACCESS_KEY;\n\n if (!accountId || !bucketName || !accessKeyId || !secretAccessKey) {\n throw new StorageError(\n \"config\",\n \"Missing R2 credentials. Provide a config object or set R2_ACCOUNT_ID, R2_BUCKET_NAME, R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY environment variables.\",\n );\n }\n\n storageConfig = {\n accountId,\n bucketName,\n accessKeyId,\n secretAccessKey,\n publicUrlBase: process.env.R2_PUBLIC_URL,\n autoUpload: false,\n mode: process.env.R2_STORAGE_MODE === 'presigned' ? 'presigned' : undefined,\n presignExpiresIn: parseExpiresIn(process.env.R2_PRESIGN_EXPIRES_IN),\n };\n}\n\nexport function getStorageConfig(): StorageConfig | null {\n return storageConfig;\n}\n\nexport function resetStorage(): void {\n storageConfig = null;\n}\n\nfunction getConfig(): StorageConfig {\n if (!storageConfig) {\n throw new StorageError(\"config\", \"Storage not configured. Call configureStorage() first.\");\n }\n return storageConfig;\n}\n\nfunction buildR2Url(config: StorageConfig, key: string): string {\n return `https://${config.accountId}.r2.cloudflarestorage.com/${config.bucketName}/${key}`;\n}\n\nfunction buildPublicUrl(config: StorageConfig, key: string): string {\n if (config.publicUrlBase) {\n const base = config.publicUrlBase.replace(/\\/$/, \"\");\n return `${base}/${key}`;\n }\n return buildR2Url(config, key);\n}\n\nfunction detectContentType(input: Buffer | Blob | File | ArrayBuffer): string {\n if (input instanceof File) return input.type || \"application/octet-stream\";\n if (input instanceof Blob) return input.type || \"application/octet-stream\";\n return \"application/octet-stream\";\n}\n\nasync function toBuffer(input: Buffer | Blob | File | ArrayBuffer): Promise<Buffer> {\n if (Buffer.isBuffer(input)) return input;\n if (input instanceof ArrayBuffer) return Buffer.from(input);\n if (input instanceof Blob) return Buffer.from(await input.arrayBuffer());\n return Buffer.from(input as ArrayBuffer);\n}\n\nexport async function uploadAsset(\n input: Buffer | Blob | File | ArrayBuffer,\n options?: UploadOptions,\n): Promise<UploadResult> {\n const config = getConfig();\n const buffer = await toBuffer(input);\n\n const maxBytes = options?.maxBytes ?? DEFAULT_MAX_BYTES;\n if (buffer.length > maxBytes) {\n throw new StorageError(\n \"upload\",\n `Asset too large (${buffer.length} bytes, max ${maxBytes})`,\n );\n }\n\n const contentType = options?.contentType ?? detectContentType(input);\n const prefix = options?.prefix ? `${options.prefix.replace(/\\/$/, \"\")}/` : \"\";\n const key = options?.key ?? `${prefix}${randomUUID()}`;\n\n const r2Url = buildR2Url(config, key);\n\n const signed = signS3Request(\n \"PUT\",\n r2Url,\n { \"Content-Type\": contentType, \"Content-Length\": String(buffer.length) },\n buffer,\n {\n accessKeyId: config.accessKeyId,\n secretAccessKey: config.secretAccessKey,\n },\n );\n\n const response = await fetch(signed.url, {\n method: \"PUT\",\n headers: signed.headers,\n body: new Uint8Array(buffer),\n });\n\n if (!response.ok) {\n const body = await response.text().catch(() => \"\");\n throw new StorageError(\"upload\", `R2 returned ${response.status}: ${body}`, response.status);\n }\n\n const url = config.mode === 'presigned'\n ? validatedPresign(config, key)\n : buildPublicUrl(config, key);\n\n return {\n url,\n key,\n size_bytes: buffer.length,\n content_type: contentType,\n };\n}\n\nfunction validatedPresign(config: StorageConfig, key: string, expiresIn?: number): string {\n const ttl = expiresIn ?? config.presignExpiresIn ?? 3600;\n if (ttl > MAX_PRESIGN_EXPIRES) {\n throw new StorageError(\n \"config\",\n `Presign expiry ${ttl}s exceeds maximum of ${MAX_PRESIGN_EXPIRES}s (7 days).`,\n );\n }\n return presignS3Url(buildR2Url(config, key), {\n accessKeyId: config.accessKeyId,\n secretAccessKey: config.secretAccessKey,\n }, { expiresIn: ttl });\n}\n\nexport function presignAsset(\n key: string,\n options?: { expiresIn?: number },\n): string {\n const config = getConfig();\n return validatedPresign(config, key, options?.expiresIn);\n}\n\nexport async function deleteAsset(key: string): Promise<void> {\n const config = getConfig();\n const r2Url = buildR2Url(config, key);\n\n const signed = signS3Request(\n \"DELETE\",\n r2Url,\n {},\n null,\n {\n accessKeyId: config.accessKeyId,\n secretAccessKey: config.secretAccessKey,\n },\n );\n\n const response = await fetch(signed.url, {\n method: \"DELETE\",\n headers: signed.headers,\n });\n\n if (!response.ok && response.status !== 404) {\n const body = await response.text().catch(() => \"\");\n throw new StorageError(\"delete\", `R2 returned ${response.status}: ${body}`, response.status);\n }\n}\n\nconst DEFAULT_PREFIX = \"getaiapi-tmp\";\nconst DEFAULT_MAX_BYTES = 500 * 1024 * 1024; // 500 MB\n\nfunction isBinaryValue(value: unknown): value is Buffer | Blob | File | ArrayBuffer {\n return (\n Buffer.isBuffer(value) ||\n value instanceof File ||\n value instanceof Blob ||\n value instanceof ArrayBuffer\n );\n}\n\nfunction isUrl(value: unknown): value is string {\n return (\n typeof value === \"string\" &&\n (value.startsWith(\"http://\") || value.startsWith(\"https://\"))\n );\n}\n\nasync function fetchAndReupload(url: string, maxBytes: number): Promise<string> {\n const response = await fetch(url);\n if (!response.ok) {\n throw new StorageError(\"upload\", `Failed to fetch URL for re-upload: ${url}`);\n }\n\n const contentLength = response.headers.get(\"content-length\");\n if (contentLength && parseInt(contentLength, 10) > maxBytes) {\n throw new StorageError(\n \"upload\",\n `URL content too large (${contentLength} bytes, max ${maxBytes}): ${url}`,\n );\n }\n\n const buffer = Buffer.from(await response.arrayBuffer());\n if (buffer.length > maxBytes) {\n throw new StorageError(\n \"upload\",\n `URL content too large (${buffer.length} bytes, max ${maxBytes}): ${url}`,\n );\n }\n\n const contentType = response.headers.get(\"content-type\") ?? \"application/octet-stream\";\n const uploaded = await uploadAsset(buffer, { contentType, prefix: DEFAULT_PREFIX });\n return uploaded.url;\n}\n\nasync function processValue(\n value: unknown,\n shouldReupload: boolean,\n maxBytes: number,\n): Promise<unknown> {\n if (isBinaryValue(value)) {\n const uploaded = await uploadAsset(value, { prefix: DEFAULT_PREFIX });\n return uploaded.url;\n }\n\n if (isUrl(value) && shouldReupload) {\n return fetchAndReupload(value, maxBytes);\n }\n\n if (Array.isArray(value)) {\n const results = await Promise.all(\n value.map((item) => processValue(item, shouldReupload, maxBytes)),\n );\n return results;\n }\n\n if (value !== null && typeof value === \"object\" && !(value instanceof Date)) {\n return processRecord(\n value as Record<string, unknown>,\n shouldReupload,\n maxBytes,\n );\n }\n\n return value;\n}\n\nasync function processRecord(\n obj: Record<string, unknown>,\n shouldReupload: boolean,\n maxBytes: number,\n): Promise<Record<string, unknown>> {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj)) {\n result[key] = await processValue(value, shouldReupload, maxBytes);\n }\n return result;\n}\n\nexport async function processParamsForUpload(\n params: Record<string, unknown>,\n options?: { reupload?: boolean; maxBytes?: number },\n): Promise<Record<string, unknown>> {\n const config = getStorageConfig();\n if (!config) return params;\n\n const shouldReupload = options?.reupload || config.autoUpload || false;\n const maxBytes = options?.maxBytes ?? DEFAULT_MAX_BYTES;\n\n return processRecord(params, shouldReupload, maxBytes);\n}\n","import { createHmac, createHash } from \"node:crypto\";\n\nexport interface S3Credentials {\n accessKeyId: string;\n secretAccessKey: string;\n region?: string;\n}\n\nexport interface SignedRequest {\n url: string;\n headers: Record<string, string>;\n}\n\nfunction sha256(data: string | Buffer): string {\n return createHash(\"sha256\").update(data).digest(\"hex\");\n}\n\nfunction hmacSha256(key: string | Buffer, data: string): Buffer {\n return createHmac(\"sha256\", key).update(data).digest();\n}\n\nfunction getSigningKey(\n secretKey: string,\n dateStamp: string,\n region: string,\n service: string,\n): Buffer {\n const kDate = hmacSha256(`AWS4${secretKey}`, dateStamp);\n const kRegion = hmacSha256(kDate, region);\n const kService = hmacSha256(kRegion, service);\n return hmacSha256(kService, \"aws4_request\");\n}\n\nfunction toAmzDate(date: Date): { amzDate: string; dateStamp: string } {\n const iso = date.toISOString().replace(/[-:]/g, \"\").replace(/\\.\\d{3}Z$/, \"Z\");\n return {\n amzDate: iso,\n dateStamp: iso.slice(0, 8),\n };\n}\n\nexport function signS3Request(\n method: \"PUT\" | \"DELETE\" | \"GET\",\n url: string,\n headers: Record<string, string>,\n body: Buffer | null,\n credentials: S3Credentials,\n): SignedRequest {\n const region = credentials.region ?? \"auto\";\n const service = \"s3\";\n const parsedUrl = new URL(url);\n const now = new Date();\n const { amzDate, dateStamp } = toAmzDate(now);\n\n const payloadHash = body ? sha256(body) : sha256(\"\");\n\n const allHeaders: Record<string, string> = {\n ...headers,\n host: parsedUrl.host,\n \"x-amz-date\": amzDate,\n \"x-amz-content-sha256\": payloadHash,\n };\n\n // Build lowercased header map once\n const lcHeaders: Record<string, string> = Object.fromEntries(\n Object.entries(allHeaders).map(([k, v]) => [k.toLowerCase(), v.trim()]),\n );\n const sortedKeys = Object.keys(lcHeaders).sort();\n const canonicalHeaders = sortedKeys\n .map((k) => `${k}:${lcHeaders[k]}`)\n .join(\"\\n\") + \"\\n\";\n const signedHeaders = sortedKeys.join(\";\");\n\n // Canonical request\n const canonicalRequest = [\n method,\n parsedUrl.pathname,\n parsedUrl.searchParams.toString(),\n canonicalHeaders,\n signedHeaders,\n payloadHash,\n ].join(\"\\n\");\n\n // String to sign\n const scope = `${dateStamp}/${region}/${service}/aws4_request`;\n const stringToSign = [\n \"AWS4-HMAC-SHA256\",\n amzDate,\n scope,\n sha256(canonicalRequest),\n ].join(\"\\n\");\n\n // Signing key and signature\n const signingKey = getSigningKey(credentials.secretAccessKey, dateStamp, region, service);\n const signature = createHmac(\"sha256\", signingKey)\n .update(stringToSign)\n .digest(\"hex\");\n\n const authorization = `AWS4-HMAC-SHA256 Credential=${credentials.accessKeyId}/${scope}, SignedHeaders=${signedHeaders}, Signature=${signature}`;\n\n return {\n url,\n headers: {\n ...lcHeaders,\n authorization,\n },\n };\n}\n\nexport interface PresignOptions {\n expiresIn?: number; // seconds, default 3600\n}\n\nexport function presignS3Url(\n url: string,\n credentials: S3Credentials,\n options?: PresignOptions,\n): string {\n const region = credentials.region ?? \"auto\";\n const service = \"s3\";\n const parsedUrl = new URL(url);\n const now = new Date();\n const { amzDate, dateStamp } = toAmzDate(now);\n const expiresIn = options?.expiresIn ?? 3600;\n\n const host = parsedUrl.host;\n const signedHeaders = \"host\";\n const scope = `${dateStamp}/${region}/${service}/aws4_request`;\n const credential = `${credentials.accessKeyId}/${scope}`;\n\n // Set query parameters for presigned URL\n const queryParams = new URLSearchParams({\n \"X-Amz-Algorithm\": \"AWS4-HMAC-SHA256\",\n \"X-Amz-Credential\": credential,\n \"X-Amz-Date\": amzDate,\n \"X-Amz-Expires\": String(expiresIn),\n \"X-Amz-SignedHeaders\": signedHeaders,\n });\n\n // Canonical request with UNSIGNED-PAYLOAD\n const canonicalRequest = [\n \"GET\",\n parsedUrl.pathname,\n queryParams.toString(),\n `host:${host}\\n`,\n signedHeaders,\n \"UNSIGNED-PAYLOAD\",\n ].join(\"\\n\");\n\n // String to sign\n const stringToSign = [\n \"AWS4-HMAC-SHA256\",\n amzDate,\n scope,\n sha256(canonicalRequest),\n ].join(\"\\n\");\n\n // Signing key and signature\n const signingKey = getSigningKey(credentials.secretAccessKey, dateStamp, region, service);\n const signature = createHmac(\"sha256\", signingKey)\n .update(stringToSign)\n .digest(\"hex\");\n\n queryParams.set(\"X-Amz-Signature\", signature);\n\n return `${parsedUrl.origin}${parsedUrl.pathname}?${queryParams.toString()}`;\n}\n","import type { ConfigureOptions } from \"./types.js\";\nimport { configureAuth } from \"./auth.js\";\nimport { configureStorage } from \"./storage.js\";\n\nexport function configure(options: ConfigureOptions): void {\n if (options.keys) {\n configureAuth(options.keys);\n }\n if (options.storage) {\n configureStorage(options.storage);\n }\n}\n","import type { ModelEntry, ModelCategory, ProviderName } from \"./types.js\";\nimport { loadRegistry } from \"./resolver.js\";\nimport { resolveModel } from \"./resolver.js\";\nimport { AuthManager } from \"./auth.js\";\n\nexport interface ListModelsFilters {\n category?: ModelCategory;\n provider?: ProviderName;\n query?: string; // search canonical name and aliases\n accessible?: boolean; // if true, only return models the caller has API keys for\n}\n\n/**\n * Lists all models in the registry.\n * Set `accessible: true` to filter to only models the caller has API keys for.\n * Optionally filters by category, provider, or text query.\n */\nexport function listModels(filters?: ListModelsFilters): ModelEntry[] {\n let models = loadRegistry();\n\n if (filters?.accessible) {\n const auth = new AuthManager();\n models = auth.listAvailableModels(models);\n }\n\n if (filters?.category) {\n models = models.filter((m) => m.category === filters.category);\n }\n if (filters?.provider) {\n models = models.filter((m) =>\n m.providers.some((p) => p.provider === filters.provider),\n );\n }\n if (filters?.query) {\n const q = filters.query.toLowerCase();\n models = models.filter(\n (m) =>\n m.canonical_name.includes(q) ||\n m.aliases.some((a) => a.includes(q)),\n );\n }\n\n return models;\n}\n\n/**\n * Resolves a model by name (canonical name, alias, or fuzzy match).\n * Throws ModelNotFoundError if no match is found.\n */\nexport function getModel(name: string): ModelEntry {\n return resolveModel(name);\n}\n"],"mappings":"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","names":["randomUUID","BASE_URL","handleHttpErrors","authHeaders","BASE_URL","handleHttpErrors","authHeaders","inferContentType","resolve","resolve","randomUUID"]}
package/dist/cli.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  generate,
4
4
  getModel,
5
5
  listModels
6
- } from "./chunk-DXIDQGB2.js";
6
+ } from "./chunk-RC2KZLI2.js";
7
7
 
8
8
  // src/cli.ts
9
9
  import { parseArgs } from "util";
package/dist/index.d.ts CHANGED
@@ -65,9 +65,39 @@ interface OutputMapping {
65
65
  extract_path: string;
66
66
  content_type?: string;
67
67
  }
68
+ interface ConfigureOptions {
69
+ keys?: Partial<Record<ProviderName, string>>;
70
+ storage?: StorageConfig;
71
+ }
72
+ interface StorageConfig {
73
+ accountId: string;
74
+ bucketName: string;
75
+ accessKeyId: string;
76
+ secretAccessKey: string;
77
+ publicUrlBase?: string;
78
+ autoUpload?: boolean;
79
+ mode?: 'public' | 'presigned';
80
+ presignExpiresIn?: number;
81
+ }
82
+ interface UploadResult {
83
+ url: string;
84
+ key: string;
85
+ size_bytes: number;
86
+ content_type: string;
87
+ }
88
+ interface UploadOptions {
89
+ key?: string;
90
+ contentType?: string;
91
+ prefix?: string;
92
+ maxBytes?: number;
93
+ }
68
94
 
69
95
  declare function generate(request: GenerateRequest): Promise<GenerateResponse>;
70
96
 
97
+ declare function configure(options: ConfigureOptions): void;
98
+
99
+ declare function configureAuth(keys: Partial<Record<ProviderName, string>>): void;
100
+
71
101
  interface ListModelsFilters {
72
102
  category?: ModelCategory;
73
103
  provider?: ProviderName;
@@ -86,6 +116,13 @@ declare function listModels(filters?: ListModelsFilters): ModelEntry[];
86
116
  */
87
117
  declare function getModel(name: string): ModelEntry;
88
118
 
119
+ declare function configureStorage(config?: StorageConfig): void;
120
+ declare function uploadAsset(input: Buffer | Blob | File | ArrayBuffer, options?: UploadOptions): Promise<UploadResult>;
121
+ declare function presignAsset(key: string, options?: {
122
+ expiresIn?: number;
123
+ }): string;
124
+ declare function deleteAsset(key: string): Promise<void>;
125
+
89
126
  declare class GetAIApiError extends Error {
90
127
  constructor(message: string);
91
128
  }
@@ -121,5 +158,11 @@ declare class RateLimitError extends GetAIApiError {
121
158
  readonly retryAfterMs: number;
122
159
  constructor(provider: ProviderName, retryAfterMs: number);
123
160
  }
161
+ type StorageOperation = "upload" | "delete" | "config";
162
+ declare class StorageError extends GetAIApiError {
163
+ readonly operation: StorageOperation;
164
+ readonly statusCode?: number;
165
+ constructor(operation: StorageOperation, message: string, statusCode?: number);
166
+ }
124
167
 
125
- export { AuthError, type GenerateRequest, type GenerateResponse, GetAIApiError, type ListModelsFilters, type ModelCategory, type ModelEntry, ModelNotFoundError, type OutputItem, type OutputType, type ProviderBinding, ProviderError, type ProviderName, RateLimitError, TimeoutError, ValidationError, generate, getModel, listModels };
168
+ export { AuthError, type ConfigureOptions, type GenerateRequest, type GenerateResponse, GetAIApiError, type ListModelsFilters, type ModelCategory, type ModelEntry, ModelNotFoundError, type OutputItem, type OutputType, type ProviderBinding, ProviderError, type ProviderName, RateLimitError, type StorageConfig, StorageError, TimeoutError, type UploadOptions, type UploadResult, ValidationError, configure, configureAuth, configureStorage, deleteAsset, generate, getModel, listModels, presignAsset, uploadAsset };
package/dist/index.js CHANGED
@@ -4,22 +4,36 @@ import {
4
4
  ModelNotFoundError,
5
5
  ProviderError,
6
6
  RateLimitError,
7
+ StorageError,
7
8
  TimeoutError,
8
9
  ValidationError,
10
+ configure,
11
+ configureAuth,
12
+ configureStorage,
13
+ deleteAsset,
9
14
  generate,
10
15
  getModel,
11
- listModels
12
- } from "./chunk-DXIDQGB2.js";
16
+ listModels,
17
+ presignAsset,
18
+ uploadAsset
19
+ } from "./chunk-RC2KZLI2.js";
13
20
  export {
14
21
  AuthError,
15
22
  GetAIApiError,
16
23
  ModelNotFoundError,
17
24
  ProviderError,
18
25
  RateLimitError,
26
+ StorageError,
19
27
  TimeoutError,
20
28
  ValidationError,
29
+ configure,
30
+ configureAuth,
31
+ configureStorage,
32
+ deleteAsset,
21
33
  generate,
22
34
  getModel,
23
- listModels
35
+ listModels,
36
+ presignAsset,
37
+ uploadAsset
24
38
  };
25
39
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "getaiapi",
3
- "version": "0.1.2",
3
+ "version": "0.3.0",
4
4
  "type": "module",
5
5
  "description": "Unified AI API Gateway - one function to call any AI model",
6
6
  "main": "./dist/index.js",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/gateway.ts","../src/errors.ts","../src/auth.ts","../src/resolver.ts","../src/mapper.ts","../src/categories/text-to-image.ts","../src/categories/image-edit.ts","../src/categories/text-to-video.ts","../src/categories/image-to-video.ts","../src/categories/upscale-image.ts","../src/categories/text-to-audio.ts","../src/categories/audio-to-text.ts","../src/categories/remove-background.ts","../src/categories/index.ts","../src/adapters/fal-ai.ts","../src/adapters/replicate.ts","../src/adapters/wavespeed.ts","../src/retry.ts","../src/discovery.ts"],"sourcesContent":["import { randomUUID } from 'crypto'\nimport { AuthManager } from './auth.js'\nimport { resolveModel } from './resolver.js'\nimport { mapInput, mapOutput } from './mapper.js'\nimport { getCategoryTemplate } from './categories/index.js'\nimport { falAiAdapter } from './adapters/fal-ai.js'\nimport { replicateAdapter } from './adapters/replicate.js'\nimport { wavespeedAdapter } from './adapters/wavespeed.js'\nimport type { GenerateRequest, GenerateResponse, ProviderAdapter, ProviderName } from './types.js'\nimport { ValidationError, ProviderError } from './errors.js'\nimport { withRetry } from './retry.js'\n\n// Adapter registry\nconst adapters: Record<string, ProviderAdapter> = {\n 'fal-ai': falAiAdapter,\n 'replicate': replicateAdapter,\n 'wavespeed': wavespeedAdapter,\n}\n\nexport async function generate(request: GenerateRequest): Promise<GenerateResponse> {\n const startTime = Date.now()\n\n // 1. Validate request\n if (!request.model) throw new ValidationError('model', 'model is required')\n\n // 2. Auth - check available providers\n const auth = new AuthManager()\n\n // 3. Resolve model\n const model = resolveModel(request.model, auth.availableProviders())\n\n // 4. Pick provider (first available)\n const availableBindings = model.providers.filter(p =>\n auth.availableProviders().includes(p.provider) && adapters[p.provider]\n )\n if (availableBindings.length === 0) {\n throw new ValidationError(\n 'model',\n `No adapter available for model \"${model.canonical_name}\". Available providers: ${model.providers.map(p => p.provider).join(', ')}`,\n )\n }\n const binding = availableBindings[0]\n\n // 5. Get category template\n const template = getCategoryTemplate(model.category)\n if (!template) {\n throw new ValidationError('model', `No category template for \"${model.category}\" yet`)\n }\n\n // 6. Map input\n const providerParams = mapInput(request, binding, template)\n\n // 7. Get adapter and auth key\n const adapter = adapters[binding.provider]\n const apiKey = auth.getKey(binding.provider)\n\n // 8. Submit with retry, then poll\n const timeoutMs = (request.options?.timeout as number | undefined) ?? template.default_timeout_ms\n const submitted = await withRetry(\n () => adapter.submit(binding.endpoint, providerParams, apiKey),\n { timeoutMs },\n )\n\n let result = submitted\n while (result.status === 'processing' || result.status === 'pending') {\n await new Promise(resolve => setTimeout(resolve, 1000))\n result = await adapter.poll(submitted.id, apiKey, binding.endpoint)\n }\n\n if (result.status === 'failed') {\n throw new ProviderError(\n binding.provider,\n model.canonical_name,\n 0,\n result.error || 'Generation failed',\n )\n }\n\n // 9. Map output\n const outputs = mapOutput(result.output, binding.output_map)\n\n // 10. Build response\n return {\n id: randomUUID(),\n model: model.canonical_name,\n provider: binding.provider,\n status: 'completed',\n outputs,\n metadata: {\n inference_time_ms: Date.now() - startTime,\n seed: typeof result.output === 'object' && result.output !== null\n ? (result.output as Record<string, unknown>).seed as number | undefined\n : undefined,\n safety_flagged: typeof result.output === 'object' && result.output !== null\n ? (\n Array.isArray((result.output as Record<string, unknown>).has_nsfw_concepts)\n ? ((result.output as Record<string, unknown>).has_nsfw_concepts as boolean[]).some((v: boolean) => v)\n : undefined\n )\n : undefined,\n },\n }\n}\n","import type { ProviderName } from \"./types.js\";\n\nexport class GetAIApiError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"GetAIApiError\";\n }\n}\n\nexport class AuthError extends GetAIApiError {\n readonly provider: ProviderName;\n readonly envVar: string;\n\n constructor(provider: ProviderName, envVar: string) {\n super(`Missing or invalid API key for ${provider}. Set the ${envVar} environment variable.`);\n this.name = \"AuthError\";\n this.provider = provider;\n this.envVar = envVar;\n }\n}\n\nexport class ModelNotFoundError extends GetAIApiError {\n readonly query: string;\n readonly suggestions: string[];\n\n constructor(query: string, suggestions: string[] = []) {\n const hint =\n suggestions.length > 0\n ? ` Did you mean: ${suggestions.join(\", \")}?`\n : \"\";\n super(`Model \"${query}\" not found.${hint}`);\n this.name = \"ModelNotFoundError\";\n this.query = query;\n this.suggestions = suggestions;\n }\n}\n\nexport class ValidationError extends GetAIApiError {\n readonly field: string;\n\n constructor(field: string, message: string) {\n super(`Validation error on \"${field}\": ${message}`);\n this.name = \"ValidationError\";\n this.field = field;\n }\n}\n\nexport class ProviderError extends GetAIApiError {\n readonly provider: ProviderName;\n readonly model: string;\n readonly statusCode: number;\n readonly raw: unknown;\n\n constructor(\n provider: ProviderName,\n model: string,\n statusCode: number,\n raw: unknown,\n ) {\n super(\n `Provider ${provider} returned status ${statusCode} for model \"${model}\".`,\n );\n this.name = \"ProviderError\";\n this.provider = provider;\n this.model = model;\n this.statusCode = statusCode;\n this.raw = raw;\n }\n}\n\nexport class TimeoutError extends GetAIApiError {\n readonly provider: ProviderName;\n readonly model: string;\n readonly timeoutMs: number;\n\n constructor(provider: ProviderName, model: string, timeoutMs: number) {\n super(\n `Generation timed out after ${timeoutMs}ms for model \"${model}\" on ${provider}.`,\n );\n this.name = \"TimeoutError\";\n this.provider = provider;\n this.model = model;\n this.timeoutMs = timeoutMs;\n }\n}\n\nexport class RateLimitError extends GetAIApiError {\n readonly provider: ProviderName;\n readonly retryAfterMs: number;\n\n constructor(provider: ProviderName, retryAfterMs: number) {\n super(\n `Rate limited by ${provider}. Retry after ${retryAfterMs}ms.`,\n );\n this.name = \"RateLimitError\";\n this.provider = provider;\n this.retryAfterMs = retryAfterMs;\n }\n}\n","import type { ProviderName, ModelEntry } from \"./types.js\";\nimport { AuthError } from \"./errors.js\";\n\nconst ENV_MAP: Record<ProviderName, string> = {\n \"fal-ai\": \"FAL_KEY\",\n replicate: \"REPLICATE_API_TOKEN\",\n wavespeed: \"WAVESPEED_API_KEY\",\n};\n\nexport class AuthManager {\n private keys: Map<string, string>;\n\n constructor() {\n this.keys = new Map();\n for (const [provider, envVar] of Object.entries(ENV_MAP)) {\n const key = process.env[envVar]?.trim();\n if (key) this.keys.set(provider, key);\n }\n }\n\n availableProviders(): ProviderName[] {\n return [...this.keys.keys()] as ProviderName[];\n }\n\n getKey(provider: ProviderName): string {\n const key = this.keys.get(provider);\n if (!key) {\n throw new AuthError(provider, ENV_MAP[provider]);\n }\n return key;\n }\n\n canAccess(model: ModelEntry): boolean {\n return model.providers.some((p) => this.keys.has(p.provider));\n }\n\n listAvailableModels(registry: ModelEntry[]): ModelEntry[] {\n return registry.filter((m) => this.canAccess(m));\n }\n}\n","import { readFileSync } from \"fs\";\nimport { resolve, dirname } from \"path\";\nimport { fileURLToPath } from \"url\";\nimport type { ModelEntry, ProviderName } from \"./types.js\";\nimport { ModelNotFoundError } from \"./errors.js\";\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nlet registryCache: ModelEntry[] | null = null;\n\n/**\n * Reads and parses registry/registry.json.\n * Caches the result so the file is only loaded once.\n */\nexport function loadRegistry(): ModelEntry[] {\n if (registryCache) {\n return registryCache;\n }\n\n // Try resolving from project root (works both from src/ and dist/)\n // Walk up from current file to find the registry directory\n let dir = __dirname;\n for (let i = 0; i < 5; i++) {\n const candidate = resolve(dir, \"registry\", \"registry.json\");\n try {\n const raw = readFileSync(candidate, \"utf-8\");\n registryCache = JSON.parse(raw) as ModelEntry[];\n return registryCache;\n } catch {\n dir = dirname(dir);\n }\n }\n\n throw new Error(\n \"Could not find registry/registry.json. Searched upward from: \" + __dirname,\n );\n}\n\n/**\n * Normalizes a model name for fuzzy matching.\n * - Lowercase\n * - Strip all non-alphanumeric characters\n * - Strip leading 'v' from version numbers (e.g., \"v4.5\" -> \"45\")\n */\nexport function normalizeModelName(input: string): string {\n return input\n .toLowerCase()\n .replace(/[^a-z0-9]/g, \"\")\n .replace(/(?<=\\d)v(?=\\d)/g, \"\") // v between digits (unlikely but safe)\n .replace(/v(?=\\d)/g, \"\"); // v before digits\n}\n\n/**\n * Resolves a user's model name query to a matching ModelEntry.\n *\n * Resolution order:\n * 1. Exact canonical match\n * 2. Exact alias match\n * 3. Normalized canonical match\n * 4. Normalized alias match\n * 5. No match -> throw ModelNotFoundError with suggestions\n */\nexport function resolveModel(\n query: string,\n availableProviders?: ProviderName[],\n): ModelEntry {\n if (!query || typeof query !== \"string\" || query.trim() === \"\") {\n throw new ModelNotFoundError(\"Model name is required\");\n }\n\n const trimmedQuery = query.trim();\n const registry = loadRegistry();\n\n let matched: ModelEntry | undefined;\n\n // 1. Exact canonical match\n matched = registry.find((e) => e.canonical_name === trimmedQuery);\n\n // 2. Exact alias match\n if (!matched) {\n matched = registry.find((e) =>\n e.aliases.some((a) => a === trimmedQuery),\n );\n }\n\n // 3. Normalized canonical match\n if (!matched) {\n const normalizedQuery = normalizeModelName(trimmedQuery);\n matched = registry.find(\n (e) => normalizeModelName(e.canonical_name) === normalizedQuery,\n );\n\n // 4. Normalized alias match\n if (!matched) {\n matched = registry.find((e) =>\n e.aliases.some((a) => normalizeModelName(a) === normalizedQuery),\n );\n }\n }\n\n if (!matched) {\n const suggestions = findSuggestions(trimmedQuery, registry);\n throw new ModelNotFoundError(trimmedQuery, suggestions);\n }\n\n // Apply provider filtering after matching\n if (availableProviders && availableProviders.length > 0) {\n const filteredProviders = matched.providers.filter((p) =>\n availableProviders.includes(p.provider),\n );\n\n if (filteredProviders.length === 0) {\n const suggestions = findSuggestions(trimmedQuery, registry);\n throw new ModelNotFoundError(trimmedQuery, suggestions);\n }\n\n return { ...matched, providers: filteredProviders };\n }\n\n return matched;\n}\n\n/**\n * Find up to 5 suggestions for a failed query.\n * Uses prefix and substring matching on normalized names.\n * Sorted by canonical_name length (shorter = more likely intended).\n */\nfunction findSuggestions(\n query: string,\n registry: ModelEntry[],\n): string[] {\n const normalizedQuery = normalizeModelName(query);\n\n if (normalizedQuery === \"\") {\n return [];\n }\n\n const matches = registry.filter((e) => {\n const normalizedCanonical = normalizeModelName(e.canonical_name);\n // Check if either is a prefix/substring of the other\n if (\n normalizedCanonical.startsWith(normalizedQuery) ||\n normalizedCanonical.includes(normalizedQuery) ||\n normalizedQuery.startsWith(normalizedCanonical)\n ) {\n return true;\n }\n // Check for a meaningful shared prefix (at least 3 chars)\n const minLen = Math.min(normalizedQuery.length, normalizedCanonical.length);\n let shared = 0;\n for (let i = 0; i < minLen; i++) {\n if (normalizedQuery[i] === normalizedCanonical[i]) {\n shared++;\n } else {\n break;\n }\n }\n return shared >= 3 && shared >= normalizedQuery.length * 0.3;\n });\n\n return matches\n .sort((a, b) => a.canonical_name.length - b.canonical_name.length)\n .slice(0, 5)\n .map((e) => e.canonical_name);\n}\n\n/**\n * Clears the registry cache. Useful for testing.\n */\nexport function clearRegistryCache(): void {\n registryCache = null;\n}\n","import type {\n GenerateRequest,\n ProviderBinding,\n CategoryTemplate,\n ParamMapping,\n OutputItem,\n OutputMapping,\n ProviderName,\n} from './types.js'\nimport { ValidationError } from './errors.js'\n\n/**\n * Maps a universal GenerateRequest to provider-specific params\n * using the category template's input_mappings.\n */\nexport function mapInput(\n request: GenerateRequest,\n binding: ProviderBinding,\n template: CategoryTemplate,\n): Record<string, unknown> {\n const result: Record<string, unknown> = {}\n const provider = binding.provider\n\n for (const mapping of template.input_mappings) {\n const value = getUniversalValue(request, mapping.universal)\n\n if (value === undefined || value === null) {\n if (mapping.required) {\n throw new ValidationError(\n mapping.universal,\n `\"${mapping.universal}\" is required but was not provided.`,\n )\n }\n continue\n }\n\n const providerKey = mapping.providers[provider]\n if (providerKey === undefined) {\n // Provider doesn't support this param — silently drop\n continue\n }\n\n const transformed = applyTransform(value, mapping, provider)\n\n if (Array.isArray(providerKey)) {\n // Spread into multiple params (e.g., Replicate's [\"width\", \"height\"])\n if (typeof transformed === 'object' && transformed !== null && !Array.isArray(transformed)) {\n const obj = transformed as Record<string, unknown>\n for (const key of providerKey) {\n if (obj[key] !== undefined) {\n result[key] = obj[key]\n }\n }\n }\n } else {\n result[providerKey] = transformed\n }\n }\n\n // Merge options passthrough — options wins on conflict\n if (request.options) {\n for (const [key, val] of Object.entries(request.options)) {\n result[key] = val\n }\n }\n\n return result\n}\n\n/**\n * Extracts a universal field value from the GenerateRequest.\n */\nfunction getUniversalValue(request: GenerateRequest, field: string): unknown {\n return (request as unknown as Record<string, unknown>)[field]\n}\n\n/**\n * Applies the specified transform to the value.\n */\nfunction applyTransform(\n value: unknown,\n mapping: ParamMapping,\n provider: ProviderName,\n): unknown {\n const transform = mapping.transform\n\n if (!transform || transform === 'none') {\n return value\n }\n\n if (transform === 'flip_boolean') {\n if (provider === 'replicate') {\n return !value\n }\n return value\n }\n\n if (transform === 'parse_size') {\n return parseSizeForProvider(value, mapping, provider)\n }\n\n return value\n}\n\n/**\n * Converts a size value to the provider-specific format.\n */\nfunction parseSizeForProvider(\n value: unknown,\n mapping: ParamMapping,\n provider: ProviderName,\n): unknown {\n if (provider === 'fal-ai') {\n if (typeof value === 'string') {\n const [w, h] = value.split('x').map(Number)\n return { width: w, height: h }\n }\n // Object passthrough\n return value\n }\n\n if (provider === 'replicate') {\n if (typeof value === 'string') {\n const [w, h] = value.split('x').map(Number)\n return { width: w, height: h }\n }\n if (typeof value === 'object' && value !== null) {\n return value\n }\n return value\n }\n\n // wavespeed and others: pass through as-is\n return value\n}\n\n/**\n * Maps raw provider response to OutputItem[] using the output mapping.\n */\nexport function mapOutput(raw: unknown, outputMapping: OutputMapping): OutputItem[] {\n const { type, extract_path, content_type } = outputMapping\n const defaultContentType = content_type || 'image/jpeg'\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const data = raw as any\n\n if (extract_path === 'images[].url') {\n const images: unknown[] = data?.images ?? []\n return images.map((img: any) => ({\n type,\n url: img.url as string,\n content_type: (img.content_type as string) || defaultContentType,\n }))\n }\n\n if (extract_path === 'output[]') {\n const arr: unknown[] = Array.isArray(data) ? data : data?.output ?? []\n return arr.map((url: unknown) => ({\n type,\n url: url as string,\n content_type: defaultContentType,\n }))\n }\n\n if (extract_path === 'data.outputs[]') {\n const outputs: unknown[] = data?.data?.outputs ?? []\n return outputs.map((url: unknown) => ({\n type,\n url: url as string,\n content_type: defaultContentType,\n }))\n }\n\n if (extract_path === 'video.url') {\n return [{\n type: 'video',\n url: data?.video?.url as string,\n content_type: 'video/mp4',\n }]\n }\n\n if (extract_path === 'audio.url') {\n return [{\n type: 'audio',\n url: data?.audio?.url as string,\n content_type: 'audio/mpeg',\n }]\n }\n\n // Generic dot-notation traversal for unknown paths\n return genericExtract(data, extract_path, type, defaultContentType)\n}\n\n/**\n * Generic dot-notation traversal for unknown extract paths.\n * Supports paths like \"foo.bar[].baz\".\n */\nfunction genericExtract(\n data: unknown,\n path: string,\n type: OutputMapping['type'],\n contentType: string,\n): OutputItem[] {\n const segments = path.split('.')\n let current: unknown = data\n\n for (const seg of segments) {\n if (current === null || current === undefined) return []\n\n const arrayMatch = seg.match(/^(.+)\\[\\]$/)\n if (arrayMatch) {\n const key = arrayMatch[1]\n current = (current as Record<string, unknown>)[key]\n if (Array.isArray(current)) {\n // If there are more segments after this, we'd need to map deeper\n // For now, treat as final array\n const remaining = segments.slice(segments.indexOf(seg) + 1).join('.')\n if (remaining) {\n return (current as unknown[]).map((item: any) => ({\n type,\n url: getNestedValue(item, remaining) as string,\n content_type: contentType,\n }))\n }\n return (current as unknown[]).map((item: unknown) => ({\n type,\n url: (typeof item === 'string' ? item : (item as any)?.url) as string,\n content_type: contentType,\n }))\n }\n return []\n }\n\n current = (current as Record<string, unknown>)[seg]\n }\n\n // Single value at end of path\n if (typeof current === 'string') {\n return [{ type, url: current, content_type: contentType }]\n }\n\n return []\n}\n\nfunction getNestedValue(obj: unknown, path: string): unknown {\n let current = obj\n for (const key of path.split('.')) {\n if (current === null || current === undefined) return undefined\n current = (current as Record<string, unknown>)[key]\n }\n return current\n}\n","import type { CategoryTemplate } from '../types.js'\n\nexport const textToImageTemplate: CategoryTemplate = {\n category: 'text-to-image',\n input_mappings: [\n {\n universal: 'prompt',\n providers: {\n 'fal-ai': 'prompt',\n 'replicate': 'prompt',\n 'wavespeed': 'prompt',\n },\n required: true,\n },\n {\n universal: 'negative_prompt',\n providers: {\n 'fal-ai': 'negative_prompt',\n 'replicate': 'negative_prompt',\n 'wavespeed': 'negative_prompt',\n },\n },\n {\n universal: 'count',\n providers: {\n 'fal-ai': 'num_images',\n 'replicate': 'num_outputs',\n 'wavespeed': 'num_outputs',\n },\n },\n {\n universal: 'size',\n providers: {\n 'fal-ai': 'image_size',\n 'replicate': ['width', 'height'],\n 'wavespeed': 'resolution',\n },\n transform: 'parse_size',\n },\n {\n universal: 'guidance',\n providers: {\n 'fal-ai': 'guidance_scale',\n 'replicate': 'guidance',\n 'wavespeed': 'guidance_scale',\n },\n },\n {\n universal: 'steps',\n providers: {\n 'fal-ai': 'num_inference_steps',\n 'replicate': 'num_inference_steps',\n 'wavespeed': 'num_inference_steps',\n },\n },\n {\n universal: 'seed',\n providers: {\n 'fal-ai': 'seed',\n 'replicate': 'seed',\n 'wavespeed': 'seed',\n },\n },\n {\n universal: 'format',\n providers: {\n 'fal-ai': 'output_format',\n 'replicate': 'output_format',\n 'wavespeed': 'output_format',\n },\n },\n {\n universal: 'quality',\n providers: {\n 'fal-ai': 'quality',\n 'replicate': 'output_quality',\n 'wavespeed': 'quality',\n },\n },\n {\n universal: 'safety',\n providers: {\n 'fal-ai': 'enable_safety_checker',\n 'replicate': 'disable_safety_checker',\n 'wavespeed': 'enable_safety_checker',\n },\n transform: 'flip_boolean',\n },\n ],\n output_type: 'image',\n output_extract: {\n 'fal-ai': 'images[].url',\n 'replicate': 'output[]',\n 'wavespeed': 'data.outputs[]',\n },\n default_timeout_ms: 60000,\n}\n","import type { CategoryTemplate } from '../types.js'\n\nexport const imageEditTemplate: CategoryTemplate = {\n category: 'image-edit',\n input_mappings: [\n {\n universal: 'image',\n providers: {\n 'fal-ai': 'image_url',\n 'replicate': 'image',\n 'wavespeed': 'image_url',\n },\n required: true,\n },\n {\n universal: 'prompt',\n providers: {\n 'fal-ai': 'prompt',\n 'replicate': 'prompt',\n 'wavespeed': 'prompt',\n },\n required: true,\n },\n {\n universal: 'strength',\n providers: {\n 'fal-ai': 'strength',\n 'replicate': 'strength',\n 'wavespeed': 'strength',\n },\n },\n {\n universal: 'mask',\n providers: {\n 'fal-ai': 'mask_url',\n 'replicate': 'mask',\n 'wavespeed': 'mask_url',\n },\n },\n {\n universal: 'seed',\n providers: {\n 'fal-ai': 'seed',\n 'replicate': 'seed',\n 'wavespeed': 'seed',\n },\n },\n {\n universal: 'format',\n providers: {\n 'fal-ai': 'output_format',\n 'replicate': 'output_format',\n 'wavespeed': 'output_format',\n },\n },\n {\n universal: 'quality',\n providers: {\n 'fal-ai': 'quality',\n 'replicate': 'output_quality',\n 'wavespeed': 'quality',\n },\n },\n {\n universal: 'safety',\n providers: {\n 'fal-ai': 'enable_safety_checker',\n 'replicate': 'disable_safety_checker',\n 'wavespeed': 'enable_safety_checker',\n },\n transform: 'flip_boolean',\n },\n ],\n output_type: 'image',\n output_extract: {\n 'fal-ai': 'images[].url',\n 'replicate': 'output[]',\n 'wavespeed': 'data.outputs[]',\n },\n default_timeout_ms: 60000,\n}\n","import type { CategoryTemplate } from '../types.js'\n\nexport const textToVideoTemplate: CategoryTemplate = {\n category: 'text-to-video',\n input_mappings: [\n {\n universal: 'prompt',\n providers: {\n 'fal-ai': 'prompt',\n 'replicate': 'prompt',\n 'wavespeed': 'prompt',\n },\n required: true,\n },\n {\n universal: 'negative_prompt',\n providers: {\n 'fal-ai': 'negative_prompt',\n 'replicate': 'negative_prompt',\n 'wavespeed': 'negative_prompt',\n },\n },\n {\n universal: 'count',\n providers: {\n 'fal-ai': 'num_videos',\n 'replicate': 'num_outputs',\n 'wavespeed': 'num_outputs',\n },\n },\n {\n universal: 'size',\n providers: {\n 'fal-ai': 'video_size',\n 'replicate': ['width', 'height'],\n 'wavespeed': 'resolution',\n },\n transform: 'parse_size',\n },\n {\n universal: 'guidance',\n providers: {\n 'fal-ai': 'guidance_scale',\n 'replicate': 'guidance',\n 'wavespeed': 'guidance_scale',\n },\n },\n {\n universal: 'steps',\n providers: {\n 'fal-ai': 'num_inference_steps',\n 'replicate': 'num_inference_steps',\n 'wavespeed': 'num_inference_steps',\n },\n },\n {\n universal: 'seed',\n providers: {\n 'fal-ai': 'seed',\n 'replicate': 'seed',\n 'wavespeed': 'seed',\n },\n },\n {\n universal: 'format',\n providers: {\n 'fal-ai': 'output_format',\n 'replicate': 'output_format',\n 'wavespeed': 'output_format',\n },\n },\n {\n universal: 'safety',\n providers: {\n 'fal-ai': 'enable_safety_checker',\n 'replicate': 'disable_safety_checker',\n 'wavespeed': 'enable_safety_checker',\n },\n transform: 'flip_boolean',\n },\n ],\n output_type: 'video',\n output_extract: {\n 'fal-ai': 'video.url',\n 'replicate': 'output',\n 'wavespeed': 'data.outputs[]',\n },\n default_timeout_ms: 300000,\n}\n","import type { CategoryTemplate } from '../types.js'\n\nexport const imageToVideoTemplate: CategoryTemplate = {\n category: 'image-to-video',\n input_mappings: [\n {\n universal: 'image',\n providers: {\n 'fal-ai': 'image_url',\n 'replicate': 'image',\n 'wavespeed': 'image_url',\n },\n required: true,\n },\n {\n universal: 'prompt',\n providers: {\n 'fal-ai': 'prompt',\n 'replicate': 'prompt',\n 'wavespeed': 'prompt',\n },\n },\n {\n universal: 'negative_prompt',\n providers: {\n 'fal-ai': 'negative_prompt',\n 'replicate': 'negative_prompt',\n 'wavespeed': 'negative_prompt',\n },\n },\n {\n universal: 'seed',\n providers: {\n 'fal-ai': 'seed',\n 'replicate': 'seed',\n 'wavespeed': 'seed',\n },\n },\n {\n universal: 'guidance',\n providers: {\n 'fal-ai': 'guidance_scale',\n 'replicate': 'guidance',\n 'wavespeed': 'guidance_scale',\n },\n },\n {\n universal: 'steps',\n providers: {\n 'fal-ai': 'num_inference_steps',\n 'replicate': 'num_inference_steps',\n 'wavespeed': 'num_inference_steps',\n },\n },\n {\n universal: 'format',\n providers: {\n 'fal-ai': 'output_format',\n 'replicate': 'output_format',\n 'wavespeed': 'output_format',\n },\n },\n {\n universal: 'safety',\n providers: {\n 'fal-ai': 'enable_safety_checker',\n 'replicate': 'disable_safety_checker',\n 'wavespeed': 'enable_safety_checker',\n },\n transform: 'flip_boolean',\n },\n ],\n output_type: 'video',\n output_extract: {\n 'fal-ai': 'video.url',\n 'replicate': 'output',\n 'wavespeed': 'data.outputs[]',\n },\n default_timeout_ms: 300000,\n}\n","import type { CategoryTemplate } from '../types.js'\n\nexport const upscaleImageTemplate: CategoryTemplate = {\n category: 'upscale-image',\n input_mappings: [\n {\n universal: 'image',\n providers: {\n 'fal-ai': 'image_url',\n 'replicate': 'image',\n 'wavespeed': 'image_url',\n },\n required: true,\n },\n {\n universal: 'strength',\n providers: {\n 'fal-ai': 'scale',\n 'replicate': 'scale',\n 'wavespeed': 'scale',\n },\n },\n {\n universal: 'format',\n providers: {\n 'fal-ai': 'output_format',\n 'replicate': 'output_format',\n 'wavespeed': 'output_format',\n },\n },\n {\n universal: 'quality',\n providers: {\n 'fal-ai': 'quality',\n 'replicate': 'output_quality',\n 'wavespeed': 'quality',\n },\n },\n ],\n output_type: 'image',\n output_extract: {\n 'fal-ai': 'images[].url',\n 'replicate': 'output[]',\n 'wavespeed': 'data.outputs[]',\n },\n default_timeout_ms: 120000,\n}\n","import type { CategoryTemplate } from '../types.js'\n\nexport const textToAudioTemplate: CategoryTemplate = {\n category: 'text-to-audio',\n input_mappings: [\n {\n universal: 'prompt',\n providers: {\n 'fal-ai': 'text',\n 'replicate': 'prompt',\n 'wavespeed': 'prompt',\n },\n required: true,\n },\n {\n universal: 'count',\n providers: {\n 'fal-ai': 'num_outputs',\n 'replicate': 'num_outputs',\n 'wavespeed': 'num_outputs',\n },\n },\n {\n universal: 'format',\n providers: {\n 'fal-ai': 'output_format',\n 'replicate': 'output_format',\n 'wavespeed': 'output_format',\n },\n },\n {\n universal: 'seed',\n providers: {\n 'fal-ai': 'seed',\n 'replicate': 'seed',\n 'wavespeed': 'seed',\n },\n },\n ],\n output_type: 'audio',\n output_extract: {\n 'fal-ai': 'audio.url',\n 'replicate': 'output',\n 'wavespeed': 'data.outputs[]',\n },\n default_timeout_ms: 60000,\n}\n","import type { CategoryTemplate } from '../types.js'\n\nexport const audioToTextTemplate: CategoryTemplate = {\n category: 'audio-to-text',\n input_mappings: [\n {\n universal: 'audio',\n providers: {\n 'fal-ai': 'audio_url',\n 'replicate': 'audio',\n 'wavespeed': 'audio_url',\n },\n required: true,\n },\n ],\n output_type: 'text',\n output_extract: {\n 'fal-ai': 'text',\n 'replicate': 'output.text',\n 'wavespeed': 'data.outputs[]',\n },\n default_timeout_ms: 120000,\n}\n","import type { CategoryTemplate } from '../types.js'\n\nexport const removeBackgroundTemplate: CategoryTemplate = {\n category: 'remove-background',\n input_mappings: [\n {\n universal: 'image',\n providers: {\n 'fal-ai': 'image_url',\n 'replicate': 'image',\n 'wavespeed': 'image_url',\n },\n required: true,\n },\n {\n universal: 'format',\n providers: {\n 'fal-ai': 'output_format',\n 'replicate': 'output_format',\n 'wavespeed': 'output_format',\n },\n },\n {\n universal: 'quality',\n providers: {\n 'fal-ai': 'quality',\n 'replicate': 'output_quality',\n 'wavespeed': 'quality',\n },\n },\n ],\n output_type: 'image',\n output_extract: {\n 'fal-ai': 'images[].url',\n 'replicate': 'output[]',\n 'wavespeed': 'data.outputs[]',\n },\n default_timeout_ms: 60000,\n}\n","import { textToImageTemplate } from './text-to-image.js'\nimport { imageEditTemplate } from './image-edit.js'\nimport { textToVideoTemplate } from './text-to-video.js'\nimport { imageToVideoTemplate } from './image-to-video.js'\nimport { upscaleImageTemplate } from './upscale-image.js'\nimport { textToAudioTemplate } from './text-to-audio.js'\nimport { audioToTextTemplate } from './audio-to-text.js'\nimport { removeBackgroundTemplate } from './remove-background.js'\nimport type { CategoryTemplate, ModelCategory } from '../types.js'\n\nconst templates: Partial<Record<ModelCategory, CategoryTemplate>> = {\n 'text-to-image': textToImageTemplate,\n 'image-edit': imageEditTemplate,\n 'text-to-video': textToVideoTemplate,\n 'image-to-video': imageToVideoTemplate,\n 'upscale-image': upscaleImageTemplate,\n 'text-to-audio': textToAudioTemplate,\n 'audio-to-text': audioToTextTemplate,\n 'remove-background': removeBackgroundTemplate,\n}\n\nexport function getCategoryTemplate(category: ModelCategory): CategoryTemplate | undefined {\n return templates[category]\n}\n\nexport {\n textToImageTemplate,\n imageEditTemplate,\n textToVideoTemplate,\n imageToVideoTemplate,\n upscaleImageTemplate,\n textToAudioTemplate,\n audioToTextTemplate,\n removeBackgroundTemplate,\n}\n","import type { ProviderAdapter, ProviderResponse, OutputItem, OutputMapping } from \"./base.js\";\nimport { AuthError, RateLimitError, ProviderError, TimeoutError } from \"../errors.js\";\n\nconst BASE_URL = \"https://queue.fal.run\";\n\nasync function handleHttpErrors(\n response: Response,\n endpoint: string,\n): Promise<void> {\n if (response.ok) return;\n\n const status = response.status;\n\n if (status === 401) {\n throw new AuthError(\"fal-ai\", \"FAL_KEY\");\n }\n\n if (status === 429) {\n const retryAfter = response.headers.get(\"retry-after\");\n const retryMs = retryAfter ? parseInt(retryAfter, 10) * 1000 : 60000;\n throw new RateLimitError(\"fal-ai\", retryMs);\n }\n\n let raw: unknown;\n try {\n raw = await response.json();\n } catch {\n raw = await response.text().catch(() => null);\n }\n\n throw new ProviderError(\"fal-ai\", endpoint, status, raw);\n}\n\nfunction authHeaders(auth: string): Record<string, string> {\n return {\n Authorization: `Key ${auth}`,\n \"Content-Type\": \"application/json\",\n };\n}\n\nexport const falAiAdapter: ProviderAdapter = {\n name: \"fal-ai\",\n\n async submit(\n endpoint: string,\n params: Record<string, unknown>,\n auth: string,\n ): Promise<ProviderResponse> {\n const url = `${BASE_URL}/${endpoint}`;\n const response = await fetch(url, {\n method: \"POST\",\n headers: authHeaders(auth),\n body: JSON.stringify(params),\n });\n\n await handleHttpErrors(response, endpoint);\n\n const data = (await response.json()) as { request_id: string };\n\n return {\n id: data.request_id,\n status: \"pending\",\n };\n },\n\n async poll(\n taskId: string,\n auth: string,\n endpoint?: string,\n ): Promise<ProviderResponse> {\n if (!endpoint) {\n throw new ProviderError(\"fal-ai\", \"unknown\", 400, \"endpoint is required for polling\");\n }\n\n // Check status\n const statusUrl = `${BASE_URL}/${endpoint}/requests/${taskId}/status`;\n const statusResponse = await fetch(statusUrl, {\n headers: { Authorization: `Key ${auth}` },\n });\n\n await handleHttpErrors(statusResponse, endpoint);\n\n const statusData = (await statusResponse.json()) as {\n status: \"IN_QUEUE\" | \"IN_PROGRESS\" | \"COMPLETED\" | \"FAILED\";\n error?: string;\n };\n\n if (statusData.status === \"FAILED\") {\n return {\n id: taskId,\n status: \"failed\",\n error: statusData.error ?? \"Unknown error\",\n };\n }\n\n if (statusData.status !== \"COMPLETED\") {\n return {\n id: taskId,\n status: \"processing\",\n };\n }\n\n // Fetch result\n const resultUrl = `${BASE_URL}/${endpoint}/requests/${taskId}`;\n const resultResponse = await fetch(resultUrl, {\n headers: { Authorization: `Key ${auth}` },\n });\n\n await handleHttpErrors(resultResponse, endpoint);\n\n const output = await resultResponse.json();\n\n return {\n id: taskId,\n status: \"completed\",\n output,\n };\n },\n\n parseOutput(raw: unknown, outputMapping: OutputMapping): OutputItem[] {\n const data = raw as Record<string, unknown>;\n const path = outputMapping.extract_path;\n\n if (path === \"images[].url\") {\n const images = data.images as Array<{\n url: string;\n content_type?: string;\n }>;\n if (!Array.isArray(images)) return [];\n return images.map((img) => ({\n type: outputMapping.type,\n url: img.url,\n content_type: img.content_type ?? outputMapping.content_type ?? \"image/jpeg\",\n }));\n }\n\n if (path === \"video.url\") {\n const video = data.video as { url: string; content_type?: string } | undefined;\n if (!video?.url) return [];\n return [\n {\n type: outputMapping.type,\n url: video.url,\n content_type: video.content_type ?? outputMapping.content_type ?? \"video/mp4\",\n },\n ];\n }\n\n if (path === \"audio.url\") {\n const audio = data.audio as { url: string; content_type?: string } | undefined;\n if (!audio?.url) return [];\n return [\n {\n type: outputMapping.type,\n url: audio.url,\n content_type: audio.content_type ?? outputMapping.content_type ?? \"audio/mpeg\",\n },\n ];\n }\n\n return [];\n },\n};\n\n/**\n * Submit a request and poll until completion or timeout.\n */\nexport async function submitAndPoll(\n endpoint: string,\n params: Record<string, unknown>,\n auth: string,\n options?: {\n timeoutMs?: number;\n intervalMs?: number;\n maxIntervalMs?: number;\n },\n): Promise<ProviderResponse> {\n const timeoutMs = options?.timeoutMs ?? 300_000;\n const startInterval = options?.intervalMs ?? 1000;\n const maxInterval = options?.maxIntervalMs ?? 5000;\n\n const submitted = await falAiAdapter.submit(endpoint, params, auth);\n const taskId = submitted.id;\n\n const start = Date.now();\n let interval = startInterval;\n\n while (Date.now() - start < timeoutMs) {\n await sleep(interval);\n\n const result = await falAiAdapter.poll(taskId, auth, endpoint);\n\n if (result.status === \"completed\" || result.status === \"failed\") {\n return result;\n }\n\n interval = Math.min(interval + 500, maxInterval);\n }\n\n throw new TimeoutError(\"fal-ai\", endpoint, timeoutMs);\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import type { ProviderAdapter, ProviderResponse, OutputItem, OutputMapping } from \"./base.js\";\nimport { AuthError, RateLimitError, ProviderError } from \"../errors.js\";\n\nconst BASE_URL = \"https://api.replicate.com/v1\";\n\nasync function handleHttpErrors(\n response: Response,\n endpoint: string,\n): Promise<void> {\n if (response.ok) return;\n\n const status = response.status;\n\n if (status === 401) {\n throw new AuthError(\"replicate\", \"REPLICATE_API_TOKEN\");\n }\n\n if (status === 429) {\n const retryAfter = response.headers.get(\"retry-after\");\n const retryMs = retryAfter ? parseInt(retryAfter, 10) * 1000 : 60000;\n throw new RateLimitError(\"replicate\", retryMs);\n }\n\n let raw: unknown;\n try {\n raw = await response.json();\n } catch {\n raw = await response.text().catch(() => null);\n }\n\n throw new ProviderError(\"replicate\", endpoint, status, raw);\n}\n\nfunction authHeaders(auth: string): Record<string, string> {\n return {\n Authorization: `Bearer ${auth}`,\n \"Content-Type\": \"application/json\",\n };\n}\n\nfunction inferContentType(url: string): string {\n const lower = url.toLowerCase();\n if (lower.includes(\".png\")) return \"image/png\";\n if (lower.includes(\".jpg\") || lower.includes(\".jpeg\")) return \"image/jpeg\";\n if (lower.includes(\".webp\")) return \"image/webp\";\n if (lower.includes(\".mp4\")) return \"video/mp4\";\n if (lower.includes(\".mp3\")) return \"audio/mpeg\";\n if (lower.includes(\".wav\")) return \"audio/wav\";\n return \"image/jpeg\";\n}\n\nexport const replicateAdapter: ProviderAdapter = {\n name: \"replicate\",\n\n async submit(\n endpoint: string,\n params: Record<string, unknown>,\n auth: string,\n ): Promise<ProviderResponse> {\n const url = `${BASE_URL}/models/${endpoint}/predictions`;\n const response = await fetch(url, {\n method: \"POST\",\n headers: authHeaders(auth),\n body: JSON.stringify({ input: params }),\n });\n\n await handleHttpErrors(response, endpoint);\n\n const data = (await response.json()) as { id: string };\n\n return {\n id: data.id,\n status: \"pending\",\n };\n },\n\n async poll(\n taskId: string,\n auth: string,\n ): Promise<ProviderResponse> {\n const url = `${BASE_URL}/predictions/${taskId}`;\n const response = await fetch(url, {\n headers: { Authorization: `Bearer ${auth}` },\n });\n\n await handleHttpErrors(response, taskId);\n\n const data = (await response.json()) as {\n id: string;\n status: \"starting\" | \"processing\" | \"succeeded\" | \"failed\" | \"canceled\";\n output?: unknown;\n error?: string;\n };\n\n if (data.status === \"succeeded\") {\n return {\n id: data.id,\n status: \"completed\",\n output: data.output,\n };\n }\n\n if (data.status === \"failed\" || data.status === \"canceled\") {\n return {\n id: data.id,\n status: \"failed\",\n error: data.error ?? `Prediction ${data.status}`,\n };\n }\n\n // starting or processing\n return {\n id: data.id,\n status: \"processing\",\n };\n },\n\n parseOutput(raw: unknown, outputMapping: OutputMapping): OutputItem[] {\n // Replicate output is typically string[] (URLs)\n if (!Array.isArray(raw)) return [];\n\n return (raw as string[]).map((url) => ({\n type: outputMapping.type,\n url,\n content_type: outputMapping.content_type ?? inferContentType(url),\n }));\n },\n};\n","import type { ProviderAdapter, ProviderResponse, OutputItem, OutputMapping } from \"./base.js\";\nimport { AuthError, RateLimitError, ProviderError } from \"../errors.js\";\n\nconst BASE_URL = \"https://api.wavespeed.ai/api/v3\";\n\nasync function handleHttpErrors(\n response: Response,\n endpoint: string,\n): Promise<void> {\n if (response.ok) return;\n\n const status = response.status;\n\n if (status === 401) {\n throw new AuthError(\"wavespeed\", \"WAVESPEED_API_KEY\");\n }\n\n if (status === 429) {\n const retryAfter = response.headers.get(\"retry-after\");\n const retryMs = retryAfter ? parseInt(retryAfter, 10) * 1000 : 60000;\n throw new RateLimitError(\"wavespeed\", retryMs);\n }\n\n let raw: unknown;\n try {\n raw = await response.json();\n } catch {\n raw = await response.text().catch(() => null);\n }\n\n throw new ProviderError(\"wavespeed\", endpoint, status, raw);\n}\n\nfunction authHeaders(auth: string): Record<string, string> {\n return {\n Authorization: `Bearer ${auth}`,\n \"Content-Type\": \"application/json\",\n };\n}\n\nfunction inferContentType(url: string): string {\n const ext = url.split(\".\").pop()?.toLowerCase()?.split(\"?\")[0];\n switch (ext) {\n case \"png\":\n return \"image/png\";\n case \"jpg\":\n case \"jpeg\":\n return \"image/jpeg\";\n case \"webp\":\n return \"image/webp\";\n case \"gif\":\n return \"image/gif\";\n case \"mp4\":\n return \"video/mp4\";\n case \"mp3\":\n return \"audio/mpeg\";\n case \"wav\":\n return \"audio/wav\";\n default:\n return \"application/octet-stream\";\n }\n}\n\nexport const wavespeedAdapter: ProviderAdapter = {\n name: \"wavespeed\",\n\n async submit(\n endpoint: string,\n params: Record<string, unknown>,\n auth: string,\n ): Promise<ProviderResponse> {\n const url = `${BASE_URL}/${endpoint}`;\n const response = await fetch(url, {\n method: \"POST\",\n headers: authHeaders(auth),\n body: JSON.stringify(params),\n });\n\n await handleHttpErrors(response, endpoint);\n\n const json = (await response.json()) as {\n data: { id: string; status: string };\n };\n\n return {\n id: json.data.id,\n status: \"pending\",\n };\n },\n\n async poll(\n taskId: string,\n auth: string,\n ): Promise<ProviderResponse> {\n const url = `${BASE_URL}/predictions/${taskId}/result`;\n const response = await fetch(url, {\n headers: { Authorization: `Bearer ${auth}` },\n });\n\n await handleHttpErrors(response, `predictions/${taskId}/result`);\n\n const json = (await response.json()) as {\n data: {\n id: string;\n status: string;\n outputs?: string[];\n error?: string;\n };\n };\n\n const { data } = json;\n\n if (data.status === \"failed\") {\n return {\n id: taskId,\n status: \"failed\",\n error: data.error ?? \"Unknown error\",\n };\n }\n\n if (data.status === \"completed\") {\n return {\n id: taskId,\n status: \"completed\",\n output: data,\n };\n }\n\n // created or processing\n return {\n id: taskId,\n status: \"processing\",\n };\n },\n\n parseOutput(raw: unknown, outputMapping: OutputMapping): OutputItem[] {\n const data = raw as Record<string, unknown>;\n const outputs = data.outputs as string[] | undefined;\n\n if (!Array.isArray(outputs)) return [];\n\n return outputs.map((url) => ({\n type: outputMapping.type,\n url,\n content_type: outputMapping.content_type ?? inferContentType(url),\n }));\n },\n};\n","import {\n AuthError,\n ValidationError,\n ModelNotFoundError,\n ProviderError,\n RateLimitError,\n TimeoutError,\n} from './errors.js'\n\nexport interface RetryOptions {\n maxRetries: number\n initialDelayMs: number\n maxDelayMs: number\n timeoutMs: number\n}\n\nconst DEFAULT_OPTIONS: RetryOptions = {\n maxRetries: 3,\n initialDelayMs: 1000,\n maxDelayMs: 10000,\n timeoutMs: 300_000,\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\nfunction isRetryable(error: unknown): boolean {\n // Never retry auth, validation, or model-not-found errors\n if (\n error instanceof AuthError ||\n error instanceof ValidationError ||\n error instanceof ModelNotFoundError\n ) {\n return false\n }\n\n // Retry rate limit errors (429)\n if (error instanceof RateLimitError) {\n return true\n }\n\n // ProviderError: only retry 5xx, not 4xx\n if (error instanceof ProviderError) {\n return error.statusCode >= 500\n }\n\n // Network errors (TypeError from fetch, etc.) are retryable\n if (error instanceof TypeError) {\n return true\n }\n\n return false\n}\n\nfunction getDelayMs(\n error: unknown,\n attempt: number,\n options: RetryOptions,\n): number {\n // RateLimitError has its own retry-after\n if (error instanceof RateLimitError) {\n return error.retryAfterMs\n }\n\n // Exponential backoff with jitter\n const jitter = Math.random() * options.initialDelayMs * 0.5\n const delay = options.initialDelayMs * Math.pow(2, attempt) + jitter\n return Math.min(delay, options.maxDelayMs)\n}\n\nexport async function withRetry<T>(\n fn: () => Promise<T>,\n options?: Partial<RetryOptions>,\n): Promise<T> {\n const opts: RetryOptions = { ...DEFAULT_OPTIONS, ...options }\n const startTime = Date.now()\n let lastError: unknown\n\n for (let attempt = 0; attempt <= opts.maxRetries; attempt++) {\n // Check total timeout before attempting\n if (attempt > 0) {\n const elapsed = Date.now() - startTime\n if (elapsed >= opts.timeoutMs) {\n throw new TimeoutError('unknown', 'unknown', opts.timeoutMs)\n }\n }\n\n try {\n return await fn()\n } catch (error) {\n lastError = error\n\n // If not retryable, throw immediately\n if (!isRetryable(error)) {\n throw error\n }\n\n // If we've exhausted retries, throw\n if (attempt >= opts.maxRetries) {\n throw error\n }\n\n const delay = getDelayMs(error, attempt, opts)\n\n // Check if waiting would exceed timeout\n const elapsed = Date.now() - startTime\n if (elapsed + delay >= opts.timeoutMs) {\n throw new TimeoutError('unknown', 'unknown', opts.timeoutMs)\n }\n\n await sleep(delay)\n }\n }\n\n /* v8 ignore next 3 */\n // Unreachable: the for loop always returns or throws\n throw lastError as Error\n}\n","import type { ModelEntry, ModelCategory, ProviderName } from \"./types.js\";\nimport { loadRegistry } from \"./resolver.js\";\nimport { resolveModel } from \"./resolver.js\";\nimport { AuthManager } from \"./auth.js\";\n\nexport interface ListModelsFilters {\n category?: ModelCategory;\n provider?: ProviderName;\n query?: string; // search canonical name and aliases\n accessible?: boolean; // if true, only return models the caller has API keys for\n}\n\n/**\n * Lists all models in the registry.\n * Set `accessible: true` to filter to only models the caller has API keys for.\n * Optionally filters by category, provider, or text query.\n */\nexport function listModels(filters?: ListModelsFilters): ModelEntry[] {\n let models = loadRegistry();\n\n if (filters?.accessible) {\n const auth = new AuthManager();\n models = auth.listAvailableModels(models);\n }\n\n if (filters?.category) {\n models = models.filter((m) => m.category === filters.category);\n }\n if (filters?.provider) {\n models = models.filter((m) =>\n m.providers.some((p) => p.provider === filters.provider),\n );\n }\n if (filters?.query) {\n const q = filters.query.toLowerCase();\n models = models.filter(\n (m) =>\n m.canonical_name.includes(q) ||\n m.aliases.some((a) => a.includes(q)),\n );\n }\n\n return models;\n}\n\n/**\n * Resolves a model by name (canonical name, alias, or fuzzy match).\n * Throws ModelNotFoundError if no match is found.\n */\nexport function getModel(name: string): ModelEntry {\n return resolveModel(name);\n}\n"],"mappings":"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","names":["BASE_URL","handleHttpErrors","authHeaders","BASE_URL","handleHttpErrors","authHeaders","inferContentType","resolve","resolve"]}