@nodaro/prompts 1.39.0 → 1.40.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-XIWWDGT5.cjs → chunk-2EW5B7ZV.cjs} +7 -7
- package/dist/{chunk-XIWWDGT5.cjs.map → chunk-2EW5B7ZV.cjs.map} +1 -1
- package/dist/{chunk-22KZOAGL.cjs → chunk-C3NHNECH.cjs} +86 -48
- package/dist/chunk-C3NHNECH.cjs.map +1 -0
- package/dist/{chunk-XRLOMTBZ.js → chunk-C46256GZ.js} +43 -5
- package/dist/chunk-C46256GZ.js.map +1 -0
- package/dist/{chunk-NMWKXAYA.cjs → chunk-DQFQJECU.cjs} +43 -5
- package/dist/chunk-DQFQJECU.cjs.map +1 -0
- package/dist/{chunk-XU54YJXQ.js → chunk-HQTHDTHN.js} +85 -49
- package/dist/chunk-HQTHDTHN.js.map +1 -0
- package/dist/{chunk-KUBZVWME.cjs → chunk-LXPKTI2K.cjs} +12 -5
- package/dist/chunk-LXPKTI2K.cjs.map +1 -0
- package/dist/{chunk-3INXNDV7.cjs → chunk-LZ53F5BN.cjs} +8 -8
- package/dist/chunk-LZ53F5BN.cjs.map +1 -0
- package/dist/{chunk-7XMTVYS5.js → chunk-N6VMPG5S.js} +12 -6
- package/dist/chunk-N6VMPG5S.js.map +1 -0
- package/dist/{chunk-6MPZHFIS.js → chunk-RB2F5JQF.js} +5 -5
- package/dist/chunk-RB2F5JQF.js.map +1 -0
- package/dist/{chunk-Z3SZXWRU.js → chunk-YS6HOWMW.js} +3 -3
- package/dist/{chunk-Z3SZXWRU.js.map → chunk-YS6HOWMW.js.map} +1 -1
- package/dist/entries/assembly.cjs +30 -22
- package/dist/entries/assembly.d.cts +90 -34
- package/dist/entries/assembly.d.ts +90 -34
- package/dist/entries/assembly.js +1 -1
- package/dist/entries/doctrine.cjs +46 -46
- package/dist/entries/doctrine.js +1 -1
- package/dist/entries/presets.cjs +32 -32
- package/dist/entries/presets.d.cts +2 -0
- package/dist/entries/presets.d.ts +2 -0
- package/dist/entries/presets.js +2 -2
- package/dist/entries/prompt-fields.cjs +26 -26
- package/dist/entries/prompt-fields.d.cts +2 -1
- package/dist/entries/prompt-fields.d.ts +2 -1
- package/dist/entries/prompt-fields.js +2 -2
- package/dist/index.cjs +133 -125
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +5 -5
- package/package.json +2 -2
- package/src/__tests__/factory-presets-prototype-keys.test.ts +43 -0
- package/src/__tests__/frame-reference-slots.test.ts +43 -0
- package/src/__tests__/gemini-omni-inputs.test.ts +12 -10
- package/src/__tests__/provider-prompt-doctrine.test.ts +14 -0
- package/src/__tests__/veo-i2v-inputs.test.ts +16 -11
- package/src/entries/assembly.ts +1 -0
- package/src/factory-presets/index.ts +4 -1
- package/src/factory-presets/references.ts +2 -1
- package/src/frame-reference-slots.ts +92 -0
- package/src/gemini-omni-inputs.ts +23 -22
- package/src/node-prompt-fields.ts +5 -3
- package/src/own-entry.ts +11 -0
- package/src/prompt-wizard-categories.ts +2 -0
- package/src/provider-prompt-doctrine.ts +45 -3
- package/src/ref-binding.ts +28 -3
- package/src/resolve-prompt.ts +2 -1
- package/src/seedance-2-inputs.ts +15 -40
- package/src/veo-i2v-inputs.ts +24 -17
- package/src/video-reference-resolver.ts +1 -1
- package/dist/chunk-22KZOAGL.cjs.map +0 -1
- package/dist/chunk-3INXNDV7.cjs.map +0 -1
- package/dist/chunk-6MPZHFIS.js.map +0 -1
- package/dist/chunk-7XMTVYS5.js.map +0 -1
- package/dist/chunk-KUBZVWME.cjs.map +0 -1
- package/dist/chunk-NMWKXAYA.cjs.map +0 -1
- package/dist/chunk-XRLOMTBZ.js.map +0 -1
- package/dist/chunk-XU54YJXQ.js.map +0 -1
|
@@ -3,6 +3,12 @@ import { resolveNodeRefs } from '@nodaro/shared/workflow';
|
|
|
3
3
|
import { readPromptAffixes } from '@nodaro/shared/nodes';
|
|
4
4
|
import { SOCIAL_POST_NODE_TYPES } from '@nodaro/shared/social';
|
|
5
5
|
|
|
6
|
+
// src/own-entry.ts
|
|
7
|
+
function ownEntry(record, key) {
|
|
8
|
+
return key !== void 0 && Object.prototype.hasOwnProperty.call(record, key) ? record[key] : void 0;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// src/resolve-prompt.ts
|
|
6
12
|
var present = (s) => typeof s === "string" && s.trim().length > 0;
|
|
7
13
|
var rr = (s, m) => m.size > 0 ? resolveNodeRefs(s, m) : s;
|
|
8
14
|
var GLUE_PUNCTUATION = /* @__PURE__ */ new Set([",", ".", ";", ":", "!", "?", ")"]);
|
|
@@ -74,7 +80,7 @@ function computeNodePrompt(nodeType, data, { override, wired, refMap, appendWire
|
|
|
74
80
|
if (nodeType === "text-to-speech") {
|
|
75
81
|
typed = data.textSource === "direct" || !present(wired) ? [data.directText] : [];
|
|
76
82
|
} else {
|
|
77
|
-
const fields = NODE_PROMPT_CANDIDATE_FIELDS
|
|
83
|
+
const fields = ownEntry(NODE_PROMPT_CANDIDATE_FIELDS, nodeType) ?? ["prompt"];
|
|
78
84
|
typed = fields.map((f) => data[f]);
|
|
79
85
|
}
|
|
80
86
|
return resolvePrompt({ override, typed, wired, refMap, appendWired, affixes: readPromptAffixes(data) });
|
|
@@ -164,7 +170,7 @@ var NODE_PROMPT_FIELDS = {
|
|
|
164
170
|
"edit-plan": { prompt: "instructions", promptLabel: "Editing instructions", media: "video", inline: false }
|
|
165
171
|
};
|
|
166
172
|
function getPromptFields(nodeType) {
|
|
167
|
-
return nodeType ? NODE_PROMPT_FIELDS
|
|
173
|
+
return nodeType ? ownEntry(NODE_PROMPT_FIELDS, nodeType) : void 0;
|
|
168
174
|
}
|
|
169
175
|
function nodeHasPromptField(nodeType) {
|
|
170
176
|
return getPromptFields(nodeType) !== void 0;
|
|
@@ -188,12 +194,12 @@ function promptFieldCarriesAffixes(nodeType, promptField) {
|
|
|
188
194
|
const core = promptAffixCoreField(nodeType);
|
|
189
195
|
if (core === void 0) return false;
|
|
190
196
|
if (promptField === void 0) return getPromptFields(nodeType).prompt === core;
|
|
191
|
-
return promptField === core || (NODE_PROMPT_CANDIDATE_FIELDS
|
|
197
|
+
return promptField === core || (ownEntry(NODE_PROMPT_CANDIDATE_FIELDS, nodeType) ?? []).includes(promptField);
|
|
192
198
|
}
|
|
193
199
|
var PROMPT_AFFIX_NODE_TYPES = new Set(
|
|
194
200
|
Object.entries(NODE_PROMPT_FIELDS).filter(([, s]) => s.affixes !== false).map(([t]) => t)
|
|
195
201
|
);
|
|
196
202
|
|
|
197
|
-
export { NODE_PROMPT_CANDIDATE_FIELDS, NODE_PROMPT_FIELDS, PROMPT_AFFIX_CORE_FIELD_OVERRIDES, PROMPT_AFFIX_NODE_TYPES, applyPromptAffixes, composeNegative, computeLlmChatFields, computeNodePrompt, computeScriptTopic, getPromptFields, getSnippetMedia, joinPromptParts, nodeHasInlinePrompt, nodeHasPromptField, nodeSupportsPromptAffixes, promptAffixCoreField, promptFieldCarriesAffixes, promptPartSeparator, resolvePrompt };
|
|
198
|
-
//# sourceMappingURL=chunk-
|
|
199
|
-
//# sourceMappingURL=chunk-
|
|
203
|
+
export { NODE_PROMPT_CANDIDATE_FIELDS, NODE_PROMPT_FIELDS, PROMPT_AFFIX_CORE_FIELD_OVERRIDES, PROMPT_AFFIX_NODE_TYPES, applyPromptAffixes, composeNegative, computeLlmChatFields, computeNodePrompt, computeScriptTopic, getPromptFields, getSnippetMedia, joinPromptParts, nodeHasInlinePrompt, nodeHasPromptField, nodeSupportsPromptAffixes, ownEntry, promptAffixCoreField, promptFieldCarriesAffixes, promptPartSeparator, resolvePrompt };
|
|
204
|
+
//# sourceMappingURL=chunk-N6VMPG5S.js.map
|
|
205
|
+
//# sourceMappingURL=chunk-N6VMPG5S.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/own-entry.ts","../src/resolve-prompt.ts","../src/node-prompt-fields.ts"],"names":[],"mappings":"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","file":"chunk-N6VMPG5S.js","sourcesContent":["/**\n * A registry keyed by node type is a plain object, and the key is\n * caller-supplied (`?nodeType=` on a public route, a preset row's `node_type`,\n * workflow JSON). A plain `record[key] ?? fallback` reads an Object.prototype\n * member for `\"constructor\"`, `\"toString\"` or `\"__proto__\"` — a function or\n * the prototype itself, which the caller then maps or iterates and throws on.\n * This reads an OWN entry only, so such a name is \"no such type\".\n */\nexport function ownEntry<T>(record: Readonly<Record<string, T>>, key: string | undefined): T | undefined {\n return key !== undefined && Object.prototype.hasOwnProperty.call(record, key) ? record[key] : undefined\n}\n","import { resolveNodeRefs } from \"@nodaro/shared/workflow\"\nimport { readPromptAffixes, type PromptAffixes } from \"@nodaro/shared/nodes\"\nimport { SOCIAL_POST_NODE_TYPES } from \"@nodaro/shared/social\"\nimport { joinSentences } from \"./hint-join.js\"\nimport { ownEntry } from \"./own-entry.js\"\n\nexport interface ResolvePromptArgs {\n override?: string\n typed?: ReadonlyArray<string | undefined>\n wired?: string\n refMap: ReadonlyMap<string, string>\n /** Opt-in (generate-image / generate-video only): APPEND the wired\n * (connected-prompt) value to the TYPED base instead of treating wired as a\n * fallback, so a connected prompt auto-injects alongside the typed prompt. An\n * `override` (list fan-out item) still fully replaces — no wired append.\n * Off/undefined = exact legacy precedence (override > typed > wired) for every\n * other node type. */\n appendWired?: boolean\n /** Pre/post text wrapped around WHICHEVER core precedence produced (override,\n * typed, wired, or the appendWired combination). Applied last. */\n affixes?: PromptAffixes\n}\nconst present = (s?: string): s is string => typeof s === \"string\" && s.trim().length > 0\nconst rr = (s: string, m: ReadonlyMap<string, string>) => (m.size > 0 ? resolveNodeRefs(s, m) : s)\n\n// ---------------------------------------------------------------------------\n// Prompt affixes (pre/post text) — see docs/prompt-pre-post-text.md (join rule, empty-core, no-op guarantee)\n// ---------------------------------------------------------------------------\n\nconst GLUE_PUNCTUATION = new Set([\",\", \".\", \";\", \":\", \"!\", \"?\", \")\"])\n\n/** The ONE join rule between two non-blank prompt parts: a single space unless\n * the boundary already has whitespace on either side or the right part opens\n * with sentence punctuation. Shared by `joinPromptParts` and the editor's\n * Final-view segment builder so preview and run agree byte-for-byte. */\nexport function promptPartSeparator(left: string, right: string): \"\" | \" \" {\n if (left.length === 0 || right.length === 0) return \"\"\n if (/\\s$/.test(left) || /^\\s/.test(right)) return \"\"\n if (GLUE_PUNCTUATION.has(right[0])) return \"\"\n return \" \"\n}\n\n/** Join prompt parts with `promptPartSeparator`; blank parts are dropped,\n * non-blank parts are used verbatim (no trimming). */\nexport function joinPromptParts(parts: ReadonlyArray<string | undefined>): string {\n let out = \"\"\n for (const part of parts) {\n if (!present(part)) continue\n out = out.length === 0 ? part : out + promptPartSeparator(out, part) + part\n }\n return out\n}\n\n/**\n * Wrap `core` with the node's pre/post text. `{Label}` refs are resolved in the\n * AFFIXES only — the core arrives exactly as the caller's precedence produced it.\n * NO-OP GUARANTEE: with no non-blank affix the core is returned unchanged (same\n * reference) — every existing workflow stays byte-identical.\n * EMPTY CORE: a blank core with affixes yields the joined affixes alone.\n */\nexport function applyPromptAffixes(core: string, affixes: PromptAffixes | undefined, refMap: ReadonlyMap<string, string>): string\nexport function applyPromptAffixes(core: string | undefined, affixes: PromptAffixes | undefined, refMap: ReadonlyMap<string, string>): string | undefined\nexport function applyPromptAffixes(\n core: string | undefined,\n affixes: PromptAffixes | undefined,\n refMap: ReadonlyMap<string, string>,\n): string | undefined {\n const prefix = present(affixes?.prefix) ? rr(affixes!.prefix!, refMap) : undefined\n const suffix = present(affixes?.suffix) ? rr(affixes!.suffix!, refMap) : undefined\n if (prefix === undefined && suffix === undefined) return core\n return joinPromptParts([prefix, core, suffix])\n}\n\n/** SINGLE SOURCE OF TRUTH for prompt precedence across both DAG engines:\n * override (list fan-out) > first present typed candidate > wired > \"\".\n * \"present\" = non-empty after trim. {Label} refs are resolved on the chosen\n * branch via the shared resolveNodeRefs. With `appendWired`, the chosen base\n * AND the wired value are both emitted, joined as sentences (`joinSentences`:\n * \". \", or a space after one that already ends). Affixes wrap the result. */\nexport function resolvePrompt({ override, typed = [], wired, refMap, appendWired, affixes }: ResolvePromptArgs): string {\n return applyPromptAffixes(resolveCore({ override, typed, wired, refMap, appendWired }), affixes, refMap)\n}\n\nfunction resolveCore({ override, typed = [], wired, refMap, appendWired }: Omit<ResolvePromptArgs, \"affixes\">): string {\n // appendWired: a connected prompt APPENDS to the TYPED base. An `override`\n // (list fan-out item) still fully REPLACES — it never receives a wired append,\n // so per-item fan-out prompts are unchanged.\n if (appendWired && !present(override)) {\n const base = typed.find(present)\n return joinSentences([base, wired].filter(present).map((s) => rr(s, refMap)))\n }\n if (present(override)) return rr(override, refMap)\n for (const t of typed) if (present(t)) return rr(t, refMap)\n if (present(wired)) return rr(wired, refMap)\n return \"\"\n}\n\n/** Compose a final NEGATIVE prompt from a TYPED base + a WIRED (connected\n * negative-handle) value: both are emitted, joined as sentences (`joinSentences`, mirrors `appendWired`\n * for the positive prompt). Pure join — the caller resolves `{label}` refs on\n * the typed value first, and the wired value is already a resolved output that\n * the input-resolver has filtered (referenced / Inject-Negative-off dropped).\n * Generate-image / generate-video only; empty parts are dropped. */\nexport function composeNegative(typed?: string, wired?: string): string {\n return joinSentences([typed, wired])\n}\n\n/** Ordered typed-candidate fields per node type — the precedence source of\n * truth (NOT NODE_MAPPABLE_FIELDS, which is field-mapping eligibility, omits\n * video-retake, and orders llm-chat wrong). */\nexport const NODE_PROMPT_CANDIDATE_FIELDS: Readonly<Record<string, readonly string[]>> = {\n \"generate-image\": [\"prompt\"],\n // motionPrompt is here so generate-video re-typed to text-to-video keeps a\n // prompt stored in data.motionPrompt (the inline picker's legacy field). Safe\n // for a standalone text-to-video node — it never carries data.motionPrompt.\n \"text-to-video\": [\"prompt\", \"motionPrompt\"],\n \"video-to-video\": [\"prompt\"],\n \"generate-music\": [\"prompt\"],\n \"speech-to-video\": [\"prompt\"],\n \"cinematic-avatar\": [\"prompt\"],\n \"extend-video\": [\"prompt\"],\n \"video-retake\": [\"prompt\"],\n \"suno-replace-section\": [\"prompt\"],\n \"image-to-video\": [\"prompt\", \"motionPrompt\"],\n \"generate-video\": [\"prompt\", \"motionPrompt\"],\n \"text-to-audio\": [\"prompt\", \"text\"],\n // Social posts: the orchestrator + frontend executor match per-platform node\n // types (node.type is \"instagram-post\", \"telegram-post\", …), NOT a unified\n // \"social-publish\" type — so every platform needs its own [\"caption\"] entry.\n // Derived from the shared SOCIAL_POST_NODE_TYPES single source of truth so a\n // new platform can't drift out of the precedence map.\n ...Object.fromEntries(\n [...SOCIAL_POST_NODE_TYPES].map((t) => [t, [\"caption\"] as readonly string[]]),\n ),\n // Kept for any caller that passes the aggregate type instead of a platform.\n \"social-publish\": [\"caption\"],\n}\n\nexport interface ComputeNodePromptArgs {\n override?: string\n wired?: string\n refMap: ReadonlyMap<string, string>\n /** See ResolvePromptArgs.appendWired — generate-image / generate-video only. */\n appendWired?: boolean\n}\n/** Resolve a single-prompt node's final prompt (typed-primary). Both engines\n * call this so field-selection + precedence are structurally identical. */\nexport function computeNodePrompt(\n nodeType: string,\n data: Record<string, unknown>,\n { override, wired, refMap, appendWired }: ComputeNodePromptArgs,\n): string {\n let typed: ReadonlyArray<string | undefined>\n if (nodeType === \"text-to-speech\") {\n // data.text is a phantom field on TTS; only directText (gated) is real.\n //\n // The gate is a PREFERENCE, not a lock: when textSource is \"connected\" we\n // still fall back to typed text if nothing is wired. Writers flip the gate\n // (PromptFieldSpec.promptGate), but data reaches nodes from places no\n // writer touches — workflows saved before that fix, JSON imports, MCP\n // writes, templates — and there the text sat visible in the node while the\n // run failed with \"no text found\" (founder, 2026-08-14). Coerce rather\n // than reject, same principle as normalizeModelInput.\n typed =\n data.textSource === \"direct\" || !present(wired)\n ? [data.directText as string | undefined]\n : []\n } else {\n const fields = ownEntry(NODE_PROMPT_CANDIDATE_FIELDS, nodeType) ?? [\"prompt\"]\n typed = fields.map((f) => data[f] as string | undefined)\n }\n return resolvePrompt({ override, typed, wired, refMap, appendWired, affixes: readPromptAffixes(data) })\n}\n\nexport interface LlmChatFieldArgs {\n override?: string\n wiredUserInput?: string\n wiredSystemPrompt?: string\n refMap: ReadonlyMap<string, string>\n}\n/** llm-chat resolves TWO independent fields. override applies to userInput only. */\nexport function computeLlmChatFields(\n data: Record<string, unknown>,\n { override, wiredUserInput, wiredSystemPrompt, refMap }: LlmChatFieldArgs,\n): { userInput: string; systemPrompt: string } {\n return {\n userInput: resolvePrompt({ override, typed: [data.userInput as string | undefined], wired: wiredUserInput, refMap, affixes: readPromptAffixes(data) }),\n systemPrompt: resolvePrompt({ typed: [data.systemPrompt as string | undefined], wired: wiredSystemPrompt, refMap }),\n }\n}\n\n/** generate-script's topic. Both engines call this, so a wired Text node reads\n * the same on a single-node run and a server run.\n *\n * Precedence is override (a list fan-out item) > wired > `data.prompt`. Wired\n * comes BEFORE the typed field, the reverse of `computeNodePrompt`, because\n * `data.prompt` has no editor: the panel's text field is the style guide. A\n * value there was written by the old connect-time `{Label}` auto-fill or by an\n * agent, and it is kept only as the fallback that saved workflows rely on. */\nexport function computeScriptTopic(\n data: Record<string, unknown>,\n { override, wired, refMap }: Omit<ComputeNodePromptArgs, \"appendWired\">,\n): string {\n const core = [override, wired, data.prompt as string | undefined].find(present)\n return applyPromptAffixes(core === undefined ? \"\" : rr(core, refMap), readPromptAffixes(data), refMap)\n}\n","/**\n * Single source of truth: which data field(s) hold a node's user-editable\n * prompt text. Drives the quick-edit Prompt modal so it can work generically\n * across every AI node without each call site hardcoding a field name.\n *\n * The registry LIVES HERE (`@nodaro/prompts`) so the backend orchestrator, the\n * `/v1/nodes` registry, the prompt-affix totality tests and the docs tooling\n * read the SAME list the editor does. `frontend/src/lib/prompt-fields.ts` is a\n * pure re-export of this module — frontend code keeps importing\n * `@/lib/prompt-fields` unchanged.\n *\n * Most nodes store the prompt in `data.prompt`, but several don't\n * (`text-prompt` → `text`, `image-to-text` → `customPrompt`, …) — this map is\n * where that knowledge lives, once.\n *\n * INVARIANT: every node that exposes a user-editable prompt MUST have an entry\n * here, or the quick-edit modal silently does nothing for it. A guard test\n * (`prompt-fields.test.ts`) keeps this in sync with the node set.\n *\n * This module is intentionally pure data (no React/lucide imports) so it can be\n * pulled into the app-runtime bundle and any test without dragging in the icon\n * library. The string `icon` kind is mapped to a concrete lucide component in\n * `prompt-edit-button.tsx` (`getPromptIcon`), the only place that renders it.\n */\n\nimport type { SnippetMedia } from \"./factory-snippets/types.js\"\nimport { NODE_PROMPT_CANDIDATE_FIELDS } from \"./resolve-prompt.js\"\nimport { ownEntry } from \"./own-entry.js\"\n\n/** Which lucide glyph a node's prompt affordance uses. Kept as a string so this\n * module stays icon-library-free; mapped to a component in the strip button. */\nexport type PromptIconKind = \"pencil\" | \"paintbrush\"\n\nexport interface PromptFieldSpec {\n /** Data key holding the primary prompt (e.g. \"prompt\", \"text\", \"customPrompt\"). */\n readonly prompt: string\n /** Data key holding the negative prompt, when the node supports one. */\n readonly negative?: string\n /** Label override for the primary field (defaults to \"Prompt\"). */\n readonly promptLabel?: string\n /** Icon for the prompt affordance (strip button + modal title). Defaults to a\n * pencil; image-editing nodes use a paintbrush to read as \"edit\". */\n readonly icon?: PromptIconKind\n /** Node modality for prompt-snippet scoping — drives which snippet pool the\n * \"/\" menu and Snippets button show for this node's prompt fields. REQUIRED\n * so a new node cannot forget to declare it (compile error). */\n readonly media: SnippetMedia\n /** True when this node renders a media-result preview body and therefore\n * participates in inline-prompt mode (the `InlineNodePrompt` editor on the\n * node face, centralized in `BaseNode`). REQUIRED (like `media`) so a new\n * prompt node must consciously choose — compile error if omitted. The set of\n * `inline: true` types is guarded in `prompt-fields.test.ts`. */\n readonly inline: boolean\n /** Some nodes only READ their prompt field when a sibling discriminator\n * selects it — TTS keeps `directText` but resolves it only while\n * `textSource === \"direct\"`, defaulting to `\"connected\"`. Writing the text\n * without flipping the discriminator saved the value and then failed with\n * \"no text found\" (founder hit it live, 2026-08-14). Declare the pair here\n * and every writer flips it automatically. */\n readonly promptGate?: { readonly field: string; readonly value: string }\n /** Prompt pre/post text (`promptPrefix` / `promptSuffix`) support. Defaults to\n * ON for every prompt node; set `false` ONLY for a node whose \"prompt\" is not\n * a model prompt (the plain Text input node). Read via `nodeSupportsPromptAffixes`. */\n readonly affixes?: false\n}\n\nexport const NODE_PROMPT_FIELDS: Readonly<Record<string, PromptFieldSpec>> = {\n // ── Image ──\n // (`edit-image` / `image-to-image` are legacy types consolidated into\n // `modify-image`; they're not in the creatable node set, so a node of that\n // type never mounts and needs no entry here. The guard test enforces that.)\n \"generate-image\": { prompt: \"prompt\", negative: \"negativePrompt\", media: \"image\", inline: true },\n \"modify-image\": { prompt: \"prompt\", negative: \"negativePrompt\", icon: \"paintbrush\", media: \"image\", inline: true },\n \"generate-mask\": { prompt: \"prompt\", promptLabel: \"What to mask\", media: \"image\", inline: true },\n // ── Video ──\n \"generate-video\": { prompt: \"prompt\", negative: \"negativePrompt\", media: \"video\", inline: true },\n // Trimmed multi-segment stitch sibling of generate-video — no negativePrompt field.\n \"generate-video-pro\": { prompt: \"prompt\", media: \"video\", inline: true },\n // Span-replace sibling of generate-video-pro — no negativePrompt field.\n \"edit-video-pro\": { prompt: \"prompt\", media: \"video\", inline: true },\n \"text-to-video\": { prompt: \"prompt\", negative: \"negativePrompt\", media: \"video\", inline: true },\n \"image-to-video\": { prompt: \"prompt\", negative: \"negativePrompt\", promptLabel: \"Motion prompt\", media: \"video\", inline: true },\n \"video-to-video\": { prompt: \"prompt\", negative: \"negativePrompt\", media: \"video\", inline: true },\n \"switchx\": { prompt: \"prompt\", promptLabel: \"Look prompt\", media: \"video\", inline: true },\n \"extend-video\": { prompt: \"prompt\", negative: \"negativePrompt\", media: \"video\", inline: true },\n \"speech-to-video\": { prompt: \"prompt\", negative: \"negativePrompt\", media: \"video\", inline: true },\n \"motion-transfer\": { prompt: \"prompt\", negative: \"negativePrompt\", media: \"video\", inline: true },\n // Cinematic Avatar (HeyGen) — generative prompt (NOT a verbatim script),\n // so it participates in the quick-edit Prompt modal like other AI video nodes.\n \"cinematic-avatar\": { prompt: \"prompt\", media: \"video\", inline: true },\n \"video-sfx\": { prompt: \"prompt\", negative: \"negativePrompt\", promptLabel: \"Sound prompt\", media: \"audio\", inline: true },\n \"video-retake\": { prompt: \"prompt\", promptLabel: \"Retake prompt\", media: \"video\", inline: true },\n // Video Mask (SAM 3) — the subject to track, like Generate Mask's \"what to mask\".\n \"video-mask\": { prompt: \"prompt\", promptLabel: \"What to mask\", media: \"video\", inline: true },\n // ── Audio / music ──\n \"generate-music\": { prompt: \"prompt\", media: \"audio\", inline: true },\n \"suno-generate\": { prompt: \"prompt\", media: \"audio\", inline: true },\n \"text-to-audio\": { prompt: \"prompt\", media: \"audio\", inline: true },\n // ── Text / LLM (no media-result preview body → no inline editor) ──\n \"text-prompt\": { prompt: \"text\", promptLabel: \"Text\", media: \"text\", inline: false, affixes: false },\n \"image-to-text\": { prompt: \"customPrompt\", promptLabel: \"Question\", media: \"text\", inline: false },\n \"llm-chat\": { prompt: \"userInput\", promptLabel: \"Prompt\", media: \"text\", inline: false },\n // ── Speech / voice ──\n \"text-to-speech\": { prompt: \"directText\", promptLabel: \"Text\", media: \"audio\", inline: true, promptGate: { field: \"textSource\", value: \"direct\" } },\n \"voice-design\": { prompt: \"voiceDescription\", promptLabel: \"Voice description\", media: \"audio\", inline: true },\n \"voice-remix\": { prompt: \"voiceDescription\", promptLabel: \"Voice description\", media: \"audio\", inline: true },\n \"lip-sync\": { prompt: \"prompt\", media: \"audio\", inline: true },\n // ── Suno (music) ──\n \"suno-cover\": { prompt: \"prompt\", media: \"audio\", inline: true },\n \"suno-extend\": { prompt: \"prompt\", media: \"audio\", inline: true },\n \"suno-replace-section\": { prompt: \"prompt\", media: \"audio\", inline: true },\n \"suno-upload-extend\": { prompt: \"prompt\", media: \"audio\", inline: true },\n // NOTE: `suno-add-vocals` is intentionally absent — its node has no\n // user-editable prompt (SunoAddVocalsData declares only `model`; the config\n // panel + backend route take taskId/audioId/model, never a prompt). A stale\n // entry here rendered a phantom Prompt editor in the quick-edit modal that\n // wrote to a `data.prompt` key nothing ever reads (the dead-field class the\n // guard test now catches via defaultData ownership).\n \"suno-lyrics\": { prompt: \"prompt\", media: \"audio\", inline: false },\n \"suno-style-boost\": { prompt: \"content\", promptLabel: \"Style\", media: \"audio\", inline: false },\n // ── Composition / FX (compact, no media-result preview → no inline editor) ──\n \"image-critic\": { prompt: \"prompt\", promptLabel: \"Criteria\", media: \"image\", inline: false },\n \"motion-graphics\": { prompt: \"motionPrompt\", promptLabel: \"Motion prompt\", media: \"video\", inline: false },\n \"pro-3d-render\": { prompt: \"scenePrompt\", promptLabel: \"Scene\", media: \"text\", inline: false },\n \"generate-3d-scene\": { prompt: \"scenePrompt\", promptLabel: \"Scene\", media: \"text\", inline: false },\n \"edit-3d-scene\": { prompt: \"editPrompt\", promptLabel: \"Edit instruction\", media: \"text\", inline: false },\n \"3d-title\": { prompt: \"titlePrompt\", promptLabel: \"Title\", media: \"text\", inline: false },\n // ── Script / alignment (their primary text field) ──\n \"generate-script\": { prompt: \"styleGuide\", promptLabel: \"Style guide\", media: \"text\", inline: false },\n \"forced-alignment\": { prompt: \"transcript\", promptLabel: \"Transcript\", media: \"audio\", inline: false },\n // Video Analysis — its focus hint is the editable prompt (renders a JSON scene\n // table, not a media preview → no inline editor).\n \"video-analysis\": { prompt: \"analysisFocus\", promptLabel: \"Analysis focus\", media: \"video\", inline: false },\n // Edit Plan (podcast editing) — its free-text editing instructions are the\n // editable prompt; the affixes wrap them. Emits an EDL (JSON), not a media\n // preview, so no inline editor.\n \"edit-plan\": { prompt: \"instructions\", promptLabel: \"Editing instructions\", media: \"video\", inline: false },\n}\n\n/** The prompt-field spec for a node type, or undefined if it has none (an\n * Object.prototype member name such as `constructor` has none). */\nexport function getPromptFields(nodeType: string | undefined): PromptFieldSpec | undefined {\n return nodeType ? ownEntry(NODE_PROMPT_FIELDS, nodeType) : undefined\n}\n\n/** True when this node type has a registered, quick-editable prompt field. */\nexport function nodeHasPromptField(nodeType: string | undefined): boolean {\n return getPromptFields(nodeType) !== undefined\n}\n\n/** Snippet modality for a node type (drives the snippet pool), or undefined\n * when the node has no prompt field. */\nexport function getSnippetMedia(nodeType: string | undefined): SnippetMedia | undefined {\n return getPromptFields(nodeType)?.media\n}\n\n/** True when this node type renders the inline on-node prompt editor — the\n * media-preview nodes (image/video/audio result body). Single source for\n * BaseNode's centralized `InlineNodePrompt` rendering and the gold nodes'\n * `showInline` derivation (`useInlinePromptActive`). */\nexport function nodeHasInlinePrompt(nodeType: string | undefined): boolean {\n return getPromptFields(nodeType)?.inline === true\n}\n\n/** True when the node type carries `promptPrefix` / `promptSuffix` — every\n * registered prompt node except explicit opt-outs (`affixes: false`). The single\n * predicate the config panel, Final view, `/v1/nodes` registry, totality tests\n * and docs tooling all gate on. */\nexport function nodeSupportsPromptAffixes(nodeType: string | undefined): boolean {\n const spec = getPromptFields(nodeType)\n return spec !== undefined && spec.affixes !== false\n}\n\n/**\n * Where the RUN-TIME prompt lives when it differs from the editor's prompt\n * field (spec §7). `generate-script`'s editable prompt is its `styleGuide`, but\n * the run wraps the topic `prompt` with the affixes — so previewing the style\n * guide must NOT show them.\n */\nexport const PROMPT_AFFIX_CORE_FIELD_OVERRIDES: Readonly<Record<string, string>> = { \"generate-script\": \"prompt\" }\n\n/** The data key whose value the run wraps with promptPrefix/promptSuffix, or\n * undefined when the node has no affixes. */\nexport function promptAffixCoreField(nodeType: string | undefined): string | undefined {\n if (!nodeSupportsPromptAffixes(nodeType)) return undefined\n return PROMPT_AFFIX_CORE_FIELD_OVERRIDES[nodeType!] ?? getPromptFields(nodeType)!.prompt\n}\n\n/**\n * True when a preview of `promptField` on this node must show the affixes —\n * i.e. that key is what the run actually wraps. THE gate for the editor's Final\n * view, so a sibling field (llm-chat's `systemPrompt`, generate-script's\n * `styleGuide`) never renders a wrap the run doesn't perform.\n *\n * Two ways a key qualifies:\n * - it IS the core field ({@link promptAffixCoreField}), or\n * - it is a run-time FALLBACK candidate for the type\n * ({@link NODE_PROMPT_CANDIDATE_FIELDS}) — `computeNodePrompt` picks the\n * first present candidate and wraps THAT, so i2v's legacy `motionPrompt`\n * genuinely receives the affixes when `data.prompt` is empty.\n *\n * The two rules never collide: no override type declares candidates (guarded in\n * `node-prompt-fields.test.ts`).\n *\n * `undefined` means \"the node's primary prompt field\" — the common call.\n */\nexport function promptFieldCarriesAffixes(nodeType: string | undefined, promptField: string | undefined): boolean {\n const core = promptAffixCoreField(nodeType)\n if (core === undefined) return false\n if (promptField === undefined) return getPromptFields(nodeType)!.prompt === core\n return promptField === core || (ownEntry(NODE_PROMPT_CANDIDATE_FIELDS, nodeType) ?? []).includes(promptField)\n}\n\n/** The affix-capable node types, derived from the registry (never hand-listed). */\nexport const PROMPT_AFFIX_NODE_TYPES: ReadonlySet<string> = new Set(\n Object.entries(NODE_PROMPT_FIELDS).filter(([, s]) => s.affixes !== false).map(([t]) => t),\n)\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getPromptFields, NODE_PROMPT_CANDIDATE_FIELDS, promptAffixCoreField, nodeSupportsPromptAffixes } from './chunk-
|
|
1
|
+
import { ownEntry, getPromptFields, NODE_PROMPT_CANDIDATE_FIELDS, promptAffixCoreField, nodeSupportsPromptAffixes } from './chunk-N6VMPG5S.js';
|
|
2
2
|
import { IMAGE_TOKEN_PATTERN } from './chunk-GILUVQQJ.js';
|
|
3
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';
|
|
4
4
|
import { MODELS_WITH_REFERENCE_IMAGE_SUPPORT, imageReferenceLimit, T2I_TO_I2I_VARIANT } from '@nodaro/shared/models';
|
|
@@ -5155,7 +5155,7 @@ var MAX_PRESET_REFERENCES = Math.max(
|
|
|
5155
5155
|
);
|
|
5156
5156
|
function promptFieldsOf(nodeType) {
|
|
5157
5157
|
const spec = getPromptFields(nodeType);
|
|
5158
|
-
const candidates = NODE_PROMPT_CANDIDATE_FIELDS
|
|
5158
|
+
const candidates = ownEntry(NODE_PROMPT_CANDIDATE_FIELDS, nodeType) ?? [];
|
|
5159
5159
|
if (!spec && candidates.length === 0) return [];
|
|
5160
5160
|
const fields = new Set(candidates);
|
|
5161
5161
|
if (spec) {
|
|
@@ -5238,7 +5238,7 @@ var FACTORY_PRESETS = {
|
|
|
5238
5238
|
"lottie-overlay": LOTTIE_OVERLAY_PRESETS
|
|
5239
5239
|
};
|
|
5240
5240
|
function getFactoryPresets(nodeType) {
|
|
5241
|
-
return FACTORY_PRESETS
|
|
5241
|
+
return ownEntry(FACTORY_PRESETS, nodeType) ?? [];
|
|
5242
5242
|
}
|
|
5243
5243
|
|
|
5244
5244
|
// src/caption-treatments.ts
|
|
@@ -5617,5 +5617,5 @@ function getFactorySnippets(target, media) {
|
|
|
5617
5617
|
}
|
|
5618
5618
|
|
|
5619
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-
|
|
5621
|
-
//# sourceMappingURL=chunk-
|
|
5620
|
+
//# sourceMappingURL=chunk-RB2F5JQF.js.map
|
|
5621
|
+
//# sourceMappingURL=chunk-RB2F5JQF.js.map
|