@neta-art/generation 0.1.8 → 0.1.10

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.
@@ -1,7 +1,8 @@
1
- import { a as cloneJson, c as getBlockMeta, l as slugifyFileName, n as getBuiltinGenerationModel, o as compactArray, r as listBuiltinGenerationModels, s as compactObject, t as builtinGenerationModels } from "./builtins--2dnc9UT.js";
1
+ import { a as compactArray, c as slugifyFileName, i as cloneJson, l as MODEL_SCHEMA, n as getBuiltinGenerationModel, o as compactObject, r as listBuiltinGenerationModels, s as getBlockMeta, t as builtinGenerationModels } from "./builtins-CcT0Ufp2.js";
2
2
  import { mkdir, readFile, readdir, writeFile } from "node:fs/promises";
3
3
  import { extname, join } from "node:path";
4
4
  import { parse, stringify } from "yaml";
5
+
5
6
  //#region src/errors.ts
6
7
  var GenerationError = class extends Error {
7
8
  constructor(message) {
@@ -45,6 +46,7 @@ var GenerationTimeoutError = class extends GenerationProviderError {
45
46
  this.name = "GenerationTimeoutError";
46
47
  }
47
48
  };
49
+
48
50
  //#endregion
49
51
  //#region src/http.ts
50
52
  function headersToRecord(headers) {
@@ -132,6 +134,7 @@ async function fetchWithTimeout(fetchFn, url, init, timeoutMs) {
132
134
  function joinUrl(baseUrl, path) {
133
135
  return `${baseUrl.replace(/\/+$/, "")}/${path.replace(/^\/+/, "")}`;
134
136
  }
137
+
135
138
  //#endregion
136
139
  //#region src/validation.ts
137
140
  function specsByType(specs) {
@@ -139,6 +142,9 @@ function specsByType(specs) {
139
142
  for (const spec of specs) map.set(spec.type, spec);
140
143
  return map;
141
144
  }
145
+ function getRole(block) {
146
+ return block.meta?.role;
147
+ }
142
148
  function validateGenerationContent(declaration, content) {
143
149
  const inputSpecs = specsByType(declaration.content.input);
144
150
  const counts = /* @__PURE__ */ new Map();
@@ -147,6 +153,11 @@ function validateGenerationContent(declaration, content) {
147
153
  if (!spec) throw new GenerationValidationError(`Content block type is not supported by ${declaration.model}: ${block.type}`);
148
154
  counts.set(block.type, (counts.get(block.type) ?? 0) + 1);
149
155
  if ("source" in block && spec.sources && !spec.sources.includes(block.source.type)) throw new GenerationValidationError(`${block.type} source is not supported by ${declaration.model}: ${block.source.type}`);
156
+ const role = getRole(block);
157
+ if (spec.roleRequired && (typeof role !== "string" || role.length === 0)) throw new GenerationValidationError(`${block.type} role is required by ${declaration.model}`);
158
+ if (role !== void 0 && spec.roles) {
159
+ if (typeof role !== "string" || role.length === 0 || !spec.roles.includes(role)) throw new GenerationValidationError(`${block.type} role is not supported by ${declaration.model}: ${String(role)}`);
160
+ }
150
161
  }
151
162
  for (const spec of declaration.content.input) {
152
163
  const count = counts.get(spec.type) ?? 0;
@@ -245,28 +256,12 @@ function mergeTextBlocks(declaration, content) {
245
256
  const separator = textSpec?.merge === "space" ? " " : textSpec?.merge === "concat" ? "" : "\n";
246
257
  return content.filter((block) => block.type === "text").map((block) => block.text).join(separator).trim();
247
258
  }
259
+
248
260
  //#endregion
249
261
  //#region src/adapters/ark-video-generations.ts
250
262
  const REQUEST_TIMEOUT_MS$5 = 186e4;
251
263
  const DEFAULT_POLL_INTERVAL_SEC$2 = 2;
252
264
  const DEFAULT_MAX_WAIT_SEC$2 = 600;
253
- const RESOLUTION_SHORT_EDGE = {
254
- "480p": 480,
255
- "720p": 720,
256
- "1080p": 1080,
257
- "2K": 1440
258
- };
259
- const ASPECT_RATIOS = {
260
- "16:9": [16, 9],
261
- "9:16": [9, 16],
262
- "1:1": [1, 1],
263
- "4:3": [4, 3],
264
- "3:2": [3, 2],
265
- "2:3": [2, 3],
266
- "3:4": [3, 4],
267
- "21:9": [21, 9],
268
- adaptive: null
269
- };
270
265
  function sleep$2(ms) {
271
266
  return new Promise((resolve) => setTimeout(resolve, ms));
272
267
  }
@@ -287,52 +282,73 @@ function getIntegerParameter(parameters, key, fallback) {
287
282
  const value = parameters[key];
288
283
  return typeof value === "number" && Number.isInteger(value) ? value : fallback;
289
284
  }
290
- function resolveSize(resolution, aspectRatio) {
291
- const ratio = ASPECT_RATIOS[aspectRatio];
292
- if (!ratio) return null;
293
- const shortEdge = RESOLUTION_SHORT_EDGE[resolution];
294
- if (!shortEdge) throw new GenerationValidationError(`Unsupported resolution: ${resolution}`);
295
- const [wRatio, hRatio] = ratio;
296
- const width = wRatio >= hRatio ? Math.round(shortEdge * wRatio / hRatio) : shortEdge;
297
- const height = wRatio >= hRatio ? shortEdge : Math.round(shortEdge * hRatio / wRatio);
298
- return {
299
- width: width % 2 === 0 ? width : width + 1,
300
- height: height % 2 === 0 ? height : height + 1
301
- };
302
- }
303
- function getImageRole$1(block) {
285
+ function getMediaRole(block) {
304
286
  const role = getBlockMeta(block)?.role;
305
287
  return typeof role === "string" && role ? role : void 0;
306
288
  }
307
- function classifyImages(images) {
308
- if (images.length === 0) return null;
309
- const hasFirstOrLast = images.some((image) => image.role === "first_frame" || image.role === "last_frame");
310
- const hasReference = images.some((image) => image.role === "reference_image");
289
+ function isFrameImage(item) {
290
+ return item.kind === "image" && (item.role === "first_frame" || item.role === "last_frame");
291
+ }
292
+ function isReferenceMedia(item) {
293
+ return item.kind === "image" && item.role === "reference_image" || item.kind === "video" && item.role === "reference_video";
294
+ }
295
+ function assertSingleRole(media, role, message) {
296
+ if (media.filter((item) => item.role === role).length > 1) throw new GenerationValidationError(message);
297
+ }
298
+ function classifyMedia(media) {
299
+ if (media.length === 0) return null;
300
+ for (const item of media) {
301
+ if (item.kind === "image" && item.role && item.role !== "first_frame" && item.role !== "last_frame" && item.role !== "reference_image") throw new GenerationValidationError("Image input must use meta.role first_frame, last_frame, or reference_image");
302
+ if (item.kind === "video" && item.role !== "reference_video") throw new GenerationValidationError("Video input must use meta.role reference_video");
303
+ }
304
+ const hasFrame = media.some(isFrameImage);
305
+ const hasReference = media.some(isReferenceMedia);
306
+ const hasPlain = media.some((item) => item.kind === "image" && !item.role);
311
307
  if ([
312
- images.some((image) => !image.role),
313
- hasFirstOrLast,
308
+ hasPlain,
309
+ hasFrame,
314
310
  hasReference
315
- ].filter(Boolean).length > 1) throw new GenerationValidationError("Cannot mix video image modes: use only plain image, first_frame/last_frame, or reference_image");
316
- if (hasReference) return "reference";
317
- if (hasFirstOrLast) return "frame";
318
- return "image";
319
- }
320
- function buildMetadataContent(prompt, images, mode) {
321
- const content = [{
322
- type: "text",
323
- text: prompt
324
- }];
325
- for (const image of images) {
326
- if (mode === "frame" && image.role !== "first_frame" && image.role !== "last_frame") throw new GenerationValidationError("Frame mode images must use meta.role first_frame or last_frame");
327
- if (mode === "reference" && image.role !== "reference_image") throw new GenerationValidationError("Reference mode images must use meta.role reference_image");
328
- content.push({
311
+ ].filter(Boolean).length > 1) throw new GenerationValidationError("Cannot mix video media modes: use only plain image, first_frame/last_frame, or reference_image/reference_video");
312
+ if (hasReference) {
313
+ assertSingleRole(media, "reference_video", "Reference mode supports at most one reference_video");
314
+ return "reference";
315
+ }
316
+ if (hasFrame) {
317
+ assertSingleRole(media, "first_frame", "Frame mode supports at most one first_frame image");
318
+ assertSingleRole(media, "last_frame", "Frame mode supports at most one last_frame image");
319
+ return "frame";
320
+ }
321
+ if (hasPlain) {
322
+ if (media.filter((item) => item.kind === "image" && !item.role).length > 1) throw new GenerationValidationError("Plain image mode supports at most one image");
323
+ return "image";
324
+ }
325
+ return null;
326
+ }
327
+ function buildMetadataContent(media, mode) {
328
+ const content = [];
329
+ for (const item of media) {
330
+ if (mode === "frame" && (item.kind !== "image" || item.role !== "first_frame" && item.role !== "last_frame")) throw new GenerationValidationError("Frame mode images must use meta.role first_frame or last_frame");
331
+ if (mode === "reference" && !(item.kind === "image" && item.role === "reference_image" || item.kind === "video" && item.role === "reference_video")) throw new GenerationValidationError("Reference mode media must use meta.role reference_image or reference_video");
332
+ if (item.kind === "image") content.push({
329
333
  type: "image_url",
330
- image_url: { url: image.url },
331
- role: image.role
334
+ image_url: { url: item.url },
335
+ role: item.role
336
+ });
337
+ else content.push({
338
+ type: "video_url",
339
+ video_url: { url: item.url },
340
+ role: item.role
332
341
  });
333
342
  }
334
343
  return content;
335
344
  }
345
+ async function resolveMedia(input, media) {
346
+ return Promise.all(media.map(async (item) => ({
347
+ kind: item.kind,
348
+ role: item.role,
349
+ url: await input.context.resolveSource(item.source)
350
+ })));
351
+ }
336
352
  function extractTaskId$2(response) {
337
353
  const taskId = asString$2(response.task_id) ?? asString$2(response.id);
338
354
  if (!taskId) throw new GenerationProviderError("Video generation provider did not return a task id", { details: { response } });
@@ -392,14 +408,15 @@ async function requestJson$2(input, path, init) {
392
408
  async function arkVideoGenerationsAdapter(input) {
393
409
  const prompt = mergeTextBlocks(input.declaration, input.request.content);
394
410
  if (!prompt) throw new GenerationValidationError("Prompt text is required");
395
- const imageBlocks = input.request.content.filter((block) => block.type === "image");
396
- const images = await Promise.all(imageBlocks.map(async (block) => ({
397
- url: await input.context.resolveSource(block.source),
398
- role: getImageRole$1(block)
399
- })));
400
- const mode = classifyImages(images);
411
+ const inputMedia = input.request.content.filter((block) => block.type === "image" || block.type === "video").map((block) => ({
412
+ kind: block.type,
413
+ source: block.source,
414
+ role: getMediaRole(block)
415
+ }));
416
+ const mode = classifyMedia(inputMedia);
417
+ const media = await resolveMedia(input, inputMedia);
401
418
  const resolution = asString$2(input.parameters.resolution) ?? "720p";
402
- const aspectRatio = asString$2(input.parameters.aspect_ratio) ?? "16:9";
419
+ const ratio = asString$2(input.request.parameters?.ratio) ?? asString$2(input.request.parameters?.aspect_ratio) ?? asString$2(input.parameters.ratio) ?? "16:9";
403
420
  const duration = getIntegerParameter(input.parameters, "duration", 5);
404
421
  const fps = getIntegerParameter(input.parameters, "fps", 30);
405
422
  const pollIntervalSec = getIntegerParameter(input.parameters, "poll_interval", DEFAULT_POLL_INTERVAL_SEC$2);
@@ -416,23 +433,18 @@ async function arkVideoGenerationsAdapter(input) {
416
433
  const metadata = {
417
434
  duration,
418
435
  fps,
419
- generate_audio: generateAudio
436
+ generate_audio: generateAudio,
437
+ resolution,
438
+ ratio
420
439
  };
421
440
  if (seed !== void 0) metadata.seed = seed;
422
441
  if (returnLastFrame) metadata.return_last_frame = true;
423
442
  if (cameraFixed) metadata.camera_fixed = true;
424
443
  if (watermark) metadata.watermark = true;
425
- if (mode === "frame" || mode === "reference") {
426
- metadata.content = buildMetadataContent(prompt, images, mode);
427
- metadata.resolution = resolution;
428
- metadata.ratio = aspectRatio;
429
- } else {
430
- const size = resolveSize(resolution, aspectRatio);
431
- if (size) {
432
- payload.width = size.width;
433
- payload.height = size.height;
434
- }
435
- if (images[0]) payload.image = images[0].url;
444
+ if (mode === "frame" || mode === "reference") metadata.content = buildMetadataContent(media, mode);
445
+ else {
446
+ const firstImage = media.find((item) => item.kind === "image");
447
+ if (firstImage) payload.image = firstImage.url;
436
448
  }
437
449
  payload.metadata = metadata;
438
450
  const taskId = extractTaskId$2(await requestJson$2(input, "/v1/video/generations", {
@@ -486,6 +498,7 @@ async function arkVideoGenerationsAdapter(input) {
486
498
  }
487
499
  throw new GenerationTimeoutError("Timed out waiting for video generation", { taskId });
488
500
  }
501
+
489
502
  //#endregion
490
503
  //#region src/adapters/gemini-generate-content.ts
491
504
  const REQUEST_TIMEOUT_MS$4 = 3e5;
@@ -590,7 +603,7 @@ async function geminiGenerateContentAdapter(input) {
590
603
  const image = {};
591
604
  if (typeof aspectRatio === "string") image.aspectRatio = aspectRatio;
592
605
  if (typeof imageSize === "string") image.imageSize = imageSize;
593
- generationConfig.responseFormat = { image };
606
+ generationConfig.imageConfig = image;
594
607
  }
595
608
  const payload = {
596
609
  contents: [{ parts: [{ text: prompt }, ...imageParts] }],
@@ -617,6 +630,7 @@ async function geminiGenerateContentAdapter(input) {
617
630
  if (output.length === 0) throw new GenerationProviderError("Gemini generation returned no output", { details: collectGeminiNoOutputDetails(raw) });
618
631
  return output;
619
632
  }
633
+
620
634
  //#endregion
621
635
  //#region src/adapters/kling-video-generations.ts
622
636
  const REQUEST_TIMEOUT_MS$3 = 186e4;
@@ -855,6 +869,7 @@ async function klingVideoGenerationsAdapter(input) {
855
869
  }
856
870
  throw new GenerationTimeoutError("Timed out waiting for Kling video generation", { taskId });
857
871
  }
872
+
858
873
  //#endregion
859
874
  //#region src/adapters/openai-image-edits.ts
860
875
  const REQUEST_TIMEOUT_MS$2 = 3e5;
@@ -924,6 +939,7 @@ async function openAiImageEditsAdapter(input) {
924
939
  if (output.length === 0) throw new GenerationProviderError("Image edit returned no output", { details: collectOpenAiImageEditsNoOutputDetails(raw) });
925
940
  return output;
926
941
  }
942
+
927
943
  //#endregion
928
944
  //#region src/adapters/openai-images.ts
929
945
  const REQUEST_TIMEOUT_MS$1 = 3e5;
@@ -1000,6 +1016,7 @@ async function openAiImagesAdapter(input) {
1000
1016
  if (output.length === 0) throw new GenerationProviderError("Image generation returned no output", { details: collectOpenAiImagesNoOutputDetails(raw) });
1001
1017
  return output;
1002
1018
  }
1019
+
1003
1020
  //#endregion
1004
1021
  //#region src/adapters/suno-tasks.ts
1005
1022
  const REQUEST_TIMEOUT_MS = 6e4;
@@ -1034,12 +1051,12 @@ const OPERATION_PATHS = {
1034
1051
  poll: true
1035
1052
  }
1036
1053
  };
1037
- const FINAL_SUCCESS_STATUSES = /* @__PURE__ */ new Set([
1054
+ const FINAL_SUCCESS_STATUSES = new Set([
1038
1055
  "success",
1039
1056
  "succeeded",
1040
1057
  "completed"
1041
1058
  ]);
1042
- const FINAL_FAILURE_STATUSES = /* @__PURE__ */ new Set([
1059
+ const FINAL_FAILURE_STATUSES = new Set([
1043
1060
  "failure",
1044
1061
  "failed",
1045
1062
  "error",
@@ -1358,6 +1375,7 @@ async function sunoTasksAdapter(input) {
1358
1375
  if (!taskId) return buildImmediateResult(operation, data, raw);
1359
1376
  return pollSunoTask(input, operation, taskId, asInteger(input.parameters.poll_interval, DEFAULT_POLL_INTERVAL_SEC), asInteger(input.parameters.max_wait, DEFAULT_MAX_WAIT_SEC));
1360
1377
  }
1378
+
1361
1379
  //#endregion
1362
1380
  //#region src/adapters/index.ts
1363
1381
  const builtinGenerationAdapters = {
@@ -1373,9 +1391,10 @@ function getGenerationAdapter(type, adapters = {}) {
1373
1391
  if (!adapter) throw new GenerationUnsupportedAdapterError(type);
1374
1392
  return adapter;
1375
1393
  }
1394
+
1376
1395
  //#endregion
1377
1396
  //#region src/config.ts
1378
- const DECLARATION_EXTENSIONS = /* @__PURE__ */ new Set([
1397
+ const DECLARATION_EXTENSIONS = new Set([
1379
1398
  ".yaml",
1380
1399
  ".yml",
1381
1400
  ".json"
@@ -1411,7 +1430,7 @@ function isGenerationModelDeclaration(value) {
1411
1430
  const parameters = value.parameters;
1412
1431
  const meta = value.meta;
1413
1432
  const examples = value.examples;
1414
- return value.schema === "neta.generation.model.v1" && typeof value.model === "string" && value.model.trim().length > 0 && (value.allowUnknownParameters === void 0 || typeof value.allowUnknownParameters === "boolean") && isRecord(adapter) && typeof adapter.type === "string" && isRecord(content) && Array.isArray(content.input) && (parameters === void 0 || isRecord(parameters) && Object.values(parameters).every(isParameterSpec)) && (meta === void 0 || isMetaSpec(meta)) && (examples === void 0 || Array.isArray(examples));
1433
+ return value.schema === MODEL_SCHEMA && typeof value.model === "string" && value.model.trim().length > 0 && (value.allowUnknownParameters === void 0 || typeof value.allowUnknownParameters === "boolean") && isRecord(adapter) && typeof adapter.type === "string" && isRecord(content) && Array.isArray(content.input) && (parameters === void 0 || isRecord(parameters) && Object.values(parameters).every(isParameterSpec)) && (meta === void 0 || isMetaSpec(meta)) && (examples === void 0 || Array.isArray(examples));
1415
1434
  }
1416
1435
  function parseGenerationModelDeclaration(rawText, filePath = "model.yaml") {
1417
1436
  const parsed = extname(filePath) === ".json" ? JSON.parse(rawText) : parse(rawText);
@@ -1445,6 +1464,7 @@ async function writeGenerationModelDeclarations(declarations, directory, options
1445
1464
  const ext = options.format === "json" ? "json" : "yaml";
1446
1465
  await Promise.all(declarations.map((declaration) => writeGenerationModelDeclaration(declaration, join(directory, `${slugifyFileName(declaration.model)}.${ext}`), options)));
1447
1466
  }
1467
+
1448
1468
  //#endregion
1449
1469
  //#region src/source.ts
1450
1470
  const defaultGenerationSourceResolver = (source) => {
@@ -1453,13 +1473,14 @@ const defaultGenerationSourceResolver = (source) => {
1453
1473
  case "base64": return `data:${source.mediaType};base64,${source.data}`;
1454
1474
  }
1455
1475
  };
1476
+
1456
1477
  //#endregion
1457
1478
  //#region src/client.ts
1458
1479
  const DEFAULT_BASE_URL = "https://router.neta.art";
1459
1480
  const REDACTED = "[REDACTED]";
1460
1481
  const SECRET_DEBUG_KEY_PATTERN = /^(authorization|api[-_]?key|token|thoughtSignature)$/i;
1461
1482
  const BASE64_DEBUG_KEY_PATTERN = /^(b64_json|data)$/i;
1462
- const MEDIA_PAYLOAD_KEYS = /* @__PURE__ */ new Set([
1483
+ const MEDIA_PAYLOAD_KEYS = new Set([
1463
1484
  "audio",
1464
1485
  "audio_url",
1465
1486
  "image",
@@ -1604,6 +1625,7 @@ async function createGenerationClientFromDirectory(directory, options = {}) {
1604
1625
  async function createGenerationClientFromFile(filePath, options = {}) {
1605
1626
  return createGenerationClientFromFiles([filePath], options);
1606
1627
  }
1628
+
1607
1629
  //#endregion
1608
1630
  //#region src/export-config.ts
1609
1631
  function stringifyBuiltinModelConfig(model, options = {}) {
@@ -1619,7 +1641,7 @@ async function exportBuiltinModelConfig(model, filePath) {
1619
1641
  async function exportBuiltinModelConfigs(directory) {
1620
1642
  await writeGenerationModelDeclarations(listBuiltinGenerationModels(), directory);
1621
1643
  }
1644
+
1622
1645
  //#endregion
1623
1646
  export { validateGenerationContent as A, klingVideoGenerationsAdapter as C, mergeTextBlocks as D, mergeGenerationMeta as E, GenerationUnsupportedAdapterError as F, GenerationValidationError as I, GenerationError as M, GenerationProviderError as N, resolveGenerationMeta as O, GenerationTimeoutError as P, openAiImageEditsAdapter as S, arkVideoGenerationsAdapter as T, writeGenerationModelDeclarations as _, createGenerationClientFromDirectory as a, sunoTasksAdapter as b, defaultGenerationSourceResolver as c, parseGenerationModelDeclaration as d, readGenerationModelDeclaration as f, writeGenerationModelDeclaration as g, stringifyGenerationModelDeclaration as h, createGenerationClient as i, GenerationConfigError as j, resolveGenerationParameters as k, isGenerationModelDeclaration as l, readGenerationModelDeclarationsFromFiles as m, exportBuiltinModelConfigs as n, createGenerationClientFromFile as o, readGenerationModelDeclarationsFromDirectory as p, stringifyBuiltinModelConfig as r, createGenerationClientFromFiles as s, exportBuiltinModelConfig as t, mergeGenerationModelDeclarations as u, builtinGenerationAdapters as v, geminiGenerateContentAdapter as w, openAiImagesAdapter as x, getGenerationAdapter as y };
1624
-
1625
- //# sourceMappingURL=export-config-BuQ5Maoj.js.map
1647
+ //# sourceMappingURL=export-config-DolxdQdi.js.map