@nodaro/prompts 1.40.0 → 1.42.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.
Files changed (95) hide show
  1. package/dist/{catalog-packs-BP21C1lp.d.cts → catalog-packs-C9CXEWfl.d.cts} +1 -1
  2. package/dist/{catalog-packs-3SxAVxPF.d.ts → catalog-packs-D7NJpo4k.d.ts} +1 -1
  3. package/dist/{chunk-3U7X6JZN.cjs → chunk-4YUXR23B.cjs} +13 -13
  4. package/dist/{chunk-3U7X6JZN.cjs.map → chunk-4YUXR23B.cjs.map} +1 -1
  5. package/dist/{chunk-DUXX6CBX.js → chunk-6JABZ5OC.js} +4 -4
  6. package/dist/{chunk-DUXX6CBX.js.map → chunk-6JABZ5OC.js.map} +1 -1
  7. package/dist/{chunk-PWWM7Q3T.cjs → chunk-AXQK7UH7.cjs} +49 -49
  8. package/dist/{chunk-PWWM7Q3T.cjs.map → chunk-AXQK7UH7.cjs.map} +1 -1
  9. package/dist/{chunk-SXXW4LCR.js → chunk-CYMIXKFT.js} +12 -8
  10. package/dist/chunk-CYMIXKFT.js.map +1 -0
  11. package/dist/{chunk-6GVFJLDL.js → chunk-GIO77YH5.js} +4 -4
  12. package/dist/{chunk-6GVFJLDL.js.map → chunk-GIO77YH5.js.map} +1 -1
  13. package/dist/{chunk-C3NHNECH.cjs → chunk-H4JMZWOE.cjs} +39 -39
  14. package/dist/{chunk-C3NHNECH.cjs.map → chunk-H4JMZWOE.cjs.map} +1 -1
  15. package/dist/{chunk-GTDKDD7Y.js → chunk-HL6PZ4A6.js} +5 -5
  16. package/dist/{chunk-GTDKDD7Y.js.map → chunk-HL6PZ4A6.js.map} +1 -1
  17. package/dist/chunk-HOMR5XFP.js +3 -0
  18. package/dist/{chunk-F4VO6YEJ.js.map → chunk-HOMR5XFP.js.map} +1 -1
  19. package/dist/{chunk-SECAGGRK.cjs → chunk-I3QS7BSY.cjs} +8 -8
  20. package/dist/{chunk-SECAGGRK.cjs.map → chunk-I3QS7BSY.cjs.map} +1 -1
  21. package/dist/{chunk-JOHYGDUU.js → chunk-IFRFYBGE.js} +3 -3
  22. package/dist/{chunk-JOHYGDUU.js.map → chunk-IFRFYBGE.js.map} +1 -1
  23. package/dist/chunk-JCYK7NSR.js +3384 -0
  24. package/dist/chunk-JCYK7NSR.js.map +1 -0
  25. package/dist/{chunk-2P26SZX5.cjs → chunk-JDNHMVEV.cjs} +35 -35
  26. package/dist/{chunk-2P26SZX5.cjs.map → chunk-JDNHMVEV.cjs.map} +1 -1
  27. package/dist/{chunk-HQTHDTHN.js → chunk-PHFOKGYS.js} +6 -6
  28. package/dist/{chunk-HQTHDTHN.js.map → chunk-PHFOKGYS.js.map} +1 -1
  29. package/dist/{chunk-C46256GZ.js → chunk-QBUSJGV3.js} +43 -2
  30. package/dist/chunk-QBUSJGV3.js.map +1 -0
  31. package/dist/{chunk-EAYEZXWT.js → chunk-QJACEKMZ.js} +3 -3
  32. package/dist/{chunk-EAYEZXWT.js.map → chunk-QJACEKMZ.js.map} +1 -1
  33. package/dist/{chunk-MQEXFCNU.cjs → chunk-SB7AYE6S.cjs} +14 -10
  34. package/dist/chunk-SB7AYE6S.cjs.map +1 -0
  35. package/dist/chunk-T4OJFIJK.cjs +4 -0
  36. package/dist/{chunk-VIT3NKGB.cjs.map → chunk-T4OJFIJK.cjs.map} +1 -1
  37. package/dist/chunk-WARNUGXT.cjs +3403 -0
  38. package/dist/chunk-WARNUGXT.cjs.map +1 -0
  39. package/dist/{chunk-DQFQJECU.cjs → chunk-XTOSNRWT.cjs} +43 -2
  40. package/dist/chunk-XTOSNRWT.cjs.map +1 -0
  41. package/dist/{chunk-QDUTMOF4.js → chunk-ZFOXGNLK.js} +4 -4
  42. package/dist/{chunk-QDUTMOF4.js.map → chunk-ZFOXGNLK.js.map} +1 -1
  43. package/dist/{chunk-IUCNJAHW.cjs → chunk-ZGA72NCT.cjs} +125 -125
  44. package/dist/{chunk-IUCNJAHW.cjs.map → chunk-ZGA72NCT.cjs.map} +1 -1
  45. package/dist/{chunk-WRM52ZBN.cjs → chunk-ZLRB5BVT.cjs} +18 -18
  46. package/dist/{chunk-WRM52ZBN.cjs.map → chunk-ZLRB5BVT.cjs.map} +1 -1
  47. package/dist/entries/assembly.cjs +29 -29
  48. package/dist/entries/assembly.js +6 -6
  49. package/dist/entries/catalog-packs.d.cts +4 -4
  50. package/dist/entries/catalog-packs.d.ts +4 -4
  51. package/dist/entries/doctrine.cjs +46 -46
  52. package/dist/entries/doctrine.js +1 -1
  53. package/dist/entries/person.d.cts +3 -3
  54. package/dist/entries/person.d.ts +3 -3
  55. package/dist/entries/picker-art.cjs +29 -17
  56. package/dist/entries/picker-art.d.cts +1122 -447
  57. package/dist/entries/picker-art.d.ts +1122 -447
  58. package/dist/entries/picker-art.js +2 -2
  59. package/dist/entries/picker-catalogs.cjs +57 -57
  60. package/dist/entries/picker-catalogs.d.cts +3 -3
  61. package/dist/entries/picker-catalogs.d.ts +3 -3
  62. package/dist/entries/picker-catalogs.js +5 -5
  63. package/dist/entries/pickers.cjs +374 -374
  64. package/dist/entries/pickers.js +3 -3
  65. package/dist/entries/prompt-builder.cjs +76 -76
  66. package/dist/entries/prompt-builder.js +5 -5
  67. package/dist/images-DrbQB9Yh.d.cts +65 -0
  68. package/dist/images-DrbQB9Yh.d.ts +65 -0
  69. package/dist/index.cjs +600 -588
  70. package/dist/index.d.cts +4 -4
  71. package/dist/index.d.ts +4 -4
  72. package/dist/index.js +11 -11
  73. package/dist/{picker-catalogs-DDjtZND3.d.ts → picker-catalogs-BM8IphF1.d.ts} +1 -1
  74. package/dist/{picker-catalogs-CmV7r0j1.d.cts → picker-catalogs-C3utGMRB.d.cts} +1 -1
  75. package/package.json +2 -2
  76. package/src/__tests__/picker-art-images.test.ts +94 -3
  77. package/src/picker-art/images.ts +59 -9
  78. package/src/picker-art/index.ts +1 -0
  79. package/src/picker-art/look-preview-sets.ts +449 -445
  80. package/src/picker-art/sound-render-sets.ts +688 -0
  81. package/src/picker-catalogs.ts +12 -8
  82. package/src/prompt-wizard-categories.ts +4 -0
  83. package/src/provider-prompt-doctrine.ts +44 -0
  84. package/dist/chunk-C46256GZ.js.map +0 -1
  85. package/dist/chunk-DQFQJECU.cjs.map +0 -1
  86. package/dist/chunk-F4VO6YEJ.js +0 -3
  87. package/dist/chunk-MQEXFCNU.cjs.map +0 -1
  88. package/dist/chunk-QGVZXBDE.cjs +0 -2708
  89. package/dist/chunk-QGVZXBDE.cjs.map +0 -1
  90. package/dist/chunk-RZJEROA2.js +0 -2692
  91. package/dist/chunk-RZJEROA2.js.map +0 -1
  92. package/dist/chunk-SXXW4LCR.js.map +0 -1
  93. package/dist/chunk-VIT3NKGB.cjs +0 -4
  94. package/dist/images-BAnMUUmW.d.cts +0 -39
  95. package/dist/images-BAnMUUmW.d.ts +0 -39
