@neta-art/generation 0.1.8 → 0.1.9

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-CcfifHB4.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,6 +256,7 @@ 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;
@@ -300,39 +312,73 @@ function resolveSize(resolution, aspectRatio) {
300
312
  height: height % 2 === 0 ? height : height + 1
301
313
  };
302
314
  }
303
- function getImageRole$1(block) {
315
+ function getMediaRole(block) {
304
316
  const role = getBlockMeta(block)?.role;
305
317
  return typeof role === "string" && role ? role : void 0;
306
318
  }
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");
319
+ function isFrameImage(item) {
320
+ return item.kind === "image" && (item.role === "first_frame" || item.role === "last_frame");
321
+ }
322
+ function isReferenceMedia(item) {
323
+ return item.kind === "image" && item.role === "reference_image" || item.kind === "video" && item.role === "reference_video";
324
+ }
325
+ function assertSingleRole(media, role, message) {
326
+ if (media.filter((item) => item.role === role).length > 1) throw new GenerationValidationError(message);
327
+ }
328
+ function classifyMedia(media) {
329
+ if (media.length === 0) return null;
330
+ for (const item of media) {
331
+ 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");
332
+ if (item.kind === "video" && item.role !== "reference_video") throw new GenerationValidationError("Video input must use meta.role reference_video");
333
+ }
334
+ const hasFrame = media.some(isFrameImage);
335
+ const hasReference = media.some(isReferenceMedia);
336
+ const hasPlain = media.some((item) => item.kind === "image" && !item.role);
311
337
  if ([
312
- images.some((image) => !image.role),
313
- hasFirstOrLast,
338
+ hasPlain,
339
+ hasFrame,
314
340
  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({
341
+ ].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");
342
+ if (hasReference) {
343
+ assertSingleRole(media, "reference_video", "Reference mode supports at most one reference_video");
344
+ return "reference";
345
+ }
346
+ if (hasFrame) {
347
+ assertSingleRole(media, "first_frame", "Frame mode supports at most one first_frame image");
348
+ assertSingleRole(media, "last_frame", "Frame mode supports at most one last_frame image");
349
+ return "frame";
350
+ }
351
+ if (hasPlain) {
352
+ if (media.filter((item) => item.kind === "image" && !item.role).length > 1) throw new GenerationValidationError("Plain image mode supports at most one image");
353
+ return "image";
354
+ }
355
+ return null;
356
+ }
357
+ function buildMetadataContent(media, mode) {
358
+ const content = [];
359
+ for (const item of media) {
360
+ 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");
361
+ 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");
362
+ if (item.kind === "image") content.push({
329
363
  type: "image_url",
330
- image_url: { url: image.url },
331
- role: image.role
364
+ image_url: { url: item.url },
365
+ role: item.role
366
+ });
367
+ else content.push({
368
+ type: "video_url",
369
+ video_url: { url: item.url },
370
+ role: item.role
332
371
  });
333
372
  }
334
373
  return content;
335
374
  }
375
+ async function resolveMedia(input, media) {
376
+ return Promise.all(media.map(async (item) => ({
377
+ kind: item.kind,
378
+ role: item.role,
379
+ url: await input.context.resolveSource(item.source)
380
+ })));
381
+ }
336
382
  function extractTaskId$2(response) {
337
383
  const taskId = asString$2(response.task_id) ?? asString$2(response.id);
338
384
  if (!taskId) throw new GenerationProviderError("Video generation provider did not return a task id", { details: { response } });
@@ -392,12 +438,13 @@ async function requestJson$2(input, path, init) {
392
438
  async function arkVideoGenerationsAdapter(input) {
393
439
  const prompt = mergeTextBlocks(input.declaration, input.request.content);
394
440
  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);
441
+ const inputMedia = input.request.content.filter((block) => block.type === "image" || block.type === "video").map((block) => ({
442
+ kind: block.type,
443
+ source: block.source,
444
+ role: getMediaRole(block)
445
+ }));
446
+ const mode = classifyMedia(inputMedia);
447
+ const media = await resolveMedia(input, inputMedia);
401
448
  const resolution = asString$2(input.parameters.resolution) ?? "720p";
402
449
  const aspectRatio = asString$2(input.parameters.aspect_ratio) ?? "16:9";
403
450
  const duration = getIntegerParameter(input.parameters, "duration", 5);
@@ -423,7 +470,7 @@ async function arkVideoGenerationsAdapter(input) {
423
470
  if (cameraFixed) metadata.camera_fixed = true;
424
471
  if (watermark) metadata.watermark = true;
425
472
  if (mode === "frame" || mode === "reference") {
426
- metadata.content = buildMetadataContent(prompt, images, mode);
473
+ metadata.content = buildMetadataContent(media, mode);
427
474
  metadata.resolution = resolution;
428
475
  metadata.ratio = aspectRatio;
429
476
  } else {
@@ -432,7 +479,8 @@ async function arkVideoGenerationsAdapter(input) {
432
479
  payload.width = size.width;
433
480
  payload.height = size.height;
434
481
  }
435
- if (images[0]) payload.image = images[0].url;
482
+ const firstImage = media.find((item) => item.kind === "image");
483
+ if (firstImage) payload.image = firstImage.url;
436
484
  }
437
485
  payload.metadata = metadata;
438
486
  const taskId = extractTaskId$2(await requestJson$2(input, "/v1/video/generations", {
@@ -486,6 +534,7 @@ async function arkVideoGenerationsAdapter(input) {
486
534
  }
487
535
  throw new GenerationTimeoutError("Timed out waiting for video generation", { taskId });
488
536
  }
537
+
489
538
  //#endregion
490
539
  //#region src/adapters/gemini-generate-content.ts
491
540
  const REQUEST_TIMEOUT_MS$4 = 3e5;
@@ -617,6 +666,7 @@ async function geminiGenerateContentAdapter(input) {
617
666
  if (output.length === 0) throw new GenerationProviderError("Gemini generation returned no output", { details: collectGeminiNoOutputDetails(raw) });
618
667
  return output;
619
668
  }
669
+
620
670
  //#endregion
621
671
  //#region src/adapters/kling-video-generations.ts
622
672
  const REQUEST_TIMEOUT_MS$3 = 186e4;
@@ -855,6 +905,7 @@ async function klingVideoGenerationsAdapter(input) {
855
905
  }
856
906
  throw new GenerationTimeoutError("Timed out waiting for Kling video generation", { taskId });
857
907
  }
908
+
858
909
  //#endregion
859
910
  //#region src/adapters/openai-image-edits.ts
860
911
  const REQUEST_TIMEOUT_MS$2 = 3e5;
@@ -924,6 +975,7 @@ async function openAiImageEditsAdapter(input) {
924
975
  if (output.length === 0) throw new GenerationProviderError("Image edit returned no output", { details: collectOpenAiImageEditsNoOutputDetails(raw) });
925
976
  return output;
926
977
  }
978
+
927
979
  //#endregion
928
980
  //#region src/adapters/openai-images.ts
929
981
  const REQUEST_TIMEOUT_MS$1 = 3e5;
@@ -1000,6 +1052,7 @@ async function openAiImagesAdapter(input) {
1000
1052
  if (output.length === 0) throw new GenerationProviderError("Image generation returned no output", { details: collectOpenAiImagesNoOutputDetails(raw) });
1001
1053
  return output;
1002
1054
  }
1055
+
1003
1056
  //#endregion
1004
1057
  //#region src/adapters/suno-tasks.ts
1005
1058
  const REQUEST_TIMEOUT_MS = 6e4;
@@ -1034,12 +1087,12 @@ const OPERATION_PATHS = {
1034
1087
  poll: true
1035
1088
  }
1036
1089
  };
1037
- const FINAL_SUCCESS_STATUSES = /* @__PURE__ */ new Set([
1090
+ const FINAL_SUCCESS_STATUSES = new Set([
1038
1091
  "success",
1039
1092
  "succeeded",
1040
1093
  "completed"
1041
1094
  ]);
1042
- const FINAL_FAILURE_STATUSES = /* @__PURE__ */ new Set([
1095
+ const FINAL_FAILURE_STATUSES = new Set([
1043
1096
  "failure",
1044
1097
  "failed",
1045
1098
  "error",
@@ -1358,6 +1411,7 @@ async function sunoTasksAdapter(input) {
1358
1411
  if (!taskId) return buildImmediateResult(operation, data, raw);
1359
1412
  return pollSunoTask(input, operation, taskId, asInteger(input.parameters.poll_interval, DEFAULT_POLL_INTERVAL_SEC), asInteger(input.parameters.max_wait, DEFAULT_MAX_WAIT_SEC));
1360
1413
  }
1414
+
1361
1415
  //#endregion
1362
1416
  //#region src/adapters/index.ts
1363
1417
  const builtinGenerationAdapters = {
@@ -1373,9 +1427,10 @@ function getGenerationAdapter(type, adapters = {}) {
1373
1427
  if (!adapter) throw new GenerationUnsupportedAdapterError(type);
1374
1428
  return adapter;
1375
1429
  }
1430
+
1376
1431
  //#endregion
1377
1432
  //#region src/config.ts
1378
- const DECLARATION_EXTENSIONS = /* @__PURE__ */ new Set([
1433
+ const DECLARATION_EXTENSIONS = new Set([
1379
1434
  ".yaml",
1380
1435
  ".yml",
1381
1436
  ".json"
@@ -1411,7 +1466,7 @@ function isGenerationModelDeclaration(value) {
1411
1466
  const parameters = value.parameters;
1412
1467
  const meta = value.meta;
1413
1468
  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));
1469
+ 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
1470
  }
1416
1471
  function parseGenerationModelDeclaration(rawText, filePath = "model.yaml") {
1417
1472
  const parsed = extname(filePath) === ".json" ? JSON.parse(rawText) : parse(rawText);
@@ -1445,6 +1500,7 @@ async function writeGenerationModelDeclarations(declarations, directory, options
1445
1500
  const ext = options.format === "json" ? "json" : "yaml";
1446
1501
  await Promise.all(declarations.map((declaration) => writeGenerationModelDeclaration(declaration, join(directory, `${slugifyFileName(declaration.model)}.${ext}`), options)));
1447
1502
  }
1503
+
1448
1504
  //#endregion
1449
1505
  //#region src/source.ts
1450
1506
  const defaultGenerationSourceResolver = (source) => {
@@ -1453,13 +1509,14 @@ const defaultGenerationSourceResolver = (source) => {
1453
1509
  case "base64": return `data:${source.mediaType};base64,${source.data}`;
1454
1510
  }
1455
1511
  };
1512
+
1456
1513
  //#endregion
1457
1514
  //#region src/client.ts
1458
1515
  const DEFAULT_BASE_URL = "https://router.neta.art";
1459
1516
  const REDACTED = "[REDACTED]";
1460
1517
  const SECRET_DEBUG_KEY_PATTERN = /^(authorization|api[-_]?key|token|thoughtSignature)$/i;
1461
1518
  const BASE64_DEBUG_KEY_PATTERN = /^(b64_json|data)$/i;
1462
- const MEDIA_PAYLOAD_KEYS = /* @__PURE__ */ new Set([
1519
+ const MEDIA_PAYLOAD_KEYS = new Set([
1463
1520
  "audio",
1464
1521
  "audio_url",
1465
1522
  "image",
@@ -1604,6 +1661,7 @@ async function createGenerationClientFromDirectory(directory, options = {}) {
1604
1661
  async function createGenerationClientFromFile(filePath, options = {}) {
1605
1662
  return createGenerationClientFromFiles([filePath], options);
1606
1663
  }
1664
+
1607
1665
  //#endregion
1608
1666
  //#region src/export-config.ts
1609
1667
  function stringifyBuiltinModelConfig(model, options = {}) {
@@ -1619,7 +1677,7 @@ async function exportBuiltinModelConfig(model, filePath) {
1619
1677
  async function exportBuiltinModelConfigs(directory) {
1620
1678
  await writeGenerationModelDeclarations(listBuiltinGenerationModels(), directory);
1621
1679
  }
1680
+
1622
1681
  //#endregion
1623
1682
  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
1683
+ //# sourceMappingURL=export-config--lWA-0gu.js.map