@nodaro/prompts 1.38.0 → 1.39.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-LVSH7K7R.cjs → chunk-22KZOAGL.cjs} +81 -42
- package/dist/chunk-22KZOAGL.cjs.map +1 -0
- package/dist/chunk-2P26SZX5.cjs +414 -0
- package/dist/chunk-2P26SZX5.cjs.map +1 -0
- package/dist/{chunk-CVPB2N3Z.cjs → chunk-3INXNDV7.cjs} +102 -4
- package/dist/chunk-3INXNDV7.cjs.map +1 -0
- package/dist/{chunk-7XKHDXCL.cjs → chunk-3U7X6JZN.cjs} +13 -12
- package/dist/chunk-3U7X6JZN.cjs.map +1 -0
- package/dist/chunk-4GKTOVFM.cjs +8 -0
- package/dist/chunk-4GKTOVFM.cjs.map +1 -0
- package/dist/{chunk-HRBBNODV.js → chunk-6GVFJLDL.js} +4 -3
- package/dist/chunk-6GVFJLDL.js.map +1 -0
- package/dist/{chunk-NO6XHX4R.js → chunk-6MPZHFIS.js} +99 -6
- package/dist/chunk-6MPZHFIS.js.map +1 -0
- package/dist/{chunk-4FDNVNJE.js → chunk-7XMTVYS5.js} +3 -76
- package/dist/chunk-7XMTVYS5.js.map +1 -0
- package/dist/{chunk-QDEWBBUR.js → chunk-DUXX6CBX.js} +12 -143
- package/dist/chunk-DUXX6CBX.js.map +1 -0
- package/dist/chunk-EAYEZXWT.js +388 -0
- package/dist/chunk-EAYEZXWT.js.map +1 -0
- package/dist/chunk-GILUVQQJ.js +6 -0
- package/dist/chunk-GILUVQQJ.js.map +1 -0
- package/dist/{chunk-KIYNOOPJ.js → chunk-GTDKDD7Y.js} +12 -6
- package/dist/chunk-GTDKDD7Y.js.map +1 -0
- package/dist/{chunk-TLVX5PXD.cjs → chunk-IUCNJAHW.cjs} +13 -7
- package/dist/chunk-IUCNJAHW.cjs.map +1 -0
- package/dist/{chunk-ZFIXQRBZ.cjs → chunk-KUBZVWME.cjs} +2 -80
- package/dist/chunk-KUBZVWME.cjs.map +1 -0
- package/dist/{chunk-JKCR6WRZ.cjs → chunk-NMWKXAYA.cjs} +2 -2
- package/dist/{chunk-JKCR6WRZ.cjs.map → chunk-NMWKXAYA.cjs.map} +1 -1
- package/dist/{chunk-LK2CZK5U.cjs → chunk-PWWM7Q3T.cjs} +7 -7
- package/dist/{chunk-LK2CZK5U.cjs.map → chunk-PWWM7Q3T.cjs.map} +1 -1
- package/dist/{chunk-N7TOWXDJ.js → chunk-QDUTMOF4.js} +3 -3
- package/dist/{chunk-N7TOWXDJ.js.map → chunk-QDUTMOF4.js.map} +1 -1
- package/dist/{chunk-MENBHEAY.cjs → chunk-WRM52ZBN.cjs} +19 -161
- package/dist/chunk-WRM52ZBN.cjs.map +1 -0
- package/dist/chunk-XIWWDGT5.cjs +86 -0
- package/dist/chunk-XIWWDGT5.cjs.map +1 -0
- package/dist/{chunk-CEPVQQVO.js → chunk-XRLOMTBZ.js} +2 -2
- package/dist/{chunk-CEPVQQVO.js.map → chunk-XRLOMTBZ.js.map} +1 -1
- package/dist/{chunk-QBEZMR2F.js → chunk-XU54YJXQ.js} +54 -15
- package/dist/chunk-XU54YJXQ.js.map +1 -0
- package/dist/chunk-Z3SZXWRU.js +80 -0
- package/dist/chunk-Z3SZXWRU.js.map +1 -0
- package/dist/entries/assembly.cjs +26 -25
- package/dist/entries/assembly.d.cts +32 -4
- package/dist/entries/assembly.d.ts +32 -4
- package/dist/entries/assembly.js +5 -4
- package/dist/entries/doctrine.cjs +46 -46
- package/dist/entries/doctrine.d.cts +3 -3
- package/dist/entries/doctrine.d.ts +3 -3
- package/dist/entries/doctrine.js +1 -1
- package/dist/entries/picker-catalogs.cjs +42 -42
- package/dist/entries/picker-catalogs.js +3 -3
- package/dist/entries/presets.cjs +49 -26
- package/dist/entries/presets.d.cts +51 -1
- package/dist/entries/presets.d.ts +51 -1
- package/dist/entries/presets.js +4 -1
- package/dist/entries/prompt-builder.cjs +135 -98
- package/dist/entries/prompt-builder.d.cts +22 -11
- package/dist/entries/prompt-builder.d.ts +22 -11
- package/dist/entries/prompt-builder.js +4 -3
- package/dist/entries/prompt-fields.cjs +41 -40
- package/dist/entries/prompt-fields.js +2 -1
- package/dist/index.cjs +331 -273
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +11 -9
- package/dist/{subject-registry-BUswuEVD.d.cts → subject-registry-CQi_CZfJ.d.cts} +78 -9
- package/dist/{subject-registry-D7V8PEG-.d.ts → subject-registry-DFiGx49v.d.ts} +78 -9
- package/package.json +2 -2
- package/src/__tests__/assemble-image-input-style-references.test.ts +173 -0
- package/src/__tests__/catalog-id-guard.test.ts +30 -0
- package/src/__tests__/factory-preset-previews.test.ts +123 -0
- package/src/__tests__/factory-preset-references.test.ts +222 -0
- package/src/__tests__/user-direction-refs.test.ts +180 -0
- package/src/assemble-image-input.ts +114 -13
- package/src/catalog-id-guard.ts +18 -2
- package/src/color-names.ts +192 -0
- package/src/direction-registry.ts +66 -5
- package/src/entries/prompt-builder.ts +2 -0
- package/src/factory-presets/generate-image.ts +29 -0
- package/src/factory-presets/index.ts +2 -0
- package/src/factory-presets/preview-files.generated.ts +4 -0
- package/src/factory-presets/previews.ts +40 -0
- package/src/factory-presets/references.ts +80 -0
- package/src/factory-presets/shared-image.ts +4 -0
- package/src/factory-presets/types.ts +8 -0
- package/src/image-reference-doctrine.ts +3 -3
- package/src/image-token-pattern.ts +13 -0
- package/src/prompt-builder.ts +4 -5
- package/src/prompt-style-section.ts +3 -3
- package/src/user-direction-refs.ts +110 -0
- package/dist/chunk-4FDNVNJE.js.map +0 -1
- package/dist/chunk-7XKHDXCL.cjs.map +0 -1
- package/dist/chunk-CVPB2N3Z.cjs.map +0 -1
- package/dist/chunk-HRBBNODV.js.map +0 -1
- package/dist/chunk-KIYNOOPJ.js.map +0 -1
- package/dist/chunk-LVSH7K7R.cjs.map +0 -1
- package/dist/chunk-MENBHEAY.cjs.map +0 -1
- package/dist/chunk-NO6XHX4R.js.map +0 -1
- package/dist/chunk-QBEZMR2F.js.map +0 -1
- package/dist/chunk-QDEWBBUR.js.map +0 -1
- package/dist/chunk-TLVX5PXD.cjs.map +0 -1
- package/dist/chunk-UJKFHPZ7.js +0 -37
- package/dist/chunk-UJKFHPZ7.js.map +0 -1
- package/dist/chunk-W5SCZIOB.cjs +0 -43
- package/dist/chunk-W5SCZIOB.cjs.map +0 -1
- package/dist/chunk-ZFIXQRBZ.cjs.map +0 -1
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkWRM52ZBN_cjs = require('./chunk-WRM52ZBN.cjs');
|
|
4
|
+
var chunk2P26SZX5_cjs = require('./chunk-2P26SZX5.cjs');
|
|
4
5
|
|
|
5
6
|
// src/read-node-direction.ts
|
|
6
7
|
function readDirectionFields(value) {
|
|
7
8
|
if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
|
|
8
9
|
const src = value;
|
|
9
10
|
const out = {};
|
|
10
|
-
for (const spec of
|
|
11
|
+
for (const spec of chunk2P26SZX5_cjs.DIRECTION_FIELDS) {
|
|
11
12
|
const v = src[spec.key];
|
|
12
13
|
if (typeof v === "string") {
|
|
13
|
-
if (v.length > 0 && v.length <=
|
|
14
|
+
if (v.length > 0 && v.length <= chunk2P26SZX5_cjs.DIRECTION_ID_MAX_CHARS) out[spec.key] = v;
|
|
14
15
|
} else if (Array.isArray(v)) {
|
|
15
16
|
const kept = [];
|
|
16
17
|
for (const x of v) {
|
|
17
|
-
if (kept.length >=
|
|
18
|
-
if (typeof x === "string" && x.length > 0 && x.length <=
|
|
18
|
+
if (kept.length >= chunk2P26SZX5_cjs.DIRECTION_ARRAY_CEILING) break;
|
|
19
|
+
if (typeof x === "string" && x.length > 0 && x.length <= chunk2P26SZX5_cjs.DIRECTION_ID_MAX_CHARS) {
|
|
19
20
|
kept.push(x);
|
|
20
21
|
}
|
|
21
22
|
}
|
|
@@ -28,19 +29,19 @@ function readSubjectFields(value) {
|
|
|
28
29
|
if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
|
|
29
30
|
const src = value;
|
|
30
31
|
const out = {};
|
|
31
|
-
for (const key of
|
|
32
|
+
for (const key of chunkWRM52ZBN_cjs.getRegisteredSubjectKeys()) {
|
|
32
33
|
const v = src[key];
|
|
33
|
-
if (key ===
|
|
34
|
+
if (key === chunkWRM52ZBN_cjs.SUBJECT_CUSTOM_AGE_KEY) {
|
|
34
35
|
if (typeof v === "number" && Number.isFinite(v)) out[key] = v;
|
|
35
36
|
continue;
|
|
36
37
|
}
|
|
37
38
|
if (typeof v === "string") {
|
|
38
|
-
if (v.length > 0 && v.length <=
|
|
39
|
+
if (v.length > 0 && v.length <= chunkWRM52ZBN_cjs.SUBJECT_ID_MAX_CHARS) out[key] = v;
|
|
39
40
|
} else if (Array.isArray(v)) {
|
|
40
41
|
const kept = [];
|
|
41
42
|
for (const x of v) {
|
|
42
|
-
if (kept.length >=
|
|
43
|
-
if (typeof x === "string" && x.length > 0 && x.length <=
|
|
43
|
+
if (kept.length >= chunkWRM52ZBN_cjs.SUBJECT_ARRAY_CEILING) break;
|
|
44
|
+
if (typeof x === "string" && x.length > 0 && x.length <= chunkWRM52ZBN_cjs.SUBJECT_ID_MAX_CHARS) {
|
|
44
45
|
kept.push(x);
|
|
45
46
|
}
|
|
46
47
|
}
|
|
@@ -117,5 +118,5 @@ function readStructuredFields(value) {
|
|
|
117
118
|
exports.readDirectionFields = readDirectionFields;
|
|
118
119
|
exports.readStructuredFields = readStructuredFields;
|
|
119
120
|
exports.readSubjectFields = readSubjectFields;
|
|
120
|
-
//# sourceMappingURL=chunk-
|
|
121
|
-
//# sourceMappingURL=chunk-
|
|
121
|
+
//# sourceMappingURL=chunk-3U7X6JZN.cjs.map
|
|
122
|
+
//# sourceMappingURL=chunk-3U7X6JZN.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/read-node-direction.ts"],"names":["DIRECTION_FIELDS","DIRECTION_ID_MAX_CHARS","DIRECTION_ARRAY_CEILING","getRegisteredSubjectKeys","SUBJECT_CUSTOM_AGE_KEY","SUBJECT_ID_MAX_CHARS","SUBJECT_ARRAY_CEILING"],"mappings":"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","file":"chunk-3U7X6JZN.cjs","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"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/image-token-pattern.ts"],"names":[],"mappings":";;;AAYO,IAAM,mBAAA,GAAsB","file":"chunk-4GKTOVFM.cjs","sourcesContent":["/**\n * The `{image:N}` / `{image:N:label}` reference-token grammar — one pattern for\n * the image prompt assembly (`prompt-builder.ts`) and for the preset metadata\n * that reads which references a template names (`factory-presets/references.ts`).\n *\n * Group 1 = position (1-based), group 2 = optional label. The label allows\n * spaces (multi-word labels like \"clothes and shoes\") but never a newline or\n * `}`, so a match can't run away across lines or token boundaries.\n *\n * Global on purpose (callers use `.replace` / `.matchAll`, which never leave a\n * `lastIndex` behind); never call `.test` / `.exec` on it.\n */\nexport const IMAGE_TOKEN_PATTERN = /\\{image:(\\d+)(?::([^}\\n]+))?\\}/gi\n"]}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
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';
|
|
2
3
|
|
|
3
4
|
// src/read-node-direction.ts
|
|
4
5
|
function readDirectionFields(value) {
|
|
@@ -113,5 +114,5 @@ function readStructuredFields(value) {
|
|
|
113
114
|
}
|
|
114
115
|
|
|
115
116
|
export { readDirectionFields, readStructuredFields, readSubjectFields };
|
|
116
|
-
//# sourceMappingURL=chunk-
|
|
117
|
-
//# sourceMappingURL=chunk-
|
|
117
|
+
//# sourceMappingURL=chunk-6GVFJLDL.js.map
|
|
118
|
+
//# sourceMappingURL=chunk-6GVFJLDL.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/read-node-direction.ts"],"names":[],"mappings":"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","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,5 +1,7 @@
|
|
|
1
|
+
import { getPromptFields, NODE_PROMPT_CANDIDATE_FIELDS, promptAffixCoreField, nodeSupportsPromptAffixes } from './chunk-7XMTVYS5.js';
|
|
2
|
+
import { IMAGE_TOKEN_PATTERN } from './chunk-GILUVQQJ.js';
|
|
1
3
|
import { realismEmptyHands, NEUTRAL_PERSON, realismViewpoint, REFERENCE_RULES, SCENE_FRAME_RULE, CINEMATIC_LOOK_TAIL, FILM_STILL_PREFIX, REALISM_PASS_INSTRUCTION, REALISM_FINISH, REALISM_SKIN } from './chunk-T64D26P4.js';
|
|
2
|
-
import { T2I_TO_I2I_VARIANT } from '@nodaro/shared/models';
|
|
4
|
+
import { MODELS_WITH_REFERENCE_IMAGE_SUPPORT, imageReferenceLimit, T2I_TO_I2I_VARIANT } from '@nodaro/shared/models';
|
|
3
5
|
|
|
4
6
|
// src/brand-tokens.ts
|
|
5
7
|
var BRAND_PRESET_IDS = [
|
|
@@ -135,7 +137,9 @@ function stylizedSubjectFor(nodeType) {
|
|
|
135
137
|
name: p.name,
|
|
136
138
|
description: p.description,
|
|
137
139
|
group: "Stylized Subject",
|
|
138
|
-
data: { provider: editProviderFor(nodeType), ...p.data }
|
|
140
|
+
data: { provider: editProviderFor(nodeType), ...p.data },
|
|
141
|
+
// Restyles the person in the connected photo ("the reference image").
|
|
142
|
+
minReferences: 1
|
|
139
143
|
}));
|
|
140
144
|
}
|
|
141
145
|
var IMAGE_EDITS = [
|
|
@@ -259,7 +263,9 @@ function editsFor(nodeType) {
|
|
|
259
263
|
name: p.name,
|
|
260
264
|
description: p.description,
|
|
261
265
|
group: "Edits",
|
|
262
|
-
data: { provider: editProviderFor(nodeType), ...p.data }
|
|
266
|
+
data: { provider: editProviderFor(nodeType), ...p.data },
|
|
267
|
+
// Every edit operates on the connected photo.
|
|
268
|
+
minReferences: 1
|
|
263
269
|
}));
|
|
264
270
|
}
|
|
265
271
|
|
|
@@ -268,12 +274,17 @@ var sentences = (...parts) => parts.join(" ");
|
|
|
268
274
|
var REALISM_MODEL = { provider: "gpt-image-2", resolution: "2K" };
|
|
269
275
|
var SKIN_STUDY_MODEL = { provider: "seedream-5-pro", quality: "high" };
|
|
270
276
|
var GENERATE_IMAGE_PRESETS = [
|
|
277
|
+
// `minReferences` marks a preset that works from connected photos its prompt
|
|
278
|
+
// describes in words ("the attached photo"); `{image:N}` tokens count on their
|
|
279
|
+
// own, so a tokenized preset declares nothing. The groups stay all-or-nothing
|
|
280
|
+
// (factory-preset-references.test.ts), so a new preset copies the line along.
|
|
271
281
|
// ── Reference Sheet ──────────────────────────────────────────────────────
|
|
272
282
|
{
|
|
273
283
|
id: "generate-image/character-board",
|
|
274
284
|
name: "Character Board",
|
|
275
285
|
description: "Connect a sharp, well-lit photo \u2192 dense character sheet; reuse it as a reference for consistent shots.",
|
|
276
286
|
group: "Reference Sheet",
|
|
287
|
+
minReferences: 1,
|
|
277
288
|
data: {
|
|
278
289
|
provider: "gpt-image-2",
|
|
279
290
|
aspectRatio: "16:9",
|
|
@@ -288,6 +299,7 @@ var GENERATE_IMAGE_PRESETS = [
|
|
|
288
299
|
name: "Pose Board",
|
|
289
300
|
description: "Connect a sharp photo \u2192 animation-ready pose & expression sheet; reuse it as a reference for consistent action.",
|
|
290
301
|
group: "Reference Sheet",
|
|
302
|
+
minReferences: 1,
|
|
291
303
|
data: {
|
|
292
304
|
provider: "gpt-image-2",
|
|
293
305
|
aspectRatio: "16:9",
|
|
@@ -302,6 +314,7 @@ var GENERATE_IMAGE_PRESETS = [
|
|
|
302
314
|
name: "Location Board",
|
|
303
315
|
description: "Connect a photo \u2192 dense location sheet; reuse it as a reference for consistent scenes.",
|
|
304
316
|
group: "Reference Sheet",
|
|
317
|
+
minReferences: 1,
|
|
305
318
|
data: {
|
|
306
319
|
provider: "gpt-image-2",
|
|
307
320
|
aspectRatio: "16:9",
|
|
@@ -316,6 +329,7 @@ var GENERATE_IMAGE_PRESETS = [
|
|
|
316
329
|
name: "Product Board",
|
|
317
330
|
description: "Connect a photo \u2192 dense product sheet; reuse it as a reference for consistent shots.",
|
|
318
331
|
group: "Reference Sheet",
|
|
332
|
+
minReferences: 1,
|
|
319
333
|
data: {
|
|
320
334
|
provider: "gpt-image-2",
|
|
321
335
|
aspectRatio: "16:9",
|
|
@@ -330,6 +344,7 @@ var GENERATE_IMAGE_PRESETS = [
|
|
|
330
344
|
name: "Outfit Board",
|
|
331
345
|
description: "Connect a photo \u2192 dense wardrobe sheet; reuse it as a reference for consistent looks.",
|
|
332
346
|
group: "Reference Sheet",
|
|
347
|
+
minReferences: 1,
|
|
333
348
|
data: {
|
|
334
349
|
provider: "gpt-image-2",
|
|
335
350
|
aspectRatio: "16:9",
|
|
@@ -344,6 +359,7 @@ var GENERATE_IMAGE_PRESETS = [
|
|
|
344
359
|
name: "Scene Board",
|
|
345
360
|
description: "Connect a photo \u2192 set-dressing & props study; reuse it as a reference for consistent sets.",
|
|
346
361
|
group: "Reference Sheet",
|
|
362
|
+
minReferences: 1,
|
|
347
363
|
data: {
|
|
348
364
|
provider: "gpt-image-2",
|
|
349
365
|
aspectRatio: "16:9",
|
|
@@ -358,6 +374,7 @@ var GENERATE_IMAGE_PRESETS = [
|
|
|
358
374
|
name: "Creature Board",
|
|
359
375
|
description: "Connect a sharp photo \u2192 dense creature sheet; reuse it as a reference for consistent shots.",
|
|
360
376
|
group: "Reference Sheet",
|
|
377
|
+
minReferences: 1,
|
|
361
378
|
data: {
|
|
362
379
|
provider: "gpt-image-2",
|
|
363
380
|
aspectRatio: "16:9",
|
|
@@ -372,6 +389,7 @@ var GENERATE_IMAGE_PRESETS = [
|
|
|
372
389
|
name: "Vehicle Board",
|
|
373
390
|
description: "Connect a photo \u2192 dense vehicle sheet; reuse it as a reference for consistent shots.",
|
|
374
391
|
group: "Reference Sheet",
|
|
392
|
+
minReferences: 1,
|
|
375
393
|
data: {
|
|
376
394
|
provider: "gpt-image-2",
|
|
377
395
|
aspectRatio: "16:9",
|
|
@@ -386,6 +404,7 @@ var GENERATE_IMAGE_PRESETS = [
|
|
|
386
404
|
name: "Food Board",
|
|
387
405
|
description: "Connect a photo \u2192 dense dish sheet; reuse it as a reference for consistent food shots.",
|
|
388
406
|
group: "Reference Sheet",
|
|
407
|
+
minReferences: 1,
|
|
389
408
|
data: {
|
|
390
409
|
provider: "gpt-image-2",
|
|
391
410
|
aspectRatio: "16:9",
|
|
@@ -400,6 +419,7 @@ var GENERATE_IMAGE_PRESETS = [
|
|
|
400
419
|
name: "Mascot Board",
|
|
401
420
|
description: "Connect a mascot image \u2192 brand-character sheet with brand applications; reuse it for a consistent mascot.",
|
|
402
421
|
group: "Reference Sheet",
|
|
422
|
+
minReferences: 1,
|
|
403
423
|
data: {
|
|
404
424
|
provider: "gpt-image-2",
|
|
405
425
|
aspectRatio: "16:9",
|
|
@@ -414,6 +434,7 @@ var GENERATE_IMAGE_PRESETS = [
|
|
|
414
434
|
name: "Pet Board",
|
|
415
435
|
description: "Connect a sharp photo \u2192 dense pet sheet; reuse it as a reference for consistent shots.",
|
|
416
436
|
group: "Reference Sheet",
|
|
437
|
+
minReferences: 1,
|
|
417
438
|
data: {
|
|
418
439
|
provider: "gpt-image-2",
|
|
419
440
|
aspectRatio: "16:9",
|
|
@@ -428,6 +449,7 @@ var GENERATE_IMAGE_PRESETS = [
|
|
|
428
449
|
name: "Skin Detail Sheet",
|
|
429
450
|
description: "Connect a sharp face photo \u2192 a six-panel skin reference.",
|
|
430
451
|
group: "Reference Sheet",
|
|
452
|
+
minReferences: 1,
|
|
431
453
|
data: {
|
|
432
454
|
...SKIN_STUDY_MODEL,
|
|
433
455
|
aspectRatio: "3:2",
|
|
@@ -450,6 +472,7 @@ var GENERATE_IMAGE_PRESETS = [
|
|
|
450
472
|
name: "Character Reference Grid",
|
|
451
473
|
description: "Connect a photo \u2192 clean 4-angle identity grid (no decorations) \u2014 the strongest consistency anchor.",
|
|
452
474
|
group: "Cast & Consistency",
|
|
475
|
+
minReferences: 1,
|
|
453
476
|
data: {
|
|
454
477
|
provider: "gpt-image-2",
|
|
455
478
|
aspectRatio: "3:4",
|
|
@@ -464,6 +487,8 @@ var GENERATE_IMAGE_PRESETS = [
|
|
|
464
487
|
name: "Cast Mega Grid",
|
|
465
488
|
description: "Connect 2\u20134 character refs \u2192 one labeled cast sheet; then reference cast members by name in scenes.",
|
|
466
489
|
group: "Cast & Consistency",
|
|
490
|
+
// A cast sheet is two characters or more ("Connect 2–4 character refs").
|
|
491
|
+
minReferences: 2,
|
|
467
492
|
data: {
|
|
468
493
|
provider: "gpt-image-2",
|
|
469
494
|
aspectRatio: "3:4",
|
|
@@ -477,6 +502,7 @@ var GENERATE_IMAGE_PRESETS = [
|
|
|
477
502
|
name: "Cast Scene (by name)",
|
|
478
503
|
description: "Connect a cast grid \u2192 stage a scene naming the characters; never re-describe their looks.",
|
|
479
504
|
group: "Cast & Consistency",
|
|
505
|
+
minReferences: 1,
|
|
480
506
|
data: {
|
|
481
507
|
provider: "gpt-image-2",
|
|
482
508
|
aspectRatio: "16:9",
|
|
@@ -491,6 +517,7 @@ var GENERATE_IMAGE_PRESETS = [
|
|
|
491
517
|
name: "Label Elements",
|
|
492
518
|
description: "Step 1 \xB7 connect a photo \u2192 the same image with a numbered label on each changeable element.",
|
|
493
519
|
group: "Edit by Name",
|
|
520
|
+
minReferences: 1,
|
|
494
521
|
data: {
|
|
495
522
|
provider: "gpt-image-2",
|
|
496
523
|
quality: "high",
|
|
@@ -503,6 +530,7 @@ var GENERATE_IMAGE_PRESETS = [
|
|
|
503
530
|
name: "Apply Named Edit",
|
|
504
531
|
description: 'Step 2 \xB7 connect the labeled sheet \u2192 type your change in the prompt (e.g. change "drink 1" to blue); the labels are removed from the result.',
|
|
505
532
|
group: "Edit by Name",
|
|
533
|
+
minReferences: 1,
|
|
506
534
|
data: {
|
|
507
535
|
provider: "gpt-image-2",
|
|
508
536
|
quality: "high",
|
|
@@ -1711,6 +1739,7 @@ var GENERATE_IMAGE_PRESETS = [
|
|
|
1711
1739
|
name: "Five Ages (Timeless Soul)",
|
|
1712
1740
|
description: "One person at 5 ages, studio line-up. Needs a reference photo.",
|
|
1713
1741
|
group: "Portrait Transformations",
|
|
1742
|
+
minReferences: 1,
|
|
1714
1743
|
data: {
|
|
1715
1744
|
provider: "gpt-image-2",
|
|
1716
1745
|
aspectRatio: "3:4",
|
|
@@ -1723,6 +1752,7 @@ var GENERATE_IMAGE_PRESETS = [
|
|
|
1723
1752
|
name: "Three-Age Triptych",
|
|
1724
1753
|
description: "Same person at 3 ages (~10 / 40 / 75). Needs a reference photo.",
|
|
1725
1754
|
group: "Portrait Transformations",
|
|
1755
|
+
minReferences: 1,
|
|
1726
1756
|
data: {
|
|
1727
1757
|
provider: "gpt-image-2",
|
|
1728
1758
|
aspectRatio: "3:4",
|
|
@@ -1735,6 +1765,7 @@ var GENERATE_IMAGE_PRESETS = [
|
|
|
1735
1765
|
name: "Five Ages \u2014 B&W",
|
|
1736
1766
|
description: "Monochrome age line-up. Needs a reference photo.",
|
|
1737
1767
|
group: "Portrait Transformations",
|
|
1768
|
+
minReferences: 1,
|
|
1738
1769
|
data: {
|
|
1739
1770
|
provider: "gpt-image-2",
|
|
1740
1771
|
aspectRatio: "3:4",
|
|
@@ -1747,6 +1778,7 @@ var GENERATE_IMAGE_PRESETS = [
|
|
|
1747
1778
|
name: "Decade Timeline",
|
|
1748
1779
|
description: "Same person across the '80s\u20132020s. Needs a reference photo.",
|
|
1749
1780
|
group: "Portrait Transformations",
|
|
1781
|
+
minReferences: 1,
|
|
1750
1782
|
data: {
|
|
1751
1783
|
provider: "gpt-image-2",
|
|
1752
1784
|
aspectRatio: "3:4",
|
|
@@ -1759,6 +1791,7 @@ var GENERATE_IMAGE_PRESETS = [
|
|
|
1759
1791
|
name: "Four Seasons",
|
|
1760
1792
|
description: "Same person in spring / summer / autumn / winter. Needs a reference photo.",
|
|
1761
1793
|
group: "Portrait Transformations",
|
|
1794
|
+
minReferences: 1,
|
|
1762
1795
|
data: {
|
|
1763
1796
|
provider: "gpt-image-2",
|
|
1764
1797
|
aspectRatio: "3:4",
|
|
@@ -1771,6 +1804,7 @@ var GENERATE_IMAGE_PRESETS = [
|
|
|
1771
1804
|
name: "Times of Day",
|
|
1772
1805
|
description: "Same person at dawn / midday / golden hour / night. Needs a reference photo.",
|
|
1773
1806
|
group: "Portrait Transformations",
|
|
1807
|
+
minReferences: 1,
|
|
1774
1808
|
data: {
|
|
1775
1809
|
provider: "gpt-image-2",
|
|
1776
1810
|
aspectRatio: "3:4",
|
|
@@ -1783,6 +1817,7 @@ var GENERATE_IMAGE_PRESETS = [
|
|
|
1783
1817
|
name: "Sports Jersey Portrait",
|
|
1784
1818
|
description: "You in an oversized team jersey, studio editorial. Needs a reference photo.",
|
|
1785
1819
|
group: "Portrait Transformations",
|
|
1820
|
+
minReferences: 1,
|
|
1786
1821
|
data: {
|
|
1787
1822
|
provider: "nano-banana-2-1",
|
|
1788
1823
|
aspectRatio: "4:5",
|
|
@@ -5114,6 +5149,64 @@ function groupFactoryPresets(presets) {
|
|
|
5114
5149
|
}
|
|
5115
5150
|
return buckets;
|
|
5116
5151
|
}
|
|
5152
|
+
var MAX_PRESET_REFERENCES = Math.max(
|
|
5153
|
+
1,
|
|
5154
|
+
...[...MODELS_WITH_REFERENCE_IMAGE_SUPPORT].map((provider) => imageReferenceLimit(provider))
|
|
5155
|
+
);
|
|
5156
|
+
function promptFieldsOf(nodeType) {
|
|
5157
|
+
const spec = getPromptFields(nodeType);
|
|
5158
|
+
const candidates = NODE_PROMPT_CANDIDATE_FIELDS[nodeType] ?? [];
|
|
5159
|
+
if (!spec && candidates.length === 0) return [];
|
|
5160
|
+
const fields = new Set(candidates);
|
|
5161
|
+
if (spec) {
|
|
5162
|
+
fields.add(spec.prompt);
|
|
5163
|
+
if (spec.negative) fields.add(spec.negative);
|
|
5164
|
+
}
|
|
5165
|
+
const core = promptAffixCoreField(nodeType);
|
|
5166
|
+
if (core) fields.add(core);
|
|
5167
|
+
if (nodeSupportsPromptAffixes(nodeType)) {
|
|
5168
|
+
fields.add("promptPrefix");
|
|
5169
|
+
fields.add("promptSuffix");
|
|
5170
|
+
}
|
|
5171
|
+
return [...fields];
|
|
5172
|
+
}
|
|
5173
|
+
function highestImageToken(text) {
|
|
5174
|
+
let highest = 0;
|
|
5175
|
+
for (const match of text.matchAll(IMAGE_TOKEN_PATTERN)) {
|
|
5176
|
+
const n = Number.parseInt(match[1] ?? "", 10);
|
|
5177
|
+
if (Number.isInteger(n) && n > highest) highest = n;
|
|
5178
|
+
}
|
|
5179
|
+
return highest;
|
|
5180
|
+
}
|
|
5181
|
+
function presetMinReferences(nodeType, data, declared) {
|
|
5182
|
+
let count = typeof declared === "number" && Number.isInteger(declared) && declared > 0 ? declared : 0;
|
|
5183
|
+
for (const field of promptFieldsOf(nodeType)) {
|
|
5184
|
+
const value = data[field];
|
|
5185
|
+
if (typeof value === "string") count = Math.max(count, highestImageToken(value));
|
|
5186
|
+
}
|
|
5187
|
+
return Math.min(count, MAX_PRESET_REFERENCES);
|
|
5188
|
+
}
|
|
5189
|
+
|
|
5190
|
+
// src/factory-presets/preview-files.generated.ts
|
|
5191
|
+
var FACTORY_PRESET_PREVIEW_FILES = {};
|
|
5192
|
+
|
|
5193
|
+
// src/factory-presets/previews.ts
|
|
5194
|
+
var PRESET_PREVIEW_PATH = "/preset-previews/";
|
|
5195
|
+
function originOf(baseUrl) {
|
|
5196
|
+
try {
|
|
5197
|
+
const url = new URL(baseUrl);
|
|
5198
|
+
if (url.protocol !== "https:" && url.protocol !== "http:") return void 0;
|
|
5199
|
+
return url.origin + url.pathname.replace(/\/+$/, "");
|
|
5200
|
+
} catch {
|
|
5201
|
+
return void 0;
|
|
5202
|
+
}
|
|
5203
|
+
}
|
|
5204
|
+
function factoryPresetPreviewUrl(presetId, baseUrl, files = FACTORY_PRESET_PREVIEW_FILES) {
|
|
5205
|
+
const file = Object.prototype.hasOwnProperty.call(files, presetId) ? files[presetId] : void 0;
|
|
5206
|
+
if (!file) return null;
|
|
5207
|
+
const origin = originOf(baseUrl);
|
|
5208
|
+
return origin ? `${origin}${PRESET_PREVIEW_PATH}${file}` : null;
|
|
5209
|
+
}
|
|
5117
5210
|
|
|
5118
5211
|
// src/factory-presets/index.ts
|
|
5119
5212
|
function forModifyImage(p) {
|
|
@@ -5523,6 +5616,6 @@ function getFactorySnippets(target, media) {
|
|
|
5523
5616
|
);
|
|
5524
5617
|
}
|
|
5525
5618
|
|
|
5526
|
-
export { BODY_CAPTIONS_PRESET_ID, BRAND_PRESETS, BRAND_PRESET_IDS, BRAND_PRESET_META, CAPTION_LEVERS_BY_LANGUAGE, CAPTION_SEGMENT_LEVER_KEYS, FACTORY_PRESETS, FACTORY_SNIPPETS, HOOK_PLATE_PRESET_ID, OBJECT_ANGLE_PRESETS, OBJECT_ANGLE_PROMPTS, OBJECT_ASSET_PRESETS, OBJECT_ASSET_PROMPTS, OBJECT_MATERIAL_PRESETS, OBJECT_MATERIAL_PROMPTS, OBJECT_VARIATION_PRESETS, OBJECT_VARIATION_PROMPTS, SNIPPET_MEDIA_VALUES, STYLE_PRESETS, getFactoryPresets, getFactorySnippets, getStylePreset, groupFactoryPresets, hookPlateCaptionSegments, resolveBrandInput };
|
|
5527
|
-
//# sourceMappingURL=chunk-
|
|
5528
|
-
//# sourceMappingURL=chunk-
|
|
5619
|
+
export { BODY_CAPTIONS_PRESET_ID, BRAND_PRESETS, BRAND_PRESET_IDS, BRAND_PRESET_META, CAPTION_LEVERS_BY_LANGUAGE, CAPTION_SEGMENT_LEVER_KEYS, FACTORY_PRESETS, FACTORY_PRESET_PREVIEW_FILES, FACTORY_SNIPPETS, HOOK_PLATE_PRESET_ID, MAX_PRESET_REFERENCES, OBJECT_ANGLE_PRESETS, OBJECT_ANGLE_PROMPTS, OBJECT_ASSET_PRESETS, OBJECT_ASSET_PROMPTS, OBJECT_MATERIAL_PRESETS, OBJECT_MATERIAL_PROMPTS, OBJECT_VARIATION_PRESETS, OBJECT_VARIATION_PROMPTS, PRESET_PREVIEW_PATH, SNIPPET_MEDIA_VALUES, STYLE_PRESETS, factoryPresetPreviewUrl, getFactoryPresets, getFactorySnippets, getStylePreset, groupFactoryPresets, hookPlateCaptionSegments, presetMinReferences, resolveBrandInput };
|
|
5620
|
+
//# sourceMappingURL=chunk-6MPZHFIS.js.map
|
|
5621
|
+
//# sourceMappingURL=chunk-6MPZHFIS.js.map
|