@@ -1,5 +1,5 @@
1
- import { getRegisteredSubjectKeys, SUBJECT_CUSTOM_AGE_KEY, SUBJECT_ID_MAX_CHARS, SUBJECT_ARRAY_CEILING } from './chunk-DUXX6CBX.js';
2
- import { DIRECTION_FIELDS, DIRECTION_ID_MAX_CHARS, DIRECTION_ARRAY_CEILING } from './chunk-EAYEZXWT.js';
1
+ import { getRegisteredSubjectKeys, SUBJECT_CUSTOM_AGE_KEY, SUBJECT_ID_MAX_CHARS, SUBJECT_ARRAY_CEILING } from './chunk-6JABZ5OC.js';
2
+ import { DIRECTION_FIELDS, DIRECTION_ID_MAX_CHARS, DIRECTION_ARRAY_CEILING } from './chunk-QJACEKMZ.js';
3
3
 
4
4
  // src/read-node-direction.ts
5
5
  function readDirectionFields(value) {
@@ -114,5 +114,5 @@ function readStructuredFields(value) {
114
114
  }
115
115
 
116
116
  export { readDirectionFields, readStructuredFields, readSubjectFields };
117
- //# sourceMappingURL=chunk-6GVFJLDL.js.map
118
- //# sourceMappingURL=chunk-6GVFJLDL.js.map
117
+ //# sourceMappingURL=chunk-GIO77YH5.js.map
118
+ //# sourceMappingURL=chunk-GIO77YH5.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/read-node-direction.ts"],"names":[],"mappings":";;;;AA2EO,SAAS,oBAAoB,KAAA,EAA6C;AAC/E,EAAA,IAAI,OAAO,UAAU,QAAA,IAAY,KAAA,KAAU,QAAQ,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG,OAAO,MAAA;AAChF,EAAA,MAAM,GAAA,GAAM,KAAA;AACZ,EAAA,MAAM,MAAyC,EAAC;AAChD,EAAA,KAAA,MAAW,QAAQ,gBAAA,EAAkB;AACnC,IAAA,MAAM,CAAA,GAAI,GAAA,CAAI,IAAA,CAAK,GAAG,CAAA;AACtB,IAAA,IAAI,OAAO,MAAM,QAAA,EAAU;AACzB,MAAA,IAAI,CAAA,CAAE,SAAS,CAAA,IAAK,CAAA,CAAE,UAAU,sBAAA,EAAwB,GAAA,CAAI,IAAA,CAAK,GAAG,CAAA,GAAI,CAAA;AAAA,IAC1E,CAAA,MAAA,IAAW,KAAA,CAAM,OAAA,CAAQ,CAAC,CAAA,EAAG;AAC3B,MAAA,MAAM,OAAiB,EAAC;AACxB,MAAA,KAAA,MAAW,KAAK,CAAA,EAAG;AACjB,QAAA,IAAI,IAAA,CAAK,UAAU,uBAAA,EAAyB;AAC5C,QAAA,IAAI,OAAO,MAAM,QAAA,IAAY,CAAA,CAAE,SAAS,CAAA,IAAK,CAAA,CAAE,UAAU,sBAAA,EAAwB;AAC/E,UAAA,IAAA,CAAK,KAAK,CAAC,CAAA;AAAA,QACb;AAAA,MACF;AACA,MAAA,IAAI,KAAK,MAAA,GAAS,CAAA,EAAG,GAAA,CAAI,IAAA,CAAK,GAAG,CAAA,GAAI,IAAA;AAAA,IACvC;AAAA,EACF;AACA,EAAA,OAAO,OAAO,IAAA,CAAK,GAAG,CAAA,CAAE,MAAA,GAAS,IAAK,GAAA,GAA0B,MAAA;AAClE;AAyBO,SAAS,kBAAkB,KAAA,EAA2C;AAC3E,EAAA,IAAI,OAAO,UAAU,QAAA,IAAY,KAAA,KAAU,QAAQ,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG,OAAO,MAAA;AAChF,EAAA,MAAM,GAAA,GAAM,KAAA;AACZ,EAAA,MAAM,MAAkD,EAAC;AACzD,EAAA,KAAA,MAAW,GAAA,IAAO,0BAAyB,EAAG;AAC5C,IAAA,MAAM,CAAA,GAAI,IAAI,GAAG,CAAA;AACjB,IAAA,IAAI,QAAQ,sBAAA,EAAwB;AAClC,MAAA,IAAI,OAAO,MAAM,QAAA,IAAY,MAAA,CAAO,SAAS,CAAC,CAAA,EAAG,GAAA,CAAI,GAAG,CAAA,GAAI,CAAA;AAC5D,MAAA;AAAA,IACF;AACA,IAAA,IAAI,OAAO,MAAM,QAAA,EAAU;AACzB,MAAA,IAAI,CAAA,CAAE,SAAS,CAAA,IAAK,CAAA,CAAE,UAAU,oBAAA,EAAsB,GAAA,CAAI,GAAG,CAAA,GAAI,CAAA;AAAA,IACnE,CAAA,MAAA,IAAW,KAAA,CAAM,OAAA,CAAQ,CAAC,CAAA,EAAG;AAG3B,MAAA,MAAM,OAAiB,EAAC;AACxB,MAAA,KAAA,MAAW,KAAK,CAAA,EAAG;AACjB,QAAA,IAAI,IAAA,CAAK,UAAU,qBAAA,EAAuB;AAC1C,QAAA,IAAI,OAAO,MAAM,QAAA,IAAY,CAAA,CAAE,SAAS,CAAA,IAAK,CAAA,CAAE,UAAU,oBAAA,EAAsB;AAC7E,UAAA,IAAA,CAAK,KAAK,CAAC,CAAA;AAAA,QACb;AAAA,MACF;AACA,MAAA,IAAI,IAAA,CAAK,MAAA,GAAS,CAAA,EAAG,GAAA,CAAI,GAAG,CAAA,GAAI,IAAA;AAAA,IAClC;AAAA,EACF;AACA,EAAA,OAAO,OAAO,IAAA,CAAK,GAAG,CAAA,CAAE,MAAA,GAAS,IAAK,GAAA,GAAwB,MAAA;AAChE;AAKA,IAAM,OAAA,GAAU,CAAC,KAAA,EAAO,OAAA,EAAS,SAAS,YAAY,CAAA;AACtD,IAAM,0BAAA,GAA6B,GAAA;AAcnC,IAAM,aAAA,GAAuC;AAAA,EAC3C,GAAA,EAAK,QAAA;AAAA,EACL,MAAA,EAAQ,QAAA;AAAA,EACR,IAAA,EAAM,QAAA;AAAA,EACN,IAAA,EAAM,QAAA;AAAA,EACN,UAAA,EAAY,QAAA;AAAA,EACZ,UAAA,EAAY,QAAA;AAAA,EACZ,WAAA,EAAa;AACf,CAAA;AACA,IAAM,cAAA,GAAyC;AAAA,EAC7C,IAAA,EAAM,QAAA;AAAA,EACN,QAAA,EAAU,QAAA;AAAA,EACV,SAAA,EAAW,QAAA;AAAA,EACX,SAAA,EAAW;AACb,CAAA;AACA,IAAM,cAAA,GAAyC;AAAA,EAC7C,GAAA,EAAK,QAAA;AAAA,EACL,UAAA,EAAY,QAAA;AAAA,EACZ,QAAA,EAAU;AACZ,CAAA;AACA,IAAM,aAAA,GAAuC;AAAA,EAC3C,OAAA,EAAS,QAAA;AAAA,EACT,MAAA,EAAQ,QAAA;AAAA,EACR,MAAA,EAAQ;AACV,CAAA;AACA,IAAM,WAAA,GAAmC,EAAE,WAAA,EAAa,QAAA,EAAU,UAAU,QAAA,EAAS;AAErF,IAAM,iBAAA,GAAsD;AAAA,EAC1D,MAAA,EAAQ,aAAA;AAAA,EACR,OAAA,EAAS,cAAA;AAAA,EACT,OAAA,EAAS,cAAA;AAAA,EACT,MAAA,EAAQ,aAAA;AAAA,EACR,IAAA,EAAM;AACR,CAAA;AAEA,SAAS,SAAA,CAAU,GAAY,IAAA,EAA8C;AAC3E,EAAA,IAAI,IAAA,KAAS,QAAA,EAAU,OAAO,OAAO,CAAA,KAAM,YAAY,MAAA,CAAO,QAAA,CAAS,CAAC,CAAA,GAAI,CAAA,GAAI,MAAA;AAChF,EAAA,IAAI,OAAO,MAAM,QAAA,IAAY,CAAA,CAAE,WAAW,CAAA,IAAK,CAAA,CAAE,SAAS,0BAAA,EAA4B;AACpF,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,IAAI,SAAS,QAAA,EAAU,OAAQ,QAA8B,QAAA,CAAS,CAAC,IAAI,CAAA,GAAI,MAAA;AAC/E,EAAA,OAAO,CAAA;AACT;AAIO,SAAS,qBAAqB,KAAA,EAAoD;AACvF,EAAA,IAAI,OAAO,UAAU,QAAA,IAAY,KAAA,KAAU,QAAQ,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG,OAAO,MAAA;AAChF,EAAA,MAAM,GAAA,GAAM,KAAA;AACZ,EAAA,MAAM,MAA+B,EAAC;AACtC,EAAA,KAAA,MAAW,KAAA,IAAS,MAAA,CAAO,IAAA,CAAK,iBAAiB,CAAA,EAAc;AAC7D,IAAA,MAAM,GAAA,GAAM,IAAI,KAAK,CAAA;AACrB,IAAA,IAAI,OAAO,QAAQ,QAAA,IAAY,GAAA,KAAQ,QAAQ,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAA,EAAG;AACnE,IAAA,MAAM,MAAA,GAAS,GAAA;AACf,IAAA,MAAM,OAAgC,EAAC;AACvC,IAAA,KAAA,MAAW,CAAC,KAAA,EAAO,IAAI,CAAA,IAAK,MAAA,CAAO,OAAA;AAAA,MACjC,kBAAkB,KAAK;AAAA,KACzB,EAAG;AACD,MAAA,MAAM,CAAA,GAAI,SAAA,CAAU,MAAA,CAAO,KAAK,GAAG,IAAI,CAAA;AACvC,MAAA,IAAI,CAAA,KAAM,MAAA,EAAW,IAAA,CAAK,KAAK,CAAA,GAAI,CAAA;AAAA,IACrC;AACA,IAAA,IAAI,MAAA,CAAO,KAAK,IAAI,CAAA,CAAE,SAAS,CAAA,EAAG,GAAA,CAAI,KAAK,CAAA,GAAI,IAAA;AAAA,EACjD;AACA,EAAA,MAAM,IAAA,GAAO,SAAA,CAAU,GAAA,CAAI,IAAA,EAAM,QAAQ,CAAA;AACzC,EAAA,IAAI,IAAA,KAAS,MAAA,EAAW,GAAA,CAAI,IAAA,GAAO,IAAA;AACnC,EAAA,OAAO,OAAO,IAAA,CAAK,GAAG,CAAA,CAAE,MAAA,GAAS,IAAK,GAAA,GAAiC,MAAA;AACzE","file":"chunk-6GVFJLDL.js","sourcesContent":["/**\n * Narrow readers turning UNTRUSTED persisted node data (`workflows.nodes`\n * JSONB — import, MCP write, node preset, a Studio-emitted graph) into the\n * typed `subject` / `direction` / `structured` levers `assembleImageInput`\n * accepts.\n * `buildPayload` has no zod and workflow writes are\n * `z.record(z.string(), z.unknown())`, so this blob may have been written years\n * ago by any client.\n *\n * Used by ALL THREE image-assembly sites so what the canvas accepts cannot\n * drift between them: the frontend single-node executor (`execute-node.ts`),\n * the orchestrator (`payload-builder.ts`), and the config-panel final-prompt\n * preview (`build-image-assemble-input.ts`).\n *\n * `readDirectionFields` is DERIVED FROM `DIRECTION_FIELDS`, never a hand list:\n * a dimension added to the registry is honored here by construction, so the\n * reader can never silently drop a key the wire schema and the renderer both\n * know about. Anything unrecognised is DROPPED, never thrown on — a malformed\n * blob must not fail a canvas run, and an unknown catalog ID already degrades\n * to `\"\"` inside each `get*PromptHint`, so this validates SHAPE only.\n *\n * BOUNDS MATCH THE WIRE SCHEMA where both exist, by SHARED CONSTANT:\n * `DIRECTION_ID_MAX_CHARS` and `DIRECTION_ARRAY_CEILING` are the same two\n * literals the `generate-image` route's `directionSchema` enforces, imported\n * from the registry rather than re-typed here — a body the route accepts and a\n * node the canvas re-runs must not disagree about which strings are ids.\n *\n * DELIBERATELY STRICTER THAN THE WIRE SCHEMA on `structured` values: the\n * route's `structuredPromptFieldsSchema` declares every field as a bare\n * `z.string().optional()` (unbounded), while `MAX_STRUCTURED_VALUE_CHARS` below\n * bounds them at 200. Do not \"fix\" that asymmetry by loosening HERE — this\n * reads a blob any client may have written years ago, and the values land\n * verbatim in `jobs.input_data.prompt`. Tightening the ROUTE instead would be a\n * new 400 on currently-accepted input, so a >200-char structured value stored\n * on a node is dropped on a canvas run while `POST /v1/generate-image` still\n * renders it. That is the one known divergence; it is bounded to a field the\n * canvas UI never writes that long.\n *\n * RETURNS `undefined`, NEVER `{}`: an empty object would still be a *defined*\n * `direction`, and the call sites' `...(x !== undefined ? { x } : {})` spread\n * would then hand `assembleImageInput` a defined-but-empty lever. Returning\n * `undefined` keeps that spread honest and the exact no-op branch taken.\n */\nimport {\n DIRECTION_ARRAY_CEILING,\n DIRECTION_FIELDS,\n DIRECTION_ID_MAX_CHARS,\n type DirectionFields,\n} from \"./direction-registry.js\"\nimport {\n SUBJECT_ARRAY_CEILING,\n SUBJECT_CUSTOM_AGE_KEY,\n SUBJECT_ID_MAX_CHARS,\n getRegisteredSubjectKeys,\n type SubjectFields,\n} from \"./subject-registry.js\"\nimport type { StructuredPromptFields } from \"./prompt-builder-structured-fields.js\"\n\n/**\n * Read a node's stored cinematic-direction ids. Accepts a single id OR an array\n * on every key (multi-pick dimensions carry arrays; a single-pick key may\n * legitimately carry one).\n *\n * The SEMANTIC per-dimension cap stays the renderer's slice (`maxPicks`) — this\n * reader does not know a row's pick budget and must not guess it. But it DOES\n * bound cardinality at `DIRECTION_ARRAY_CEILING`, the same ceiling the wire\n * schema enforces: the value is untrusted persisted JSONB (a node blob is\n * validated only as `z.record(z.string(), z.unknown())` on write), and handing\n * an unbounded array to `renderDirectionHints` would put an `includes`-dedupe\n * scan in front of that slice. Keeping the FIRST `DIRECTION_ARRAY_CEILING`\n * survivors is what the wire door already does to the same input.\n *\n * Junk is filtered BEFORE the cap, so valid ids sitting behind malformed\n * entries survive rather than being crowded out by them.\n */\nexport function readDirectionFields(value: unknown): DirectionFields | undefined {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) return undefined\n const src = value as Record<string, unknown>\n const out: Record<string, string | string[]> = {}\n for (const spec of DIRECTION_FIELDS) {\n const v = src[spec.key]\n if (typeof v === \"string\") {\n if (v.length > 0 && v.length <= DIRECTION_ID_MAX_CHARS) out[spec.key] = v\n } else if (Array.isArray(v)) {\n const kept: string[] = []\n for (const x of v) {\n if (kept.length >= DIRECTION_ARRAY_CEILING) break\n if (typeof x === \"string\" && x.length > 0 && x.length <= DIRECTION_ID_MAX_CHARS) {\n kept.push(x)\n }\n }\n if (kept.length > 0) out[spec.key] = kept\n }\n }\n return Object.keys(out).length > 0 ? (out as DirectionFields) : undefined\n}\n\n// ── subject ──────────────────────────────────────────────────────────────────\n\n/**\n * Read a node's stored SUBJECT ids — the flat Person / Styling / prop bag the\n * `subject` channel carries. Same three contracts as `readDirectionFields`:\n * drop-never-throw, `undefined` never `{}`, and bounds shared with the wire\n * door by CONSTANT (`SUBJECT_ID_MAX_CHARS` / `SUBJECT_ARRAY_CEILING`, which are\n * defined AS the direction constants) so a body the route accepts and the same\n * node re-run from the canvas cannot disagree about which strings are ids.\n *\n * DERIVED from `getRegisteredSubjectKeys()`, never a hand-authored field list —\n * that is the whole lesson of `readStructuredFields` below, whose hand table is\n * only viable because `StructuredPromptFields` is a small hand-authored type.\n * The subject vocabulary is ~54 catalog-derived fields PLUS deployment-registered\n * pack dimensions unknown at compile time, so it is read from the registry at\n * call time. Iterating the KEY SET (never `Object.keys(value)`) is also what\n * keeps an adversarial blob's key count off the hot path.\n *\n * The SEMANTIC per-dimension cap stays the renderer's job\n * (`normalizeSubjectFields`), exactly as `maxPicks` does for direction: this\n * reader bounds cardinality only. `customAge` is the one number on the wire and\n * is passed through finite-only — the renderer clamps it.\n */\nexport function readSubjectFields(value: unknown): SubjectFields | undefined {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) return undefined\n const src = value as Record<string, unknown>\n const out: Record<string, string | string[] | number> = {}\n for (const key of getRegisteredSubjectKeys()) {\n const v = src[key]\n if (key === SUBJECT_CUSTOM_AGE_KEY) {\n if (typeof v === \"number\" && Number.isFinite(v)) out[key] = v\n continue\n }\n if (typeof v === \"string\") {\n if (v.length > 0 && v.length <= SUBJECT_ID_MAX_CHARS) out[key] = v\n } else if (Array.isArray(v)) {\n // Junk is filtered BEFORE the cap, so valid ids sitting behind malformed\n // entries survive rather than being crowded out by them.\n const kept: string[] = []\n for (const x of v) {\n if (kept.length >= SUBJECT_ARRAY_CEILING) break\n if (typeof x === \"string\" && x.length > 0 && x.length <= SUBJECT_ID_MAX_CHARS) {\n kept.push(x)\n }\n }\n if (kept.length > 0) out[key] = kept\n }\n }\n return Object.keys(out).length > 0 ? (out as SubjectFields) : undefined\n}\n\n// ── structured ───────────────────────────────────────────────────────────────\n\ntype FieldKind = \"string\" | \"number\" | \"gender\"\nconst GENDERS = [\"man\", \"woman\", \"child\", \"non-binary\"] as const\nconst MAX_STRUCTURED_VALUE_CHARS = 200\n\ntype Group = Exclude<keyof StructuredPromptFields, \"mood\">\ntype GroupFields<K extends Group> = Record<keyof NonNullable<StructuredPromptFields[K]>, FieldKind>\n\n/**\n * A FIELD-BY-FIELD table (not a registry walk) on purpose:\n * `StructuredPromptFields` is a small HAND-AUTHORED type, not catalog-derived,\n * and the table is what blocks `person: { age: \"drop table\" }` from rendering\n * verbatim into `jobs.input_data.prompt` — `renderStructuredFields` never\n * throws on junk, but it does render it. Totality is enforced by the\n * `GroupFields<K>` / `{ [K in Group]: … }` mapped types: a new field or group\n * on the published type fails to typecheck here.\n */\nconst PERSON_FIELDS: GroupFields<\"person\"> = {\n age: \"number\",\n gender: \"gender\",\n hair: \"string\",\n eyes: \"string\",\n expression: \"string\",\n profession: \"string\",\n warriorType: \"string\",\n}\nconst STYLING_FIELDS: GroupFields<\"styling\"> = {\n mood: \"string\",\n lighting: \"string\",\n aesthetic: \"string\",\n colorLook: \"string\",\n}\nconst SETTING_FIELDS: GroupFields<\"setting\"> = {\n era: \"string\",\n atmosphere: \"string\",\n backdrop: \"string\",\n}\nconst CAMERA_FIELDS: GroupFields<\"camera\"> = {\n framing: \"string\",\n motion: \"string\",\n format: \"string\",\n}\nconst LENS_FIELDS: GroupFields<\"lens\"> = { focalLength: \"string\", aperture: \"string\" }\n\nconst STRUCTURED_GROUPS: { [K in Group]: GroupFields<K> } = {\n person: PERSON_FIELDS,\n styling: STYLING_FIELDS,\n setting: SETTING_FIELDS,\n camera: CAMERA_FIELDS,\n lens: LENS_FIELDS,\n}\n\nfunction readField(v: unknown, kind: FieldKind): string | number | undefined {\n if (kind === \"number\") return typeof v === \"number\" && Number.isFinite(v) ? v : undefined\n if (typeof v !== \"string\" || v.length === 0 || v.length > MAX_STRUCTURED_VALUE_CHARS) {\n return undefined\n }\n if (kind === \"gender\") return (GENDERS as readonly string[]).includes(v) ? v : undefined\n return v\n}\n\n/** Read a node's stored Path-1 structured prompt fields. Same drop-never-throw\n * and `undefined`-never-`{}` contract as `readDirectionFields`. */\nexport function readStructuredFields(value: unknown): StructuredPromptFields | undefined {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) return undefined\n const src = value as Record<string, unknown>\n const out: Record<string, unknown> = {}\n for (const group of Object.keys(STRUCTURED_GROUPS) as Group[]) {\n const raw = src[group]\n if (typeof raw !== \"object\" || raw === null || Array.isArray(raw)) continue\n const rawRec = raw as Record<string, unknown>\n const kept: Record<string, unknown> = {}\n for (const [field, kind] of Object.entries(\n STRUCTURED_GROUPS[group] as Record<string, FieldKind>,\n )) {\n const v = readField(rawRec[field], kind)\n if (v !== undefined) kept[field] = v\n }\n if (Object.keys(kept).length > 0) out[group] = kept\n }\n const mood = readField(src.mood, \"string\")\n if (mood !== undefined) out.mood = mood\n return Object.keys(out).length > 0 ? (out as StructuredPromptFields) : undefined\n}\n"]}
1
+ {"version":3,"sources":["../src/read-node-direction.ts"],"names":[],"mappings":"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","file":"chunk-GIO77YH5.js","sourcesContent":["/**\n * Narrow readers turning UNTRUSTED persisted node data (`workflows.nodes`\n * JSONB — import, MCP write, node preset, a Studio-emitted graph) into the\n * typed `subject` / `direction` / `structured` levers `assembleImageInput`\n * accepts.\n * `buildPayload` has no zod and workflow writes are\n * `z.record(z.string(), z.unknown())`, so this blob may have been written years\n * ago by any client.\n *\n * Used by ALL THREE image-assembly sites so what the canvas accepts cannot\n * drift between them: the frontend single-node executor (`execute-node.ts`),\n * the orchestrator (`payload-builder.ts`), and the config-panel final-prompt\n * preview (`build-image-assemble-input.ts`).\n *\n * `readDirectionFields` is DERIVED FROM `DIRECTION_FIELDS`, never a hand list:\n * a dimension added to the registry is honored here by construction, so the\n * reader can never silently drop a key the wire schema and the renderer both\n * know about. Anything unrecognised is DROPPED, never thrown on — a malformed\n * blob must not fail a canvas run, and an unknown catalog ID already degrades\n * to `\"\"` inside each `get*PromptHint`, so this validates SHAPE only.\n *\n * BOUNDS MATCH THE WIRE SCHEMA where both exist, by SHARED CONSTANT:\n * `DIRECTION_ID_MAX_CHARS` and `DIRECTION_ARRAY_CEILING` are the same two\n * literals the `generate-image` route's `directionSchema` enforces, imported\n * from the registry rather than re-typed here — a body the route accepts and a\n * node the canvas re-runs must not disagree about which strings are ids.\n *\n * DELIBERATELY STRICTER THAN THE WIRE SCHEMA on `structured` values: the\n * route's `structuredPromptFieldsSchema` declares every field as a bare\n * `z.string().optional()` (unbounded), while `MAX_STRUCTURED_VALUE_CHARS` below\n * bounds them at 200. Do not \"fix\" that asymmetry by loosening HERE — this\n * reads a blob any client may have written years ago, and the values land\n * verbatim in `jobs.input_data.prompt`. Tightening the ROUTE instead would be a\n * new 400 on currently-accepted input, so a >200-char structured value stored\n * on a node is dropped on a canvas run while `POST /v1/generate-image` still\n * renders it. That is the one known divergence; it is bounded to a field the\n * canvas UI never writes that long.\n *\n * RETURNS `undefined`, NEVER `{}`: an empty object would still be a *defined*\n * `direction`, and the call sites' `...(x !== undefined ? { x } : {})` spread\n * would then hand `assembleImageInput` a defined-but-empty lever. Returning\n * `undefined` keeps that spread honest and the exact no-op branch taken.\n */\nimport {\n DIRECTION_ARRAY_CEILING,\n DIRECTION_FIELDS,\n DIRECTION_ID_MAX_CHARS,\n type DirectionFields,\n} from \"./direction-registry.js\"\nimport {\n SUBJECT_ARRAY_CEILING,\n SUBJECT_CUSTOM_AGE_KEY,\n SUBJECT_ID_MAX_CHARS,\n getRegisteredSubjectKeys,\n type SubjectFields,\n} from \"./subject-registry.js\"\nimport type { StructuredPromptFields } from \"./prompt-builder-structured-fields.js\"\n\n/**\n * Read a node's stored cinematic-direction ids. Accepts a single id OR an array\n * on every key (multi-pick dimensions carry arrays; a single-pick key may\n * legitimately carry one).\n *\n * The SEMANTIC per-dimension cap stays the renderer's slice (`maxPicks`) — this\n * reader does not know a row's pick budget and must not guess it. But it DOES\n * bound cardinality at `DIRECTION_ARRAY_CEILING`, the same ceiling the wire\n * schema enforces: the value is untrusted persisted JSONB (a node blob is\n * validated only as `z.record(z.string(), z.unknown())` on write), and handing\n * an unbounded array to `renderDirectionHints` would put an `includes`-dedupe\n * scan in front of that slice. Keeping the FIRST `DIRECTION_ARRAY_CEILING`\n * survivors is what the wire door already does to the same input.\n *\n * Junk is filtered BEFORE the cap, so valid ids sitting behind malformed\n * entries survive rather than being crowded out by them.\n */\nexport function readDirectionFields(value: unknown): DirectionFields | undefined {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) return undefined\n const src = value as Record<string, unknown>\n const out: Record<string, string | string[]> = {}\n for (const spec of DIRECTION_FIELDS) {\n const v = src[spec.key]\n if (typeof v === \"string\") {\n if (v.length > 0 && v.length <= DIRECTION_ID_MAX_CHARS) out[spec.key] = v\n } else if (Array.isArray(v)) {\n const kept: string[] = []\n for (const x of v) {\n if (kept.length >= DIRECTION_ARRAY_CEILING) break\n if (typeof x === \"string\" && x.length > 0 && x.length <= DIRECTION_ID_MAX_CHARS) {\n kept.push(x)\n }\n }\n if (kept.length > 0) out[spec.key] = kept\n }\n }\n return Object.keys(out).length > 0 ? (out as DirectionFields) : undefined\n}\n\n// ── subject ──────────────────────────────────────────────────────────────────\n\n/**\n * Read a node's stored SUBJECT ids — the flat Person / Styling / prop bag the\n * `subject` channel carries. Same three contracts as `readDirectionFields`:\n * drop-never-throw, `undefined` never `{}`, and bounds shared with the wire\n * door by CONSTANT (`SUBJECT_ID_MAX_CHARS` / `SUBJECT_ARRAY_CEILING`, which are\n * defined AS the direction constants) so a body the route accepts and the same\n * node re-run from the canvas cannot disagree about which strings are ids.\n *\n * DERIVED from `getRegisteredSubjectKeys()`, never a hand-authored field list —\n * that is the whole lesson of `readStructuredFields` below, whose hand table is\n * only viable because `StructuredPromptFields` is a small hand-authored type.\n * The subject vocabulary is ~54 catalog-derived fields PLUS deployment-registered\n * pack dimensions unknown at compile time, so it is read from the registry at\n * call time. Iterating the KEY SET (never `Object.keys(value)`) is also what\n * keeps an adversarial blob's key count off the hot path.\n *\n * The SEMANTIC per-dimension cap stays the renderer's job\n * (`normalizeSubjectFields`), exactly as `maxPicks` does for direction: this\n * reader bounds cardinality only. `customAge` is the one number on the wire and\n * is passed through finite-only — the renderer clamps it.\n */\nexport function readSubjectFields(value: unknown): SubjectFields | undefined {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) return undefined\n const src = value as Record<string, unknown>\n const out: Record<string, string | string[] | number> = {}\n for (const key of getRegisteredSubjectKeys()) {\n const v = src[key]\n if (key === SUBJECT_CUSTOM_AGE_KEY) {\n if (typeof v === \"number\" && Number.isFinite(v)) out[key] = v\n continue\n }\n if (typeof v === \"string\") {\n if (v.length > 0 && v.length <= SUBJECT_ID_MAX_CHARS) out[key] = v\n } else if (Array.isArray(v)) {\n // Junk is filtered BEFORE the cap, so valid ids sitting behind malformed\n // entries survive rather than being crowded out by them.\n const kept: string[] = []\n for (const x of v) {\n if (kept.length >= SUBJECT_ARRAY_CEILING) break\n if (typeof x === \"string\" && x.length > 0 && x.length <= SUBJECT_ID_MAX_CHARS) {\n kept.push(x)\n }\n }\n if (kept.length > 0) out[key] = kept\n }\n }\n return Object.keys(out).length > 0 ? (out as SubjectFields) : undefined\n}\n\n// ── structured ───────────────────────────────────────────────────────────────\n\ntype FieldKind = \"string\" | \"number\" | \"gender\"\nconst GENDERS = [\"man\", \"woman\", \"child\", \"non-binary\"] as const\nconst MAX_STRUCTURED_VALUE_CHARS = 200\n\ntype Group = Exclude<keyof StructuredPromptFields, \"mood\">\ntype GroupFields<K extends Group> = Record<keyof NonNullable<StructuredPromptFields[K]>, FieldKind>\n\n/**\n * A FIELD-BY-FIELD table (not a registry walk) on purpose:\n * `StructuredPromptFields` is a small HAND-AUTHORED type, not catalog-derived,\n * and the table is what blocks `person: { age: \"drop table\" }` from rendering\n * verbatim into `jobs.input_data.prompt` — `renderStructuredFields` never\n * throws on junk, but it does render it. Totality is enforced by the\n * `GroupFields<K>` / `{ [K in Group]: … }` mapped types: a new field or group\n * on the published type fails to typecheck here.\n */\nconst PERSON_FIELDS: GroupFields<\"person\"> = {\n age: \"number\",\n gender: \"gender\",\n hair: \"string\",\n eyes: \"string\",\n expression: \"string\",\n profession: \"string\",\n warriorType: \"string\",\n}\nconst STYLING_FIELDS: GroupFields<\"styling\"> = {\n mood: \"string\",\n lighting: \"string\",\n aesthetic: \"string\",\n colorLook: \"string\",\n}\nconst SETTING_FIELDS: GroupFields<\"setting\"> = {\n era: \"string\",\n atmosphere: \"string\",\n backdrop: \"string\",\n}\nconst CAMERA_FIELDS: GroupFields<\"camera\"> = {\n framing: \"string\",\n motion: \"string\",\n format: \"string\",\n}\nconst LENS_FIELDS: GroupFields<\"lens\"> = { focalLength: \"string\", aperture: \"string\" }\n\nconst STRUCTURED_GROUPS: { [K in Group]: GroupFields<K> } = {\n person: PERSON_FIELDS,\n styling: STYLING_FIELDS,\n setting: SETTING_FIELDS,\n camera: CAMERA_FIELDS,\n lens: LENS_FIELDS,\n}\n\nfunction readField(v: unknown, kind: FieldKind): string | number | undefined {\n if (kind === \"number\") return typeof v === \"number\" && Number.isFinite(v) ? v : undefined\n if (typeof v !== \"string\" || v.length === 0 || v.length > MAX_STRUCTURED_VALUE_CHARS) {\n return undefined\n }\n if (kind === \"gender\") return (GENDERS as readonly string[]).includes(v) ? v : undefined\n return v\n}\n\n/** Read a node's stored Path-1 structured prompt fields. Same drop-never-throw\n * and `undefined`-never-`{}` contract as `readDirectionFields`. */\nexport function readStructuredFields(value: unknown): StructuredPromptFields | undefined {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) return undefined\n const src = value as Record<string, unknown>\n const out: Record<string, unknown> = {}\n for (const group of Object.keys(STRUCTURED_GROUPS) as Group[]) {\n const raw = src[group]\n if (typeof raw !== \"object\" || raw === null || Array.isArray(raw)) continue\n const rawRec = raw as Record<string, unknown>\n const kept: Record<string, unknown> = {}\n for (const [field, kind] of Object.entries(\n STRUCTURED_GROUPS[group] as Record<string, FieldKind>,\n )) {\n const v = readField(rawRec[field], kind)\n if (v !== undefined) kept[field] = v\n }\n if (Object.keys(kept).length > 0) out[group] = kept\n }\n const mood = readField(src.mood, \"string\")\n if (mood !== undefined) out.mood = mood\n return Object.keys(out).length > 0 ? (out as StructuredPromptFields) : undefined\n}\n"]}
@@ -1,11 +1,11 @@
1
1
  'use strict';
2
2
 
3
- var chunkWRM52ZBN_cjs = require('./chunk-WRM52ZBN.cjs');
3
+ var chunkZLRB5BVT_cjs = require('./chunk-ZLRB5BVT.cjs');
4
4
  var chunkXUZXBY75_cjs = require('./chunk-XUZXBY75.cjs');
5
5
  var chunk2NJTFCKQ_cjs = require('./chunk-2NJTFCKQ.cjs');
6
- var chunkPWWM7Q3T_cjs = require('./chunk-PWWM7Q3T.cjs');
7
- var chunk2P26SZX5_cjs = require('./chunk-2P26SZX5.cjs');
8
- var chunkMQEXFCNU_cjs = require('./chunk-MQEXFCNU.cjs');
6
+ var chunkAXQK7UH7_cjs = require('./chunk-AXQK7UH7.cjs');
7
+ var chunkJDNHMVEV_cjs = require('./chunk-JDNHMVEV.cjs');
8
+ var chunkSB7AYE6S_cjs = require('./chunk-SB7AYE6S.cjs');
9
9
  var entities = require('@nodaro/shared/entities');
10
10
  var models = require('@nodaro/shared/models');
11
11
  var video = require('@nodaro/shared/video');
@@ -71,11 +71,11 @@ function resolveRefIdTokens(prompt, ctx) {
71
71
  var REFERENCE_TOKEN_RE = /\{(image|video|audio):(\d+)(?::([a-zA-Z0-9_ -]+))?\}/gi;
72
72
  function resolveReferenceTokens(prompt, counts) {
73
73
  if (!prompt) return prompt;
74
- return chunkWRM52ZBN_cjs.tidyReferenceTokenGaps(
74
+ return chunkZLRB5BVT_cjs.tidyReferenceTokenGaps(
75
75
  prompt.replace(REFERENCE_TOKEN_RE, (_match, rawKind, nStr, label) => {
76
76
  const kind = rawKind.toLowerCase();
77
77
  const n = parseInt(nStr, 10);
78
- if (n < 1 || n > counts[kind]) return chunkWRM52ZBN_cjs.unboundReferenceTokenText(label);
78
+ if (n < 1 || n > counts[kind]) return chunkZLRB5BVT_cjs.unboundReferenceTokenText(label);
79
79
  if (label) return REF_BINDING[kind](label, n);
80
80
  return `@${kind}_${n}`;
81
81
  })
@@ -134,7 +134,7 @@ function resolveVideoCharacterMentionsHybrid(prompt, tokens, refs, offset) {
134
134
  const binding = bindingFor(m.url);
135
135
  const lock = chunk2NJTFCKQ_cjs.buildIdentityLockLine(chunk2NJTFCKQ_cjs.withForcedIdentityLock(ref, lockOverrideByUrl.get(m.url)), binding);
136
136
  if (lock) lockLines.push(lock);
137
- const overrideLine = chunkWRM52ZBN_cjs.referenceDescriptionLine(binding, ref.descriptionOverride);
137
+ const overrideLine = chunkZLRB5BVT_cjs.referenceDescriptionLine(binding, ref.descriptionOverride);
138
138
  if (overrideLine) elementDirectives.push(overrideLine);
139
139
  const inject = ref.elementInjection?.trim();
140
140
  if (inject) elementDirectives.push(inject);
@@ -162,8 +162,8 @@ function resolveVideoReferenceCore(args) {
162
162
  audio: args.audioRefCount ?? 0
163
163
  });
164
164
  const describedAndCaptionLines = [
165
- ...chunkWRM52ZBN_cjs.renderDescribedReferenceLines(args.describedReferences),
166
- ...chunkWRM52ZBN_cjs.renderReferenceCaptionLines(args.videoCaptions, args.audioCaptions, {
165
+ ...chunkZLRB5BVT_cjs.renderDescribedReferenceLines(args.describedReferences),
166
+ ...chunkZLRB5BVT_cjs.renderReferenceCaptionLines(args.videoCaptions, args.audioCaptions, {
167
167
  video: args.videoRefCount ?? 0,
168
168
  audio: args.audioRefCount ?? 0
169
169
  })
@@ -200,7 +200,7 @@ function resolveVideoReferenceCore(args) {
200
200
  // Described references and rail captions are the ONE thing this branch can
201
201
  // still contribute: they need no seat, so a request that carries only them
202
202
  // (a story landing before any entity exists) reaches the model here.
203
- prompt: describedAndCaptionLines.length > 0 ? chunkWRM52ZBN_cjs.appendReferenceLines(resolved2 ?? "", describedAndCaptionLines, args.hybridRoles === true ? "hybrid" : "legacy") : resolved2,
203
+ prompt: describedAndCaptionLines.length > 0 ? chunkZLRB5BVT_cjs.appendReferenceLines(resolved2 ?? "", describedAndCaptionLines, args.hybridRoles === true ? "hybrid" : "legacy") : resolved2,
204
204
  additionalUrls: [...leadingRefUrls]
205
205
  };
206
206
  }
@@ -221,7 +221,7 @@ function resolveVideoReferenceCore(args) {
221
221
  mentionLockLines = h.lockLines;
222
222
  mentionElementDirectives = h.elementDirectives;
223
223
  } else {
224
- resolved = mentionTokens.length > 0 ? chunkWRM52ZBN_cjs.resolveCharacterMentions(promptForResolution, mentionTokens, wiredCharRefs) : { prompt: promptForResolution, additionalUrls: [], mentionedCharacterSlugs: /* @__PURE__ */ new Set() };
224
+ resolved = mentionTokens.length > 0 ? chunkZLRB5BVT_cjs.resolveCharacterMentions(promptForResolution, mentionTokens, wiredCharRefs) : { prompt: promptForResolution, additionalUrls: [], mentionedCharacterSlugs: /* @__PURE__ */ new Set() };
225
225
  }
226
226
  const fallbackUrls = [];
227
227
  const fallbackDirectiveLines = [];
@@ -258,7 +258,7 @@ function resolveVideoReferenceCore(args) {
258
258
  canonicalPhrases.push(entities.roleToPhrase(entities.resolveDefaultRole(r.defaultRole, r.defaultUsageMode, r.source), binding));
259
259
  const lock = chunk2NJTFCKQ_cjs.buildIdentityLockLine(r, binding);
260
260
  if (lock) canonicalLockLines.push(lock);
261
- const overrideLine = chunkWRM52ZBN_cjs.referenceDescriptionLine(binding, r.descriptionOverride);
261
+ const overrideLine = chunkZLRB5BVT_cjs.referenceDescriptionLine(binding, r.descriptionOverride);
262
262
  if (overrideLine) canonicalElementDirectives.push(overrideLine);
263
263
  const inject = r.elementInjection?.trim();
264
264
  if (inject) canonicalElementDirectives.push(inject);
@@ -390,7 +390,7 @@ function resolveVideoReferenceCore(args) {
390
390
  const lockBlock = lockLines.length > 0 ? `${lockLines.join("\n")}
391
391
 
392
392
  ` : "";
393
- finalPrompt = `${lockBlock}${chunkWRM52ZBN_cjs.insertBeforeStyleSection(finalPrompt, trailingLines)}`;
393
+ finalPrompt = `${lockBlock}${chunkZLRB5BVT_cjs.insertBeforeStyleSection(finalPrompt, trailingLines)}`;
394
394
  } else {
395
395
  const allFallbackLines = [...fallbackDirectiveLines, ...extraDirectiveLines];
396
396
  if (allFallbackLines.length > 0) {
@@ -440,7 +440,7 @@ ${finalPrompt}` : block;
440
440
  merged.push(u);
441
441
  }
442
442
  }
443
- finalPrompt = chunkWRM52ZBN_cjs.appendReferenceLines(
443
+ finalPrompt = chunkZLRB5BVT_cjs.appendReferenceLines(
444
444
  finalPrompt,
445
445
  describedAndCaptionLines,
446
446
  hybrid ? "hybrid" : "legacy"
@@ -468,7 +468,7 @@ ${finalPrompt}` : block;
468
468
  });
469
469
  }
470
470
  }
471
- const reordered = chunkWRM52ZBN_cjs.applyReferenceOrderToVideo(assetUrls, finalPrompt, refsForOrdering, referenceOrder, void 0, offset);
471
+ const reordered = chunkZLRB5BVT_cjs.applyReferenceOrderToVideo(assetUrls, finalPrompt, refsForOrdering, referenceOrder, void 0, offset);
472
472
  return {
473
473
  prompt: resolveReferenceTokens(reordered.prompt, tokenCounts(merged.length)),
474
474
  additionalUrls: [...leadingRefUrls, ...reordered.urls]
@@ -522,7 +522,7 @@ function composeSoundHintFromConnections(consumer, consumerType, ctx) {
522
522
  continue;
523
523
  }
524
524
  }
525
- const hint = chunkPWWM7Q3T_cjs.getParameterPromptHint(src);
525
+ const hint = chunkAXQK7UH7_cjs.getParameterPromptHint(src);
526
526
  if (hint) acceptedHints.push(hint);
527
527
  if ((consumerType === "suno-generate" || consumerType === "generate-music") && t === "voice-character" && src.data) {
528
528
  const gender = src.data.gender;
@@ -536,14 +536,14 @@ function composeSoundHintFromConnections(consumer, consumerType, ctx) {
536
536
  const sub = typeof data.subgenre === "string" ? data.subgenre : void 0;
537
537
  const genreId = typeof data.genre === "string" ? data.genre : void 0;
538
538
  const eraId = typeof data.era === "string" ? data.era : void 0;
539
- const eraHint = chunkMQEXFCNU_cjs.getMusicEra(eraId)?.promptHint;
540
- const genre = chunkMQEXFCNU_cjs.getMusicGenre(genreId);
539
+ const eraHint = chunkSB7AYE6S_cjs.getMusicEra(eraId)?.promptHint;
540
+ const genre = chunkSB7AYE6S_cjs.getMusicGenre(genreId);
541
541
  const subHint = genre?.subgenres.find((s) => s.id === sub)?.promptHint ?? genre?.promptHint;
542
542
  const composed = [eraHint, subHint].filter(Boolean).join(" ");
543
543
  if (composed && !fields.genre) Object.assign(fields, { genre: composed });
544
544
  }
545
545
  if (t === "music-mood" && data) {
546
- const composed = chunkMQEXFCNU_cjs.buildMusicMoodHints({
546
+ const composed = chunkSB7AYE6S_cjs.buildMusicMoodHints({
547
547
  energy: typeof data.energy === "string" ? data.energy : void 0,
548
548
  emotion: data.emotion,
549
549
  vibe: data.vibe
@@ -630,23 +630,23 @@ function assembleSunoInput(input) {
630
630
  function renderImageHintPieces(subject, direction, structured, directionRefs) {
631
631
  return {
632
632
  hintClauses: [
633
- ...chunkWRM52ZBN_cjs.asBodyClauses(
634
- chunkWRM52ZBN_cjs.renderSubjectHints(subject, {
633
+ ...chunkZLRB5BVT_cjs.asBodyClauses(
634
+ chunkZLRB5BVT_cjs.renderSubjectHints(subject, {
635
635
  surface: "image",
636
- mode: chunkWRM52ZBN_cjs.SUBJECT_IMAGE_HINT_MODE_DEFAULT
636
+ mode: chunkZLRB5BVT_cjs.SUBJECT_IMAGE_HINT_MODE_DEFAULT
637
637
  })
638
638
  ),
639
- ...chunkWRM52ZBN_cjs.partitionStyleClauses(direction, {
639
+ ...chunkZLRB5BVT_cjs.partitionStyleClauses(direction, {
640
640
  surface: "image",
641
- mode: chunk2P26SZX5_cjs.IMAGE_HINT_MODE_DEFAULT,
641
+ mode: chunkJDNHMVEV_cjs.IMAGE_HINT_MODE_DEFAULT,
642
642
  ...directionRefs !== void 0 ? { refs: directionRefs } : {}
643
643
  })
644
644
  ].filter((c) => c.text.length > 0),
645
- structuredFragment: structured ? chunkWRM52ZBN_cjs.renderStructuredFields(structured) : ""
645
+ structuredFragment: structured ? chunkZLRB5BVT_cjs.renderStructuredFields(structured) : ""
646
646
  };
647
647
  }
648
648
  function composePromptText(userPrompt, pieces, keptHintClauses) {
649
- return chunkWRM52ZBN_cjs.composeSectionedPrompt(
649
+ return chunkZLRB5BVT_cjs.composeSectionedPrompt(
650
650
  userPrompt,
651
651
  pieces.hintClauses.slice(0, keptHintClauses),
652
652
  pieces.structuredFragment
@@ -693,12 +693,12 @@ function styleConnectedReference(s, index) {
693
693
  url: s.url,
694
694
  isExtraRef: true,
695
695
  defaultRole: "style",
696
- description: chunk2P26SZX5_cjs.styleReferenceDescription(index, s.caption)
696
+ description: chunkJDNHMVEV_cjs.styleReferenceDescription(index, s.caption)
697
697
  };
698
698
  }
699
699
  function assembleOnce(input) {
700
700
  const pieces = renderImageHintPieces(input.subject, input.direction, input.structured, input.directionRefs);
701
- const assembleWith = (keptHintClauses) => chunkWRM52ZBN_cjs.buildImagePromptWithOverflow({
701
+ const assembleWith = (keptHintClauses) => chunkZLRB5BVT_cjs.buildImagePromptWithOverflow({
702
702
  prompt: composePromptText(input.userPrompt, pieces, keptHintClauses),
703
703
  provider: input.provider,
704
704
  ...input.connectedReferences !== void 0 ? { connectedReferences: input.connectedReferences } : {},
@@ -726,7 +726,7 @@ function assembleOnce(input) {
726
726
  let kept = pieces.hintClauses.length;
727
727
  let fitted = assembleWith(kept);
728
728
  if (fitted.overflowChars > 0) {
729
- const costs = chunkWRM52ZBN_cjs.sectionedClauseCosts(
729
+ const costs = chunkZLRB5BVT_cjs.sectionedClauseCosts(
730
730
  input.userPrompt,
731
731
  pieces.hintClauses,
732
732
  pieces.structuredFragment
@@ -744,19 +744,19 @@ function assembleOnce(input) {
744
744
  // src/assemble-video-input.ts
745
745
  function composeVideoPromptText(userPrompt, direction, structured, opts) {
746
746
  const hintClauses = [
747
- ...chunkWRM52ZBN_cjs.asBodyClauses(
748
- chunkWRM52ZBN_cjs.renderSubjectHints(opts?.subject, {
747
+ ...chunkZLRB5BVT_cjs.asBodyClauses(
748
+ chunkZLRB5BVT_cjs.renderSubjectHints(opts?.subject, {
749
749
  surface: "video",
750
- mode: opts?.subjectHintMode ?? chunkWRM52ZBN_cjs.SUBJECT_VIDEO_HINT_MODE_DEFAULT
750
+ mode: opts?.subjectHintMode ?? chunkZLRB5BVT_cjs.SUBJECT_VIDEO_HINT_MODE_DEFAULT
751
751
  })
752
752
  ),
753
- ...chunkWRM52ZBN_cjs.partitionStyleClauses(direction, {
753
+ ...chunkZLRB5BVT_cjs.partitionStyleClauses(direction, {
754
754
  surface: "video",
755
- mode: opts?.hintMode ?? chunk2P26SZX5_cjs.VIDEO_HINT_MODE_DEFAULT
755
+ mode: opts?.hintMode ?? chunkJDNHMVEV_cjs.VIDEO_HINT_MODE_DEFAULT
756
756
  })
757
757
  ].filter((c) => c.text.length > 0);
758
- const structuredFragment = structured ? chunkWRM52ZBN_cjs.renderStructuredFields(structured) : "";
759
- const composeWith = (kept2) => chunkWRM52ZBN_cjs.composeSectionedPrompt(userPrompt, hintClauses.slice(0, kept2), structuredFragment);
758
+ const structuredFragment = structured ? chunkZLRB5BVT_cjs.renderStructuredFields(structured) : "";
759
+ const composeWith = (kept2) => chunkZLRB5BVT_cjs.composeSectionedPrompt(userPrompt, hintClauses.slice(0, kept2), structuredFragment);
760
760
  const cap = opts?.cap;
761
761
  if (cap === void 0) return composeWith(hintClauses.length);
762
762
  const frame = opts?.frame ?? ((body2) => body2);
@@ -764,7 +764,7 @@ function composeVideoPromptText(userPrompt, direction, structured, opts) {
764
764
  let body = composeWith(kept);
765
765
  let framedLength = frame(body)?.length ?? 0;
766
766
  if (framedLength <= cap) return body;
767
- const costs = chunkWRM52ZBN_cjs.sectionedClauseCosts(userPrompt, hintClauses, structuredFragment);
767
+ const costs = chunkZLRB5BVT_cjs.sectionedClauseCosts(userPrompt, hintClauses, structuredFragment);
768
768
  const texts = hintClauses.map((c) => c.text);
769
769
  while (framedLength > cap && kept > 0) {
770
770
  kept = chunkXUZXBY75_cjs.keepableDirectionHints(texts, kept, framedLength - cap, costs);
@@ -988,5 +988,5 @@ exports.resolveSeedance2Inputs = resolveSeedance2Inputs;
988
988
  exports.resolveVeoI2vInputs = resolveVeoI2vInputs;
989
989
  exports.resolveVideoReferenceCore = resolveVideoReferenceCore;
990
990
  exports.truncateForField = truncateForField;
991
- //# sourceMappingURL=chunk-C3NHNECH.cjs.map
992
- //# sourceMappingURL=chunk-C3NHNECH.cjs.map
991
+ //# sourceMappingURL=chunk-H4JMZWOE.cjs.map
992
+ //# sourceMappingURL=chunk-H4JMZWOE.cjs.map