@koda-sl/baker-cli 0.158.0 → 0.158.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../node_modules/.pnpm/safe-stable-stringify@2.5.0/node_modules/safe-stable-stringify/index.js","../src/engine/index.ts","../src/engine/client/http.ts","../src/engine/client/backend-client.ts","../src/engine/client/env.ts","../src/engine/engine/errors.ts","../../canvas-contract/src/adPlatformFormats.ts","../../../node_modules/.pnpm/safe-stable-stringify@2.5.0/node_modules/safe-stable-stringify/esm/wrapper.js","../../canvas-contract/src/canonical.ts","../../canvas-contract/src/registry.ts","../../canvas-contract/src/validateParams.ts","../../canvas-contract/src/videoCost.ts","../src/engine/lib/concurrency.ts","../src/engine/lib/ulid.ts","../src/engine/storage/remote-cache-store.ts","../src/engine/nodes/remote/upload.ts","../src/engine/schema/canvas.ts","../src/engine/schema/prompts.ts","../src/engine/storage/output-writer.ts","../src/engine/storage/asset-store.ts","../src/engine/storage/sha256.ts","../src/engine/engine/cache-key.ts","../src/engine/engine/refs.ts","../src/engine/engine/scheduler.ts","../src/engine/engine/validator.ts","../src/engine/lib/url.ts","../src/engine/scaffold/lib/prompt-profiles.ts","../src/engine/scaffold/spine-input.ts","../src/engine/engine/define.ts","../src/engine/engine/didyoumean.ts","../src/engine/engine/executor.ts","../src/engine/engine/registry.ts","../src/engine/nodes/ingest.ts","../src/engine/schema/refs.ts","../src/engine/schema/primitives.ts","../src/engine/nodes/remote/delegate.ts","../src/engine/nodes/local/audioTimeline.ts","../src/engine/nodes/local/lib/cli-runner.ts","../src/engine/nodes/local/collect.ts","../src/engine/nodes/local/ffmpeg.ts","../src/engine/nodes/local/fontSpecimen.ts","../src/engine/nodes/local/lib/assets.ts","../src/engine/nodes/local/hyperframe.ts","../src/engine/engine/composition-hash.ts","../src/engine/engine/composition-meta.ts","../src/engine/nodes/local/lib/hyperframe-check.ts","../src/engine/nodes/local/lib/hyperframe-errors.ts","../src/engine/nodes/local/lib/hyperframe-meta.ts","../src/engine/nodes/local/lib/templating.ts","../src/engine/nodes/local/hyperframe-snapshot.ts","../src/engine/nodes/local/imagemagick.ts","../src/engine/nodes/local/text.ts","../src/engine/nodes/remote/audioVoiceConvert.ts","../src/engine/nodes/remote/dialogue.ts","../src/engine/nodes/remote/image.ts","../src/engine/nodes/remote/imageAspectAdapt.ts","../src/engine/nodes/remote/imageBackgroundRemove.ts","../src/engine/nodes/remote/imageDescribe.ts","../src/engine/nodes/remote/imageReferenceSheet.ts","../src/engine/nodes/remote/imageSearch.ts","../src/engine/nodes/remote/imageSelect.ts","../src/engine/nodes/remote/music.ts","../src/engine/nodes/remote/soundEffect.ts","../src/engine/nodes/remote/textGenerate.ts","../src/engine/nodes/remote/tts.ts","../src/engine/nodes/remote/video.ts","../src/engine/nodes/remote/videoBackgroundRemove.ts","../src/engine/nodes/remote/videoDeconstruct.ts","../src/engine/nodes/remote/videoLipsync.ts","../src/engine/nodes/remote/videoTranscribe.ts","../src/engine/nodes/local/lib/ffmpeg.ts","../src/engine/nodes/remote/voiceSelect.ts","../src/engine/schema/catalog.ts","../src/engine/storage/cache-store.ts"],"sourcesContent":["'use strict'\n\nconst { hasOwnProperty } = Object.prototype\n\nconst stringify = configure()\n\n// @ts-expect-error\nstringify.configure = configure\n// @ts-expect-error\nstringify.stringify = stringify\n\n// @ts-expect-error\nstringify.default = stringify\n\n// @ts-expect-error used for named export\nexports.stringify = stringify\n// @ts-expect-error used for named export\nexports.configure = configure\n\nmodule.exports = stringify\n\n// eslint-disable-next-line no-control-regex\nconst strEscapeSequencesRegExp = /[\\u0000-\\u001f\\u0022\\u005c\\ud800-\\udfff]/\n\n// Escape C0 control characters, double quotes, the backslash and every code\n// unit with a numeric value in the inclusive range 0xD800 to 0xDFFF.\nfunction strEscape (str) {\n // Some magic numbers that worked out fine while benchmarking with v8 8.0\n if (str.length < 5000 && !strEscapeSequencesRegExp.test(str)) {\n return `\"${str}\"`\n }\n return JSON.stringify(str)\n}\n\nfunction sort (array, comparator) {\n // Insertion sort is very efficient for small input sizes, but it has a bad\n // worst case complexity. Thus, use native array sort for bigger values.\n if (array.length > 2e2 || comparator) {\n return array.sort(comparator)\n }\n for (let i = 1; i < array.length; i++) {\n const currentValue = array[i]\n let position = i\n while (position !== 0 && array[position - 1] > currentValue) {\n array[position] = array[position - 1]\n position--\n }\n array[position] = currentValue\n }\n return array\n}\n\nconst typedArrayPrototypeGetSymbolToStringTag =\n Object.getOwnPropertyDescriptor(\n Object.getPrototypeOf(\n Object.getPrototypeOf(\n new Int8Array()\n )\n ),\n Symbol.toStringTag\n ).get\n\nfunction isTypedArrayWithEntries (value) {\n return typedArrayPrototypeGetSymbolToStringTag.call(value) !== undefined && value.length !== 0\n}\n\nfunction stringifyTypedArray (array, separator, maximumBreadth) {\n if (array.length < maximumBreadth) {\n maximumBreadth = array.length\n }\n const whitespace = separator === ',' ? '' : ' '\n let res = `\"0\":${whitespace}${array[0]}`\n for (let i = 1; i < maximumBreadth; i++) {\n res += `${separator}\"${i}\":${whitespace}${array[i]}`\n }\n return res\n}\n\nfunction getCircularValueOption (options) {\n if (hasOwnProperty.call(options, 'circularValue')) {\n const circularValue = options.circularValue\n if (typeof circularValue === 'string') {\n return `\"${circularValue}\"`\n }\n if (circularValue == null) {\n return circularValue\n }\n if (circularValue === Error || circularValue === TypeError) {\n return {\n toString () {\n throw new TypeError('Converting circular structure to JSON')\n }\n }\n }\n throw new TypeError('The \"circularValue\" argument must be of type string or the value null or undefined')\n }\n return '\"[Circular]\"'\n}\n\nfunction getDeterministicOption (options) {\n let value\n if (hasOwnProperty.call(options, 'deterministic')) {\n value = options.deterministic\n if (typeof value !== 'boolean' && typeof value !== 'function') {\n throw new TypeError('The \"deterministic\" argument must be of type boolean or comparator function')\n }\n }\n return value === undefined ? true : value\n}\n\nfunction getBooleanOption (options, key) {\n let value\n if (hasOwnProperty.call(options, key)) {\n value = options[key]\n if (typeof value !== 'boolean') {\n throw new TypeError(`The \"${key}\" argument must be of type boolean`)\n }\n }\n return value === undefined ? true : value\n}\n\nfunction getPositiveIntegerOption (options, key) {\n let value\n if (hasOwnProperty.call(options, key)) {\n value = options[key]\n if (typeof value !== 'number') {\n throw new TypeError(`The \"${key}\" argument must be of type number`)\n }\n if (!Number.isInteger(value)) {\n throw new TypeError(`The \"${key}\" argument must be an integer`)\n }\n if (value < 1) {\n throw new RangeError(`The \"${key}\" argument must be >= 1`)\n }\n }\n return value === undefined ? Infinity : value\n}\n\nfunction getItemCount (number) {\n if (number === 1) {\n return '1 item'\n }\n return `${number} items`\n}\n\nfunction getUniqueReplacerSet (replacerArray) {\n const replacerSet = new Set()\n for (const value of replacerArray) {\n if (typeof value === 'string' || typeof value === 'number') {\n replacerSet.add(String(value))\n }\n }\n return replacerSet\n}\n\nfunction getStrictOption (options) {\n if (hasOwnProperty.call(options, 'strict')) {\n const value = options.strict\n if (typeof value !== 'boolean') {\n throw new TypeError('The \"strict\" argument must be of type boolean')\n }\n if (value) {\n return (value) => {\n let message = `Object can not safely be stringified. Received type ${typeof value}`\n if (typeof value !== 'function') message += ` (${value.toString()})`\n throw new Error(message)\n }\n }\n }\n}\n\nfunction configure (options) {\n options = { ...options }\n const fail = getStrictOption(options)\n if (fail) {\n if (options.bigint === undefined) {\n options.bigint = false\n }\n if (!('circularValue' in options)) {\n options.circularValue = Error\n }\n }\n const circularValue = getCircularValueOption(options)\n const bigint = getBooleanOption(options, 'bigint')\n const deterministic = getDeterministicOption(options)\n const comparator = typeof deterministic === 'function' ? deterministic : undefined\n const maximumDepth = getPositiveIntegerOption(options, 'maximumDepth')\n const maximumBreadth = getPositiveIntegerOption(options, 'maximumBreadth')\n\n function stringifyFnReplacer (key, parent, stack, replacer, spacer, indentation) {\n let value = parent[key]\n\n if (typeof value === 'object' && value !== null && typeof value.toJSON === 'function') {\n value = value.toJSON(key)\n }\n value = replacer.call(parent, key, value)\n\n switch (typeof value) {\n case 'string':\n return strEscape(value)\n case 'object': {\n if (value === null) {\n return 'null'\n }\n if (stack.indexOf(value) !== -1) {\n return circularValue\n }\n\n let res = ''\n let join = ','\n const originalIndentation = indentation\n\n if (Array.isArray(value)) {\n if (value.length === 0) {\n return '[]'\n }\n if (maximumDepth < stack.length + 1) {\n return '\"[Array]\"'\n }\n stack.push(value)\n if (spacer !== '') {\n indentation += spacer\n res += `\\n${indentation}`\n join = `,\\n${indentation}`\n }\n const maximumValuesToStringify = Math.min(value.length, maximumBreadth)\n let i = 0\n for (; i < maximumValuesToStringify - 1; i++) {\n const tmp = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation)\n res += tmp !== undefined ? tmp : 'null'\n res += join\n }\n const tmp = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation)\n res += tmp !== undefined ? tmp : 'null'\n if (value.length - 1 > maximumBreadth) {\n const removedKeys = value.length - maximumBreadth - 1\n res += `${join}\"... ${getItemCount(removedKeys)} not stringified\"`\n }\n if (spacer !== '') {\n res += `\\n${originalIndentation}`\n }\n stack.pop()\n return `[${res}]`\n }\n\n let keys = Object.keys(value)\n const keyLength = keys.length\n if (keyLength === 0) {\n return '{}'\n }\n if (maximumDepth < stack.length + 1) {\n return '\"[Object]\"'\n }\n let whitespace = ''\n let separator = ''\n if (spacer !== '') {\n indentation += spacer\n join = `,\\n${indentation}`\n whitespace = ' '\n }\n const maximumPropertiesToStringify = Math.min(keyLength, maximumBreadth)\n if (deterministic && !isTypedArrayWithEntries(value)) {\n keys = sort(keys, comparator)\n }\n stack.push(value)\n for (let i = 0; i < maximumPropertiesToStringify; i++) {\n const key = keys[i]\n const tmp = stringifyFnReplacer(key, value, stack, replacer, spacer, indentation)\n if (tmp !== undefined) {\n res += `${separator}${strEscape(key)}:${whitespace}${tmp}`\n separator = join\n }\n }\n if (keyLength > maximumBreadth) {\n const removedKeys = keyLength - maximumBreadth\n res += `${separator}\"...\":${whitespace}\"${getItemCount(removedKeys)} not stringified\"`\n separator = join\n }\n if (spacer !== '' && separator.length > 1) {\n res = `\\n${indentation}${res}\\n${originalIndentation}`\n }\n stack.pop()\n return `{${res}}`\n }\n case 'number':\n return isFinite(value) ? String(value) : fail ? fail(value) : 'null'\n case 'boolean':\n return value === true ? 'true' : 'false'\n case 'undefined':\n return undefined\n case 'bigint':\n if (bigint) {\n return String(value)\n }\n // fallthrough\n default:\n return fail ? fail(value) : undefined\n }\n }\n\n function stringifyArrayReplacer (key, value, stack, replacer, spacer, indentation) {\n if (typeof value === 'object' && value !== null && typeof value.toJSON === 'function') {\n value = value.toJSON(key)\n }\n\n switch (typeof value) {\n case 'string':\n return strEscape(value)\n case 'object': {\n if (value === null) {\n return 'null'\n }\n if (stack.indexOf(value) !== -1) {\n return circularValue\n }\n\n const originalIndentation = indentation\n let res = ''\n let join = ','\n\n if (Array.isArray(value)) {\n if (value.length === 0) {\n return '[]'\n }\n if (maximumDepth < stack.length + 1) {\n return '\"[Array]\"'\n }\n stack.push(value)\n if (spacer !== '') {\n indentation += spacer\n res += `\\n${indentation}`\n join = `,\\n${indentation}`\n }\n const maximumValuesToStringify = Math.min(value.length, maximumBreadth)\n let i = 0\n for (; i < maximumValuesToStringify - 1; i++) {\n const tmp = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation)\n res += tmp !== undefined ? tmp : 'null'\n res += join\n }\n const tmp = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation)\n res += tmp !== undefined ? tmp : 'null'\n if (value.length - 1 > maximumBreadth) {\n const removedKeys = value.length - maximumBreadth - 1\n res += `${join}\"... ${getItemCount(removedKeys)} not stringified\"`\n }\n if (spacer !== '') {\n res += `\\n${originalIndentation}`\n }\n stack.pop()\n return `[${res}]`\n }\n stack.push(value)\n let whitespace = ''\n if (spacer !== '') {\n indentation += spacer\n join = `,\\n${indentation}`\n whitespace = ' '\n }\n let separator = ''\n for (const key of replacer) {\n const tmp = stringifyArrayReplacer(key, value[key], stack, replacer, spacer, indentation)\n if (tmp !== undefined) {\n res += `${separator}${strEscape(key)}:${whitespace}${tmp}`\n separator = join\n }\n }\n if (spacer !== '' && separator.length > 1) {\n res = `\\n${indentation}${res}\\n${originalIndentation}`\n }\n stack.pop()\n return `{${res}}`\n }\n case 'number':\n return isFinite(value) ? String(value) : fail ? fail(value) : 'null'\n case 'boolean':\n return value === true ? 'true' : 'false'\n case 'undefined':\n return undefined\n case 'bigint':\n if (bigint) {\n return String(value)\n }\n // fallthrough\n default:\n return fail ? fail(value) : undefined\n }\n }\n\n function stringifyIndent (key, value, stack, spacer, indentation) {\n switch (typeof value) {\n case 'string':\n return strEscape(value)\n case 'object': {\n if (value === null) {\n return 'null'\n }\n if (typeof value.toJSON === 'function') {\n value = value.toJSON(key)\n // Prevent calling `toJSON` again.\n if (typeof value !== 'object') {\n return stringifyIndent(key, value, stack, spacer, indentation)\n }\n if (value === null) {\n return 'null'\n }\n }\n if (stack.indexOf(value) !== -1) {\n return circularValue\n }\n const originalIndentation = indentation\n\n if (Array.isArray(value)) {\n if (value.length === 0) {\n return '[]'\n }\n if (maximumDepth < stack.length + 1) {\n return '\"[Array]\"'\n }\n stack.push(value)\n indentation += spacer\n let res = `\\n${indentation}`\n const join = `,\\n${indentation}`\n const maximumValuesToStringify = Math.min(value.length, maximumBreadth)\n let i = 0\n for (; i < maximumValuesToStringify - 1; i++) {\n const tmp = stringifyIndent(String(i), value[i], stack, spacer, indentation)\n res += tmp !== undefined ? tmp : 'null'\n res += join\n }\n const tmp = stringifyIndent(String(i), value[i], stack, spacer, indentation)\n res += tmp !== undefined ? tmp : 'null'\n if (value.length - 1 > maximumBreadth) {\n const removedKeys = value.length - maximumBreadth - 1\n res += `${join}\"... ${getItemCount(removedKeys)} not stringified\"`\n }\n res += `\\n${originalIndentation}`\n stack.pop()\n return `[${res}]`\n }\n\n let keys = Object.keys(value)\n const keyLength = keys.length\n if (keyLength === 0) {\n return '{}'\n }\n if (maximumDepth < stack.length + 1) {\n return '\"[Object]\"'\n }\n indentation += spacer\n const join = `,\\n${indentation}`\n let res = ''\n let separator = ''\n let maximumPropertiesToStringify = Math.min(keyLength, maximumBreadth)\n if (isTypedArrayWithEntries(value)) {\n res += stringifyTypedArray(value, join, maximumBreadth)\n keys = keys.slice(value.length)\n maximumPropertiesToStringify -= value.length\n separator = join\n }\n if (deterministic) {\n keys = sort(keys, comparator)\n }\n stack.push(value)\n for (let i = 0; i < maximumPropertiesToStringify; i++) {\n const key = keys[i]\n const tmp = stringifyIndent(key, value[key], stack, spacer, indentation)\n if (tmp !== undefined) {\n res += `${separator}${strEscape(key)}: ${tmp}`\n separator = join\n }\n }\n if (keyLength > maximumBreadth) {\n const removedKeys = keyLength - maximumBreadth\n res += `${separator}\"...\": \"${getItemCount(removedKeys)} not stringified\"`\n separator = join\n }\n if (separator !== '') {\n res = `\\n${indentation}${res}\\n${originalIndentation}`\n }\n stack.pop()\n return `{${res}}`\n }\n case 'number':\n return isFinite(value) ? String(value) : fail ? fail(value) : 'null'\n case 'boolean':\n return value === true ? 'true' : 'false'\n case 'undefined':\n return undefined\n case 'bigint':\n if (bigint) {\n return String(value)\n }\n // fallthrough\n default:\n return fail ? fail(value) : undefined\n }\n }\n\n function stringifySimple (key, value, stack) {\n switch (typeof value) {\n case 'string':\n return strEscape(value)\n case 'object': {\n if (value === null) {\n return 'null'\n }\n if (typeof value.toJSON === 'function') {\n value = value.toJSON(key)\n // Prevent calling `toJSON` again\n if (typeof value !== 'object') {\n return stringifySimple(key, value, stack)\n }\n if (value === null) {\n return 'null'\n }\n }\n if (stack.indexOf(value) !== -1) {\n return circularValue\n }\n\n let res = ''\n\n const hasLength = value.length !== undefined\n if (hasLength && Array.isArray(value)) {\n if (value.length === 0) {\n return '[]'\n }\n if (maximumDepth < stack.length + 1) {\n return '\"[Array]\"'\n }\n stack.push(value)\n const maximumValuesToStringify = Math.min(value.length, maximumBreadth)\n let i = 0\n for (; i < maximumValuesToStringify - 1; i++) {\n const tmp = stringifySimple(String(i), value[i], stack)\n res += tmp !== undefined ? tmp : 'null'\n res += ','\n }\n const tmp = stringifySimple(String(i), value[i], stack)\n res += tmp !== undefined ? tmp : 'null'\n if (value.length - 1 > maximumBreadth) {\n const removedKeys = value.length - maximumBreadth - 1\n res += `,\"... ${getItemCount(removedKeys)} not stringified\"`\n }\n stack.pop()\n return `[${res}]`\n }\n\n let keys = Object.keys(value)\n const keyLength = keys.length\n if (keyLength === 0) {\n return '{}'\n }\n if (maximumDepth < stack.length + 1) {\n return '\"[Object]\"'\n }\n let separator = ''\n let maximumPropertiesToStringify = Math.min(keyLength, maximumBreadth)\n if (hasLength && isTypedArrayWithEntries(value)) {\n res += stringifyTypedArray(value, ',', maximumBreadth)\n keys = keys.slice(value.length)\n maximumPropertiesToStringify -= value.length\n separator = ','\n }\n if (deterministic) {\n keys = sort(keys, comparator)\n }\n stack.push(value)\n for (let i = 0; i < maximumPropertiesToStringify; i++) {\n const key = keys[i]\n const tmp = stringifySimple(key, value[key], stack)\n if (tmp !== undefined) {\n res += `${separator}${strEscape(key)}:${tmp}`\n separator = ','\n }\n }\n if (keyLength > maximumBreadth) {\n const removedKeys = keyLength - maximumBreadth\n res += `${separator}\"...\":\"${getItemCount(removedKeys)} not stringified\"`\n }\n stack.pop()\n return `{${res}}`\n }\n case 'number':\n return isFinite(value) ? String(value) : fail ? fail(value) : 'null'\n case 'boolean':\n return value === true ? 'true' : 'false'\n case 'undefined':\n return undefined\n case 'bigint':\n if (bigint) {\n return String(value)\n }\n // fallthrough\n default:\n return fail ? fail(value) : undefined\n }\n }\n\n function stringify (value, replacer, space) {\n if (arguments.length > 1) {\n let spacer = ''\n if (typeof space === 'number') {\n spacer = ' '.repeat(Math.min(space, 10))\n } else if (typeof space === 'string') {\n spacer = space.slice(0, 10)\n }\n if (replacer != null) {\n if (typeof replacer === 'function') {\n return stringifyFnReplacer('', { '': value }, [], replacer, spacer, '')\n }\n if (Array.isArray(replacer)) {\n return stringifyArrayReplacer('', value, [], getUniqueReplacerSet(replacer), spacer, '')\n }\n }\n if (spacer.length !== 0) {\n return stringifyIndent('', value, [], spacer, '')\n }\n }\n return stringifySimple('', value, [])\n }\n\n return stringify\n}\n","import path from \"node:path\";\nimport { BackendClient as _BackendClient } from \"./client/backend-client.ts\";\nimport { remoteCacheEnabledFromEnv, requireCredentialsFromEnv } from \"./client/env.ts\";\nimport type { NodeDefinition } from \"./engine/define.ts\";\nimport { ValidationError as _ValidationError } from \"./engine/errors.ts\";\nimport { Engine as _Engine } from \"./engine/executor.ts\";\nimport { NodeRegistry } from \"./engine/registry.ts\";\nimport { validateCanvasDeep as _validateCanvasDeep } from \"./engine/validator.ts\";\nimport { ingestNode } from \"./nodes/ingest.ts\";\nimport { audioTimelineNode } from \"./nodes/local/audioTimeline.ts\";\nimport { collectNode } from \"./nodes/local/collect.ts\";\nimport { ffmpegNode } from \"./nodes/local/ffmpeg.ts\";\nimport { fontSpecimenNode } from \"./nodes/local/fontSpecimen.ts\";\nimport { hyperframeRenderNode } from \"./nodes/local/hyperframe.ts\";\nimport { hyperframeSnapshotNode } from \"./nodes/local/hyperframe-snapshot.ts\";\nimport { imagemagickNode } from \"./nodes/local/imagemagick.ts\";\nimport { textNode } from \"./nodes/local/text.ts\";\nimport { audioVoiceConvertNode } from \"./nodes/remote/audioVoiceConvert.ts\";\nimport { dialogueNode } from \"./nodes/remote/dialogue.ts\";\nimport { imageGenerateNode } from \"./nodes/remote/image.ts\";\nimport { imageAspectAdaptNode } from \"./nodes/remote/imageAspectAdapt.ts\";\nimport { imageBackgroundRemoveNode } from \"./nodes/remote/imageBackgroundRemove.ts\";\nimport { imageDescribeNode } from \"./nodes/remote/imageDescribe.ts\";\nimport { imageReferenceSheetNode } from \"./nodes/remote/imageReferenceSheet.ts\";\nimport { imageSearchNode } from \"./nodes/remote/imageSearch.ts\";\nimport { imageSelectNode } from \"./nodes/remote/imageSelect.ts\";\nimport { musicNode } from \"./nodes/remote/music.ts\";\nimport { soundEffectNode } from \"./nodes/remote/soundEffect.ts\";\nimport { textGenerateNode } from \"./nodes/remote/textGenerate.ts\";\nimport { ttsNode } from \"./nodes/remote/tts.ts\";\nimport { videoGenerateNode } from \"./nodes/remote/video.ts\";\nimport { videoBackgroundRemoveNode } from \"./nodes/remote/videoBackgroundRemove.ts\";\nimport { videoDeconstructNode } from \"./nodes/remote/videoDeconstruct.ts\";\nimport { videoLipsyncNode } from \"./nodes/remote/videoLipsync.ts\";\nimport { videoTranscribeNode } from \"./nodes/remote/videoTranscribe.ts\";\nimport { voiceSelectNode } from \"./nodes/remote/voiceSelect.ts\";\nimport { generateCatalog as _generateCatalog } from \"./schema/catalog.ts\";\nimport { LocalAssetStore as _LocalAssetStore } from \"./storage/asset-store.ts\";\nimport { LocalCacheStore as _LocalCacheStore } from \"./storage/cache-store.ts\";\nimport { LayeredCacheStore, RemoteCacheStore } from \"./storage/remote-cache-store.ts\";\n\nexport const BackendClient = _BackendClient;\nexport const Engine = _Engine;\nexport const LocalAssetStore = _LocalAssetStore;\nexport const LocalCacheStore = _LocalCacheStore;\nexport const validateCanvasDeep = _validateCanvasDeep;\nexport const generateCatalog = _generateCatalog;\nexport const ValidationError = _ValidationError;\n\nconst LOCAL_NODES: readonly NodeDefinition[] = [\n textNode as NodeDefinition,\n ingestNode as NodeDefinition,\n hyperframeRenderNode as NodeDefinition,\n hyperframeSnapshotNode as NodeDefinition,\n ffmpegNode as NodeDefinition,\n imagemagickNode as NodeDefinition,\n videoTranscribeNode as NodeDefinition,\n fontSpecimenNode as NodeDefinition,\n audioTimelineNode as NodeDefinition,\n collectNode as NodeDefinition,\n];\n\nconst REMOTE_NODES: readonly NodeDefinition[] = [\n textGenerateNode as NodeDefinition,\n imageGenerateNode as NodeDefinition,\n imageAspectAdaptNode as NodeDefinition,\n imageDescribeNode as NodeDefinition,\n imageReferenceSheetNode as NodeDefinition,\n imageSearchNode as NodeDefinition,\n imageSelectNode as NodeDefinition,\n videoGenerateNode as NodeDefinition,\n ttsNode as NodeDefinition,\n audioVoiceConvertNode as NodeDefinition,\n musicNode as NodeDefinition,\n dialogueNode as NodeDefinition,\n soundEffectNode as NodeDefinition,\n videoLipsyncNode as NodeDefinition,\n videoBackgroundRemoveNode as NodeDefinition,\n videoDeconstructNode as NodeDefinition,\n voiceSelectNode as NodeDefinition,\n imageBackgroundRemoveNode as NodeDefinition,\n];\n\n/** Convenience: registry pre-loaded with every node ships with the engine. */\nexport function defaultRegistry(): NodeRegistry {\n const r = new NodeRegistry();\n for (const n of LOCAL_NODES) r.register(n);\n for (const n of REMOTE_NODES) r.register(n);\n return r;\n}\n\n/** Build a ready-to-run engine using env vars + the project cwd. */\nexport function createEngineFromEnv(\n opts: {\n cwd?: string;\n cacheDir?: string;\n outputsDir?: string;\n log?: (line: string) => void;\n /**\n * Layer the company-scoped remote cache over the local one (and stamp\n * durable asset URLs onto fresh outputs) so a fresh sandbox re-runs an\n * already-computed canvas at zero credits. Defaults to on; disable with\n * `remoteCache: false` or env BAKER_CANVAS_REMOTE_CACHE=off.\n */\n remoteCache?: boolean;\n } = {},\n): _Engine {\n const cwd = opts.cwd ?? process.cwd();\n const cacheDir = opts.cacheDir ?? path.join(cwd, \"canvas\", \".cache\");\n const outputsDir = opts.outputsDir ?? path.join(cwd, \"canvas\");\n const creds = requireCredentialsFromEnv();\n const client = new _BackendClient({ baseUrl: creds.url, apiKey: creds.apiKey });\n const assets = new _LocalAssetStore(path.join(cacheDir, \"assets\"));\n const localCache = new _LocalCacheStore(path.join(cacheDir, \"index\"));\n const remoteCacheEnabled = opts.remoteCache ?? remoteCacheEnabledFromEnv();\n const cache = remoteCacheEnabled\n ? new LayeredCacheStore({\n local: localCache,\n remote: new RemoteCacheStore(client, opts.log),\n assets,\n log: opts.log,\n })\n : localCache;\n return new _Engine({\n registry: defaultRegistry(),\n client,\n assets,\n cache,\n outputsDir,\n log: opts.log,\n persistAssets: remoteCacheEnabled,\n });\n}\n","import { debugLogHttp, readBodyForLog } from \"../../debugLog.ts\";\n\n// A deterministic provider content-policy block (fal/Seedance rejecting a photoreal\n// face). Backends signal it with `code: \"content_policy_blocked\"`; we key off the code,\n// not the HTTP status, because fal's proxy chain surfaces the same block as a clean 422\n// OR a masked 502 — treating it as a 5xx would retry a call that can never succeed.\nexport const CONTENT_POLICY_CODE = \"content_policy_blocked\";\n\ntype HttpError =\n | { kind: \"unauthorized\"; status: number; message: string }\n | { kind: \"validation\"; status: number; message: string; details?: unknown }\n | { kind: \"provider\"; status: number; provider?: string; code: string; message: string; retryable: boolean }\n | { kind: \"content_policy\"; status: number; provider?: string; message: string }\n | { kind: \"timeout\"; provider?: string; message: string }\n | { kind: \"server\"; status: number; message: string }\n | { kind: \"network\"; cause: unknown };\n\nexport class BackendHttpError extends Error {\n detail: HttpError;\n constructor(detail: HttpError) {\n super(describe(detail));\n this.name = \"BackendHttpError\";\n this.detail = detail;\n }\n}\n\nfunction describe(d: HttpError): string {\n switch (d.kind) {\n case \"unauthorized\":\n return `unauthorized: ${d.message}`;\n case \"validation\":\n return `invalid request: ${d.message}`;\n case \"provider\":\n return `provider error${d.provider ? ` (${d.provider})` : \"\"}: ${d.message}`;\n case \"content_policy\":\n return `content policy blocked${d.provider ? ` (${d.provider})` : \"\"}: ${d.message}`;\n case \"timeout\":\n return `provider timeout${d.provider ? ` (${d.provider})` : \"\"}: ${d.message}`;\n case \"server\":\n return `server error ${d.status}: ${d.message}`;\n case \"network\":\n return d.cause instanceof Error ? `network: ${d.cause.message}` : \"network error\";\n default: {\n const _ex: never = d;\n return String(_ex);\n }\n }\n}\n\ntype HttpClientOpts = {\n baseUrl: string;\n apiKey: string;\n timeoutMs?: number;\n maxRetries?: number;\n fetchFn?: typeof fetch;\n sleepFn?: (ms: number) => Promise<void>;\n};\n\nexport class HttpClient {\n private readonly baseUrl: string;\n private readonly apiKey: string;\n private readonly timeoutMs: number;\n private readonly maxRetries: number;\n private readonly fetchFn: typeof fetch;\n private readonly sleepFn: (ms: number) => Promise<void>;\n\n constructor(opts: HttpClientOpts) {\n this.baseUrl = opts.baseUrl.replace(/\\/+$/, \"\");\n this.apiKey = opts.apiKey;\n this.timeoutMs = opts.timeoutMs ?? 10 * 60 * 1000;\n this.maxRetries = opts.maxRetries ?? 3;\n this.fetchFn = opts.fetchFn ?? fetch;\n this.sleepFn = opts.sleepFn ?? ((ms) => new Promise((r) => setTimeout(r, ms)));\n }\n\n async postJson<T>(path: string, body: unknown, signal?: AbortSignal): Promise<T> {\n return await this.requestJson<T>(\"POST\", path, body, signal);\n }\n\n async putJson<T>(path: string, body: unknown, signal?: AbortSignal): Promise<T> {\n return await this.requestJson<T>(\"PUT\", path, body, signal);\n }\n\n async getJson<T>(path: string, signal?: AbortSignal): Promise<T> {\n return await this.requestJson<T>(\"GET\", path, undefined, signal);\n }\n\n private async requestJson<T>(\n method: \"GET\" | \"POST\" | \"PUT\",\n path: string,\n body: unknown,\n signal?: AbortSignal,\n ): Promise<T> {\n const url = `${this.baseUrl}${path.startsWith(\"/\") ? path : `/${path}`}`;\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n const outcome = await this.attempt<T>(method, url, body, attempt, signal);\n if (outcome.kind === \"value\") return outcome.value;\n if (outcome.kind === \"retry\") {\n await this.sleepFn(backoffMs(attempt));\n continue;\n }\n throw outcome.error;\n }\n throw new BackendHttpError({ kind: \"server\", status: 0, message: \"retries exhausted\" });\n }\n\n private async attempt<T>(\n method: \"GET\" | \"POST\" | \"PUT\",\n url: string,\n body: unknown,\n attempt: number,\n signal: AbortSignal | undefined,\n ): Promise<{ kind: \"value\"; value: T } | { kind: \"retry\" } | { kind: \"throw\"; error: BackendHttpError }> {\n const controller = new AbortController();\n const onAbort = () => controller.abort(signal?.reason);\n if (signal) {\n if (signal.aborted) controller.abort(signal.reason);\n else signal.addEventListener(\"abort\", onAbort, { once: true });\n }\n const timer = setTimeout(() => controller.abort(new Error(\"timeout\")), this.timeoutMs);\n const startedAt = Date.now();\n try {\n const res = await this.fetchFn(url, {\n method,\n headers:\n method === \"GET\"\n ? { Authorization: `Bearer ${this.apiKey}` }\n : { \"Content-Type\": \"application/json\", Authorization: `Bearer ${this.apiKey}` },\n body: method === \"GET\" ? undefined : JSON.stringify(body),\n signal: controller.signal,\n });\n debugLogHttp({\n source: \"canvas\",\n method,\n url,\n requestBody: method === \"GET\" ? undefined : body,\n status: res.status,\n ok: res.ok,\n responseBody: await readBodyForLog(res),\n durationMs: Date.now() - startedAt,\n });\n if (res.ok) return { kind: \"value\", value: (await res.json()) as T };\n const err = await parseErrorBody(res);\n if (attempt < this.maxRetries && shouldRetry(err)) return { kind: \"retry\" };\n return { kind: \"throw\", error: new BackendHttpError(err) };\n } catch (e) {\n debugLogHttp({\n source: \"canvas\",\n method,\n url,\n requestBody: method === \"GET\" ? undefined : body,\n durationMs: Date.now() - startedAt,\n error: e,\n });\n return this.handleAttemptException(e, attempt, signal, method);\n } finally {\n clearTimeout(timer);\n if (signal) signal.removeEventListener(\"abort\", onAbort);\n }\n }\n\n private handleAttemptException(\n e: unknown,\n attempt: number,\n signal: AbortSignal | undefined,\n method: \"GET\" | \"POST\" | \"PUT\",\n ): { kind: \"retry\" } | { kind: \"throw\"; error: BackendHttpError } {\n if (e instanceof BackendHttpError) return { kind: \"throw\", error: e };\n const aborted = (e as { name?: string }).name === \"AbortError\";\n if (aborted && signal?.aborted) {\n return { kind: \"throw\", error: new BackendHttpError({ kind: \"network\", cause: signal.reason ?? e }) };\n }\n // Internal timeout: retrying a POST re-dispatches a non-idempotent provider\n // call (the backend only replays *completed* responses, and a timeout means\n // nothing was stored), so only GETs auto-retry — a POST fails terminally\n // rather than risk a double charge.\n if (aborted) {\n if (method === \"GET\" && attempt < this.maxRetries) return { kind: \"retry\" };\n return { kind: \"throw\", error: new BackendHttpError({ kind: \"timeout\", message: \"request timed out\" }) };\n }\n if (attempt < this.maxRetries) return { kind: \"retry\" };\n return { kind: \"throw\", error: new BackendHttpError({ kind: \"network\", cause: e }) };\n }\n}\n\ntype ErrorBody = { code?: string; message?: string; provider?: string; retryable?: boolean; details?: unknown };\n\nasync function parseErrorBody(res: Response): Promise<HttpError> {\n let body: { error?: ErrorBody } = {};\n try {\n body = (await res.json()) as typeof body;\n } catch {\n // ignore parse errors\n }\n const errObj = body.error ?? {};\n return classifyHttpError(res.status, errObj, errObj.message ?? `HTTP ${res.status}`);\n}\n\nfunction classifyHttpError(status: number, errObj: ErrorBody, message: string): HttpError {\n // Code-based override FIRST: a content-policy block is non-retryable regardless of\n // the HTTP status it arrives on (fal masks the same 422 as a 502 in its proxy chain).\n if (errObj.code === CONTENT_POLICY_CODE) {\n return { kind: \"content_policy\", status, provider: errObj.provider, message };\n }\n if (status === 401 || status === 403) {\n return { kind: \"unauthorized\", status, message };\n }\n if (status === 400 || status === 422) {\n return { kind: \"validation\", status, message, details: errObj.details };\n }\n if (status === 502 || status === 504) {\n if (errObj.code === \"provider_timeout\" || status === 504) {\n return { kind: \"timeout\", provider: errObj.provider, message };\n }\n return {\n kind: \"provider\",\n status,\n provider: errObj.provider,\n code: errObj.code ?? \"provider_error\",\n message,\n retryable: errObj.retryable ?? true,\n };\n }\n if (status >= 500 || status === 429) {\n return { kind: \"server\", status, message };\n }\n // Remaining 4xx (404, 405, 409, …): the request itself is wrong, so a retry\n // can't help — and re-dispatching a POST risks a double provider charge.\n return { kind: \"validation\", status, message, details: errObj.details };\n}\n\nfunction backoffMs(attempt: number): number {\n return 1000 * 2 ** attempt;\n}\n\nfunction shouldRetry(err: HttpError): boolean {\n if (err.kind === \"server\") return true;\n if (err.kind === \"provider\" && err.retryable) return true;\n return false;\n}\n","import { BackendHttpError, CONTENT_POLICY_CODE, HttpClient } from \"./http.ts\";\n\nexport type RawAssetOutput = {\n kind: \"image\" | \"video\" | \"audio\" | \"json\" | \"text\" | \"font\";\n url: string;\n sha256: string;\n mime: string;\n metadata?: Record<string, unknown>;\n};\n\ntype ExecRequest = {\n nodeType: string;\n nodeVersion: string;\n params: unknown;\n inputs: Record<string, unknown>;\n /** Run-scoped dedupe key: the backend replays the stored response for a\n * repeated key instead of re-dispatching to the provider (and re-charging). */\n idempotency_key?: string;\n /** Run + node identity, so a completed async job can be mapped back to its\n * frozen run's node by the backend stale-run reconciliation sweep. */\n canvas_run_id?: string;\n node_id?: string;\n};\n\ntype ExecResponse = {\n outputs: Record<string, RawAssetOutput | RawAssetOutput[] | unknown>;\n credits_charged?: number;\n duration_ms?: number;\n};\n\n/** A long-running node accepted as a background job (HTTP 202). */\ntype AsyncJobAccepted = { job_id: string; status: \"running\" };\n\n/** Poll response for `GET /api/canvas/jobs/{id}`. */\ntype JobStatus =\n | { status: \"running\" }\n | { status: \"completed\"; result: ExecResponse }\n | { status: \"failed\"; error: JobError };\n\nfunction isAsyncJob(res: ExecResponse | AsyncJobAccepted): res is AsyncJobAccepted {\n return typeof (res as AsyncJobAccepted).job_id === \"string\";\n}\n\nconst sleep = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));\n\ntype JobError = { code?: string; message?: string; provider?: string; retryable?: boolean; status?: number };\n\n// Surface the backend's classification so the engine maps it to a node execution\n// error (and honors `retryable`) — never an opaque crash or a blind whole-node\n// retry. A content-policy block keeps its distinct kind (async video_generate is\n// the primary node that hits it) so operators get the actionable guidance, not a\n// generic provider error.\nfunction failedJobError(error: JobError): BackendHttpError {\n if (error.code === CONTENT_POLICY_CODE) {\n return new BackendHttpError({\n kind: \"content_policy\",\n status: error.status ?? 422,\n provider: error.provider,\n message: error.message ?? \"content policy blocked\",\n });\n }\n return new BackendHttpError({\n kind: \"provider\",\n status: error.status ?? 502,\n provider: error.provider,\n code: error.code ?? \"provider_error\",\n message: error.message ?? \"deconstruct failed\",\n retryable: error.retryable ?? false,\n });\n}\n\n/**\n * Adaptive poll cadence: hit the status row fast for the first ~15 attempts so a\n * quick node (a cache hit, a short generation) surfaces in ~1s instead of ~3s,\n * then ease to 3s so a multi-minute video job is not hammered. Attempt-indexed\n * and pure so the schedule is unit-testable.\n */\nexport function pollInterval(attempt: number): number {\n return attempt < 15 ? 1_000 : 3_000;\n}\n/** Outer safety bound before giving up polling an async job. */\nconst JOB_POLL_MAX_MS = 20 * 60 * 1000;\n\n/** A resumable run as reported by `GET /api/canvas/runs/active`. */\nexport type ActiveRunInfo = {\n runId: string;\n status: \"running\" | \"completed\" | \"failed\";\n interrupted?: boolean;\n updatedAt?: number;\n canvasSha?: string;\n canvasSnapshotUrl?: string;\n};\n\n/** The newest snapshot-bearing run for a creative — `GET /api/canvas/runs/latest`. */\nexport type SnapshotRunInfo = {\n runId: string;\n status: \"running\" | \"completed\" | \"failed\";\n interrupted?: boolean;\n canvasSha?: string;\n canvasSnapshotUrl: string;\n};\n\ntype ArtifactResponse = {\n artifact: {\n kind: string;\n name: string;\n version: string;\n description?: string;\n tags?: string[];\n slots: Record<string, RawAssetOutput | RawAssetOutput[]>;\n };\n manifest_sha: string;\n};\n\nexport class BackendClient {\n private readonly http: HttpClient;\n\n constructor(opts: {\n baseUrl: string;\n apiKey: string;\n fetchFn?: typeof fetch;\n timeoutMs?: number;\n maxRetries?: number;\n }) {\n this.http = new HttpClient(opts);\n }\n\n async exec(req: ExecRequest, signal?: AbortSignal): Promise<ExecResponse> {\n const res = await this.http.postJson<ExecResponse | AsyncJobAccepted>(\"/api/canvas/nodes/exec\", req, signal);\n // Long-running nodes (video_deconstruct) return a job id instead of running\n // synchronously, so no HTTP connection is held for their multi-minute\n // duration. Poll the cheap status endpoint until the job is terminal; each\n // poll is a fast request, so a stalled provider can never drop the work.\n if (isAsyncJob(res)) {\n return await this.pollJob(res.job_id, signal);\n }\n return res;\n }\n\n private async pollJob(jobId: string, signal?: AbortSignal): Promise<ExecResponse> {\n const deadline = Date.now() + JOB_POLL_MAX_MS;\n const path = `/api/canvas/jobs/${encodeURIComponent(jobId)}`;\n for (let attempt = 0; ; attempt++) {\n if (signal?.aborted) {\n throw new BackendHttpError({ kind: \"network\", cause: signal.reason ?? new Error(\"aborted\") });\n }\n const job = await this.http.getJson<JobStatus>(path, signal);\n if (job.status === \"completed\") return job.result;\n if (job.status === \"failed\") throw failedJobError(job.error);\n if (Date.now() > deadline) {\n throw new BackendHttpError({ kind: \"timeout\", message: `job ${jobId} did not finish in time` });\n }\n await sleep(pollInterval(attempt));\n }\n }\n\n presignAssetUpload(\n sha256: string,\n mime: string,\n signal?: AbortSignal,\n // GC-registry attribution: \"source\" marks bytes wired into COMMITTED repo\n // files (never sweepable), \"blueprint\" a portable run snapshot; omitted →\n // ordinary node output.\n purpose?: \"output\" | \"source\" | \"blueprint\",\n ): Promise<{ putUrl: string; publicUrl: string }> {\n return this.http.postJson<{ putUrl: string; publicUrl: string }>(\n \"/api/canvas/assets/presign\",\n { sha256, mime, purpose },\n signal,\n );\n }\n\n /** Remote cache lookup. A miss (404) — or an old backend without the route — returns null. */\n async getCacheEntry<T>(cacheKey: string, signal?: AbortSignal): Promise<T | null> {\n try {\n const res = await this.http.getJson<{ entry: T }>(`/api/canvas/cache/${encodeURIComponent(cacheKey)}`, signal);\n return res.entry;\n } catch (e) {\n if (e instanceof BackendHttpError && \"status\" in e.detail && e.detail.status === 404) return null;\n throw e;\n }\n }\n\n async putCacheEntry(entry: { cacheKey: string }, signal?: AbortSignal): Promise<void> {\n await this.http.putJson<{ success: boolean }>(\n `/api/canvas/cache/${encodeURIComponent(entry.cacheKey)}`,\n entry,\n signal,\n );\n }\n\n /** Durable run-history record — POST /api/canvas/runs (idempotent server-side on runId). */\n async recordRun(payload: unknown, signal?: AbortSignal): Promise<void> {\n await this.http.postJson<{ success: boolean }>(\"/api/canvas/runs\", payload, signal);\n }\n\n /**\n * Resumable-run lookup — GET /api/canvas/runs/active. Returns the newest\n * still-running/interrupted run for the creative (pinned to the exact canvas\n * sha), so a fresh sandbox can adopt its run id and re-attach billed\n * in-flight jobs. Null on no active run — or an older backend without the\n * route (both 404).\n */\n async getActiveRun(creativeSlug: string, canvasSha?: string, signal?: AbortSignal): Promise<ActiveRunInfo | null> {\n const params = new URLSearchParams({ slug: creativeSlug });\n if (canvasSha) params.set(\"sha\", canvasSha);\n try {\n const res = await this.http.getJson<{ run: ActiveRunInfo }>(`/api/canvas/runs/active?${params}`, signal);\n return res.run;\n } catch (e) {\n if (e instanceof BackendHttpError && \"status\" in e.detail && e.detail.status === 404) return null;\n throw e;\n }\n }\n\n /**\n * Portable-rerun lookup — GET /api/canvas/runs/latest. The newest run for\n * the creative that recorded a canvas snapshot manifest; null when none\n * exists (or the backend predates the route — both 404).\n */\n async getLatestSnapshotRun(creativeSlug: string, signal?: AbortSignal): Promise<SnapshotRunInfo | null> {\n const params = new URLSearchParams({ slug: creativeSlug });\n try {\n const res = await this.http.getJson<{ run: SnapshotRunInfo }>(`/api/canvas/runs/latest?${params}`, signal);\n return res.run;\n } catch (e) {\n if (e instanceof BackendHttpError && \"status\" in e.detail && e.detail.status === 404) return null;\n throw e;\n }\n }\n\n /**\n * Chat-scoped blueprint sync — POST /api/creatives/definition. Lets the\n * dashboard draw a scaffolded creative's workflow graph BEFORE the first run.\n * Additive on the backend (never archives siblings, never sets definitionPath).\n */\n async syncCreativeDefinition(payload: unknown, signal?: AbortSignal): Promise<void> {\n await this.http.postJson<{ success: boolean }>(\"/api/creatives/definition\", payload, signal);\n }\n\n getArtifact(kind: string, name: string, version?: string, signal?: AbortSignal): Promise<ArtifactResponse> {\n const path = version\n ? `/api/canvas/artifacts/${encodeURIComponent(kind)}/${encodeURIComponent(name)}/${encodeURIComponent(version)}`\n : `/api/canvas/artifacts/${encodeURIComponent(kind)}/${encodeURIComponent(name)}`;\n return this.http.getJson<ArtifactResponse>(path, signal);\n }\n}\n","type BackendCredentials = {\n url: string;\n apiKey: string;\n};\n\nfunction credentialsFromEnv(env: NodeJS.ProcessEnv = process.env): BackendCredentials | null {\n const url = env.BAKER_API_URL;\n const apiKey = env.BAKER_API_KEY;\n if (!url || !apiKey) return null;\n return { url, apiKey };\n}\n\nexport function requireCredentialsFromEnv(env: NodeJS.ProcessEnv = process.env): BackendCredentials {\n const c = credentialsFromEnv(env);\n if (!c) {\n throw new Error(\"missing BAKER_API_URL and/or BAKER_API_KEY environment variables\");\n }\n if (!c.apiKey.startsWith(\"bk_\")) {\n throw new Error(\"BAKER_API_KEY must start with 'bk_'\");\n }\n return c;\n}\n\n/** Remote canvas cache + durable asset persistence — on unless explicitly opted out. */\nexport function remoteCacheEnabledFromEnv(env: NodeJS.ProcessEnv = process.env): boolean {\n return env.BAKER_CANVAS_REMOTE_CACHE !== \"off\";\n}\n","export type ValidationIssue = {\n path: string;\n code: string;\n message: string;\n // \"error\" (default) blocks validate/run; \"warning\" is advisory — surfaced but\n // never fatal, so a still-runnable canvas can flag a likely-wrong-but-legal\n // configuration (a missing element reference, a scene span past a model's cap).\n severity?: \"error\" | \"warning\";\n received?: unknown;\n expected?: string;\n did_you_mean?: string[];\n node_id?: string;\n node_type?: string;\n};\n\n/** An issue is blocking unless it is explicitly a warning. */\nexport function isBlocking(issue: ValidationIssue): boolean {\n return issue.severity !== \"warning\";\n}\n\nclass CanvasError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"CanvasError\";\n }\n}\n\nexport class ValidationError extends CanvasError {\n issues: ValidationIssue[];\n constructor(issues: ValidationIssue[]) {\n const head = issues[0];\n const summary = head ? `${head.code}: ${head.message}` : \"canvas validation failed\";\n super(`${issues.length} validation issue(s): ${summary}`);\n this.name = \"ValidationError\";\n this.issues = issues;\n }\n}\n\ntype NodeExecutionErrorCause =\n | { kind: \"local\"; cause: unknown }\n // `retryable` is the backend's authoritative classification: `providerErr`\n // pins every provider failure to HTTP 502 and carries real retryability in a\n // separate body field, so `status` alone can't be trusted for it.\n | { kind: \"remote\"; status: number; code: string; message: string; provider?: string; retryable?: boolean }\n | { kind: \"timeout\"; provider?: string }\n | { kind: \"network\"; cause: unknown }\n // A deterministic provider content-policy block (e.g. fal/Seedance rejecting a\n // photoreal face as a real-person likeness). NEVER retryable — it fails identically\n // on every attempt — so it surfaces as its own actionable kind, not a generic error.\n | { kind: \"content_policy\"; provider?: string; message: string };\n\nexport class NodeExecutionError extends CanvasError {\n nodeId: string;\n nodeType: string;\n cause: NodeExecutionErrorCause;\n constructor(nodeId: string, nodeType: string, cause: NodeExecutionErrorCause) {\n super(`node ${nodeId} (${nodeType}) failed: ${describeCause(cause)}`);\n this.name = \"NodeExecutionError\";\n this.nodeId = nodeId;\n this.nodeType = nodeType;\n this.cause = cause;\n }\n}\n\n/**\n * The run was deliberately aborted rather than failing on its own.\n * - \"signal\" (SIGINT/SIGTERM): terminal for this process but RESUMABLE — the\n * caller must preserve the in-flight marker so the next run re-attaches\n * in-flight billed jobs instead of re-billing them.\n * - \"cost_cap\" (--max-credits): enforced only at safe points (pre-flight and\n * layer boundaries) where no async job is in flight, so the marker may be\n * cleared; completed nodes stay cached for a capped-up retry.\n */\nexport class RunAbortedError extends CanvasError {\n reason: \"signal\" | \"cost_cap\";\n constructor(reason: \"signal\" | \"cost_cap\", message: string) {\n super(message);\n this.name = \"RunAbortedError\";\n this.reason = reason;\n }\n}\n\nexport type LayerFailure = { nodeId: string; reason: unknown };\n\n/** Two or more nodes of the same topological layer failed; every failure is kept. */\nexport class LayerExecutionError extends CanvasError {\n failures: LayerFailure[];\n constructor(failures: LayerFailure[]) {\n const ids = failures.map((f) => f.nodeId).join(\", \");\n super(`${failures.length} nodes failed in one layer: ${ids}`);\n this.name = \"LayerExecutionError\";\n this.failures = failures;\n }\n}\n\nexport function describeFailureReason(reason: unknown): string {\n return reason instanceof Error ? reason.message : String(reason);\n}\n\n/**\n * Structured per-node failure detail persisted onto the run record so the\n * dashboard can show *why* a node died — the real upstream status/provider —\n * instead of only a red node and the layer's summary banner. Mirrors the\n * `NodeExecutionErrorCause` variants into a compact, display-ready shape.\n */\nexport type NodeFailureDetail = {\n message: string;\n /** Engine/provider error code (`server_error`, `unauthorized`, `content_policy`, `timeout`, …). */\n code?: string;\n provider?: string;\n retryable?: boolean;\n};\n\nexport function failureDetail(reason: unknown): NodeFailureDetail {\n if (reason instanceof NodeExecutionError) {\n const c = reason.cause;\n switch (c.kind) {\n case \"remote\":\n // `c.message` carries the true upstream text (e.g. `elevenlabs 502: …`).\n // Prefer the backend's authoritative `retryable` flag; only fall back to\n // status (5xx/429 transient) when it's absent, since `providerErr` masks\n // every provider failure as HTTP 502 and a bare status would then read\n // as \"retryable\" even for a non-retryable 4xx (e.g. an ElevenLabs 401).\n return {\n message: c.message,\n code: c.code,\n provider: c.provider,\n retryable: c.retryable ?? (c.status >= 500 || c.status === 429),\n };\n case \"timeout\":\n return {\n message: `timed out${c.provider ? ` (${c.provider})` : \"\"}`,\n code: \"timeout\",\n provider: c.provider,\n retryable: true,\n };\n case \"content_policy\":\n return { message: c.message, code: \"content_policy\", provider: c.provider, retryable: false };\n case \"network\":\n return {\n message: c.cause instanceof Error ? c.cause.message : \"network error\",\n code: \"network\",\n retryable: true,\n };\n case \"local\":\n return { message: c.cause instanceof Error ? c.cause.message : String(c.cause), code: \"local\" };\n default: {\n const _exhaustive: never = c;\n return { message: String(_exhaustive) };\n }\n }\n }\n return { message: describeFailureReason(reason) };\n}\n\nfunction describeCause(c: NodeExecutionErrorCause): string {\n switch (c.kind) {\n case \"local\":\n return c.cause instanceof Error ? c.cause.message : String(c.cause);\n case \"remote\":\n return `[${c.code}] ${c.message}${c.provider ? ` (${c.provider})` : \"\"}`;\n case \"timeout\":\n return `timeout${c.provider ? ` (${c.provider})` : \"\"}`;\n case \"network\":\n return c.cause instanceof Error ? `network: ${c.cause.message}` : \"network error\";\n case \"content_policy\":\n return `CONTENT_POLICY_BLOCKED${c.provider ? ` (${c.provider})` : \"\"}: ${c.message}`;\n default: {\n const _exhaustive: never = c;\n return String(_exhaustive);\n }\n }\n}\n","/**\n * Ad-platform → aspect-ratio presets for the `image_aspect_adapt` node.\n *\n * A creative is authored at ONE base ratio; fanning it out to every placement\n * a platform expects is mechanical, but the ratio set is easy to misremember.\n * These presets name the platform once and expand to the canonical set, so the\n * agent (and the node) never hand-list ratios from memory.\n *\n * Only **on-grid** ratios (a subset of the node's `ASPECT_ADAPT_FORMATS`) are\n * emitted — the node renders those directly, and formats that already match the\n * source ratio pass through free. Off-grid targets a platform also accepts\n * (e.g. Google's 1.91:1 landscape) are recorded in `offGrid` for a follow-up\n * `baker images crop` pass; they are NOT rendered by the adapt node.\n *\n * Shared by the CLI node (cost estimate) and the backend handler (expansion),\n * so both price and run a `platform` request identically.\n */\n\nexport const AD_FORMAT_PLATFORMS = [\n \"meta_feed\",\n \"meta_feed_stories\",\n \"meta_all\",\n \"linkedin\",\n \"google_demandgen\",\n \"tiktok\",\n \"youtube\",\n] as const;\n\nexport type AdFormatPlatform = (typeof AD_FORMAT_PLATFORMS)[number];\n\nexport type AdPlatformPreset = {\n /** On-grid target ratios the adapt node renders (source-matching ones pass through free). */\n readonly formats: readonly string[];\n /** Ratios the platform also accepts that the node can't render directly — crop from the nearest rendered format. */\n readonly offGrid?: readonly string[];\n /** One-line, agent-facing description of the set. */\n readonly note: string;\n};\n\nexport const AD_PLATFORM_FORMAT_PRESETS: Record<AdFormatPlatform, AdPlatformPreset> = {\n meta_feed: { formats: [\"4:5\"], note: \"Meta/Instagram feed static.\" },\n meta_feed_stories: { formats: [\"4:5\", \"9:16\"], note: \"Meta feed + Stories/Reels.\" },\n meta_all: { formats: [\"4:5\", \"9:16\", \"1:1\"], note: \"Meta feed + Stories/Reels + square.\" },\n linkedin: { formats: [\"1:1\"], note: \"LinkedIn single-image feed (square).\" },\n google_demandgen: {\n // Renders 16:9 too so the off-grid 1.91:1 landscape has a native source to crop from.\n formats: [\"1:1\", \"4:5\", \"16:9\"],\n offGrid: [\"1.91:1\"],\n note: \"Google Demand Gen; also wants 1.91:1 landscape — crop that from the rendered 16:9.\",\n },\n tiktok: { formats: [\"9:16\"], note: \"TikTok full-screen vertical.\" },\n youtube: { formats: [\"16:9\"], note: \"YouTube in-stream / companion display.\" },\n};\n\n/** The canonical on-grid ratio set the node should render for a platform. */\nexport function platformFormats(platform: AdFormatPlatform): readonly string[] {\n return AD_PLATFORM_FORMAT_PRESETS[platform].formats;\n}\n\n/**\n * The target ratios an `image_aspect_adapt` node renders: a `platform` preset\n * expanded to its canonical set, or the explicit `formats` list. The CLI (cost\n * estimate) and the backend (dispatch) both resolve through this one function\n * so they price and run a `platform` request identically.\n */\nexport function resolveAdaptFormats(params: {\n formats?: readonly string[];\n platform?: AdFormatPlatform;\n}): readonly string[] {\n if (params.platform) return platformFormats(params.platform);\n return params.formats ?? [];\n}\n","import cjsModule from '../index.js'\n\nexport const configure = cjsModule.configure\n\nexport const stringify = cjsModule\nexport default cjsModule\n","import stableStringify from \"safe-stable-stringify\";\n\n/**\n * Deterministic JSON encoding for cache keys.\n *\n * Rules (locked — drift breaks all caches):\n * 1. Object keys sorted alphabetically (codepoint order, locale-independent).\n * 2. No whitespace.\n * 3. `undefined` values and entries are dropped (not serialized as null).\n * 4. Strings are NFC-normalized before encoding.\n * 5. Numbers use the shortest representation (V8 default; we don't post-process).\n * 6. `NaN` and `±Infinity` throw — explicit reject, never silently encode.\n * 7. Arrays preserve order.\n */\nexport function canonicalize(value: unknown): string {\n const normalized = normalizeForCanonical(value);\n const out = stableStringify(normalized);\n if (out === undefined) {\n throw new Error(\"canonicalize: value serialized to undefined (top-level undefined?)\");\n }\n return out;\n}\n\nfunction normalizeForCanonical(value: unknown): unknown {\n if (value === null) return null;\n if (typeof value === \"string\") return value.normalize(\"NFC\");\n if (typeof value === \"number\") {\n if (!Number.isFinite(value)) {\n throw new Error(`canonicalize: non-finite number ${value}`);\n }\n return value;\n }\n if (typeof value === \"boolean\") return value;\n if (typeof value === \"bigint\") {\n throw new Error(\"canonicalize: bigint not supported\");\n }\n if (Array.isArray(value)) {\n return value.map(normalizeForCanonical);\n }\n if (typeof value === \"object\") {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(value)) {\n if (v === undefined) continue;\n out[k.normalize(\"NFC\")] = normalizeForCanonical(v);\n }\n return out;\n }\n // undefined, function, symbol — drop\n return undefined;\n}\n","/**\n * Model registry — single source of truth for per-model capabilities.\n *\n * Curated for the ad-creative use case. The canvas-engine runs inside the\n * controlled E2B sandbox (see `packages/e2b-template/src/template.ts`); we\n * expose a small, opinionated set of models rather than the full provider\n * catalogue. Param names here are CANONICAL — one name per concept across\n * all models. Provider-specific shapes get translated at the backend adapter\n * layer.\n *\n * Consumed by:\n * - the engine's pre-run validator (`validateModelParams`)\n * - the dashboard model picker (param controls + input slot icons)\n * - the backend handlers (defence-in-depth, when wired)\n */\n\nimport { AD_FORMAT_PLATFORMS } from \"./adPlatformFormats\";\n\nexport type ParamSchema =\n | { kind: \"string\"; enum?: readonly string[]; maxLength?: number }\n | { kind: \"number\"; enum?: readonly number[]; min?: number; max?: number }\n | { kind: \"boolean\" }\n | { kind: \"json\" };\n\nexport type InputKind = \"image\" | \"video\" | \"audio\";\n\n/**\n * A single input slot the model can consume. `mimes` is the set of MIME types\n * the provider accepts for that kind — used by Stage 3 pre-flight MIME\n * enforcement (a mime mismatch between source output and sink accepted set is\n * a `mime_not_accepted` validation error).\n */\ntype InputSpec = {\n kind: InputKind;\n mimes?: readonly string[];\n};\n\ntype ModelSpec = {\n /** Human label shown in the model picker. */\n label: string;\n /** Input slots the canvas MUST wire up for this model to run. */\n inputs: readonly InputSpec[];\n /**\n * Input slots the model can use if provided but does not require. The UI\n * shows icons for these as drop-targets; the validator does not require\n * them.\n */\n optional_inputs?: readonly InputSpec[];\n /** Canonical param names that MUST be present. */\n required: readonly string[];\n /** Allowed params keyed by canonical name + per-param schema. */\n params: Readonly<Record<string, ParamSchema>>;\n};\n\nexport type NodeKind =\n | \"text_generate\"\n | \"image_aspect_adapt\"\n | \"image_describe\"\n | \"image_generate\"\n | \"image_reference_sheet\"\n | \"image_select\"\n | \"video_generate\"\n | \"video_deconstruct\"\n | \"video_lipsync\"\n | \"tts\"\n | \"audio_voice_convert\"\n | \"music\"\n | \"dialogue\"\n | \"sound_effect\";\n\n// ---------------------------------------------------------------------------\n// Shared enums\n// ---------------------------------------------------------------------------\n\nconst OPENROUTER_IMAGE_AR = [\"1:1\", \"2:3\", \"3:2\", \"3:4\", \"4:3\", \"4:5\", \"5:4\", \"9:16\", \"16:9\", \"21:9\"] as const;\nconst OPENROUTER_IMAGE_AR_EXTREME = [...OPENROUTER_IMAGE_AR, \"1:4\", \"4:1\", \"1:8\", \"8:1\"] as const;\n\n// gpt-image-2 accepts a NARROWER ratio set than every other image model here —\n// notably no 4:5 or 5:4, which are the Meta/Instagram feed portrait formats.\n// OpenRouter rejects an unlisted ratio with a pre-dispatch 400\n// (\"aspect_ratio: not supported. Accepted: 1:1, 3:2, 2:3, 4:3, 3:4, 16:9, 9:16,\n// 21:9, auto\"), so portrait ad formats must come from `image_aspect_adapt` on a\n// Gemini model rather than straight out of gpt-image-2.\n// Source: GET /api/v1/images/models/openai/gpt-image-2/endpoints.\nconst OPENROUTER_IMAGE_AR_GPT = [\"1:1\", \"2:3\", \"3:2\", \"3:4\", \"4:3\", \"9:16\", \"16:9\", \"21:9\"] as const;\n\nconst OPENROUTER_IMAGE_SIZE = [\"1K\", \"2K\", \"4K\"] as const;\nconst OPENROUTER_IMAGE_SIZE_EXTENDED = [\"0.5K\", ...OPENROUTER_IMAGE_SIZE] as const;\n\n// OpenRouter's unified image API forwards a `quality` knob (providers without one\n// ignore it). The scaffolder sets `high` for photoreal ad frames on the models that\n// honor it (gpt-image, Gemini).\nconst OPENROUTER_IMAGE_QUALITY = [\"auto\", \"low\", \"medium\", \"high\"] as const;\n\n// Seedance accepts only specific durations per provider docs; the gaps\n// (7/9/11/13/14) trigger 400s. Exported so the video scaffold snaps scene\n// lengths to the same allowed set instead of keeping a copy that can drift.\nexport const SEEDANCE_DURATIONS = [4, 5, 6, 8, 10, 12, 15] as const;\n\n// Kling accepts ANY whole second from 3 to 15 (OpenRouter\n// GET /api/v1/videos/models). Unlike Seedance's fal-era gaps, there are none.\nexport const KLING_DURATIONS = [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] as const;\n\n// ElevenLabs `output_format` values the pipeline supports. Constrained to the\n// mp3 family: the backend handlers label every stored audio asset audio/mpeg,\n// so pcm/opus/ulaw would be saved under a wrong mime and break downstream\n// ffmpeg/composition steps. Widen only together with mime handling.\nexport const ELEVENLABS_OUTPUT_FORMATS = [\n \"mp3_22050_32\",\n \"mp3_44100_32\",\n \"mp3_44100_64\",\n \"mp3_44100_96\",\n \"mp3_44100_128\",\n \"mp3_44100_192\",\n] as const;\n\n// Hard validation bounds derived from the backend's per-node cost cap\n// (MAX_CANVAS_NODE_COST_USD = $10): anything above these always dies at\n// dispatch with `cost_limit_exceeded`, so reject it at validation instead.\n// tts/dialogue: $10 / $0.00022 per character. music: $10 / $0.022 per second.\nexport const ELEVENLABS_MAX_TEXT_CHARS = 45_454;\nexport const ELEVENLABS_MAX_MUSIC_LENGTH_MS = 454_545;\n\n// ---------------------------------------------------------------------------\n// Accepted-mime sets — keyed by provider transport, not by model.\n// ---------------------------------------------------------------------------\n\nconst OPENROUTER_IMAGE_MIMES = [\"image/png\", \"image/jpeg\", \"image/webp\", \"image/gif\"] as const;\nconst REPLICATE_IMAGE_MIMES = [\"image/png\", \"image/jpeg\", \"image/webp\"] as const;\nconst REPLICATE_VIDEO_MIMES = [\"video/mp4\", \"video/webm\", \"video/quicktime\"] as const;\n// Formats both Mux (frame extraction) and Gemini (multimodal analysis) accept.\nconst DECONSTRUCT_VIDEO_MIMES = [\"video/mp4\", \"video/webm\", \"video/quicktime\"] as const;\nconst REPLICATE_AUDIO_MIMES = [\"audio/wav\", \"audio/mpeg\", \"audio/mp3\"] as const;\n\n// ---------------------------------------------------------------------------\n// Registry\n// ---------------------------------------------------------------------------\n\n/**\n * Canonical, ordered list of `image_generate` model ids. Single source of truth\n * shared by the backend HTTP boundary (`z.enum`) and the CLI `images generate`\n * command, so the accepted-model set can never drift between them. These MUST\n * stay in sync with the keys of `MODEL_REGISTRY.image_generate` below — the\n * `_assertImageGenerateModelsMatchRegistry` type guard enforces it at compile time.\n */\nexport const IMAGE_GENERATE_MODELS = [\n \"openai/gpt-image-2\",\n \"openai/gpt-5.4-image-2\",\n \"google/gemini-3.1-flash-image-preview\",\n \"google/gemini-3-pro-image-preview\",\n \"recraft/recraft-v4.1-pro-vector\",\n] as const;\n\n/**\n * Default image-generation model when a caller doesn't specify one — Nano Banana\n * flash (`google/gemini-3.1-flash-image-preview`): fast iteration, reference\n * editing, and extreme aspect ratios.\n * The `(typeof IMAGE_GENERATE_MODELS)[number]` annotation guarantees at compile\n * time that the default is one of the accepted models. Consumed by the backend\n * `/api/images/generate` handler so the literal lives in exactly one place.\n */\nexport const DEFAULT_IMAGE_GENERATE_MODEL: (typeof IMAGE_GENERATE_MODELS)[number] =\n \"google/gemini-3.1-flash-image-preview\";\n\n/**\n * Canonical, ordered list of `video_generate` model ids — a deliberately SMALL,\n * curated roster (not a Higgsfield-style catalog). Each slot earns its place as\n * \"the best model for a specific job\":\n * - `bytedance/seedance-2.0` — identity/product workhorse (cheap, strong i2v).\n * - `google/veo-3.1` — photoreal cine ceiling + real-face fallback (dodges the\n * ByteDance real-person filter).\n * - `google/veo-3.1-fast` — cheap Veo iteration tier.\n * - `kwaivgi/kling-v3.0-pro` — motion-transfer / dynamic multi-shot beats.\n * Kept in sync with the keys of `MODEL_REGISTRY.video_generate` by the\n * `video_generate lists exactly the keys` invariant in `registry.test.ts`.\n */\nexport const VIDEO_GENERATE_MODELS = [\n \"bytedance/seedance-2.0\",\n \"google/veo-3.1\",\n \"google/veo-3.1-fast\",\n \"kwaivgi/kling-v3.0-pro\",\n] as const;\n\n/**\n * Default video-generation model when a caller doesn't specify one — the\n * identity/product workhorse. Kept as a named constant (not a hardcoded string\n * at call sites) per the model-catalog rule; the CLI scaffolder's scored router\n * can override it per brief.\n */\nexport const DEFAULT_VIDEO_GENERATE_MODEL: (typeof VIDEO_GENERATE_MODELS)[number] = \"bytedance/seedance-2.0\";\n\n/**\n * Which models can do REFERENCE-to-video — several images used as visual\n * guidance rather than as the exact opening frame.\n *\n * Only Seedance, and only because we route it through Replicate, whose Seedance\n * wrapper takes `reference_images`. Every model reached through OpenRouter is\n * frame-only: `GET /api/v1/videos/models` reports `supported_frame_images:\n * [\"first_frame\", \"last_frame\"]` for Veo and Kling and advertises no reference\n * capability at all. OpenRouter's generic body does define `input_references`,\n * but sending it to a frame-only model produces a request with no usable image\n * conditioning, which the provider rejects — every clip in the batch, every\n * time. Gate on this instead of discovering it one billed refusal at a time.\n */\nexport const REFERENCE_TO_VIDEO_MODELS = [\"bytedance/seedance-2.0\"] as const;\n\nexport function supportsReferenceToVideo(model: string): boolean {\n return (REFERENCE_TO_VIDEO_MODELS as readonly string[]).includes(model);\n}\n\nexport const MODEL_REGISTRY: Readonly<Record<NodeKind, Readonly<Record<string, ModelSpec>>>> = {\n text_generate: {\n \"~google/gemini-flash-latest\": {\n label: \"Google Gemini Flash (latest)\",\n inputs: [],\n required: [\"prompt\"],\n params: {\n prompt: { kind: \"string\" },\n system: { kind: \"string\" },\n response_format: { kind: \"string\", enum: [\"text\", \"json_object\"] },\n web_search: { kind: \"boolean\" },\n temperature: { kind: \"number\", min: 0, max: 2 },\n max_tokens: { kind: \"number\", min: 1 },\n },\n },\n \"~google/gemini-pro-latest\": {\n label: \"Google Gemini Pro (latest)\",\n inputs: [],\n required: [\"prompt\"],\n params: {\n prompt: { kind: \"string\" },\n system: { kind: \"string\" },\n response_format: { kind: \"string\", enum: [\"text\", \"json_object\"] },\n web_search: { kind: \"boolean\" },\n temperature: { kind: \"number\", min: 0, max: 2 },\n max_tokens: { kind: \"number\", min: 1 },\n },\n },\n },\n\n image_describe: {\n // Vision extraction — the Visual Architect system prompt lives on the\n // backend, so there is no `prompt` param; `focus` appends emphasis only.\n \"~google/gemini-pro-latest\": {\n label: \"Google Gemini Pro (latest, Vision)\",\n inputs: [{ kind: \"image\", mimes: OPENROUTER_IMAGE_MIMES }],\n required: [],\n params: {\n focus: { kind: \"string\" },\n context: { kind: \"string\" },\n temperature: { kind: \"number\", min: 0, max: 2 },\n max_tokens: { kind: \"number\", min: 1 },\n },\n },\n \"~google/gemini-flash-latest\": {\n label: \"Google Gemini Flash (latest, Vision)\",\n inputs: [{ kind: \"image\", mimes: OPENROUTER_IMAGE_MIMES }],\n required: [],\n params: {\n focus: { kind: \"string\" },\n context: { kind: \"string\" },\n temperature: { kind: \"number\", min: 0, max: 2 },\n max_tokens: { kind: \"number\", min: 1 },\n },\n },\n },\n\n image_select: {\n // Vision judgement — the selection contract (numbered images, JSON\n // response) is baked into the backend prompt; `prompt` carries only the\n // selection criteria. `count` has an engine-side default of 1, so it is\n // not registry-required.\n \"~google/gemini-flash-latest\": {\n label: \"Google Gemini Flash (latest, Vision)\",\n inputs: [{ kind: \"image\", mimes: OPENROUTER_IMAGE_MIMES }],\n required: [\"prompt\"],\n params: {\n prompt: { kind: \"string\" },\n count: { kind: \"number\", min: 1 },\n temperature: { kind: \"number\", min: 0, max: 2 },\n max_tokens: { kind: \"number\", min: 1 },\n },\n },\n \"~google/gemini-pro-latest\": {\n label: \"Google Gemini Pro (latest, Vision)\",\n inputs: [{ kind: \"image\", mimes: OPENROUTER_IMAGE_MIMES }],\n required: [\"prompt\"],\n params: {\n prompt: { kind: \"string\" },\n count: { kind: \"number\", min: 1 },\n temperature: { kind: \"number\", min: 0, max: 2 },\n max_tokens: { kind: \"number\", min: 1 },\n },\n },\n },\n\n image_generate: {\n // `seed` is omitted on every entry — OpenRouter's `image_config` schema\n // has no `seed` slot for image-gen (different from video-gen), so passing\n // it would be a silent no-op.\n // The direct image model, not the `gpt-5.4-image-2` chat model that emitted\n // images as a side effect. Notable capability gaps vs the Gemini entries:\n // no `image_size` (OpenAI picks the pixel dimensions from the ratio, and a\n // `resolution` is silently ignored) and the narrower `..._AR_GPT` ratio set.\n \"openai/gpt-image-2\": {\n label: \"OpenAI GPT Image 2\",\n inputs: [],\n optional_inputs: [{ kind: \"image\", mimes: OPENROUTER_IMAGE_MIMES }],\n required: [\"prompt\"],\n params: {\n prompt: { kind: \"string\" },\n aspect_ratio: { kind: \"string\", enum: OPENROUTER_IMAGE_AR_GPT },\n quality: { kind: \"string\", enum: OPENROUTER_IMAGE_QUALITY },\n },\n },\n // LEGACY — kept so canvases authored before the gpt-image-2 switch still\n // validate and re-run unchanged (`baker canvas rerun` restores a recorded\n // canvas verbatim, so dropping this model would break every stored creative\n // that used it). Its param surface is the ORIGINAL one on purpose: unlike\n // gpt-image-2 it still honors 4:5/5:4, and `image_size` is accepted-then-\n // ignored upstream rather than rejected. Verified live on /api/v1/images.\n // Don't reach for it in new work — the scaffolders default to gpt-image-2.\n \"openai/gpt-5.4-image-2\": {\n label: \"OpenAI GPT-5.4 Image 2 (legacy)\",\n inputs: [],\n optional_inputs: [{ kind: \"image\", mimes: OPENROUTER_IMAGE_MIMES }],\n required: [\"prompt\"],\n params: {\n prompt: { kind: \"string\" },\n aspect_ratio: { kind: \"string\", enum: OPENROUTER_IMAGE_AR },\n image_size: { kind: \"string\", enum: OPENROUTER_IMAGE_SIZE },\n quality: { kind: \"string\", enum: OPENROUTER_IMAGE_QUALITY },\n },\n },\n \"google/gemini-3.1-flash-image-preview\": {\n label: \"Google Gemini 3.1 Flash Image (Preview)\",\n inputs: [],\n optional_inputs: [{ kind: \"image\", mimes: OPENROUTER_IMAGE_MIMES }],\n required: [\"prompt\"],\n params: {\n prompt: { kind: \"string\" },\n aspect_ratio: { kind: \"string\", enum: OPENROUTER_IMAGE_AR_EXTREME },\n image_size: { kind: \"string\", enum: OPENROUTER_IMAGE_SIZE_EXTENDED },\n },\n },\n \"google/gemini-3-pro-image-preview\": {\n label: \"Google Gemini 3 Pro Image (Nano Banana Pro)\",\n inputs: [],\n optional_inputs: [{ kind: \"image\", mimes: OPENROUTER_IMAGE_MIMES }],\n required: [\"prompt\"],\n params: {\n prompt: { kind: \"string\" },\n aspect_ratio: { kind: \"string\", enum: OPENROUTER_IMAGE_AR },\n image_size: { kind: \"string\", enum: OPENROUTER_IMAGE_SIZE },\n quality: { kind: \"string\", enum: OPENROUTER_IMAGE_QUALITY },\n },\n },\n \"recraft/recraft-v4.1-pro-vector\": {\n label: \"Recraft v4.1 Pro Vector\",\n inputs: [],\n optional_inputs: [{ kind: \"image\", mimes: OPENROUTER_IMAGE_MIMES }],\n required: [\"prompt\"],\n params: {\n prompt: { kind: \"string\" },\n aspect_ratio: { kind: \"string\", enum: OPENROUTER_IMAGE_AR },\n image_size: { kind: \"string\", enum: OPENROUTER_IMAGE_SIZE },\n strength: { kind: \"number\", min: 0, max: 1 },\n rgb_colors: { kind: \"json\" },\n background_rgb_color: { kind: \"json\" },\n },\n },\n },\n\n image_reference_sheet: {\n // Multi-view subject reference sheets (turnaround grids). The sheet prompt\n // is baked into the backend handler — params here are semantic levers\n // only. Both models consume MULTIPLE reference images via the `references`\n // input slot (required: a sheet without source images is just image_generate).\n \"google/gemini-3-pro-image-preview\": {\n label: \"Google Gemini 3 Pro Image (Nano Banana Pro)\",\n inputs: [{ kind: \"image\", mimes: OPENROUTER_IMAGE_MIMES }],\n required: [\"subject_description\", \"subject_type\"],\n params: {\n subject_description: { kind: \"string\" },\n subject_type: { kind: \"string\", enum: [\"character\", \"person\", \"product\", \"location\"] },\n views: { kind: \"json\" },\n style: { kind: \"string\" },\n prompt_override: { kind: \"string\" },\n aspect_ratio: { kind: \"string\", enum: OPENROUTER_IMAGE_AR },\n image_size: { kind: \"string\", enum: OPENROUTER_IMAGE_SIZE },\n },\n },\n \"google/gemini-3.1-flash-image-preview\": {\n label: \"Google Gemini 3.1 Flash Image (Preview)\",\n inputs: [{ kind: \"image\", mimes: OPENROUTER_IMAGE_MIMES }],\n required: [\"subject_description\", \"subject_type\"],\n params: {\n subject_description: { kind: \"string\" },\n subject_type: { kind: \"string\", enum: [\"character\", \"person\", \"product\", \"location\"] },\n views: { kind: \"json\" },\n style: { kind: \"string\" },\n prompt_override: { kind: \"string\" },\n aspect_ratio: { kind: \"string\", enum: OPENROUTER_IMAGE_AR_EXTREME },\n image_size: { kind: \"string\", enum: OPENROUTER_IMAGE_SIZE_EXTENDED },\n },\n },\n },\n\n image_aspect_adapt: {\n // Multi-format adaptation of one creative. The recomposition prompt is\n // baked into the backend handler. The target ratios come from EITHER an\n // explicit `formats` list OR a `platform` preset that expands to the\n // canonical set; exactly one of the two is required — that \"one of\" gate,\n // and per-element ratio validation, live in the node's Zod schema (the\n // registry can't express \"one of\" or gate array elements), so `formats`\n // is not listed as registry-required. The source creative is a required\n // input slot.\n \"google/gemini-3-pro-image-preview\": {\n label: \"Google Gemini 3 Pro Image (Nano Banana Pro)\",\n inputs: [{ kind: \"image\", mimes: OPENROUTER_IMAGE_MIMES }],\n required: [],\n params: {\n formats: { kind: \"json\" },\n platform: { kind: \"string\", enum: AD_FORMAT_PLATFORMS },\n guidance: { kind: \"string\" },\n image_size: { kind: \"string\", enum: OPENROUTER_IMAGE_SIZE },\n },\n },\n \"google/gemini-3.1-flash-image-preview\": {\n label: \"Google Gemini 3.1 Flash Image (Preview)\",\n inputs: [{ kind: \"image\", mimes: OPENROUTER_IMAGE_MIMES }],\n required: [],\n params: {\n formats: { kind: \"json\" },\n platform: { kind: \"string\", enum: AD_FORMAT_PLATFORMS },\n guidance: { kind: \"string\" },\n image_size: { kind: \"string\", enum: OPENROUTER_IMAGE_SIZE_EXTENDED },\n },\n },\n },\n\n video_generate: {\n \"bytedance/seedance-2.0\": {\n // Routed via Replicate's official `bytedance/seedance-2.0` model. NOTE:\n // ByteDance's upstream likeness filter blocks photoreal human faces on ANY\n // reseller, and it does NOT care whether the person is real: it classifies\n // pixels, so an AI-generated face that looks photographic is refused\n // exactly like a photograph (E005 / content_policy_blocked). Confirmed in\n // production against faces we generated ourselves. The only escape is Veo\n // — NOT a synthetic presenter, which an earlier version of this note\n // wrongly recommended and which sends you round the same loop.\n label: \"ByteDance Seedance 2.0\",\n inputs: [],\n optional_inputs: [{ kind: \"image\", mimes: REPLICATE_IMAGE_MIMES }],\n required: [\"prompt\"],\n params: {\n // Replicate's Seedance wrapper hard-caps the prompt at 4000 chars; gate\n // it here so an over-length prompt fails validate (free) not the billed call.\n prompt: { kind: \"string\", maxLength: 4000 },\n aspect_ratio: {\n kind: \"string\",\n enum: [\"1:1\", \"3:4\", \"9:16\", \"4:3\", \"16:9\", \"21:9\", \"9:21\"],\n },\n resolution: { kind: \"string\", enum: [\"480p\", \"720p\", \"1080p\", \"4k\"] },\n duration: { kind: \"number\", enum: SEEDANCE_DURATIONS },\n seed: { kind: \"number\" },\n generate_audio: { kind: \"boolean\" },\n },\n },\n \"google/veo-3.1\": {\n // Photoreal CINE CEILING + the real-face fallback (Veo generates adult\n // humans from a keyframe, dodging ByteDance's real-person filter). Same\n // OpenRouter google-vertex routing as the fast tier; the quality dial is\n // `resolution: 1080p` + `generate_audio` + a real `negative_prompt`, not a\n // separate provider knob. Reach for this for hero beats and any clip that\n // must carry a real human likeness.\n label: \"Google Veo 3.1\",\n inputs: [],\n optional_inputs: [{ kind: \"image\", mimes: OPENROUTER_IMAGE_MIMES }],\n required: [\"prompt\"],\n params: {\n prompt: { kind: \"string\" },\n negative_prompt: { kind: \"string\" },\n aspect_ratio: { kind: \"string\", enum: [\"16:9\", \"9:16\"] },\n resolution: { kind: \"string\", enum: [\"720p\", \"1080p\", \"4K\"] },\n duration: { kind: \"number\", enum: [4, 6, 8] },\n seed: { kind: \"number\" },\n generate_audio: { kind: \"boolean\" },\n person_generation: { kind: \"string\", enum: [\"allow_all\", \"allow_adult\"] },\n enhance_prompt: { kind: \"boolean\" },\n conditioning_scale: { kind: \"number\" },\n },\n },\n \"kwaivgi/kling-v3.0-pro\": {\n // Motion-transfer / dynamic multi-shot beats. Reachable through the default\n // OpenRouter gateway (generic video body — no google-vertex block), so it\n // needs no direct-provider exception. `cfg_scale` trades prompt adherence\n // vs motion freedom; higher = closer to prompt.\n //\n // Params below are the ones OpenRouter actually advertises for this model\n // (GET /api/v1/videos/models). Three were wrong before and each was a free\n // 400 or a silently unsupported knob: it renders 720p ONLY (1080p was\n // offered and rejected), it takes ANY duration from 3-15s (we allowed just\n // 5 and 10), and it does not support `seed` at all.\n label: \"Kling 3.0\",\n inputs: [],\n optional_inputs: [{ kind: \"image\", mimes: OPENROUTER_IMAGE_MIMES }],\n required: [\"prompt\"],\n params: {\n // Kling caps the prompt shorter than Seedance; gate it here so an\n // over-length prompt fails validate (free) not the billed call.\n prompt: { kind: \"string\", maxLength: 2500 },\n negative_prompt: { kind: \"string\" },\n aspect_ratio: { kind: \"string\", enum: [\"16:9\", \"9:16\", \"1:1\"] },\n resolution: { kind: \"string\", enum: [\"720p\"] },\n duration: { kind: \"number\", enum: KLING_DURATIONS },\n generate_audio: { kind: \"boolean\" },\n cfg_scale: { kind: \"number\", min: 0, max: 1 },\n },\n },\n \"google/veo-3.1-fast\": {\n // Cheap test/iteration model. Forwarded by the backend via\n // `provider.options.google-vertex.parameters` (camelCased on the wire).\n label: \"Google Veo 3.1 Fast\",\n inputs: [],\n optional_inputs: [{ kind: \"image\", mimes: OPENROUTER_IMAGE_MIMES }],\n required: [\"prompt\"],\n params: {\n prompt: { kind: \"string\" },\n negative_prompt: { kind: \"string\" },\n aspect_ratio: { kind: \"string\", enum: [\"16:9\", \"9:16\"] },\n resolution: { kind: \"string\", enum: [\"720p\", \"1080p\", \"4K\"] },\n duration: { kind: \"number\", enum: [4, 6, 8] },\n seed: { kind: \"number\" },\n generate_audio: { kind: \"boolean\" },\n // Image-to-video and EU/UK/CH/MENA regions cap this at `allow_adult`;\n // `allow_all` is text-to-video only. Allow both so an image-conditioned\n // Veo clip (the real-face fallback) validates.\n person_generation: { kind: \"string\", enum: [\"allow_all\", \"allow_adult\"] },\n enhance_prompt: { kind: \"boolean\" },\n conditioning_scale: { kind: \"number\" },\n },\n },\n },\n\n video_deconstruct: {\n // Replication-grade video extraction — the forensic system prompts live on\n // the backend; `focus` appends emphasis only. Frames ride on a throwaway\n // Mux asset; analysis runs on Gemini with the video as a file part.\n \"~google/gemini-flash-latest\": {\n label: \"Google Gemini Flash (latest, Video)\",\n inputs: [{ kind: \"video\", mimes: DECONSTRUCT_VIDEO_MIMES }],\n required: [],\n params: {\n mode: { kind: \"string\", enum: [\"full\", \"index\"] },\n language: { kind: \"string\" },\n max_scenes: { kind: \"number\", min: 1, max: 60 },\n focus: { kind: \"string\" },\n start_s: { kind: \"number\", min: 0 },\n end_s: { kind: \"number\", min: 0 },\n max_clip_s: { kind: \"number\", min: 1, max: 60 },\n transcriber: { kind: \"string\", enum: [\"groq\", \"deepgram\"] },\n // Real visual shot-cut timestamps (seconds) from local PySceneDetect;\n // scene boundaries snap onto them so frames never straddle a hard cut.\n // Shape (number[]) is enforced by the node + backend Zod schemas.\n shot_cuts: { kind: \"json\" },\n },\n },\n \"~google/gemini-pro-latest\": {\n label: \"Google Gemini Pro (latest, Video)\",\n inputs: [{ kind: \"video\", mimes: DECONSTRUCT_VIDEO_MIMES }],\n required: [],\n params: {\n mode: { kind: \"string\", enum: [\"full\", \"index\"] },\n language: { kind: \"string\" },\n max_scenes: { kind: \"number\", min: 1, max: 60 },\n focus: { kind: \"string\" },\n start_s: { kind: \"number\", min: 0 },\n end_s: { kind: \"number\", min: 0 },\n max_clip_s: { kind: \"number\", min: 1, max: 60 },\n transcriber: { kind: \"string\", enum: [\"groq\", \"deepgram\"] },\n // See gemini-flash-latest above — local PySceneDetect shot-cut timestamps.\n shot_cuts: { kind: \"json\" },\n },\n },\n },\n\n video_lipsync: {\n \"fal/veed-lipsync\": {\n label: \"VEED Lipsync (fal.ai)\",\n inputs: [\n { kind: \"video\", mimes: REPLICATE_VIDEO_MIMES },\n { kind: \"audio\", mimes: REPLICATE_AUDIO_MIMES },\n ],\n required: [],\n params: {},\n },\n },\n\n tts: {\n \"elevenlabs/eleven_v3\": {\n // eleven_v3 does NOT yet support context stitching\n // (previous_text/next_text/*_request_ids). ElevenLabs returns a clean\n // `unsupported_model` 400 if you pass them.\n label: \"ElevenLabs Eleven v3\",\n inputs: [],\n required: [\"text\", \"voice\"],\n params: {\n text: { kind: \"string\", maxLength: ELEVENLABS_MAX_TEXT_CHARS },\n voice: { kind: \"string\" },\n language_code: { kind: \"string\" },\n stability: { kind: \"number\", min: 0, max: 1 },\n similarity_boost: { kind: \"number\", min: 0, max: 1 },\n voice_settings: { kind: \"json\" },\n seed: { kind: \"number\", min: 0, max: 4_294_967_295 },\n pronunciation_dictionary_locators: { kind: \"json\" },\n apply_text_normalization: { kind: \"string\", enum: [\"auto\", \"on\", \"off\"] },\n apply_language_text_normalization: { kind: \"boolean\" },\n with_timestamps: { kind: \"boolean\" },\n output_format: { kind: \"string\", enum: ELEVENLABS_OUTPUT_FORMATS },\n },\n },\n },\n\n audio_voice_convert: {\n \"elevenlabs/eleven_multilingual_sts_v2\": {\n // Speech-to-speech / Voice Changer: re-voice an existing audio clip in the\n // TARGET voice, preserving timing/prosody. Used to normalize a talking-head\n // clip's native (generator-chosen) voice into ONE consistent brand voice.\n label: \"ElevenLabs Voice Changer (multilingual STS v2)\",\n inputs: [{ kind: \"audio\", mimes: REPLICATE_AUDIO_MIMES }],\n required: [\"voice\"],\n params: {\n voice: { kind: \"string\" },\n output_format: { kind: \"string\", enum: ELEVENLABS_OUTPUT_FORMATS },\n remove_background_noise: { kind: \"boolean\" },\n },\n },\n },\n\n music: {\n \"elevenlabs/music-v1\": {\n label: \"ElevenLabs Music v1 (Compose)\",\n inputs: [],\n required: [],\n params: {\n prompt: { kind: \"string\" },\n composition_plan: { kind: \"json\" },\n music_length_ms: { kind: \"number\", min: 3000, max: ELEVENLABS_MAX_MUSIC_LENGTH_MS },\n seed: { kind: \"number\" },\n force_instrumental: { kind: \"boolean\" },\n respect_sections_durations: { kind: \"boolean\" },\n with_timestamps: { kind: \"boolean\" },\n output_format: { kind: \"string\", enum: ELEVENLABS_OUTPUT_FORMATS },\n },\n },\n \"elevenlabs/video-background-music-v1\": {\n label: \"ElevenLabs Video Background Music v1\",\n inputs: [{ kind: \"video\", mimes: REPLICATE_VIDEO_MIMES }],\n required: [],\n params: {\n description: { kind: \"string\" },\n tags: { kind: \"json\" },\n output_format: { kind: \"string\", enum: ELEVENLABS_OUTPUT_FORMATS },\n },\n },\n },\n\n dialogue: {\n \"elevenlabs/eleven_v3\": {\n label: \"ElevenLabs Eleven v3 (Dialogue)\",\n inputs: [],\n required: [\"inputs\"],\n params: {\n inputs: { kind: \"json\" },\n language_code: { kind: \"string\" },\n settings: { kind: \"json\" },\n seed: { kind: \"number\", min: 0, max: 4_294_967_295 },\n apply_text_normalization: { kind: \"string\", enum: [\"auto\", \"on\", \"off\"] },\n with_timestamps: { kind: \"boolean\" },\n output_format: { kind: \"string\", enum: ELEVENLABS_OUTPUT_FORMATS },\n },\n },\n },\n\n sound_effect: {\n \"elevenlabs/eleven_text_to_sound_v2\": {\n label: \"ElevenLabs Text-to-Sound v2\",\n inputs: [],\n required: [\"text\"],\n params: {\n text: { kind: \"string\" },\n duration_seconds: { kind: \"number\", min: 0.5, max: 30 },\n prompt_influence: { kind: \"number\", min: 0, max: 1 },\n loop: { kind: \"boolean\" },\n output_format: { kind: \"string\", enum: ELEVENLABS_OUTPUT_FORMATS },\n },\n },\n },\n};\n\n// ---------------------------------------------------------------------------\n// Capability lookups\n// ---------------------------------------------------------------------------\n//\n// Scaffolders build node params for whatever model the caller picked, and the\n// curated models do NOT agree on what they accept: gpt-image-2 has no\n// `image_size` and no 4:5/5:4, Gemini flash goes down to 0.5K and out to 8:1.\n// Reading the registry keeps that knowledge in one place instead of a per-model\n// `if` at every site that emits an `image_generate` node.\n\n/** Whether a model accepts a canonical param at all — false for unknown models. */\nexport function supportsParam(kind: NodeKind, model: string, param: string): boolean {\n return MODEL_REGISTRY[kind]?.[model]?.params[param] !== undefined;\n}\n\n/** The ratios a model accepts, or undefined when it has no `aspect_ratio` enum. */\nexport function supportedAspectRatios(kind: NodeKind, model: string): readonly string[] | undefined {\n const schema = MODEL_REGISTRY[kind]?.[model]?.params.aspect_ratio;\n return schema?.kind === \"string\" ? schema.enum : undefined;\n}\n\nfunction ratioValue(ratio: string): number | null {\n const [w, h] = ratio.split(\":\").map(Number);\n if (!w || !h || !Number.isFinite(w) || !Number.isFinite(h)) return null;\n return w / h;\n}\n\n/**\n * Snap a target ratio onto what `model` actually accepts, picking the closest\n * supported shape when the exact one is missing (4:5 → 3:4 on gpt-image-2).\n * Returns the target untouched when the model has no ratio enum or already\n * supports it, so callers can apply this unconditionally.\n */\nexport function nearestSupportedAspectRatio(kind: NodeKind, model: string, target: string): string {\n const supported = supportedAspectRatios(kind, model);\n if (!supported || supported.includes(target)) return target;\n const wanted = ratioValue(target);\n if (wanted === null) return target;\n let best = target;\n let bestDistance = Number.POSITIVE_INFINITY;\n for (const candidate of supported) {\n const value = ratioValue(candidate);\n if (value === null) continue;\n const distance = Math.abs(Math.log(value / wanted));\n if (distance < bestDistance) {\n bestDistance = distance;\n best = candidate;\n }\n }\n return best;\n}\n\n// NOTE: `IMAGE_GENERATE_MODELS` (above) must list exactly the keys of\n// `MODEL_REGISTRY.image_generate`. A compile-time check isn't possible —\n// MODEL_REGISTRY's `Record<string, ModelSpec>` annotation widens its keys to\n// `string` — so the invariant is enforced by `registry.test.ts` instead, which\n// keeps this module a pure, side-effect-free data export.\n","import { type InputKind, MODEL_REGISTRY, type NodeKind, type ParamSchema } from \"./registry\";\n\ntype ModelValidationError =\n | { code: \"unknown_model\"; message: string }\n | { code: \"missing_required_param\"; param: string; message: string }\n | { code: \"unknown_param\"; param: string; message: string }\n | { code: \"invalid_value\"; param: string; message: string }\n | { code: \"missing_input\"; input: InputKind; message: string };\n\ntype ModelValidationResult = { ok: true } | { ok: false; errors: ModelValidationError[] };\n\n// Derived from `MODEL_REGISTRY` (the canonical source of truth) rather than a\n// hand-maintained list — adding a kind to the registry forces it here too, so\n// the guard can never silently go stale. `Object.keys` matches own keys only,\n// so inherited prototype names (\"toString\" etc.) correctly return false; it also\n// stays ES2021-clean (the backend typechecks this package under `lib: ES2021`,\n// which rules out `Object.hasOwn`).\nfunction isManagedNodeKind(nodeType: string): nodeType is NodeKind {\n return Object.keys(MODEL_REGISTRY).includes(nodeType);\n}\n\n/**\n * Validate canvas params against the per-model spec. Use for any node whose\n * `nodeType` is one of the managed kinds (image_generate / video_generate /\n * video_lipsync / tts). Nodes outside this set fall back to their generic Zod\n * schema only.\n *\n * `model` is the canonical `<provider>/<model>` id from `params.model`.\n *\n * The `model` field itself is always allowed and not validated as a param.\n */\nfunction checkRequiredParams(\n spec: { required: readonly string[] },\n params: Record<string, unknown>,\n model: string,\n): ModelValidationError[] {\n const errors: ModelValidationError[] = [];\n for (const req of spec.required) {\n if (params[req] === undefined || params[req] === null) {\n errors.push({\n code: \"missing_required_param\",\n param: req,\n message: `missing required param \"${req}\" for model \"${model}\"`,\n });\n }\n }\n return errors;\n}\n\nfunction checkParamValues(\n spec: { params: Record<string, ParamSchema> },\n params: Record<string, unknown>,\n model: string,\n): ModelValidationError[] {\n const errors: ModelValidationError[] = [];\n for (const [key, value] of Object.entries(params)) {\n if (key === \"model\") continue;\n if (value === undefined) continue;\n const schema = spec.params[key];\n if (!schema) {\n errors.push({\n code: \"unknown_param\",\n param: key,\n message: `param \"${key}\" is not supported by model \"${model}\"`,\n });\n continue;\n }\n const valueErr = validateValue(key, value, schema, model);\n if (valueErr) errors.push(valueErr);\n }\n return errors;\n}\n\nexport function validateModelParams(\n nodeType: NodeKind,\n model: string,\n params: Record<string, unknown>,\n): ModelValidationResult {\n const spec = MODEL_REGISTRY[nodeType][model];\n if (!spec) {\n return {\n ok: false,\n errors: [{ code: \"unknown_model\", message: `unknown model \"${model}\" for node \"${nodeType}\"` }],\n };\n }\n\n const errors = [...checkRequiredParams(spec, params, model), ...checkParamValues(spec, params, model)];\n if (errors.length > 0) return { ok: false, errors };\n return { ok: true };\n}\n\n/**\n * Validate that every REQUIRED input slot the model declares is wired up.\n * `providedKinds` is the set of input kinds the canvas supplies (e.g.\n * [\"video\", \"audio\"]). Optional input slots are not checked — they only\n * affect UI rendering, not run validity.\n */\nexport function validateModelInputs(\n nodeType: NodeKind,\n model: string,\n providedKinds: readonly InputKind[],\n): ModelValidationResult {\n const spec = MODEL_REGISTRY[nodeType][model];\n if (!spec) {\n return {\n ok: false,\n errors: [{ code: \"unknown_model\", message: `unknown model \"${model}\" for node \"${nodeType}\"` }],\n };\n }\n const have = new Set(providedKinds);\n const errors: ModelValidationError[] = [];\n for (const inputSpec of spec.inputs) {\n if (!have.has(inputSpec.kind)) {\n errors.push({\n code: \"missing_input\",\n input: inputSpec.kind,\n message: `model \"${model}\" requires input of kind \"${inputSpec.kind}\"`,\n });\n }\n }\n if (errors.length > 0) return { ok: false, errors };\n return { ok: true };\n}\n\nfunction validateStringValue(\n key: string,\n value: unknown,\n schema: Extract<ParamSchema, { kind: \"string\" }>,\n model: string,\n): ModelValidationError | null {\n if (typeof value !== \"string\") {\n return { code: \"invalid_value\", param: key, message: `${key}: expected string, got ${typeof value}` };\n }\n if (schema.enum && !schema.enum.includes(value)) {\n return {\n code: \"invalid_value\",\n param: key,\n message: `${key}: \"${value}\" not allowed by \"${model}\" (allowed: ${schema.enum.join(\", \")})`,\n };\n }\n if (schema.maxLength !== undefined && value.length > schema.maxLength) {\n return {\n code: \"invalid_value\",\n param: key,\n message: `${key}: ${value.length} characters exceeds max ${schema.maxLength} for \"${model}\"`,\n };\n }\n return null;\n}\n\nfunction validateNumberValue(\n key: string,\n value: unknown,\n schema: Extract<ParamSchema, { kind: \"number\" }>,\n model: string,\n): ModelValidationError | null {\n if (typeof value !== \"number\" || Number.isNaN(value)) {\n return { code: \"invalid_value\", param: key, message: `${key}: expected number, got ${typeof value}` };\n }\n if (schema.enum && !schema.enum.includes(value)) {\n return {\n code: \"invalid_value\",\n param: key,\n message: `${key}: ${value} not allowed by \"${model}\" (allowed: ${schema.enum.join(\", \")})`,\n };\n }\n if (schema.min !== undefined && value < schema.min) {\n return { code: \"invalid_value\", param: key, message: `${key}: ${value} below min ${schema.min}` };\n }\n if (schema.max !== undefined && value > schema.max) {\n return { code: \"invalid_value\", param: key, message: `${key}: ${value} above max ${schema.max}` };\n }\n return null;\n}\n\nfunction validateValue(key: string, value: unknown, schema: ParamSchema, model: string): ModelValidationError | null {\n switch (schema.kind) {\n case \"string\":\n return validateStringValue(key, value, schema, model);\n case \"number\":\n return validateNumberValue(key, value, schema, model);\n case \"boolean\":\n if (typeof value !== \"boolean\") {\n return { code: \"invalid_value\", param: key, message: `${key}: expected boolean, got ${typeof value}` };\n }\n return null;\n case \"json\":\n return null;\n default: {\n const _exhaustive: never = schema satisfies never;\n return _exhaustive;\n }\n }\n}\n\nexport { isManagedNodeKind };\n","/**\n * Per-model video cost, shared by everything that needs to say what a clip will\n * cost BEFORE it runs: the engine's pre-run estimate, the backend's per-request\n * cost cap, and the studio's prompt bar.\n *\n * It lives in the contract, next to the model registry, because a price is\n * per-model data exactly like a duration enum — and because the estimate and the\n * charge drifting apart is the failure this module exists to prevent. The engine\n * previously quoted a FLAT 50 credits for every clip regardless of duration,\n * resolution, or model, which under-quoted a 1080p 8s clip by roughly 10×.\n */\n\n/** Credits per USD of provider cost. Mirrors the backend's credit accounting. */\nexport const CREDITS_PER_USD = 100;\n\n/**\n * Seedance $/second by resolution. 4k bills at the 1080p rate as a conservative\n * floor until a real 4k rate exists.\n */\nexport const SEEDANCE_USD_PER_SECOND: Readonly<Record<string, number>> = {\n \"480p\": 0.18,\n \"720p\": 0.5,\n \"1080p\": 0.62,\n \"4k\": 0.62,\n};\n\n/** What the provider assumes when a clip does not pin a resolution. */\nexport const DEFAULT_VIDEO_RESOLUTION = \"720p\";\n\n/** What a clip costs when the model does not declare a duration. */\nexport const DEFAULT_VIDEO_DURATION_S = 5;\n\nexport function isSeedanceModel(model: string): boolean {\n return model.startsWith(\"bytedance/seedance\");\n}\n\n/** Rate for an unrecognised resolution — the 720p middle tier, never zero. */\nconst FALLBACK_USD_PER_SECOND = 0.5;\n\nexport function seedanceUsdPerSecond(resolution: string | undefined): number {\n return SEEDANCE_USD_PER_SECOND[resolution ?? DEFAULT_VIDEO_RESOLUTION] ?? FALLBACK_USD_PER_SECOND;\n}\n\n/**\n * Published $/second per model, from OpenRouter's own model listing\n * (GET /api/v1/videos/models → `pricing_skus`). Audio is a separate, higher\n * rate on every model that offers it, so it is priced rather than ignored.\n */\ninterface ModelRate {\n silent: number;\n audio: number;\n /** Per-resolution overrides, where the provider publishes one. */\n byResolution?: Readonly<Record<string, { silent: number; audio: number }>>;\n}\n\nconst USD_PER_SECOND: Readonly<Record<string, ModelRate>> = {\n // Kling publishes one flat rate across every resolution and mode.\n \"kwaivgi/kling-v3.0-pro\": { silent: 0.112, audio: 0.168 },\n // Veo prices 4K far above the base tier — and 4K is a selectable resolution,\n // so folding it into the base rate under-quotes the dearest clip we can make.\n \"google/veo-3.1\": {\n silent: 0.2,\n audio: 0.4,\n byResolution: { \"4K\": { silent: 0.4, audio: 0.6 } },\n },\n \"google/veo-3.1-fast\": {\n silent: 0.1,\n audio: 0.12,\n byResolution: {\n \"720p\": { silent: 0.08, audio: 0.1 },\n \"4K\": { silent: 0.25, audio: 0.3 },\n },\n },\n};\n\nexport interface VideoCostInput {\n model: string;\n duration?: number;\n resolution?: string;\n generateAudio?: boolean;\n}\n\n/**\n * USD estimate for one clip.\n *\n * Veo and Kling bill by provider usage reported in the response, so their true\n * cost is not knowable up front. Rather than quote a flat number that is wrong\n * in the DANGEROUS direction (too low), they are estimated at the most expensive\n * known per-second rate — an over-estimate scales with the clip, and a user who\n * is quoted more than they are charged is never the one who gets hurt.\n */\nexport function estimateVideoCostUsd({ model, duration, resolution, generateAudio }: VideoCostInput): number {\n const seconds = duration ?? DEFAULT_VIDEO_DURATION_S;\n if (isSeedanceModel(model)) return seedanceUsdPerSecond(resolution) * seconds;\n\n const published = USD_PER_SECOND[model];\n if (published) {\n const rate = (resolution ? published.byResolution?.[resolution] : undefined) ?? published;\n return (generateAudio ? rate.audio : rate.silent) * seconds;\n }\n\n // Unknown model: quote the dearest rate we know. Over-quoting is the safe\n // direction — a user charged less than they were told is never the one hurt.\n const dearestKnownRate = Math.max(...Object.values(SEEDANCE_USD_PER_SECOND));\n return dearestKnownRate * seconds;\n}\n\n/**\n * The same estimate in credits, rounded up so a quote is never under the charge.\n *\n * The tiny rounding step matters: `0.112 * 5 * 100` is 56.00000000000001 in\n * IEEE-754, and a bare ceil turns an exact 56 into 57. Snapping to a\n * sub-credit precision first keeps clean rates showing as clean numbers.\n */\nexport function estimateVideoCredits(input: VideoCostInput): number {\n const credits = estimateVideoCostUsd(input) * CREDITS_PER_USD;\n return Math.ceil(Number(credits.toFixed(6)));\n}\n","// Max nodes per layer executed at once. Video canvases fan out many\n// `video_generate` clips into one layer, and each worker blocks on a\n// multi-minute poll — so a low bound serializes clips into slow waves. 8 keeps\n// multi-clip renders moving while staying well under the backend job workpool\n// (maxParallelism 32) and typical provider rate limits. Raise per-run with\n// `--parallel`/`--concurrency` or `BAKER_CANVAS_CONCURRENCY`.\nexport const DEFAULT_CONCURRENCY = 8;\n\n/**\n * Pick the node-execution concurrency limit from ordered candidates (e.g.\n * CLI flag, then env var). A candidate counts only if it parses to a finite\n * number >= 1; otherwise the default applies.\n */\nexport function resolveConcurrency(...candidates: Array<string | number | undefined>): number {\n for (const candidate of candidates) {\n if (candidate === undefined || candidate === \"\") continue;\n const n = typeof candidate === \"number\" ? candidate : Number(candidate);\n if (Number.isFinite(n) && n >= 1) return Math.floor(n);\n }\n return DEFAULT_CONCURRENCY;\n}\n\n/**\n * Map `fn` over `items` with at most `limit` calls in flight, settling every\n * item — one rejection never abandons its siblings. Results preserve input\n * order (index i of the result array is item i's outcome).\n */\nexport async function mapWithConcurrency<T, R>(\n items: readonly T[],\n limit: number,\n fn: (item: T, index: number) => Promise<R>,\n): Promise<PromiseSettledResult<R>[]> {\n const results: PromiseSettledResult<R>[] = new Array(items.length);\n let next = 0;\n const worker = async (): Promise<void> => {\n while (next < items.length) {\n const index = next++;\n try {\n results[index] = { status: \"fulfilled\", value: await fn(items[index] as T, index) };\n } catch (reason) {\n results[index] = { status: \"rejected\", reason };\n }\n }\n };\n const workers = Array.from({ length: Math.min(limit, items.length) }, worker);\n await Promise.all(workers);\n return results;\n}\n","import { randomBytes } from \"node:crypto\";\n\nconst ENCODING = \"0123456789ABCDEFGHJKMNPQRSTVWXYZ\";\n\n/** A minimal monotonic-ish ULID (Crockford base32). Sufficient for run ids. */\nexport function ulid(now: number = Date.now()): string {\n const time = encodeTime(now);\n const rand = encodeRandom();\n return time + rand;\n}\n\nfunction encodeTime(now: number): string {\n let n = now;\n let out = \"\";\n for (let i = 0; i < 10; i++) {\n const mod = n % 32;\n out = ENCODING[mod] + out;\n n = (n - mod) / 32;\n }\n return out;\n}\n\nfunction encodeRandom(): string {\n const bytes = randomBytes(10);\n let out = \"\";\n for (let i = 0; i < 16; i++) {\n // 16 chars * 5 bits = 80 bits = 10 bytes\n const bitIndex = i * 5;\n const byteIndex = Math.floor(bitIndex / 8);\n const bitOffset = bitIndex % 8;\n const high = bytes[byteIndex] ?? 0;\n const low = bytes[byteIndex + 1] ?? 0;\n const combined = ((high << 8) | low) & 0xffff;\n const shift = 11 - bitOffset;\n const value = (combined >> shift) & 0x1f;\n out += ENCODING[value];\n }\n return out;\n}\n","import type { BackendClient } from \"../client/backend-client.ts\";\nimport type { AssetKind } from \"../schema/refs.ts\";\nimport type { AssetStore } from \"./asset-store.ts\";\nimport type { CacheEntry, CacheStore } from \"./cache-store.ts\";\n\n/**\n * Remote canvas cache, backend-mediated. Entries are small JSON pointer\n * records; their AssetRefs must carry content-addressed `canvas-assets/` URLs\n * so any sandbox can rehydrate the bytes from R2 (sha-verified by\n * `ingestRemote`). The layered store makes a fresh sandbox re-run an\n * already-computed canvas at zero credits: local hit → use it; local miss →\n * remote fetch + rehydrate + write back locally.\n *\n * Cache traffic is strictly best-effort: a remote failure NEVER fails the run\n * (a paid render must not die on a cache write), it only costs a warning.\n */\n\nexport const CANVAS_ASSETS_URL_SEGMENT = \"/canvas-assets/\";\n\nexport type AssetRefLike = Record<string, unknown> & { sha256: string; mime: string };\n\n/**\n * A ref counts as persisted only when its url points at OUR content-addressed\n * store entry for THESE bytes. R2 shards keys by the first sha byte, so the\n * canonical key is `canvas-assets/<sha0:2>/<sha>.<ext>` — the sha appears after\n * a 2-hex shard segment, NOT right after \"/canvas-assets/\". (An unsharded\n * layout is tolerated for legacy/seed pointers.) A foreign/ingested URL that\n * merely contains \"/canvas-assets/\" must NOT pass, or persistOutputAssetUrls\n * would skip uploading its bytes and the poisoned pointer would fail every\n * cache PUT and run record downstream.\n *\n * Historically this required the sha right after the segment, which matched no\n * real R2 url — so every render output and cache entry was silently dropped.\n */\nexport function isPersistedAssetRef(ref: AssetRefLike): ref is AssetRefLike & { url: string } {\n const { url, sha256 } = ref;\n if (typeof url !== \"string\" || typeof sha256 !== \"string\") return false;\n return (\n url.includes(`${CANVAS_ASSETS_URL_SEGMENT}${sha256.slice(0, 2)}/${sha256}`) ||\n url.includes(`${CANVAS_ASSETS_URL_SEGMENT}${sha256}`)\n );\n}\n\nexport function isAssetRefLike(value: unknown): value is AssetRefLike {\n return (\n typeof value === \"object\" &&\n value !== null &&\n !Array.isArray(value) &&\n typeof (value as Record<string, unknown>).sha256 === \"string\" &&\n typeof (value as Record<string, unknown>).mime === \"string\"\n );\n}\n\n/**\n * Depth-first collect of every AssetRef-shaped object inside a value. A ref is\n * not a leaf — refs nested inside other refs are collected too, mirroring the\n * backend's persisted-ref validation walk so an entry we upload never carries\n * a ref the server would treat differently.\n */\nexport function collectAssetRefLikes(value: unknown, out: AssetRefLike[] = []): AssetRefLike[] {\n if (Array.isArray(value)) {\n for (const item of value) collectAssetRefLikes(item, out);\n return out;\n }\n if (typeof value !== \"object\" || value === null) return out;\n if (isAssetRefLike(value)) {\n out.push(value);\n }\n for (const item of Object.values(value)) collectAssetRefLikes(item, out);\n return out;\n}\n\n/** True when every ref in the entry is rehydratable from the persisted store. */\nexport function entryFullyPersisted(entry: CacheEntry): boolean {\n return collectAssetRefLikes(entry.outputs).every((ref) => isPersistedAssetRef(ref));\n}\n\n/** Deep-clone the entry and drop sandbox-local fields from every ref. */\nexport function stripLocalFields(entry: CacheEntry): CacheEntry {\n const clone = JSON.parse(JSON.stringify(entry)) as CacheEntry;\n for (const ref of collectAssetRefLikes(clone.outputs)) {\n delete ref.path;\n delete ref.bytes;\n }\n return clone;\n}\n\nexport class RemoteCacheStore {\n private readonly client: BackendClient;\n private readonly log: (line: string) => void;\n\n constructor(client: BackendClient, log?: (line: string) => void) {\n this.client = client;\n this.log = log ?? (() => undefined);\n }\n\n async get(cacheKey: string): Promise<CacheEntry | null> {\n return await this.client.getCacheEntry<CacheEntry>(cacheKey);\n }\n\n async put(entry: CacheEntry): Promise<void> {\n // An entry with a local-only ref can't rehydrate elsewhere — keeping it\n // local-only is correct, not an error (the persist hook normally prevents\n // this; it can happen when an asset upload failed mid-run).\n if (!entryFullyPersisted(entry)) {\n this.log(`[cache ] ${entry.cacheKey.slice(0, 12)}… has local-only assets, kept local`);\n return;\n }\n const stripped = stripLocalFields(entry);\n // Mirror the backend intake cap. refs only feed a future GC sweep, so a\n // truncated list degrades GC accounting — never correctness — while an\n // over-cap array would 400 and keep the whole entry out of the shared cache.\n if (stripped.refs.length > MAX_REMOTE_REFS) {\n stripped.refs = stripped.refs.slice(0, MAX_REMOTE_REFS);\n }\n await this.client.putCacheEntry(stripped);\n }\n}\n\nconst MAX_REMOTE_REFS = 512;\n\nexport class LayeredCacheStore implements CacheStore {\n readonly rootDir: string;\n private readonly local: CacheStore;\n private readonly remote: RemoteCacheStore;\n private readonly assets: AssetStore;\n private readonly log: (line: string) => void;\n\n constructor(opts: { local: CacheStore; remote: RemoteCacheStore; assets: AssetStore; log?: (line: string) => void }) {\n this.local = opts.local;\n this.remote = opts.remote;\n this.assets = opts.assets;\n this.rootDir = opts.local.rootDir;\n this.log = opts.log ?? (() => undefined);\n }\n\n async get(cacheKey: string): Promise<CacheEntry | null> {\n const localHit = await this.local.get(cacheKey);\n if (localHit) return localHit;\n\n let remoteEntry: CacheEntry | null;\n try {\n remoteEntry = await this.remote.get(cacheKey);\n } catch (e) {\n this.log(`[cache ] remote lookup failed (${message(e)}) — treating as miss`);\n return null;\n }\n if (!remoteEntry) return null;\n\n let rehydrated: CacheEntry;\n try {\n rehydrated = await this.rehydrate(remoteEntry);\n } catch (e) {\n this.log(`[cache ] ${cacheKey.slice(0, 12)}… rehydration failed (${message(e)}) — treating as miss`);\n return null;\n }\n // Write back locally so subsequent hits in this sandbox skip the network.\n await this.local.put(rehydrated);\n return rehydrated;\n }\n\n async put(entry: CacheEntry): Promise<void> {\n await this.local.put(entry);\n try {\n await this.remote.put(entry);\n } catch (e) {\n this.log(`[cache ] remote write failed (${message(e)}) — entry kept local`);\n }\n }\n\n /**\n * Download every referenced asset into the local content-addressed store\n * (sha-verified) and stamp fresh local paths. Any ref that cannot be\n * rehydrated fails the WHOLE entry — a partially-hydrated cache hit would\n * crash materialization later with a far less actionable error.\n */\n private async rehydrate(entry: CacheEntry): Promise<CacheEntry> {\n const clone = JSON.parse(JSON.stringify(entry)) as CacheEntry;\n for (const ref of collectAssetRefLikes(clone.outputs)) {\n if (!isPersistedAssetRef(ref)) {\n throw new Error(`ref ${ref.sha256.slice(0, 12)}… has no persisted url`);\n }\n const ingested = await this.assets.ingestRemote({\n kind: (typeof ref.kind === \"string\" ? ref.kind : \"json\") as AssetKind,\n url: ref.url,\n sha256: ref.sha256,\n mime: ref.mime,\n metadata: (ref.metadata ?? undefined) as Record<string, unknown> | undefined,\n });\n ref.path = ingested.path;\n }\n return clone;\n }\n}\n\nfunction message(e: unknown): string {\n return e instanceof Error ? e.message : String(e);\n}\n","import type { ExecCtx } from \"../../engine/context.ts\";\nimport type { AssetRef } from \"../../schema/refs.ts\";\nimport { collectAssetRefLikes, isPersistedAssetRef } from \"../../storage/remote-cache-store.ts\";\n\nconst PUT_MAX_ATTEMPTS = 4;\n\nconst sleep = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));\n\n/**\n * Presign an R2 upload slot for `sha256`/`mime` and PUT the bytes. Returns the\n * public URL a remote node can fetch. Shared by the `ingest` node (which uploads\n * freshly-fetched bytes) and `ensureUploaded` (which uploads an existing\n * local-only asset before it is handed to a remote node).\n *\n * Retried with backoff: one TCP reset on a large body must not cost a paid\n * render its durable copy. Replays are safe — the key is content-addressed, so\n * a repeated PUT writes identical bytes. Each attempt presigns FRESH: a retry\n * after a long stall can straddle the 1-hour signature window, and\n * re-presigning the same sha is idempotent (same key).\n */\nexport async function presignAndPut(args: {\n bytes: Buffer;\n sha256: string;\n mime: string;\n ctx: ExecCtx;\n}): Promise<string> {\n let lastFailure: Error | null = null;\n for (let attempt = 0; attempt < PUT_MAX_ATTEMPTS; attempt++) {\n if (args.ctx.signal?.aborted) break;\n if (attempt > 0) await sleep(500 * 2 ** (attempt - 1) * (1 + Math.random() * 0.25));\n const result = await attemptPresignedPut(args);\n if (result.ok) return result.url;\n lastFailure = result.failure;\n if (!result.retryable) break;\n }\n throw lastFailure ?? new Error(\"upload: aborted before the PUT could start\");\n}\n\ntype PutAttempt = { ok: true; url: string } | { ok: false; failure: Error; retryable: boolean };\n\nasync function attemptPresignedPut(args: {\n bytes: Buffer;\n sha256: string;\n mime: string;\n ctx: ExecCtx;\n}): Promise<PutAttempt> {\n try {\n const { putUrl, publicUrl } = await args.ctx.client.presignAssetUpload(args.sha256, args.mime, args.ctx.signal);\n const putRes = await fetch(putUrl, {\n method: \"PUT\",\n body: new Uint8Array(args.bytes),\n headers: { \"Content-Type\": args.mime },\n signal: args.ctx.signal,\n });\n if (putRes.ok) return { ok: true, url: publicUrl };\n return {\n ok: false,\n failure: new Error(`upload: presigned PUT failed ${putRes.status} ${putRes.statusText}`),\n // Only transient statuses warrant a replay — a 400/403 fails identically every attempt.\n retryable: putRes.status >= 500 || putRes.status === 429 || putRes.status === 408,\n };\n } catch (e) {\n // Network reset mid-body (or a presign that couldn't reach the backend) —\n // retryable unless the run itself was aborted.\n return {\n ok: false,\n failure: e instanceof Error ? e : new Error(String(e)),\n retryable: args.ctx.signal?.aborted !== true,\n };\n }\n}\n\n/**\n * Guarantee a remote-fetchable `url` for an asset before it crosses to a remote\n * node. Local-node outputs (ffmpeg/magick via `runCli`, any `runCli` consumer)\n * are ingested into the content-addressed store with a `path` but NO `url`\n * (`LocalAssetStore` is local-only). A remote node receiving such a ref would be\n * told `url: undefined`, which the backend rejects (e.g. `audio_voice_convert\n * requires inputs.audio`). This uploads the local bytes to R2 and stamps `url`.\n * Idempotent: refs that already carry a `url` (ingest/remote outputs) pass through.\n */\nexport async function ensureUploaded(ref: AssetRef, ctx: ExecCtx): Promise<AssetRef> {\n if (ref.url) return ref;\n const bytes = await ctx.assets.readBytes(ref.sha256, ref.mime);\n const url = await presignAndPut({ bytes, sha256: ref.sha256, mime: ref.mime, ctx });\n return { ...ref, url } as AssetRef;\n}\n\n/**\n * Stamp a durable `canvas-assets/` URL onto every AssetRef in a node's fresh\n * outputs, uploading local-only bytes (and re-uploading refs whose url points\n * at an external origin — an ingested source URL can die tomorrow; the cache\n * entry and run record that reference it must not). Mutates refs in place —\n * the outputs object was just produced by the node and is not shared yet.\n * URL-only stamping never changes cache keys: inputs hash by sha256 and\n * params are normalized to content identity (see normalizeParamsForCacheKey).\n */\nexport async function persistOutputAssetUrls(outputs: Record<string, unknown>, ctx: ExecCtx): Promise<void> {\n for (const ref of collectAssetRefLikes(outputs)) {\n if (isPersistedAssetRef(ref)) continue;\n const bytes = await ctx.assets.readBytes(ref.sha256, ref.mime);\n ref.url = await presignAndPut({ bytes, sha256: ref.sha256, mime: ref.mime, ctx });\n }\n}\n","import { z } from \"zod\";\n\n// $ref:<node_id>.<output> — pass-through the full output (often a list)\n// $ref:<node_id>.<output>#<index> — pick a static index\nexport const REF_PREFIX = \"$ref:\";\n\nexport type RefExpr = { kind: \"ref\"; nodeId: string; output: string; index?: number };\n\nexport function parseRefExpr(input: string): RefExpr | null {\n if (!input.startsWith(REF_PREFIX)) return null;\n const rest = input.slice(REF_PREFIX.length);\n const hashIdx = rest.indexOf(\"#\");\n const head = hashIdx === -1 ? rest : rest.slice(0, hashIdx);\n const tail = hashIdx === -1 ? null : rest.slice(hashIdx + 1);\n const dot = head.indexOf(\".\");\n if (dot <= 0) return null;\n const nodeId = head.slice(0, dot);\n const output = head.slice(dot + 1);\n if (!nodeId || !output) return null;\n let index: number | undefined;\n if (tail !== null) {\n // Reject an empty index (`...#`): Number(\"\") is 0 and would silently\n // resolve to element 0 instead of failing on the malformed ref.\n const n = Number(tail);\n if (tail === \"\" || !Number.isInteger(n) || n < 0) return null;\n index = n;\n }\n return { kind: \"ref\", nodeId, output, index };\n}\n\nconst NodeIdRe = /^[a-z][a-z0-9_]*$/;\n\nexport const NodeDecl = z\n .object({\n id: z.string().regex(NodeIdRe, \"node id must be lower_snake_case\"),\n type: z.string().min(1),\n version: z.string().min(1).optional(),\n inputs: z.record(z.string(), z.unknown()).optional(),\n params: z.record(z.string(), z.unknown()).optional(),\n when: z.unknown().optional(),\n // Regenerate knob. The engine is content-addressed: identical params + inputs\n // return the cached render, so re-running an unchanged node NEVER re-bills or\n // produces a new result. Bump this token (any string/number — a `2`, a `\"v3\"`,\n // a note) and re-run to force THIS node to render fresh; because its new output\n // changes downstream input hashes, everything depending on it regenerates too.\n // This is the declarative \"change a value, re-run, get a new render\" affordance.\n regenerate: z.union([z.string(), z.number()]).optional(),\n })\n .strict();\nexport type NodeDecl = z.infer<typeof NodeDecl>;\n\nconst OutputRef = z\n .object({\n node: z.string(),\n output: z.string(),\n })\n .strict();\n\n/**\n * The timing plan a video scaffold emits so `validate` can prove audio/lip-sync\n * invariants STATICALLY — before any billed render. The engine ignores it at run\n * time; only the validator reads it (see checkVideoInvariants). Hand-authored\n * video canvases can add this block to opt into the same checks.\n */\nconst VideoMeta = z\n .object({\n duration_s: z.number(),\n // The one-clock contract: the spine's summed clip lengths and every audio\n // timeline reachable from the final mux must equal `expected_total_s` — the\n // validator recomputes both from the LIVE graph (`-shortest` at the final mux\n // silently truncates the longer stream on any mismatch). Emitted by\n // scaffold-video; optional so hand-authored canvases still parse.\n timeline: z\n .object({\n spine_node: z.string(),\n expected_total_s: z.number(),\n audio_mix_node: z.string().optional(),\n })\n .strict()\n .optional(),\n // Each sequenced voiceover turn on the absolute timeline.\n vo_segments: z\n .array(\n z.object({\n slot: z.string(),\n start_s: z.number(),\n end_s: z.number(),\n scene: z.number().optional(),\n speaker: z.string().optional(),\n }),\n )\n .default([]),\n // Scenes with a single on-camera speaker, voiced NATIVELY by the video model\n // (Seedance generate_audio) then re-voiced to one brand voice. Each entry names\n // the `audio_voice_convert` node the validator confirms is present — the\n // native-audio replacement for the retired post-hoc lipsync check. A bare scene\n // index (legacy) or `{ scene, lipsync_node }` (legacy veed canvases) still parse.\n talking_scenes: z\n .array(\n z.union([\n z.number(),\n z.object({\n scene: z.number(),\n voice_convert_node: z.string(),\n // Advisory: the scene's visual length vs the estimated spoken length, so\n // a reviewer can see a native line that may run past its cut. Not gated.\n scene_s: z.number().optional(),\n est_speech_s: z.number().optional(),\n // Word count of the line est_speech_s was measured for. Together they carry\n // the speaker's OBSERVED pace (from the deconstruct's word timings), so the\n // overrun check budgets re-authored lines at the real rate, not a wps guess.\n speech_words: z.number().optional(),\n }),\n z.object({ scene: z.number(), lipsync_node: z.string() }),\n ]),\n )\n .default([]),\n // Advisory, NOT gated: scenes where a presenter's later same-shot turns play as\n // `tts` over their one native clip (a held shot can hold only ONE lip-synced clip,\n // and voiceover turns can't overlap), so the lips may not match those words. The\n // scaffold surfaces it so the agent can cut away or rely on the burned-in captions.\n lip_sync_caution: z\n .array(z.object({ scene: z.number(), speaker: z.string(), tts_over_native: z.array(z.string()) }))\n .optional(),\n // Advisory, NOT gated by the validator: the reviewable \"which graphic fires\n // on which spoken beat\" map emitted by scaffold-video (per-scene window,\n // spoken line, storyboard frames, scheduled graphics). Free-form rows so the\n // schema stays decoupled from the scaffold's exact shape.\n motion_board: z.array(z.unknown()).optional(),\n // The recurring identity elements the scaffold wired (one shared reference slot\n // per cast member / pet / product / logo). The reference-completeness check reads\n // this to warn when a frame's description mentions an element whose ref isn't\n // wired on that frame node (the wrong-identity-animal failure).\n elements: z\n .array(\n z.object({\n ref: z.string(),\n label: z.string(),\n type: z.string(),\n description: z.string().optional(),\n }),\n )\n .optional(),\n // Per video_generate node: the scene's natural visual span. The validator warns\n // when a clip's span exceeds the assigned model's max clip duration (e.g. a 9.2s\n // scene on Veo, which caps at 8s) — the clip would truncate.\n clip_spans: z.array(z.object({ node: z.string(), span_s: z.number() })).optional(),\n // WHY the graph has the nodes it has: one route per scene (clip / still_hold /\n // screen_still / graphic_plate / brand_card / phrase_slice / phrase_run /\n // composite) + a node-type histogram, stamped by scaffold-video. Read this first\n // when a canvas looks big.\n graph_stats: z\n .object({\n nodes_total: z.number(),\n nodes_billable: z.number(),\n node_types: z.record(z.string(), z.number()),\n scene_routes: z.array(z.object({ scene: z.number(), route: z.string(), window_s: z.number() })),\n })\n .strict()\n .optional(),\n })\n .strict()\n .optional();\n\nconst CanvasMetadata = z\n .object({\n name: z.string().optional(),\n description: z.string().optional(),\n // Free-form, human-facing next-steps guide embedded by scaffolds (e.g.\n // `scaffold-video`) so the editable checklist travels inside the canvas\n // instead of only printing to stdout. Ignored by the engine.\n todo: z.unknown().optional(),\n video: VideoMeta,\n })\n .strict()\n .optional();\n\nexport const CanvasSchema = z\n .object({\n schema: z.literal(\"baker-canvas/1\"),\n cache_salt: z.string().optional(),\n metadata: CanvasMetadata,\n nodes: z.array(NodeDecl).min(1),\n output: OutputRef.optional(),\n })\n .strict();\n\nexport type Canvas = z.infer<typeof CanvasSchema>;\n","const SLOT_RE = /\\{\\{\\s*([a-zA-Z_][a-zA-Z0-9_]*)\\s*\\}\\}/g;\n\nexport function extractSlots(template: string): string[] {\n const out = new Set<string>();\n for (const match of template.matchAll(SLOT_RE)) {\n const name = match[1];\n if (name) out.add(name);\n }\n return [...out];\n}\n\nexport function renderTemplate(template: string, values: Record<string, string>): string {\n return template.replace(SLOT_RE, (_full, name: string) => {\n if (Object.hasOwn(values, name)) {\n return values[name] ?? \"\";\n }\n return \"\";\n });\n}\n\nexport function hasUnresolvedSlots(template: string, values: Record<string, string>): string[] {\n const slots = extractSlots(template);\n return slots.filter((s) => !Object.hasOwn(values, s));\n}\n","import { copyFile, link, mkdir, unlink, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { AssetRef } from \"../schema/refs.ts\";\nimport { extForMime } from \"./asset-store.ts\";\n\ntype OutputWriterOpts = {\n outputsDir: string;\n runId: string;\n};\n\n/**\n * Writes per-run human-readable filenames pointing at content-addressed cache assets.\n * Tries hardlink, falls back to copy.\n */\nexport class OutputWriter {\n readonly runDir: string;\n\n constructor(opts: OutputWriterOpts) {\n this.runDir = path.join(opts.outputsDir, opts.runId);\n }\n\n async ensure(): Promise<void> {\n await mkdir(this.runDir, { recursive: true });\n }\n\n async writeAsset(name: string, ref: AssetRef): Promise<string> {\n await this.ensure();\n const ext = extForMime(ref.mime);\n const dest = path.join(this.runDir, `${name}.${ext}`);\n if (!ref.path) {\n // No on-disk bytes — write a JSON pointer.\n const pointer = path.join(this.runDir, `${name}.json`);\n await writeFile(pointer, JSON.stringify(ref, null, 2));\n return pointer;\n }\n await safeReplace(ref.path, dest);\n return dest;\n }\n\n async writeManifest(name: string, value: unknown): Promise<string> {\n await this.ensure();\n const dest = path.join(this.runDir, `${name}.json`);\n await writeFile(dest, JSON.stringify(value, null, 2));\n return dest;\n }\n}\n\nasync function safeReplace(src: string, dest: string): Promise<void> {\n try {\n await unlink(dest);\n } catch {\n // ignore — likely doesn't exist\n }\n try {\n await link(src, dest);\n return;\n } catch {\n // fall back to copy\n }\n await copyFile(src, dest);\n}\n","import { randomUUID } from \"node:crypto\";\nimport { createWriteStream } from \"node:fs\";\nimport { mkdir, readFile, rename, stat, unlink, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { Readable, Transform } from \"node:stream\";\nimport { pipeline } from \"node:stream/promises\";\nimport type { AssetKind, AssetRef } from \"../schema/refs.ts\";\nimport { sha256Hex } from \"./sha256.ts\";\n\n/**\n * Hard ceiling on any single asset the engine downloads or reads from disk.\n * Generated ad creatives are tens of MB; 2 GiB leaves generous headroom while\n * keeping a hostile or mistaken URL from exhausting the disk.\n */\nexport const MAX_ASSET_BYTES = 2 * 1024 * 1024 * 1024;\n\nconst MIME_TO_EXT: Record<string, string> = {\n \"image/png\": \"png\",\n \"image/jpeg\": \"jpg\",\n \"image/webp\": \"webp\",\n \"image/gif\": \"gif\",\n \"image/avif\": \"avif\",\n \"video/mp4\": \"mp4\",\n \"video/webm\": \"webm\",\n \"video/quicktime\": \"mov\",\n \"audio/mpeg\": \"mp3\",\n \"audio/wav\": \"wav\",\n \"audio/x-wav\": \"wav\",\n \"audio/ogg\": \"ogg\",\n \"audio/mp4\": \"m4a\",\n \"application/json\": \"json\",\n \"text/plain\": \"txt\",\n \"text/markdown\": \"md\",\n \"text/html\": \"html\",\n \"font/ttf\": \"ttf\",\n \"font/otf\": \"otf\",\n \"font/woff\": \"woff\",\n \"font/woff2\": \"woff2\",\n};\n\nexport function extForMime(mime: string): string {\n return MIME_TO_EXT[mime] ?? \"bin\";\n}\n\nexport type IngestRemoteArgs = {\n kind: AssetKind;\n url: string;\n sha256: string;\n mime: string;\n metadata?: Record<string, unknown>;\n};\n\nexport interface AssetStore {\n rootDir: string;\n ingestBytes(args: {\n bytes: Buffer;\n kind: AssetKind;\n mime: string;\n metadata?: Record<string, unknown>;\n }): Promise<AssetRef>;\n ingestRemote(args: IngestRemoteArgs): Promise<AssetRef>;\n /** Local FS path for an asset by sha. Returns undefined if absent. */\n pathFor(sha: string, mime: string): string;\n exists(sha: string, mime: string): Promise<boolean>;\n readBytes(sha: string, mime: string): Promise<Buffer>;\n}\n\nexport class LocalAssetStore implements AssetStore {\n rootDir: string;\n private readonly fetchFn: typeof fetch;\n private readonly maxRemoteAssetBytes: number;\n constructor(rootDir: string, fetchFn: typeof fetch = fetch, opts?: { maxRemoteAssetBytes?: number }) {\n this.rootDir = rootDir;\n this.fetchFn = fetchFn;\n this.maxRemoteAssetBytes = opts?.maxRemoteAssetBytes ?? MAX_ASSET_BYTES;\n }\n\n pathFor(sha: string, mime: string): string {\n const ext = extForMime(mime);\n const shard = sha.slice(0, 2);\n return path.join(this.rootDir, shard, `${sha}.${ext}`);\n }\n\n async exists(sha: string, mime: string): Promise<boolean> {\n try {\n await stat(this.pathFor(sha, mime));\n return true;\n } catch {\n return false;\n }\n }\n\n readBytes(sha: string, mime: string): Promise<Buffer> {\n return readFile(this.pathFor(sha, mime));\n }\n\n async ingestBytes(args: {\n bytes: Buffer;\n kind: AssetKind;\n mime: string;\n metadata?: Record<string, unknown>;\n }): Promise<AssetRef> {\n const sha = sha256Hex(args.bytes);\n const dest = this.pathFor(sha, args.mime);\n await mkdir(path.dirname(dest), { recursive: true });\n if (!(await this.exists(sha, args.mime))) {\n const tmp = `${dest}.tmp-${process.pid}-${randomUUID()}`;\n await writeFile(tmp, args.bytes);\n await rename(tmp, dest);\n }\n return buildRef({ kind: args.kind, sha, mime: args.mime, path: dest, metadata: args.metadata });\n }\n\n async ingestRemote(args: IngestRemoteArgs): Promise<AssetRef> {\n const dest = this.pathFor(args.sha256, args.mime);\n let bytes: Buffer;\n if (await this.exists(args.sha256, args.mime)) {\n bytes = await readFile(dest);\n } else {\n await mkdir(path.dirname(dest), { recursive: true });\n const res = await this.fetchFn(args.url);\n if (!res.ok || !res.body) {\n throw new Error(`asset-store: fetch ${args.url} → ${res.status}`);\n }\n const declared = Number(res.headers.get(\"content-length\"));\n if (Number.isFinite(declared) && declared > this.maxRemoteAssetBytes) {\n throw new Error(\n `asset-store: ${args.url} is ${declared} bytes, exceeds the ${this.maxRemoteAssetBytes} byte limit`,\n );\n }\n const tmp = `${dest}.tmp-${process.pid}-${randomUUID()}`;\n try {\n await pipeline(\n Readable.fromWeb(res.body as never),\n byteLimit(args.url, this.maxRemoteAssetBytes),\n createWriteStream(tmp),\n );\n const written = await readFile(tmp);\n const computed = sha256Hex(written);\n if (computed !== args.sha256) {\n throw new Error(`asset-store: sha mismatch for ${args.url} (got ${computed}, expected ${args.sha256})`);\n }\n await rename(tmp, dest);\n bytes = written;\n } catch (e) {\n await unlink(tmp).catch(() => undefined);\n throw e;\n }\n }\n return buildRef({\n kind: args.kind,\n sha: args.sha256,\n mime: args.mime,\n url: args.url,\n path: dest,\n metadata: args.metadata,\n bytes,\n });\n }\n}\n\nfunction byteLimit(url: string, maxBytes: number): Transform {\n let total = 0;\n return new Transform({\n transform(chunk: Buffer, _enc, cb) {\n total += chunk.length;\n if (total > maxBytes) {\n cb(new Error(`asset-store: ${url} exceeds the ${maxBytes} byte limit (aborted at ${total} bytes)`));\n return;\n }\n cb(null, chunk);\n },\n });\n}\n\nexport function buildRef(args: {\n kind: AssetKind;\n sha: string;\n mime: string;\n url?: string;\n path?: string;\n metadata?: Record<string, unknown>;\n bytes?: Buffer;\n}): AssetRef {\n const base = {\n sha256: args.sha,\n mime: args.mime,\n url: args.url,\n path: args.path,\n metadata: args.metadata,\n };\n switch (args.kind) {\n case \"image\": {\n const { width, height } = (args.metadata ?? {}) as { width?: number; height?: number };\n return { kind: \"image\", ...base, width, height };\n }\n case \"video\": {\n const { width, height, duration_ms } = (args.metadata ?? {}) as {\n width?: number;\n height?: number;\n duration_ms?: number;\n };\n return { kind: \"video\", ...base, width, height, duration_ms };\n }\n case \"audio\": {\n const { duration_ms } = (args.metadata ?? {}) as { duration_ms?: number };\n return { kind: \"audio\", ...base, duration_ms };\n }\n case \"json\":\n return { kind: \"json\", ...base };\n case \"text\":\n return { kind: \"text\", ...base };\n case \"font\":\n return { kind: \"font\", ...base };\n default: {\n const _exhaustive: never = args.kind;\n throw new Error(`asset-store: unknown kind ${String(_exhaustive)}`);\n }\n }\n}\n","import { createHash } from \"node:crypto\";\n\nexport function sha256Hex(input: Buffer | string): string {\n const h = createHash(\"sha256\");\n h.update(input);\n return h.digest(\"hex\");\n}\n","import { canonicalize } from \"@baker/canvas-contract\";\nimport { sha256Hex } from \"../storage/sha256.ts\";\n\ntype CacheKeyInputs = {\n node_id: string;\n node_version: string;\n params: unknown;\n input_hashes: Record<string, string | string[]>;\n cache_salt?: string;\n /**\n * Extra string fields folded into the cache key alongside `params`. Used\n * by nodes whose output depends on external content not captured by params\n * — e.g. `hyperframe_render` adds `composition_content_sha` so editing a\n * composition's HTML or CSS invalidates the cache automatically.\n *\n * Keys are sorted before hashing to keep the key stable.\n */\n extras?: Record<string, string>;\n};\n\nexport function computeCacheKey(inputs: CacheKeyInputs): string {\n // Sort the input_hashes keys explicitly — canonicalize sorts, but we also\n // freeze the input shape so callers can pass any record without surprises.\n const sortedInputs: Record<string, string | string[]> = {};\n for (const key of Object.keys(inputs.input_hashes).sort()) {\n const v = inputs.input_hashes[key];\n if (v === undefined) continue;\n sortedInputs[key] = Array.isArray(v) ? [...v] : v;\n }\n let sortedExtras: Record<string, string> | undefined;\n if (inputs.extras && Object.keys(inputs.extras).length > 0) {\n sortedExtras = {};\n for (const key of Object.keys(inputs.extras).sort()) {\n const v = inputs.extras[key];\n if (v === undefined) continue;\n sortedExtras[key] = v;\n }\n }\n const payload = {\n node_id: inputs.node_id,\n node_version: inputs.node_version,\n params: inputs.params,\n input_hashes: sortedInputs,\n cache_salt: inputs.cache_salt,\n extras: sortedExtras,\n };\n return sha256Hex(canonicalize(payload));\n}\n","import { parseRefExpr, REF_PREFIX, type RefExpr } from \"../schema/canvas.ts\";\n\nexport type NodeOutputs = Record<string, unknown>;\nexport type AllOutputs = Record<string, NodeOutputs>;\n\ntype ResolveDeps = {\n outputs: AllOutputs;\n};\n\n/**\n * Recursively walks any JSON-like input and resolves `$ref:` strings against\n * upstream node outputs. Strings that are not refs are passed through unchanged.\n */\nexport function resolveRefs(value: unknown, deps: ResolveDeps): unknown {\n if (typeof value === \"string\") {\n if (value.startsWith(REF_PREFIX)) {\n const expr = parseRefExpr(value);\n if (!expr) return value;\n return resolveExpr(expr, deps);\n }\n return value;\n }\n if (Array.isArray(value)) {\n return value.map((v) => resolveRefs(v, deps));\n }\n if (value && typeof value === \"object\") {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n out[k] = resolveRefs(v, deps);\n }\n return out;\n }\n return value;\n}\n\nfunction resolveExpr(expr: RefExpr, deps: ResolveDeps): unknown {\n return resolveNodeRef(expr.nodeId, expr.output, expr.index, deps);\n}\n\nfunction resolveNodeRef(nodeId: string, output: string, index: number | undefined, deps: ResolveDeps): unknown {\n const node = deps.outputs[nodeId];\n if (!node) throw new Error(`ref: unknown node \"${nodeId}\"`);\n if (!(output in node)) throw new Error(`ref: node \"${nodeId}\" has no output \"${output}\"`);\n const value = node[output];\n if (index === undefined) return value;\n if (!Array.isArray(value)) {\n throw new Error(`ref: ${nodeId}.${output} is not a list (cannot index #${index})`);\n }\n if (index >= value.length) {\n throw new Error(`ref: index #${index} out of bounds for ${nodeId}.${output} (length ${value.length})`);\n }\n return value[index];\n}\n","/**\n * Kahn's algorithm: produce execution layers from a dependency graph.\n * Each layer contains node ids whose dependencies are all in earlier layers.\n *\n * Throws if the graph has a cycle. The caller should run cycle detection in\n * the validator stage, but we double-check here as a safety net.\n */\nexport function topologicalLayers(graph: ReadonlyMap<string, ReadonlySet<string>>): string[][] {\n const remaining = cloneGraph(graph);\n const layers: string[][] = [];\n while (remaining.size > 0) {\n const ready = collectReady(remaining);\n if (ready.length === 0) {\n throw new Error(`scheduler: cycle detected among ${[...remaining.keys()].join(\", \")}`);\n }\n layers.push(ready);\n removeNodes(remaining, ready);\n }\n return layers;\n}\n\n/**\n * Node ids reachable from `roots` by following dependency edges (each node maps\n * to the set of nodes it depends on). Used for dead-node elimination: only the\n * transitive dependencies of the canvas output need to execute — orphaned nodes\n * left behind by an edit (or a `--out` rewire) would otherwise still run, bill,\n * and abort the whole run on their own failure.\n */\nexport function reachableNodes(graph: ReadonlyMap<string, ReadonlySet<string>>, roots: readonly string[]): Set<string> {\n const reachable = new Set<string>();\n const stack = [...roots];\n while (stack.length > 0) {\n const id = stack.pop();\n if (id === undefined || reachable.has(id) || !graph.has(id)) continue;\n reachable.add(id);\n for (const dep of graph.get(id) ?? []) stack.push(dep);\n }\n return reachable;\n}\n\n/**\n * Restrict a dependency graph to `keep`, dropping nodes outside the set and any\n * edges to dropped nodes. Returns a new graph; the input is untouched.\n */\nexport function subgraph(\n graph: ReadonlyMap<string, ReadonlySet<string>>,\n keep: ReadonlySet<string>,\n): Map<string, Set<string>> {\n const out = new Map<string, Set<string>>();\n for (const [id, deps] of graph) {\n if (!keep.has(id)) continue;\n out.set(id, new Set([...deps].filter((d) => keep.has(d))));\n }\n return out;\n}\n\nfunction cloneGraph(graph: ReadonlyMap<string, ReadonlySet<string>>): Map<string, Set<string>> {\n const out = new Map<string, Set<string>>();\n for (const [k, deps] of graph) out.set(k, new Set(deps));\n return out;\n}\n\nfunction collectReady(remaining: Map<string, Set<string>>): string[] {\n const ready: string[] = [];\n for (const [id, deps] of remaining) if (deps.size === 0) ready.push(id);\n ready.sort();\n return ready;\n}\n\nfunction removeNodes(remaining: Map<string, Set<string>>, ready: readonly string[]): void {\n for (const id of ready) remaining.delete(id);\n for (const deps of remaining.values()) {\n for (const id of ready) deps.delete(id);\n }\n}\n\nexport function findCycle(graph: ReadonlyMap<string, ReadonlySet<string>>): string[] | null {\n const reverseAdj = buildReverseAdj(graph);\n const color = new Map<string, number>();\n for (const k of graph.keys()) color.set(k, 0);\n const stack: string[] = [];\n for (const id of graph.keys()) {\n if ((color.get(id) ?? 0) !== 0) continue;\n const found = dfsCycle(id, color, stack, reverseAdj);\n if (found) return found;\n }\n return null;\n}\n\nfunction buildReverseAdj(graph: ReadonlyMap<string, ReadonlySet<string>>): Map<string, string[]> {\n const reverseAdj = new Map<string, string[]>();\n for (const [node, deps] of graph) {\n for (const dep of deps) {\n const arr = reverseAdj.get(dep) ?? [];\n arr.push(node);\n reverseAdj.set(dep, arr);\n }\n }\n return reverseAdj;\n}\n\nfunction dfsCycle(\n u: string,\n color: Map<string, number>,\n stack: string[],\n reverseAdj: Map<string, string[]>,\n): string[] | null {\n color.set(u, 1);\n stack.push(u);\n const children = reverseAdj.get(u) ?? [];\n for (const v of children) {\n const c = color.get(v) ?? 0;\n if (c === 1) {\n const idx = stack.indexOf(v);\n return [...stack.slice(idx), v];\n }\n if (c === 0) {\n const r = dfsCycle(v, color, stack, reverseAdj);\n if (r) return r;\n }\n }\n color.set(u, 2);\n stack.pop();\n return null;\n}\n","// The Dialogue-marker parser lives with the prompt profiles so the emitter and this\n// validator can never drift on the parse contract.\nimport { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport {\n type InputKind,\n isManagedNodeKind,\n MODEL_REGISTRY,\n validateModelInputs,\n validateModelParams,\n} from \"@baker/canvas-contract\";\nimport { z } from \"zod\";\nimport { looksLikeHttpUrl } from \"../lib/url.ts\";\nimport { clipProfileFor, imageProfileFor, nativeDialogueOf } from \"../scaffold/lib/prompt-profiles.ts\";\nimport { parseSpineInputLens } from \"../scaffold/spine-input.ts\";\nimport { type Canvas, CanvasSchema, type NodeDecl, parseRefExpr, REF_PREFIX } from \"../schema/canvas.ts\";\nimport { extractSlots } from \"../schema/prompts.ts\";\nimport { resolveOutputKinds } from \"./define.ts\";\nimport { didYouMean } from \"./didyoumean.ts\";\nimport { isBlocking, type ValidationIssue } from \"./errors.ts\";\nimport type { NodeRegistry } from \"./registry.ts\";\nimport { findCycle } from \"./scheduler.ts\";\n\nconst MODEL_INPUT_KINDS = new Set<InputKind>([\"image\", \"video\", \"audio\"]);\n\ntype ValidationResult =\n | { ok: true; canvas: Canvas; estimatedCredits: number; warnings?: ValidationIssue[] }\n | { ok: false; issues: ValidationIssue[] };\n\ntype ValidationDeep = ValidationResult & {\n /** Per-node credit estimate, in canvas order. Useful for `validate` cost previews. */\n perNodeCredits?: Array<{ node_id: string; node_type: string; credits: number }>;\n};\n\nconst STAGE_CODES = {\n PARSE: \"PARSE_ERROR\",\n SHAPE: \"SHAPE_ERROR\",\n UNKNOWN_NODE: \"UNKNOWN_NODE_TYPE\",\n PARAMS: \"INVALID_PARAMS\",\n PARAMS_EXTRA: \"INVALID_PARAMS_EXTRA\",\n MODEL_PARAMS: \"MODEL_INVALID_PARAMS\",\n MODEL_INPUTS: \"MODEL_INVALID_INPUTS\",\n REF_UNRESOLVED: \"UNRESOLVED_REF\",\n REF_OUT_OF_BOUNDS: \"REF_INDEX_OUT_OF_BOUNDS\",\n REF_TYPE: \"REF_TYPE_MISMATCH\",\n DUPLICATE_ID: \"DUPLICATE_NODE_ID\",\n CYCLE: \"GRAPH_CYCLE\",\n SLOT: \"PROMPT_SLOT_UNRESOLVED\",\n OUTPUT: \"OUTPUT_REF_INVALID\",\n VO_OVERLAP: \"VIDEO_VO_OVERLAP\",\n AUDIO_DURATION: \"VIDEO_AUDIO_DURATION\",\n LIPSYNC_MISSING: \"VIDEO_LIPSYNC_MISSING\",\n SPEECH_OVERRUN: \"VIDEO_SPEECH_OVERRUN\",\n ASPECT_MISMATCH: \"VIDEO_ASPECT_MISMATCH\",\n REFERENCE_MISSING: \"VIDEO_REFERENCE_MISSING\",\n SPAN_EXCEEDS_MODEL: \"VIDEO_SPAN_EXCEEDS_MODEL\",\n UI_IN_PROMPT: \"VIDEO_UI_IN_PROMPT\",\n BRANDMARK_IN_PROMPT: \"VIDEO_BRANDMARK_IN_PROMPT\",\n SPEECH_EXCEEDS_EXTRACT: \"VIDEO_SPEECH_EXCEEDS_EXTRACT\",\n PROMPT_PROFILE_MISSING: \"VIDEO_PROMPT_PROFILE_MISSING\",\n PROMPT_DECISION_MISSING: \"VIDEO_PROMPT_DECISION_MISSING\",\n HOOK_LAYER_MISSING: \"VIDEO_HOOK_LAYER_MISSING\",\n IMAGE_PROFILE_MISSING: \"IMAGE_PROMPT_PROFILE_MISSING\",\n PROMPT_OVER_BUDGET: \"VIDEO_PROMPT_OVER_BUDGET\",\n PERSON_GENERATION_MISSING: \"VIDEO_PERSON_GENERATION_MISSING\",\n RAW_FACE_KEYFRAME: \"VIDEO_RAW_FACE_KEYFRAME\",\n TIMELINE_TOTAL: \"VIDEO_TIMELINE_TOTAL_MISMATCH\",\n NATIVE_SEG_OVERLAP: \"VIDEO_NATIVE_SEG_OVERLAP\",\n SPINE_UNNORMALIZED: \"VIDEO_SPINE_UNNORMALIZED\",\n ODD_DIMENSIONS: \"VIDEO_ODD_DIMENSIONS\",\n REGION_DROPPED: \"VIDEO_REGION_DROPPED\",\n OVERLAY_OUT_OF_BOUNDS: \"VIDEO_OVERLAY_OUT_OF_BOUNDS\",\n ORPHAN_NODE: \"ORPHAN_NODE\",\n INGEST_PATH_URL_HEALED: \"INGEST_PATH_URL_HEALED\",\n PARALLEL_FORMAT_RENDERS: \"IMAGE_PARALLEL_FORMAT_RENDERS\",\n} as const;\n\n// A clip span may sit a hair above a model's max after rounding; only warn on a real gap.\nconst SPAN_MODEL_SLACK_S = 0.25;\n\n// A voiceover turn may legitimately spill slightly past the next turn's start (tts\n// length is approximate), and the audio mix may run a touch past the video. Only\n// flag clear breakage beyond this slack.\nconst VIDEO_TIME_SLACK_S = 0.75;\n\n// Conversational speech pace used to estimate a native line's spoken length from its\n// word count (mirrors the scaffold's estSpeechS in engine/scaffold/video.ts). The\n// overrun ratio is deliberately LOOSER than the scaffold's 1.3 advisory: word count is\n// the only signal here (no real timings survive a script re-craft), and real fast UGC\n// speech runs 3.5–4 words/s, so flagging above 2.5×1.6 = 4 words/s catches only lines\n// that physically cannot fit their clip (the audit's 4.3 w/s render-killer) without\n// false-positives on energetic-but-renderable reads.\nconst SPEECH_WORDS_PER_SECOND = 2.5;\nconst SPEECH_OVERRUN_RATIO = 1.6;\n\n/** The duration an ffmpeg node's output carries: the LAST `-t` value in its args. */\nexport function ffmpegTrimSeconds(node: NodeDecl): number | null {\n const args = (node.params as Record<string, unknown> | undefined)?.args;\n if (!Array.isArray(args)) return null;\n let t: number | null = null;\n for (let i = 0; i < args.length - 1; i++) {\n if (args[i] === \"-t\") {\n const v = Number(args[i + 1]);\n if (Number.isFinite(v)) t = v;\n }\n }\n return t;\n}\n\n/** The node a `$ref:<id>.<output>` expression points at, when it is one. */\nfunction refNodeOf(ctx: Ctx, value: unknown): NodeDecl | null {\n if (typeof value !== \"string\" || !value.startsWith(REF_PREFIX)) return null;\n const parsed = parseRefExpr(value);\n if (!parsed) return null;\n const idx = ctx.idToIndex.get(parsed.nodeId);\n return idx === undefined ? null : (ctx.canvas.nodes[idx] as NodeDecl);\n}\n\n/**\n * A node's on-timeline video duration, recomputed from the LIVE graph: an ffmpeg\n * trim's `-t`, a `video_generate`'s `duration` param, or — for a composite/passthrough\n * ffmpeg with no `-t` — its first video input's duration (bounded recursion). Null\n * when the graph doesn't say (the caller skips the check rather than guessing).\n */\nfunction liveNodeDurationS(ctx: Ctx, node: NodeDecl | null, depth = 0): number | null {\n if (!node || depth > 3) return null;\n if (node.type === \"video_generate\") {\n const d = (node.params as Record<string, unknown> | undefined)?.duration;\n return typeof d === \"number\" ? d : null;\n }\n if (node.type === \"ffmpeg\") {\n const t = ffmpegTrimSeconds(node);\n if (t !== null) return t;\n for (const v of Object.values(node.inputs ?? {})) {\n const upstream = refNodeOf(ctx, v);\n const d = liveNodeDurationS(ctx, upstream, depth + 1);\n if (d !== null) return d;\n }\n return null;\n }\n return null;\n}\n\ntype Ctx = {\n canvas: Canvas;\n registry: NodeRegistry;\n issues: ValidationIssue[];\n idToIndex: Map<string, number>;\n};\n\nexport function validateCanvas(input: unknown, registry: NodeRegistry): ValidationResult {\n const issues: ValidationIssue[] = [];\n const shape = CanvasSchema.safeParse(input);\n if (!shape.success) {\n pushZodIssues(issues, shape.error, \"\", STAGE_CODES.SHAPE);\n return { ok: false, issues };\n }\n const canvas = shape.data;\n const idToIndex = buildIdToIndex(canvas);\n const ctx: Ctx = { canvas, registry, issues, idToIndex };\n\n checkDuplicateIds(ctx);\n checkUnknownNodeTypes(ctx);\n if (issues.some((i) => i.code === STAGE_CODES.UNKNOWN_NODE)) return { ok: false, issues };\n\n checkAllParams(ctx);\n checkIngestPathUrlHeals(ctx);\n checkAllModelParams(ctx);\n checkAllRefs(ctx);\n checkAllModelInputs(ctx);\n checkCycle(ctx);\n checkAllSlots(ctx);\n const estimatedCredits = estimateCredits(ctx);\n checkOutputRef(ctx);\n checkOrphanNodes(ctx);\n checkParallelFormatRenders(ctx);\n checkVideoInvariants(ctx);\n\n // Warnings are advisory: they never block. Only error-severity issues make the\n // canvas invalid; on failure we still return every issue (warnings included) so\n // nothing is dropped from the report.\n const hasBlocking = issues.some(isBlocking);\n if (hasBlocking) return { ok: false, issues };\n const warnings = issues.filter((i) => !isBlocking(i));\n return { ok: true, canvas, estimatedCredits, warnings: warnings.length > 0 ? warnings : undefined };\n}\n\n/**\n * Async second pass that lets each node run its own `validateExtra` hook.\n * Use this from `canvas validate` so composition-meta checks (and any\n * future async validators) surface as standard validation issues.\n *\n * Returns the same result the sync pass would, with `perNodeCredits` added\n * when the canvas is structurally OK.\n */\nexport async function validateCanvasDeep(input: unknown, registry: NodeRegistry): Promise<ValidationDeep> {\n const shallow = validateCanvas(input, registry);\n if (!shallow.ok) return shallow;\n const canvas = shallow.canvas;\n const issues: ValidationIssue[] = [];\n\n for (let i = 0; i < canvas.nodes.length; i++) {\n const n = canvas.nodes[i];\n if (!n) continue;\n const def = registry.get(n.type);\n if (!def?.validateExtra) continue;\n let extra: Awaited<ReturnType<typeof def.validateExtra>>;\n try {\n extra = await def.validateExtra({ rawParams: n.params, rawInputs: n.inputs });\n } catch (e) {\n issues.push({\n path: `nodes[${i}].params`,\n code: STAGE_CODES.PARAMS_EXTRA,\n message: (e as Error).message,\n node_id: n.id,\n node_type: n.type,\n });\n continue;\n }\n for (const item of extra) {\n issues.push({\n path: `nodes[${i}].${item.path}`,\n code: STAGE_CODES.PARAMS_EXTRA,\n message: item.message,\n node_id: n.id,\n node_type: n.type,\n });\n }\n }\n\n await checkOverlayTimingBounds(canvas, issues);\n\n const hasBlocking = issues.some(isBlocking);\n if (hasBlocking) return { ok: false, issues };\n // Carry the shallow pass's advisory warnings through, plus any warning-severity\n // deep-validator issues, onto the ok result.\n const warnings = [...(shallow.warnings ?? []), ...issues.filter((i) => !isBlocking(i))];\n\n const perNodeCredits = canvas.nodes.map((n) => {\n const def = registry.get(n.type);\n let credits = 0;\n if (def?.cost) {\n try {\n const parsed = def.params.parse(n.params ?? {});\n credits = def.cost({ params: parsed as never }).credits;\n } catch {\n // Already validated above; defensive fallback.\n }\n }\n return { node_id: n.id, node_type: n.type, credits };\n });\n\n return {\n ok: true,\n canvas,\n estimatedCredits: shallow.estimatedCredits,\n perNodeCredits,\n warnings: warnings.length > 0 ? warnings : undefined,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Stage helpers\n// ---------------------------------------------------------------------------\n\nfunction buildIdToIndex(canvas: Canvas): Map<string, number> {\n const m = new Map<string, number>();\n for (let i = 0; i < canvas.nodes.length; i++) {\n const n = canvas.nodes[i];\n if (n) m.set(n.id, i);\n }\n return m;\n}\n\nfunction checkDuplicateIds(ctx: Ctx): void {\n const seen = new Set<string>();\n for (let i = 0; i < ctx.canvas.nodes.length; i++) {\n const n = ctx.canvas.nodes[i];\n if (!n) continue;\n if (seen.has(n.id)) {\n ctx.issues.push({\n path: `nodes[${i}].id`,\n code: STAGE_CODES.DUPLICATE_ID,\n message: `duplicate node id \"${n.id}\"`,\n node_id: n.id,\n });\n }\n seen.add(n.id);\n }\n}\n\nfunction checkUnknownNodeTypes(ctx: Ctx): void {\n const known = ctx.registry.ids();\n for (let i = 0; i < ctx.canvas.nodes.length; i++) {\n const n = ctx.canvas.nodes[i];\n if (!n || ctx.registry.has(n.type)) continue;\n ctx.issues.push({\n path: `nodes[${i}].type`,\n code: STAGE_CODES.UNKNOWN_NODE,\n message: `unknown node type \"${n.type}\"`,\n received: n.type,\n did_you_mean: didYouMean(n.type, known),\n node_id: n.id,\n node_type: n.type,\n });\n }\n}\n\nfunction checkAllParams(ctx: Ctx): void {\n for (let i = 0; i < ctx.canvas.nodes.length; i++) {\n const n = ctx.canvas.nodes[i];\n if (!n) continue;\n const def = ctx.registry.get(n.type);\n if (!def) continue;\n const parsed = def.params.safeParse(n.params ?? {});\n if (parsed.success) continue;\n pushZodIssues(ctx.issues, parsed.error, `nodes[${i}].params`, STAGE_CODES.PARAMS, n.id, n.type);\n }\n}\n\n/**\n * The ingest schema silently heals a `source:\"path\"` node whose value is an http(s) URL into a\n * `source:\"url\"` ingest (so the run works instead of dying at execute with file_not_found). Surface\n * that heal as an advisory: the run behaves correctly, but the on-disk canvas JSON still literally\n * says `source:\"path\"`, so the operator should correct it. Non-blocking — the canvas stays runnable.\n */\nfunction checkIngestPathUrlHeals(ctx: Ctx): void {\n for (let i = 0; i < ctx.canvas.nodes.length; i++) {\n const n = ctx.canvas.nodes[i];\n if (!n || n.type !== \"ingest\") continue;\n const params = (n.params ?? {}) as Record<string, unknown>;\n if (params.source !== \"path\" || !looksLikeHttpUrl(params.path)) continue;\n ctx.issues.push({\n path: `nodes[${i}].params.source`,\n code: STAGE_CODES.INGEST_PATH_URL_HEALED,\n message: `ingest \"${n.id}\" declares source:\"path\" but its value is a URL — running it as source:\"url\". Update the canvas JSON to source:\"url\" so it matches what baker runs.`,\n severity: \"warning\",\n node_id: n.id,\n node_type: n.type,\n });\n }\n}\n\nfunction checkAllModelParams(ctx: Ctx): void {\n for (let i = 0; i < ctx.canvas.nodes.length; i++) {\n const n = ctx.canvas.nodes[i];\n if (!n || !isManagedNodeKind(n.type)) continue;\n const params = (n.params ?? {}) as Record<string, unknown>;\n const model = params.model;\n if (typeof model !== \"string\" || model.length === 0) continue; // shape validator will have flagged this\n const r = validateModelParams(n.type, model, params);\n if (r.ok) continue;\n for (const err of r.errors) {\n ctx.issues.push({\n path: `nodes[${i}].params${\"param\" in err ? `.${err.param}` : \"\"}`,\n code: STAGE_CODES.MODEL_PARAMS,\n message: err.message,\n node_id: n.id,\n node_type: n.type,\n });\n }\n }\n}\n\nfunction checkAllRefs(ctx: Ctx): void {\n for (let i = 0; i < ctx.canvas.nodes.length; i++) {\n const n = ctx.canvas.nodes[i];\n if (!n) continue;\n walkRefs(n.inputs, (refStr, jsonPath) => {\n checkOneRef(ctx, n, i, refStr, jsonPath, \"inputs\");\n });\n walkRefs(n.params, (refStr, jsonPath) => {\n checkOneRef(ctx, n, i, refStr, jsonPath, \"params\");\n });\n }\n}\n\n/**\n * For every managed-kind node (image_generate / video_generate / video_lipsync\n * / tts / music / dialogue / sound_effect), confirm the model's REQUIRED input\n * kinds are wired. The kind of each wired ref comes from the target node's\n * declared `outputKinds[slot]`. Refs that can't be resolved (missing target,\n * bad output, etc.) are skipped — `checkAllRefs` already surfaced those.\n */\nfunction checkAllModelInputs(ctx: Ctx): void {\n for (let i = 0; i < ctx.canvas.nodes.length; i++) {\n const n = ctx.canvas.nodes[i];\n if (!n || !isManagedNodeKind(n.type)) continue;\n const params = (n.params ?? {}) as Record<string, unknown>;\n const model = params.model;\n if (typeof model !== \"string\" || model.length === 0) continue;\n const providedKinds = collectProvidedKinds(ctx, n);\n const r = validateModelInputs(n.type, model, providedKinds);\n if (r.ok) continue;\n for (const err of r.errors) {\n ctx.issues.push({\n path: `nodes[${i}].inputs`,\n code: STAGE_CODES.MODEL_INPUTS,\n message: err.message,\n node_id: n.id,\n node_type: n.type,\n });\n }\n }\n}\n\nfunction collectProvidedKinds(ctx: Ctx, n: NodeDecl): InputKind[] {\n const kinds = new Set<InputKind>();\n walkRefs(n.inputs, (refStr) => {\n const kind = resolveRefKind(ctx, refStr);\n if (kind) kinds.add(kind);\n });\n return [...kinds];\n}\n\nfunction resolveRefKind(ctx: Ctx, refStr: string): InputKind | null {\n if (!refStr.startsWith(REF_PREFIX)) return null;\n const expr = parseRefExpr(refStr);\n if (!expr || expr.kind !== \"ref\") return null;\n const targetIdx = ctx.idToIndex.get(expr.nodeId);\n if (targetIdx === undefined) return null;\n const target = ctx.canvas.nodes[targetIdx];\n if (!target) return null;\n const targetDef = ctx.registry.get(target.type);\n if (!targetDef) return null;\n const targetParams = targetDef.params.safeParse(target.params ?? {});\n const resolvedKinds = resolveOutputKinds(targetDef.outputKinds, targetParams.success ? targetParams.data : {});\n // Nodes with dynamic outputs (ffmpeg) declare each output's kind on the instance\n // (`params.outputs.<name>.kind`); honor that so an ffmpeg-produced audio/video can\n // satisfy a typed model input (e.g. audio_voice_convert reading extracted audio).\n const declaredKind = (target.params as { outputs?: Record<string, { kind?: string }> } | undefined)?.outputs?.[\n expr.output\n ]?.kind;\n const kind = resolvedKinds[expr.output] ?? declaredKind;\n return kind && MODEL_INPUT_KINDS.has(kind as InputKind) ? (kind as InputKind) : null;\n}\n\nfunction checkOneRef(\n ctx: Ctx,\n n: NodeDecl,\n i: number,\n refStr: string,\n jsonPath: string,\n field: \"inputs\" | \"params\",\n): void {\n if (!refStr.startsWith(REF_PREFIX)) return;\n const expr = parseRefExpr(refStr);\n if (!expr || expr.kind !== \"ref\") {\n ctx.issues.push({\n path: `nodes[${i}].${field}.${jsonPath}`,\n code: STAGE_CODES.REF_UNRESOLVED,\n message: `malformed ref \"${refStr}\"`,\n node_id: n.id,\n node_type: n.type,\n });\n return;\n }\n const targetIdx = ctx.idToIndex.get(expr.nodeId);\n if (targetIdx === undefined) {\n ctx.issues.push({\n path: `nodes[${i}].${field}.${jsonPath}`,\n code: STAGE_CODES.REF_UNRESOLVED,\n message: `ref \"${refStr}\" — no node with id \"${expr.nodeId}\"`,\n did_you_mean: didYouMean(expr.nodeId, [...ctx.idToIndex.keys()]),\n node_id: n.id,\n node_type: n.type,\n });\n return;\n }\n checkRefOutput(ctx, n, i, jsonPath, field, refStr, expr.nodeId, expr.output, targetIdx);\n}\n\nfunction checkRefOutput(\n ctx: Ctx,\n n: NodeDecl,\n i: number,\n jsonPath: string,\n field: \"inputs\" | \"params\",\n refStr: string,\n nodeId: string,\n output: string,\n targetIdx: number,\n): void {\n const target = ctx.canvas.nodes[targetIdx];\n if (!target) return;\n const targetDef = ctx.registry.get(target.type);\n if (!targetDef) return;\n const outputNames = listShapeKeys(targetDef.outputs);\n if (!outputNames || outputNames.includes(output)) return;\n ctx.issues.push({\n path: `nodes[${i}].${field}.${jsonPath}`,\n code: STAGE_CODES.REF_UNRESOLVED,\n message: `ref \"${refStr}\" — node \"${nodeId}\" (${target.type}) has no output \"${output}\"`,\n did_you_mean: didYouMean(output, outputNames),\n node_id: n.id,\n node_type: n.type,\n });\n}\n\nfunction checkCycle(ctx: Ctx): void {\n const graph = buildDepGraph(ctx.canvas);\n const cycle = findCycle(graph);\n if (cycle) {\n ctx.issues.push({ path: \"nodes\", code: STAGE_CODES.CYCLE, message: `cycle detected: ${cycle.join(\" → \")}` });\n }\n}\n\nfunction checkAllSlots(ctx: Ctx): void {\n for (let i = 0; i < ctx.canvas.nodes.length; i++) {\n const n = ctx.canvas.nodes[i];\n if (!n) continue;\n if (!ctx.registry.get(n.type)) continue;\n checkSlotsForNode(ctx, n, i);\n }\n}\n\nfunction checkSlotsForNode(ctx: Ctx, n: NodeDecl, _i: number): void {\n const slots = new Set<string>();\n walkPromptStrings(n.params, (text) => {\n for (const s of extractSlots(text)) slots.add(s);\n });\n if (slots.size === 0) return;\n const inputKeys = Object.keys(n.inputs ?? {});\n for (const slot of slots) {\n if (inputKeys.includes(slot)) continue;\n ctx.issues.push({\n path: `nodes[${_i}].params`,\n code: STAGE_CODES.SLOT,\n message: `prompt slot \"{{${slot}}}\" has no matching input on node \"${n.id}\"`,\n did_you_mean: didYouMean(slot, inputKeys),\n node_id: n.id,\n node_type: n.type,\n });\n }\n}\n\nfunction estimateCredits(ctx: Ctx): number {\n let total = 0;\n for (const n of ctx.canvas.nodes) {\n const def = ctx.registry.get(n.type);\n if (!def?.cost) continue;\n try {\n const parsed = def.params.parse(n.params ?? {});\n total += def.cost({ params: parsed }).credits;\n } catch {\n // params already errored above; skip\n }\n }\n return total;\n}\n\n/**\n * The seeded overlay windows in a composition's index.html, flagged when they run\n * past the video end. An out-of-bounds element simply never hides — the \"stuck last\n * overlay\" render bug — and re-timed scenes are exactly when it happens. Pure.\n */\nexport function overlayTimingIssues(html: string, durationS: number): Array<{ start: number; dur: number }> {\n const out: Array<{ start: number; dur: number }> = [];\n for (const m of html.matchAll(/<[^>]*\\bdata-start=\"([\\d.]+)\"[^>]*\\bdata-dur=\"([\\d.]+)\"[^>]*>/g)) {\n const start = Number(m[1]);\n const dur = Number(m[2]);\n if (!Number.isFinite(start) || !Number.isFinite(dur)) continue;\n if (start >= durationS || start + dur > durationS + 0.25) out.push({ start, dur });\n }\n return out;\n}\n\n/** Deep advisory: every hyperframe composition's seeded overlay windows fit the video. */\nasync function checkOverlayTimingBounds(canvas: Canvas, issues: ValidationIssue[]): Promise<void> {\n const durationS = canvas.metadata?.video?.duration_s;\n if (typeof durationS !== \"number\") return;\n for (let i = 0; i < canvas.nodes.length; i++) {\n const n = canvas.nodes[i];\n if (n?.type !== \"hyperframe_render\") continue;\n const composition = (n.params as Record<string, unknown> | undefined)?.composition;\n if (typeof composition !== \"string\" || !path.isAbsolute(composition)) continue;\n const html = await readFile(path.join(composition, \"index.html\"), \"utf8\").catch(() => null);\n if (!html) continue;\n for (const w of overlayTimingIssues(html, durationS)) {\n issues.push({\n path: `nodes[${i}].params.composition`,\n code: STAGE_CODES.OVERLAY_OUT_OF_BOUNDS,\n severity: \"warning\",\n node_id: n.id,\n node_type: n.type,\n message: `an overlay in ${path.basename(composition)}/index.html runs [${w.start}s, ${w.start + w.dur}s] but the video ends at ${durationS}s — it never hides on screen. Re-time its data-start/data-dur to fit the video`,\n });\n }\n }\n}\n\ntype TalkingSceneEntry =\n | number\n | { scene: number; voice_convert_node: string; est_speech_s?: number; speech_words?: number }\n | { scene: number; lipsync_node: string };\n\n/**\n * Does the scene's native clip audio (or its extraction) reach the audio mix\n * directly, without the STS convert node? This is the valid fallback config when\n * the one-brand-voice convert chain is intentionally bypassed: the native clip\n * already carries lip-matched speech, so routing it straight to the mix keeps the\n * lips correct (only brand-voice normalization is given up). Accepts the per-scene\n * `s<scene>_voextract`/`s<scene>_clip` audio (or a region clip) wired into any\n * `audio_timeline`.\n */\nfunction nativeAudioReachesMix(ctx: Ctx, scene: number): boolean {\n const wanted = [\n `$ref:s${scene}_voextract.audio`,\n `$ref:s${scene}_clip.audio`,\n new RegExp(`\\\\$ref:s${scene}_r\\\\d+_(voextract|clip)\\\\.audio`),\n ];\n return ctx.canvas.nodes.some((n) => {\n if (n.type !== \"audio_timeline\") return false;\n const blob = JSON.stringify(n.inputs ?? {});\n return wanted.some((w) => (typeof w === \"string\" ? blob.includes(w) : w.test(blob)));\n });\n}\n\n/**\n * Is a single-on-camera-speaker scene correctly voiced? Native scaffold output\n * (`{ scene, voice_convert_node }`) requires the clip to carry native audio\n * (`generate_audio: true`) — the invariant that keeps lips matched — AND that the\n * native audio reaches the mix, EITHER through the `audio_voice_convert` node\n * (one-brand-voice, the default) OR routed directly (native-audio fallback).\n * Legacy veed forms (`{ scene, lipsync_node }` / bare index) require a\n * `video_lipsync` node.\n */\nfunction talkingSceneSatisfied(ctx: Ctx, entry: TalkingSceneEntry, scene: number): boolean {\n const nodes = ctx.canvas.nodes;\n if (typeof entry === \"object\" && \"voice_convert_node\" in entry) {\n // The scene's native clip is `s<scene>_clip` for a full-frame scene, or the\n // PRESENTER region's clip (`s<scene>_r<n>_clip`) for a composited scene — either\n // carrying the generated speech is what the voice-convert node re-voices.\n const nativeClipRe = new RegExp(`^s${scene}(_r\\\\d+)?_clip$`);\n const clipNativeAudio = nodes.some(\n (n) =>\n nativeClipRe.test(n.id) &&\n n.type === \"video_generate\" &&\n (n.params as Record<string, unknown>)?.generate_audio === true,\n );\n const converted = nodes.some((n) => n.id === entry.voice_convert_node && n.type === \"audio_voice_convert\");\n return clipNativeAudio && (converted || nativeAudioReachesMix(ctx, scene));\n }\n if (typeof entry === \"object\") {\n return nodes.some((n) => n.id === entry.lipsync_node && n.type === \"video_lipsync\");\n }\n return nodes.some((n) => {\n if (n.type !== \"video_lipsync\") return false;\n const video = (n.inputs as Record<string, unknown>)?.video;\n return video === `$ref:s${scene}_trim.video` || video === `$ref:s${scene}_clip.video`;\n });\n}\n\n/**\n * Whole-canvas video invariants, proven STATICALLY from the timing plan a video\n * scaffold records in `metadata.video` (per-node `validateExtra` can't see across\n * nodes). This catches the failure modes that otherwise only surface after a\n * ~50cr/clip render: voiceover turns playing on top of each other, an audio mix\n * that runs well past the picture, and a talking subject whose clip was never\n * natively voiced. Silent when no `metadata.video` is present (non-video canvases).\n */\nfunction checkVideoInvariants(ctx: Ctx): void {\n // Node-local model-profile checks run for ANY canvas (they scan node params, not the\n // metadata.video timing plan) — a hand-edited canvas that lost its metadata still gets\n // the prompt/param advisories.\n checkPromptProfile(ctx);\n checkImageProfile(ctx);\n checkPersonGeneration(ctx);\n checkPromptBudget(ctx);\n checkRawFaceKeyframe(ctx);\n checkPromptDecisions(ctx);\n checkHookLayers(ctx);\n\n const meta = ctx.canvas.metadata?.video;\n if (!meta) return;\n\n // 1. No two voiceover turns overlap in time (the parallel-monologue symptom).\n const segments = [...meta.vo_segments].sort((a, b) => a.start_s - b.start_s);\n for (let i = 1; i < segments.length; i++) {\n const prev = segments[i - 1];\n const cur = segments[i];\n if (!prev || !cur) continue;\n if (cur.start_s < prev.end_s - VIDEO_TIME_SLACK_S) {\n ctx.issues.push({\n path: \"metadata.video.vo_segments\",\n code: STAGE_CODES.VO_OVERLAP,\n message: `voiceover turns overlap: \"${prev.slot}\" runs to ${prev.end_s}s but \"${cur.slot}\" starts at ${cur.start_s}s — sequence them so dialogue alternates instead of stacking`,\n });\n }\n }\n\n // 2. The audio timeline should not run materially longer than the video.\n const audioEnd = segments.reduce((m, s) => Math.max(m, s.end_s), 0);\n if (audioEnd > meta.duration_s + VIDEO_TIME_SLACK_S) {\n ctx.issues.push({\n path: \"metadata.video.duration_s\",\n code: STAGE_CODES.AUDIO_DURATION,\n message: `audio runs to ${audioEnd}s but the video is ${meta.duration_s}s — trim the voiceover or extend the video so audio ≈ video length`,\n });\n }\n\n // 3. Every single-on-camera-speaker scene must be a NATIVELY-voiced talking head:\n // the Seedance clip generates the speech+lips (`generate_audio: true` + the line in\n // its prompt) and an `audio_voice_convert` node re-voices it to the brand voice. We\n // confirm both — the clip carries native audio AND the convert node is wired — so\n // the lips can't drift (they were generated with the audio). Entry forms:\n // { scene, voice_convert_node } — native (current scaffold)\n // { scene, lipsync_node } / bare index — legacy veed canvases (still accepted)\n for (const entry of meta.talking_scenes) {\n const scene = typeof entry === \"number\" ? entry : entry.scene;\n if (!talkingSceneSatisfied(ctx, entry, scene)) {\n ctx.issues.push({\n path: \"metadata.video.talking_scenes\",\n code: STAGE_CODES.LIPSYNC_MISSING,\n message: `scene ${scene} is a single-on-camera-speaker talking head but its clip lacks native audio (generate_audio: true) — the lips would drift. Generate the clip with native audio, then route it to the mix via either the audio_voice_convert node (one brand voice) or directly (s${scene}_voextract → audio_mix)`,\n });\n }\n }\n\n // 4. A native line must physically FIT its generated clip. The scaffold's overstuff\n // advisories ran against the ORIGINAL blueprint; the operator then re-crafts the\n // script inside the canvas, so re-derive the spoken length from each native clip's\n // CURRENT prompt and fail when it clearly overruns the clip duration (the render\n // either fails or crams — either way lips and timeline break).\n checkSpeechOverrun(ctx, meta.talking_scenes);\n\n // 5. Every clip must land on ONE canvas geometry. Mixed (or partially-defaulted)\n // aspect_ratio params across video_generate nodes ship a spine whose segments\n // disagree in shape — the composite silently crops/letterboxes.\n checkAspectConsistency(ctx);\n\n // 6. Advisory: no clip prompt should narrate a screen/UI surface (garbled UI).\n checkUiInPrompt(ctx);\n\n // 6b. Advisory: no generate prompt should request a brand logo/wordmark as content.\n checkBrandmarkInPrompt(ctx);\n\n // 6. Advisory: a frame that describes a recurring element (a pet, product, logo)\n // must WIRE that element's reference, or the generator invents a wrong-identity one.\n checkReferenceCompleteness(ctx, meta);\n\n // 7. Advisory: a scene's natural span must fit the assigned model's max clip length\n // (a 9.2s scene on Veo, which caps at 8s, would truncate). Caught before a run.\n checkClipSpanFitsModel(ctx, meta);\n\n // 8-12. The one-clock contract, recomputed from the LIVE graph — the frozen\n // metadata plan above catches scaffold-time breakage, but operators re-craft the\n // canvas by hand and `-shortest` at the final mux silently truncates whichever\n // stream runs longer, so the REAL node params are what must agree.\n checkTimelineContract(ctx, meta);\n checkNativeSegOverlap(ctx);\n checkSpineNormalized(ctx, meta);\n checkOddDimensions(ctx);\n checkRegionDropped(ctx);\n}\n\n/**\n * Advisory: a clip on a video model with NO prompt profile was authored with the\n * default Seedance syntax — its dialogue/emotion markup may not carry over (Veo,\n * for one, renders [brackets] as literal text). Review before billing.\n */\nfunction checkPromptProfile(ctx: Ctx): void {\n for (const n of ctx.canvas.nodes) {\n if (n.type !== \"video_generate\") continue;\n const model = (n.params as Record<string, unknown> | undefined)?.model;\n if (typeof model !== \"string\" || clipProfileFor(model)) continue;\n ctx.issues.push({\n path: `nodes[${ctx.idToIndex.get(n.id) ?? -1}].params.model`,\n code: STAGE_CODES.PROMPT_PROFILE_MISSING,\n severity: \"warning\",\n node_id: n.id,\n message: `\"${n.id}\" runs on \"${model}\", a model with no clip-prompt profile — its prompt was authored with the default Seedance syntax. Review the dialogue/emotion markup for this model before billing`,\n });\n }\n}\n\n// A clip prompt that made the TECHNIQUE decision names a camera/motion move.\nconst TECHNIQUE_CUE =\n /\\b(camera|push[- ]?in|pull[- ]?out|pan|dolly|zoom|tilt|track|handheld|locked|orbit|crane|whip|motion|move)\\b/i;\n// A clip prompt that made the NEGATIVES/constraints decision: Seedance phrases it as an\n// affirmative stability line (\"Keep it clean and stable: …\"), Veo/Kling take a real\n// `negative_prompt` param, and a hand-written prompt may still use a literal `Avoid:` tail.\nconst NEGATIVES_CUE = /\\bavoid:|\\bno subtitles|\\bnegative\\b|keep it clean and stable/i;\n// The VIBE layer: lighting / grade / tone words in the hook's frame or clip prompt.\nconst VIBE_CUE =\n /\\b(light|lighting|golden|moody|warm|cool|tone|grade|contrast|shadow|glow|rim|backlit|neon|soft|harsh)\\b/i;\n\n/**\n * Advisory (T3.1): mechanizes the skill's \"six decisions\" (route / spec / beats /\n * copy / technique / negatives) at the two that are checkable from a single clip\n * node — TECHNIQUE (a named camera/motion move) and NEGATIVES (an `Avoid:` line or\n * a `negative_prompt` param). A clip prompt missing BOTH is a thin prompt the model\n * will fill with its own defaults; warn so the operator decides the missing beats.\n * Doctrine: `creative-canvas-ads/references/prompt-anatomy.md`.\n */\nfunction checkPromptDecisions(ctx: Ctx): void {\n for (const n of ctx.canvas.nodes) {\n if (n.type !== \"video_generate\") continue;\n const params = n.params as Record<string, unknown> | undefined;\n const prompt = typeof params?.prompt === \"string\" ? params.prompt : \"\";\n if (!prompt) continue;\n const hasTechnique = TECHNIQUE_CUE.test(prompt);\n const hasNegatives = NEGATIVES_CUE.test(prompt) || typeof params?.negative_prompt === \"string\";\n if (hasTechnique || hasNegatives) continue;\n ctx.issues.push({\n path: `nodes[${ctx.idToIndex.get(n.id) ?? -1}].params.prompt`,\n code: STAGE_CODES.PROMPT_DECISION_MISSING,\n severity: \"warning\",\n node_id: n.id,\n message: `\"${n.id}\" is a thin clip prompt — it names no camera/motion move (TECHNIQUE) and no constraints (NEGATIVES: an affirmative \"Keep it clean and stable\" line, a negative_prompt param, or an \"Avoid:\" tail). Make the six decisions (route / spec / beats / copy / technique / negatives) so the model doesn't fill the gaps with drift. See prompt-anatomy.md`,\n });\n }\n}\n\n/**\n * Advisory (T3.1): a strong hook works on all FOUR layers — text (overlay), sound\n * (line/SFX), visual (the frame), vibe (lighting+tone). This scans scene 0's nodes\n * and warns when two or more layers are absent, so a bare hook doesn't ship. Only\n * fires on scene-based video canvases (a node id starting `s0`). Doctrine:\n * `creative-canvas-ads/references/hook-craft.md`.\n */\nfunction checkHookLayers(ctx: Ctx): void {\n const scene0 = ctx.canvas.nodes.filter((n) => /^s0(?:[_a-z0-9])*_/.test(n.id) || n.id === \"s0\");\n const hookClip = scene0.find((n) => n.type === \"video_generate\");\n if (!hookClip) return;\n const scene0Text = scene0\n .map((n) => {\n const p = (n.params as Record<string, unknown> | undefined)?.prompt;\n return typeof p === \"string\" ? p : \"\";\n })\n .join(\"\\n\");\n const hookParams = hookClip.params as Record<string, unknown> | undefined;\n\n const hasOverlayLayer = ctx.canvas.nodes.some((n) => /hyperframe/.test(n.type));\n const hasSound =\n hookParams?.generate_audio === true ||\n /Dialogue:|Audio:/.test(scene0Text) ||\n ctx.canvas.nodes.some((n) => n.type === \"tts\" || n.type === \"dialogue\" || n.type === \"music\");\n const hasVisual = scene0Text.trim().length > 40;\n const hasVibe = VIBE_CUE.test(scene0Text);\n\n const missing: string[] = [];\n if (!hasOverlayLayer) missing.push(\"text (overlay)\");\n if (!hasSound) missing.push(\"sound (line/SFX)\");\n if (!hasVisual) missing.push(\"visual (the frame)\");\n if (!hasVibe) missing.push(\"vibe (lighting/tone)\");\n if (missing.length < 2) return;\n\n ctx.issues.push({\n path: `nodes[${ctx.idToIndex.get(hookClip.id) ?? -1}]`,\n code: STAGE_CODES.HOOK_LAYER_MISSING,\n severity: \"warning\",\n node_id: hookClip.id,\n message: `the hook (scene 0) is thin across layers — missing ${missing.join(\", \")}. A scroll-stopping hook works on all four layers (text / sound / visual / vibe); strengthen the missing ones. See hook-craft.md`,\n });\n}\n\n/** Advisory: an image frame renders on a model with no per-model prompt profile, so\n * it got the generic frame template (exclusion placement / photoreal cue not tuned). */\nfunction checkImageProfile(ctx: Ctx): void {\n for (const n of ctx.canvas.nodes) {\n if (n.type !== \"image_generate\") continue;\n const model = (n.params as Record<string, unknown> | undefined)?.model;\n if (typeof model !== \"string\" || imageProfileFor(model)) continue;\n ctx.issues.push({\n path: `nodes[${ctx.idToIndex.get(n.id) ?? -1}].params.model`,\n code: STAGE_CODES.IMAGE_PROFILE_MISSING,\n severity: \"warning\",\n node_id: n.id,\n message: `\"${n.id}\" renders on \"${model}\", an image model with no frame-prompt profile — it got the generic template (constraint placement / photoreal cue not tuned). Add an ImageModelProfile for this model`,\n });\n }\n}\n\n/** Advisory: a Veo image-to-video clip must set `person_generation` (only `allow_adult`\n * is legal for image-driven modes, and the sole legal value in the EU/UK). */\nfunction checkPersonGeneration(ctx: Ctx): void {\n for (const n of ctx.canvas.nodes) {\n if (n.type !== \"video_generate\") continue;\n const params = n.params as Record<string, unknown> | undefined;\n const model = params?.model;\n if (clipProfileFor(typeof model === \"string\" ? model : \"\")?.id !== \"veo\") continue;\n const hasKeyframe = Boolean(n.inputs?.first_frame ?? n.inputs?.reference);\n if (!hasKeyframe || params?.person_generation) continue;\n ctx.issues.push({\n path: `nodes[${ctx.idToIndex.get(n.id) ?? -1}].params`,\n code: STAGE_CODES.PERSON_GENERATION_MISSING,\n severity: \"warning\",\n node_id: n.id,\n message: `Veo clip \"${n.id}\" drives from a keyframe but sets no person_generation — set \"allow_adult\" (the only legal value for image-to-video, and the only one allowed in the EU/UK)`,\n });\n }\n}\n\n/** Advisory: a clip prompt runs past the model's quality word budget — long prompts\n * pack conflicting instructions and the model starts dropping beats. */\nfunction checkPromptBudget(ctx: Ctx): void {\n for (const n of ctx.canvas.nodes) {\n if (n.type !== \"video_generate\") continue;\n const params = n.params as Record<string, unknown> | undefined;\n const model = params?.model;\n const prompt = params?.prompt;\n const profile = typeof model === \"string\" ? clipProfileFor(model) : undefined;\n if (!profile || typeof prompt !== \"string\") continue;\n const words = prompt.trim().split(/\\s+/).filter(Boolean).length;\n if (words <= profile.wordBudget) continue;\n ctx.issues.push({\n path: `nodes[${ctx.idToIndex.get(n.id) ?? -1}].params.prompt`,\n code: STAGE_CODES.PROMPT_OVER_BUDGET,\n severity: \"warning\",\n node_id: n.id,\n message: `\"${n.id}\" prompt is ${words} words — over ${model}'s ~${profile.wordBudget}-word budget; trim it (the frames carry the content, so keep the clip prompt to motion + audio)`,\n });\n }\n}\n\n/** Advisory: a Seedance image-to-video clip whose first frame is a RAW ingested image\n * (reuse mode, or a dropped photo) rather than a generated frame. If it contains a real\n * human face, ByteDance's real-person filter rejects it (a non-retryable 422) — the fix\n * is an AI-generated portrait keyframe (recast), or route the clip to Veo. */\nfunction checkRawFaceKeyframe(ctx: Ctx): void {\n for (const n of ctx.canvas.nodes) {\n if (n.type !== \"video_generate\") continue;\n const model = (n.params as Record<string, unknown> | undefined)?.model;\n if (clipProfileFor(typeof model === \"string\" ? model : \"\")?.id !== \"seedance\") continue;\n const src = refNodeOf(ctx, n.inputs?.first_frame ?? n.inputs?.reference);\n if (!src || src.type !== \"ingest\") continue;\n ctx.issues.push({\n path: `nodes[${ctx.idToIndex.get(n.id) ?? -1}].inputs.first_frame`,\n code: STAGE_CODES.RAW_FACE_KEYFRAME,\n severity: \"warning\",\n node_id: n.id,\n message: `Seedance clip \"${n.id}\" animates a RAW ingested image (\"${src.id}\"), not a generated frame — if it shows a real human face, ByteDance's real-person filter rejects it (422). Anchor on an AI-generated portrait (recast), or route this clip to Veo`,\n });\n }\n}\n\n/** The spine's LIVE total: Σ input clip durations, minus any xfade overlap it eats. */\nfunction spineTotalS(ctx: Ctx, spine: NodeDecl): number | null {\n let total = 0;\n const inputs = Object.entries(spine.inputs ?? {}).filter(([k]) => /^c\\d+$/.test(k));\n if (inputs.length === 0) return null;\n // The spine's own per-input chain is the authority when it absorbs a length (a\n // trim= cut or a looped still's input-side -t — spine-input.ts); only an input\n // with no absorbed length falls back to sizing the upstream node.\n const rawArgs = (spine.params as Record<string, unknown>).args;\n const absorbed = Array.isArray(rawArgs) ? parseSpineInputLens(rawArgs.map(String)) : new Map<number, number>();\n for (const [k, v] of inputs) {\n const inputIdx = Number(k.slice(1));\n const d = absorbed.get(inputIdx) ?? liveNodeDurationS(ctx, refNodeOf(ctx, v));\n if (d === null) return null; // an input the graph can't size — skip, don't guess\n total += d;\n }\n const graph = ((spine.params as Record<string, unknown>).args as unknown[])?.join?.(\" \") ?? \"\";\n for (const m of String(graph).matchAll(/xfade=transition=[^:]+:duration=([\\d.]+)/g)) {\n total -= Number(m[1]);\n }\n return total;\n}\n\n/**\n * The one-clock length gate: the spine's live total, every per-speaker voice track,\n * and the final mix must all equal the stamped `expected_total_s` — a mismatch means\n * `-shortest` truncates real content (a cut CTA) with no error at render time.\n */\nfunction checkTimelineContract(ctx: Ctx, meta: VideoMetaT): void {\n const stamp = meta.timeline;\n const spineId = stamp?.spine_node ?? (ctx.idToIndex.has(\"spine\") ? \"spine\" : null);\n if (!spineId) return;\n const expected = stamp?.expected_total_s ?? meta.duration_s;\n checkSpineTotal(ctx, spineId, expected);\n checkAudioTimelineTotals(ctx, stamp?.audio_mix_node, expected);\n}\n\n/** The spine's live summed length must equal the stamped total. */\nfunction checkSpineTotal(ctx: Ctx, spineId: string, expected: number): void {\n const spineIdx = ctx.idToIndex.get(spineId);\n const spine = spineIdx === undefined ? null : (ctx.canvas.nodes[spineIdx] as NodeDecl);\n const spineLen = spine ? spineTotalS(ctx, spine) : null;\n if (spineLen === null || Math.abs(spineLen - expected) <= VIDEO_TIME_SLACK_S) return;\n ctx.issues.push({\n path: `nodes[${spineIdx}].params.args`,\n code: STAGE_CODES.TIMELINE_TOTAL,\n node_id: spineId,\n message: `the picture sums to ${round2(spineLen)}s but the timeline is pinned to ${expected}s — \\`-shortest\\` at the final mux will silently cut the longer stream. Re-time the seg trims (or the audio total_ms) so both match`,\n });\n}\n\n/**\n * Full-length audio timelines must equal the stamped total: the mix, plus every\n * per-speaker voice track (their absolute placement collapses if the track isn't\n * timeline-length).\n */\nfunction checkAudioTimelineTotals(ctx: Ctx, audioMixNode: string | undefined, expected: number): void {\n const mustBeFullLength = new Set<string>();\n if (audioMixNode) mustBeFullLength.add(audioMixNode);\n ctx.canvas.nodes.forEach((n) => {\n if (n.type !== \"audio_voice_convert\") return;\n const track = refNodeOf(ctx, (n.inputs ?? {}).audio);\n if (track?.type === \"audio_timeline\") mustBeFullLength.add(track.id);\n });\n for (const id of mustBeFullLength) {\n const idx = ctx.idToIndex.get(id);\n const node = idx === undefined ? null : (ctx.canvas.nodes[idx] as NodeDecl);\n const totalMs = (node?.params as Record<string, unknown> | undefined)?.total_ms;\n if (typeof totalMs !== \"number\") continue;\n if (Math.abs(totalMs / 1000 - expected) > VIDEO_TIME_SLACK_S) {\n ctx.issues.push({\n path: `nodes[${idx}].params.total_ms`,\n code: STAGE_CODES.TIMELINE_TOTAL,\n node_id: id,\n message: `audio timeline \"${id}\" is pinned to ${totalMs}ms but the picture timeline is ${expected}s — \\`-shortest\\` at the final mux will silently cut the longer stream. Pin total_ms to ${Math.round(expected * 1000)}`,\n });\n }\n }\n}\n\n/**\n * No two windows on a per-speaker voice track may overlap: both extracts PLAY — the\n * voice doubles into an echo. Windows come from the LIVE graph: each track entry's\n * `duration_s` cap, else its extract node's `-t`. (The frozen vo_segments check has a\n * 0.75s slack for tts estimates; native extract windows are exact, so 10ms is real.)\n */\nfunction checkNativeSegOverlap(ctx: Ctx): void {\n for (const conv of ctx.canvas.nodes) {\n if (conv.type !== \"audio_voice_convert\") continue;\n const track = refNodeOf(ctx, (conv.inputs ?? {}).audio);\n if (track?.type !== \"audio_timeline\") continue;\n const params = track.params as { tracks?: Array<{ slot: string; start_s: number; duration_s?: number }> };\n const windows = (params.tracks ?? [])\n .map((t) => {\n const extract = refNodeOf(ctx, (track.inputs ?? {})[t.slot]);\n const len = t.duration_s ?? (extract ? ffmpegTrimSeconds(extract) : null);\n return len === null ? null : { slot: t.slot, start: t.start_s, end: t.start_s + len };\n })\n .filter((w): w is { slot: string; start: number; end: number } => w !== null)\n .sort((a, b) => a.start - b.start);\n for (let i = 1; i < windows.length; i++) {\n const prev = windows[i - 1];\n const cur = windows[i];\n if (!prev || !cur || cur.start >= prev.end - 0.01) continue;\n const trackIdx = ctx.idToIndex.get(track.id);\n ctx.issues.push({\n path: `nodes[${trackIdx}].params.tracks`,\n code: STAGE_CODES.NATIVE_SEG_OVERLAP,\n node_id: track.id,\n message: `voice track \"${track.id}\": \"${prev.slot}\" runs to ${round2(prev.end)}s but \"${cur.slot}\" starts at ${cur.start}s — both play at once (echo). Cap the first with duration_s: ${round2(cur.start - prev.start)} or re-time the windows`,\n });\n }\n }\n}\n\n/** Warn when a concat spine feeds bare `[i:v]` labels — inputs with unproven fps/SAR. */\nfunction checkSpineNormalized(ctx: Ctx, meta: VideoMetaT): void {\n const spineId = meta.timeline?.spine_node ?? \"spine\";\n const idx = ctx.idToIndex.get(spineId);\n const spine = idx === undefined ? null : (ctx.canvas.nodes[idx] as NodeDecl);\n if (!spine || spine.type !== \"ffmpeg\") return;\n const args = (spine.params as Record<string, unknown>).args;\n const graph = Array.isArray(args) ? args.join(\" \") : \"\";\n if (!graph.includes(\"concat=n=\")) return;\n if (/\\[\\d+:v\\](?:\\[|concat)/.test(graph)) {\n ctx.issues.push({\n path: `nodes[${idx}].params.args`,\n code: STAGE_CODES.SPINE_UNNORMALIZED,\n severity: \"warning\",\n node_id: spineId,\n message: `the spine concat feeds raw input labels — generated clips carry no fps/SAR guarantee, and one 24fps clip silently stretches the picture off the audio/overlay clock. Chain \\`format=yuv420p,fps=30,setsar=1,settb=AVTB\\` on every input before the concat`,\n });\n }\n}\n\n/** Warn on odd scale/crop/pad dimensions in any ffmpeg node — libx264 yuv420p hard-fails. */\nfunction checkOddDimensions(ctx: Ctx): void {\n ctx.canvas.nodes.forEach((node, idx) => {\n if (node.type !== \"ffmpeg\") return;\n const args = (node.params as Record<string, unknown>).args;\n const blob = Array.isArray(args) ? args.join(\" \") : \"\";\n for (const m of blob.matchAll(/(?:scale|crop|pad)=(\\d+):(\\d+)/g)) {\n const w = Number(m[1]);\n const h = Number(m[2]);\n if (w % 2 === 0 && h % 2 === 0) continue;\n ctx.issues.push({\n path: `nodes[${idx}].params.args`,\n code: STAGE_CODES.ODD_DIMENSIONS,\n severity: \"warning\",\n node_id: node.id,\n message: `\"${m[0]}\" produces an odd dimension — libx264 yuv420p rejects odd sizes, so this node fails at render time. Round both to even numbers`,\n });\n return; // one warning per node is enough\n }\n });\n}\n\n/** Warn when a scene generated more region clips than its composite consumes — billed, then dropped. */\nfunction checkRegionDropped(ctx: Ctx): void {\n const regionClips = new Map<string, number>();\n for (const node of ctx.canvas.nodes) {\n const m = /^s(\\d+)_r\\d+_clip$/.exec(node.id);\n if (m && node.type === \"video_generate\")\n regionClips.set(m[1] as string, (regionClips.get(m[1] as string) ?? 0) + 1);\n }\n for (const [scene, billed] of regionClips) {\n const idx = ctx.idToIndex.get(`s${scene}_composite`);\n if (idx === undefined) continue;\n const composite = ctx.canvas.nodes[idx] as NodeDecl;\n const consumed = Object.keys(composite.inputs ?? {}).filter((k) => /^c\\d+$/.test(k)).length;\n if (billed > consumed) {\n ctx.issues.push({\n path: `nodes[${idx}].inputs`,\n code: STAGE_CODES.REGION_DROPPED,\n severity: \"warning\",\n node_id: composite.id,\n message: `scene s${scene} bills ${billed} region clips but its composite consumes ${consumed} — the extra generation is paid for and never reaches the frame. Wire every region into the composite or delete the unused clip node`,\n });\n }\n }\n}\n\nfunction round2(n: number): number {\n return Math.round(n * 100) / 100;\n}\n\n// Type-noun synonyms per element type — the low-false-positive nouns whose presence\n// in a frame description strongly implies the element is on screen. Person is\n// deliberately excluded: pronouns/role-words are too noisy and identity is already\n// locked by the multi-view sheet.\nconst ELEMENT_TYPE_KEYWORDS: Record<string, string[]> = {\n animal: [\"dog\", \"puppy\", \"pup\", \"cat\", \"kitten\", \"kitty\", \"pet\", \"canine\", \"feline\"],\n logo: [\"logo\", \"wordmark\"],\n badge: [\"badge\", \"seal\"],\n product: [],\n};\nconst CHECKED_ELEMENT_TYPES = new Set(Object.keys(ELEMENT_TYPE_KEYWORDS));\n// Tokens too generic to signal a specific element in a frame description.\nconst KEYWORD_STOPWORDS = new Set([\n \"the\",\n \"and\",\n \"with\",\n \"for\",\n \"brand\",\n \"logo\",\n \"image\",\n \"shot\",\n \"main\",\n \"hero\",\n \"element\",\n \"product\",\n \"reference\",\n]);\n\n/** Significant lowercase tokens (len ≥ 3, non-stopword) of a label/description. */\nfunction keywordTokens(text: string | undefined): string[] {\n if (!text) return [];\n return text\n .toLowerCase()\n .split(/[^a-z0-9]+/)\n .filter((t) => t.length >= 3 && !KEYWORD_STOPWORDS.has(t));\n}\n\n/**\n * The keyword set that, in a frame description, implies an element of this\n * type/label/description is on screen. Shared with the scaffold's wiring pass so a\n * frame the validator would flag is wired by construction (same matcher both sides).\n */\nexport function elementMentionKeywords(el: { type: string; label?: string; description?: string }): string[] {\n const typeWords = ELEMENT_TYPE_KEYWORDS[el.type.toLowerCase()] ?? [];\n return [...new Set([...typeWords, ...keywordTokens(el.label), ...keywordTokens(el.description)])];\n}\n\ntype VideoMetaT = NonNullable<NonNullable<Canvas[\"metadata\"]>[\"video\"]>;\ntype VideoElement = NonNullable<VideoMetaT[\"elements\"]>[number];\n\n/** The keyword set that, in a frame description, implies this element is on screen. */\nfunction keywordsForElement(el: VideoElement): string[] {\n return elementMentionKeywords(el);\n}\n\n/** Does `text` contain `word` as a whole word (avoids \"cat\" ⊂ \"category\")? */\nfunction containsWord(text: string, word: string): boolean {\n const esc = word.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n return new RegExp(`\\\\b${esc}\\\\b`, \"i\").test(text);\n}\n\n/**\n * Advisory (§13, the wrong-dog defect): every `image_generate` frame whose FRAME\n * DESCRIPTION plausibly includes a recurring element (a pet, product, logo, badge)\n * must wire that element's reference. When it doesn't, the frame model has nothing to\n * lock the element's identity to — its own system prompt forbids trusting prose — so\n * it invents a generic one (a different breed of dog). Scoped to non-person elements,\n * where a keyword→missing-ref match is high-signal; person identity is sheet-backed.\n */\ntype KeywordedElement = { el: VideoElement; keywords: string[] };\n\n// The scaffold's frame prompts wrap the editable FRAME DESCRIPTION in boilerplate\n// that itself mentions element keywords (\"If a reference image (a logo, a desk…)\",\n// \"do not invent brand logos\") — matching the whole prompt false-positived on every\n// scaffolded frame. Only the description between these markers is the frame's OWN\n// content; a hand-authored prompt (no marker) is matched whole.\nconst FRAME_DESCRIPTION_START = \"FRAME DESCRIPTION (this frame's editable prompt):\";\nconst FRAME_DESCRIPTION_END = \"Render exactly what the FRAME DESCRIPTION\";\nfunction frameDescriptionOf(prompt: string): string {\n const i = prompt.indexOf(FRAME_DESCRIPTION_START);\n if (i < 0) return prompt;\n const rest = prompt.slice(i + FRAME_DESCRIPTION_START.length);\n const j = rest.indexOf(FRAME_DESCRIPTION_END);\n return j < 0 ? rest : rest.slice(0, j);\n}\n\n/** Warn for each keyworded element a frame describes but doesn't wire. */\nfunction checkFrameReferences(ctx: Ctx, node: NodeDecl, index: number, keyworded: KeywordedElement[]): void {\n const rawPrompt = (node.params as Record<string, unknown> | undefined)?.prompt;\n if (typeof rawPrompt !== \"string\" || rawPrompt.length === 0) return;\n const prompt = frameDescriptionOf(rawPrompt);\n const inputsBlob = JSON.stringify(node.inputs ?? {});\n for (const { el, keywords } of keyworded) {\n if (inputsBlob.includes(el.ref)) continue; // element already wired on this frame\n const hit = keywords.find((kw) => containsWord(prompt, kw));\n if (!hit) continue;\n ctx.issues.push({\n path: `nodes[${index}].inputs.reference`,\n code: STAGE_CODES.REFERENCE_MISSING,\n severity: \"warning\",\n message: `frame \"${node.id}\" describes a \"${hit}\" but the \"${el.label}\" reference (${el.ref}) isn't wired on this node — the generator will invent a wrong-identity ${el.type} from prose. Add ${el.ref} to inputs.reference`,\n node_id: node.id,\n node_type: node.type,\n });\n }\n}\n\nfunction checkReferenceCompleteness(ctx: Ctx, meta: VideoMetaT): void {\n const elements = (meta.elements ?? []).filter((el) => CHECKED_ELEMENT_TYPES.has(el.type.toLowerCase()));\n const keyworded = elements\n .map((el) => ({ el, keywords: keywordsForElement(el) }))\n .filter((e) => e.keywords.length > 0);\n if (keyworded.length === 0) return;\n\n for (let i = 0; i < ctx.canvas.nodes.length; i++) {\n const n = ctx.canvas.nodes[i];\n if (n?.type === \"image_generate\") checkFrameReferences(ctx, n, i, keyworded);\n }\n}\n\n/** The max clip duration a video model allows, read from its registry duration enum. */\nfunction videoModelMaxDuration(model: string): number | undefined {\n const spec = (\n MODEL_REGISTRY.video_generate as Record<string, { params?: Record<string, { enum?: readonly unknown[] }> }>\n )[model];\n const durations = spec?.params?.duration?.enum;\n if (!durations) return undefined;\n const nums = durations.filter((d): d is number => typeof d === \"number\");\n return nums.length > 0 ? Math.max(...nums) : undefined;\n}\n\n/**\n * Advisory (§2): a scene's natural visual span must fit the assigned model's max clip\n * length. Switching a subset of clips to a shorter-max model (Seedance's 15s → Veo's\n * 8s) leaves any >8s scene unable to render its full content — it truncates. Caught\n * from the scaffold's recorded `clip_spans` BEFORE a billed run, not after.\n */\nfunction checkClipSpanFitsModel(ctx: Ctx, meta: VideoMetaT): void {\n for (const { node, span_s } of meta.clip_spans ?? []) {\n const target = ctx.canvas.nodes.find((n) => n.id === node && n.type === \"video_generate\");\n if (!target) continue;\n const model = (target.params as Record<string, unknown> | undefined)?.model;\n if (typeof model !== \"string\") continue;\n const max = videoModelMaxDuration(model);\n if (max === undefined || span_s <= max + SPAN_MODEL_SLACK_S) continue;\n ctx.issues.push({\n path: `nodes[${ctx.idToIndex.get(node) ?? -1}].params.duration`,\n code: STAGE_CODES.SPAN_EXCEEDS_MODEL,\n severity: \"warning\",\n message: `scene for clip \"${node}\" needs ~${span_s}s but ${model} caps clips at ${max}s — the clip will truncate. Split the scene, or keep it on a model whose max duration covers the span`,\n node_id: node,\n node_type: \"video_generate\",\n });\n }\n}\n\n// Sanity band for a stamped observed speech rate: real speech sits well inside\n// 1–6 words/s; a stamp outside it is junk timing data and must not silence the check.\nconst OBSERVED_WPS_MIN = 1;\nconst OBSERVED_WPS_MAX = 6;\n\n/**\n * Seconds per word to budget a native line at. Prefers the speaker's OBSERVED pace —\n * the scaffold stamps `est_speech_s` (measured from the deconstruct's word timings)\n * with `speech_words` (the word count it was measured for) — so a fast talker's line\n * isn't failed by the generic wps guess, and a re-authored line still scales at the\n * real rate. Falls back to the guess when no plausible stamp exists.\n */\nfunction secondsPerWord(stamped?: { est_speech_s?: number; speech_words?: number }): number {\n const est = stamped?.est_speech_s;\n const words = stamped?.speech_words;\n if (est && words && est > 0 && words > 0) {\n const wps = words / est;\n if (wps >= OBSERVED_WPS_MIN && wps <= OBSERVED_WPS_MAX) return est / words;\n }\n return 1 / SPEECH_WORDS_PER_SECOND;\n}\n\n/** The overrun of one candidate native clip node, or null when it fits / isn't one. */\nfunction speechOverrunOf(\n node: Canvas[\"nodes\"][number],\n secPerWord: number,\n): { estSpeechS: number; duration: number } | null {\n const params = node.params as Record<string, unknown> | undefined;\n if (params?.generate_audio !== true) return null;\n const line = nativeDialogueOf(params.prompt);\n const duration = typeof params.duration === \"number\" ? params.duration : undefined;\n if (!line || !duration) return null;\n const estSpeechS = line.split(/\\s+/).filter(Boolean).length * secPerWord;\n return estSpeechS > duration * SPEECH_OVERRUN_RATIO ? { estSpeechS, duration } : null;\n}\n\n/** Invariant 4: est. speech from each native clip's prompt vs its generated duration. */\nfunction checkSpeechOverrun(ctx: Ctx, talkingScenes: TalkingSceneEntry[]): void {\n for (const entry of talkingScenes) {\n if (typeof entry !== \"object\" || !(\"voice_convert_node\" in entry)) continue;\n const nativeClipRe = new RegExp(`^s${entry.scene}(_r\\\\d+)?_clip$`);\n for (const n of ctx.canvas.nodes) {\n if (!nativeClipRe.test(n.id) || n.type !== \"video_generate\") continue;\n const overrun = speechOverrunOf(n, secondsPerWord(entry));\n if (overrun) {\n ctx.issues.push({\n path: `nodes[${ctx.idToIndex.get(n.id) ?? -1}].params.prompt`,\n code: STAGE_CODES.SPEECH_OVERRUN,\n message: `\"${n.id}\" asks Seedance to speak ~${Math.round(overrun.estSpeechS * 10) / 10}s of dialogue inside a ${overrun.duration}s clip — the line cannot fit (>${SPEECH_OVERRUN_RATIO}× the clip). Shorten the line, split the scene, or lengthen the clip duration`,\n });\n continue;\n }\n checkSpeechExceedsExtract(ctx, n, entry);\n }\n }\n}\n\n/**\n * The REAL audio budget for a re-authored native line is the extract window (the\n * `s<i>_voextract` `-t`), not the padded ≥4s generated clip: the picture is trimmed\n * back to the scene window on the spine, so a 3s line in a 1s window passes the clip\n * check and then gets cut mid-word at render. Compared against the extract — not the\n * seg — because a voiceover deliberately carries over b-roll cutaways (the extract\n * window IS that full spoken span). Blocking: the cut is certain, not stylistic.\n */\nfunction checkSpeechExceedsExtract(\n ctx: Ctx,\n clip: NodeDecl,\n entry: { scene: number; est_speech_s?: number; speech_words?: number },\n): void {\n const params = clip.params as Record<string, unknown> | undefined;\n if (params?.generate_audio !== true) return;\n const line = nativeDialogueOf(params.prompt);\n if (!line) return;\n const regionTag = /^s\\d+(_r\\d+)?_clip$/.exec(clip.id)?.[1] ?? \"\";\n const extractIdx =\n ctx.idToIndex.get(`s${entry.scene}${regionTag}_voextract`) ?? ctx.idToIndex.get(`s${entry.scene}_voextract`);\n const extract = extractIdx === undefined ? null : (ctx.canvas.nodes[extractIdx] as NodeDecl);\n const windowS = extract ? ffmpegTrimSeconds(extract) : null;\n if (windowS === null) return;\n const estSpeechS = line.split(/\\s+/).filter(Boolean).length * secondsPerWord(entry);\n if (estSpeechS <= windowS * SPEECH_OVERRUN_RATIO) return;\n ctx.issues.push({\n path: `nodes[${ctx.idToIndex.get(clip.id) ?? -1}].params.prompt`,\n code: STAGE_CODES.SPEECH_EXCEEDS_EXTRACT,\n node_id: clip.id,\n message: `\"${clip.id}\"'s line is ~${Math.round(estSpeechS * 10) / 10}s of speech but its extract window (s${entry.scene}_voextract) is ${windowS}s — the read gets cut mid-word on the spine. Shorten the Dialogue line, lengthen the scene in prompt.json and re-scaffold, or raise the voextract \\`-t\\` when the read should carry over the next cutaway`,\n });\n}\n\n// A screen/UI surface narrated in a video_generate prompt: a generative model garbles\n// UI text and brand chrome, so a screen surface must be composited as a REAL asset on\n// the overlay layer, never described into a clip. Narrow on purpose (screen-recording\n// language, not any mention of a phone) — advisory, not blocking.\nconst UI_IN_PROMPT_RE =\n /\\bscreen[- ]?(?:recording|capture|grab|share)\\b|\\bapp (?:interface|screen)\\b|\\bphone screen overlay\\b/i;\n\n/** Advisory: a clip prompt asking the video model to render a screen/UI surface. */\nfunction checkUiInPrompt(ctx: Ctx): void {\n for (const n of ctx.canvas.nodes) {\n if (n.type !== \"video_generate\") continue;\n const prompt = (n.params as Record<string, unknown> | undefined)?.prompt;\n if (typeof prompt !== \"string\" || !UI_IN_PROMPT_RE.test(prompt)) continue;\n ctx.issues.push({\n path: `nodes[${ctx.idToIndex.get(n.id) ?? -1}].params.prompt`,\n code: STAGE_CODES.UI_IN_PROMPT,\n severity: \"warning\",\n message: `\"${n.id}\" asks the video model to render a screen/UI surface — generative video garbles UI text and chrome. Composite the real screen on the overlay layer (screenshot / brand HTML) and keep this prompt to the background plate`,\n node_id: n.id,\n node_type: \"video_generate\",\n });\n }\n}\n\n// A brand mark REQUESTED as picture content: \"…logo overlay/animation/sting\", or a\n// named third-party mark. A logo merely worn/present in the filmed scene (on a polo,\n// a storefront) is part of the picture and stays — the pattern needs the mark to be\n// the rendered element itself. Generative models garble wordmarks, and a real mark\n// belongs on the overlay layer as a sourced asset. Advisory, not blocking.\nconst BRANDMARK_IN_PROMPT_RE =\n /\\b(?:logo|wordmark) (?:overlay|animation|sting|card|reveal)\\b|\\b(?:google|facebook|instagram|tiktok|youtube|amazon|apple|microsoft|whatsapp|netflix|spotify|excel|trustpilot) (?:logo|wordmark|branding)\\b/i;\n\n/** Advisory: a generate prompt asking the model to paint a brand logo/wordmark. */\nfunction checkBrandmarkInPrompt(ctx: Ctx): void {\n for (const n of ctx.canvas.nodes) {\n if (n.type !== \"video_generate\" && n.type !== \"image_generate\") continue;\n const prompt = (n.params as Record<string, unknown> | undefined)?.prompt;\n if (typeof prompt !== \"string\" || !BRANDMARK_IN_PROMPT_RE.test(prompt)) continue;\n ctx.issues.push({\n path: `nodes[${ctx.idToIndex.get(n.id) ?? -1}].params.prompt`,\n code: STAGE_CODES.BRANDMARK_IN_PROMPT,\n severity: \"warning\",\n message: `\"${n.id}\" asks the model to render a brand logo/wordmark — generation garbles marks and third-party logos carry IP exposure. Source the real mark (baker images logo <domain>) and composite it on the overlay layer`,\n node_id: n.id,\n node_type: n.type,\n });\n }\n}\n\n/** Invariant 5: all video_generate nodes agree on one aspect_ratio (none silently defaulted). */\nfunction checkAspectConsistency(ctx: Ctx): void {\n const clips = ctx.canvas.nodes.filter((n) => n.type === \"video_generate\");\n if (clips.length < 2) return;\n const ratios = new Set(clips.map((n) => String((n.params as Record<string, unknown>)?.aspect_ratio ?? \"(unset)\")));\n if (ratios.size <= 1) return;\n ctx.issues.push({\n path: \"nodes\",\n code: STAGE_CODES.ASPECT_MISMATCH,\n message: `video_generate nodes disagree on aspect_ratio (${[...ratios].sort().join(\", \")}) — the spine's segments would render at different shapes and the composite silently crops. Pin every clip to the same aspect_ratio`,\n });\n}\n\n// Two prompts this similar (Jaccard over their word sets) are the SAME creative — a\n// per-ratio copy, not a second concept. Deliberately high: variants of one concept\n// share wording too, and they're only flagged when the RATIOS also differ.\nconst SAME_CREATIVE_PROMPT_SIMILARITY = 0.6;\n\nfunction promptWordSet(text: string): Set<string> {\n return new Set(\n text\n .toLowerCase()\n .split(/[^a-z0-9']+/)\n .filter((w) => w.length >= 3),\n );\n}\n\nfunction jaccard(a: Set<string>, b: Set<string>): number {\n if (a.size === 0 || b.size === 0) return 0;\n let shared = 0;\n for (const w of a) if (b.has(w)) shared++;\n return shared / (a.size + b.size - shared);\n}\n\ntype FormatRenderNode = { id: string; prompt: string; ratio: string };\n\n/**\n * Groups of `image_generate` nodes that render the SAME creative once per aspect\n * ratio (near-identical prompts, different `aspect_ratio`). Pure, so the clustering\n * is testable on its own. Single-link clustering: any two similar-prompt nodes with\n * different ratios join the same group.\n */\nexport function parallelFormatRenderGroups(nodes: readonly FormatRenderNode[]): FormatRenderNode[][] {\n const parent = nodes.map((_, i) => i);\n const find = (i: number): number => {\n let root = i;\n while (parent[root] !== root) root = parent[root] as number;\n return root;\n };\n const words = nodes.map((n) => promptWordSet(n.prompt));\n for (let i = 0; i < nodes.length; i++) {\n for (let j = i + 1; j < nodes.length; j++) {\n const a = nodes[i] as FormatRenderNode;\n const b = nodes[j] as FormatRenderNode;\n if (a.ratio === b.ratio) continue;\n if (jaccard(words[i] as Set<string>, words[j] as Set<string>) < SAME_CREATIVE_PROMPT_SIMILARITY) continue;\n parent[find(i)] = find(j);\n }\n }\n const groups = new Map<number, FormatRenderNode[]>();\n for (let i = 0; i < nodes.length; i++) {\n const root = find(i);\n const group = groups.get(root) ?? [];\n group.push(nodes[i] as FormatRenderNode);\n groups.set(root, group);\n }\n return [...groups.values()].filter((g) => g.length > 1);\n}\n\n/**\n * Advisory: the same creative generated once per placement ratio instead of once,\n * then fanned out. Each render is an independent generation, so the \"same\" ad comes\n * back with different type, crop, and color per format — the set stops looking like\n * one campaign. The fix is always the terminal `image_aspect_adapt` node: render ONE\n * hero, re-frame it into every other ratio from that single image.\n */\nfunction checkParallelFormatRenders(ctx: Ctx): void {\n const candidates: FormatRenderNode[] = [];\n for (const n of ctx.canvas.nodes) {\n if (n.type !== \"image_generate\") continue;\n const params = n.params as Record<string, unknown> | undefined;\n const prompt = params?.prompt;\n if (typeof prompt !== \"string\" || prompt.length === 0) continue;\n candidates.push({ id: n.id, prompt, ratio: String(params?.aspect_ratio ?? \"(unset)\") });\n }\n if (candidates.length < 2) return;\n for (const group of parallelFormatRenderGroups(candidates)) {\n const ids = group.map((g) => g.id);\n const ratios = [...new Set(group.map((g) => g.ratio))].sort();\n ctx.issues.push({\n path: \"nodes\",\n code: STAGE_CODES.PARALLEL_FORMAT_RENDERS,\n severity: \"warning\",\n message: `${ids.join(\", \")} render the same creative once per aspect ratio (${ratios.join(\", \")}) — each is an independent generation, so the formats come back with different type, crop, and color and stop reading as one ad. Keep ONE hero render and add a terminal image_aspect_adapt node fed from it (params.formats or params.platform) so every ratio is re-framed from the same image`,\n });\n }\n}\n\n/**\n * Warn on nodes unreachable from `output` — every ref edge walked backward from the\n * output node. The engine still executes orphans (Kahn layers cover the whole graph),\n * so an orphaned billable node silently burns credits for pixels nothing consumes —\n * almost always a wiring bug (a consumer was skipped but its producer still emitted).\n * `ingest` nodes are exempt: parking a free ingest (the scaffold's editable `prompt`\n * blueprint, an operator's spare asset) is a legitimate pattern.\n */\nfunction checkOrphanNodes(ctx: Ctx): void {\n const out = ctx.canvas.output;\n if (!out || !ctx.idToIndex.has(out.node)) return;\n const graph = buildDepGraph(ctx.canvas);\n const reachable = new Set<string>();\n const stack = [out.node];\n while (stack.length > 0) {\n const id = stack.pop();\n if (id === undefined || reachable.has(id)) continue;\n reachable.add(id);\n for (const dep of graph.get(id) ?? []) stack.push(dep);\n }\n for (const n of ctx.canvas.nodes) {\n if (reachable.has(n.id) || n.type === \"ingest\") continue;\n ctx.issues.push({\n path: `nodes[${ctx.idToIndex.get(n.id)}]`,\n code: STAGE_CODES.ORPHAN_NODE,\n severity: \"warning\",\n message: `node \"${n.id}\" (${n.type}) is not reachable from output \"${out.node}\" — it will still execute (and bill, if billable) but nothing consumes its result; wire it in or remove it`,\n });\n }\n}\n\nfunction checkOutputRef(ctx: Ctx): void {\n const out = ctx.canvas.output;\n if (!out) return;\n const targetIdx = ctx.idToIndex.get(out.node);\n if (targetIdx === undefined) {\n ctx.issues.push({\n path: \"output.node\",\n code: STAGE_CODES.OUTPUT,\n message: `output references unknown node \"${out.node}\"`,\n did_you_mean: didYouMean(out.node, [...ctx.idToIndex.keys()]),\n });\n return;\n }\n const target = ctx.canvas.nodes[targetIdx];\n if (!target) return;\n const targetDef = ctx.registry.get(target.type);\n if (!targetDef) return;\n const outs = listShapeKeys(targetDef.outputs);\n if (!outs || outs.includes(out.output)) return;\n ctx.issues.push({\n path: \"output.output\",\n code: STAGE_CODES.OUTPUT,\n message: `node \"${out.node}\" (${target.type}) has no output \"${out.output}\"`,\n did_you_mean: didYouMean(out.output, outs),\n });\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction pushZodIssues(\n issues: ValidationIssue[],\n err: z.ZodError,\n pathPrefix: string,\n code: string,\n nodeId?: string,\n nodeType?: string,\n): void {\n for (const issue of err.issues) {\n const tail = pathToString(issue.path);\n const path = pathPrefix ? (tail ? `${pathPrefix}.${tail}` : pathPrefix) : tail;\n issues.push({\n path,\n code,\n message: issue.message,\n received: issue.code === \"invalid_type\" ? (issue as { received?: unknown }).received : undefined,\n node_id: nodeId,\n node_type: nodeType,\n });\n }\n}\n\nfunction pathToString(path: ReadonlyArray<PropertyKey>): string {\n return path\n .map((p) => (typeof p === \"number\" ? `[${p}]` : `.${String(p)}`))\n .join(\"\")\n .replace(/^\\./, \"\");\n}\n\nfunction buildDepGraph(canvas: Canvas): Map<string, Set<string>> {\n const graph = new Map<string, Set<string>>();\n for (const n of canvas.nodes) graph.set(n.id, new Set());\n for (const n of canvas.nodes) {\n const collect = (refStr: string) => {\n if (!refStr.startsWith(REF_PREFIX)) return;\n const expr = parseRefExpr(refStr);\n if (!expr || expr.kind !== \"ref\") return;\n const deps = graph.get(n.id);\n if (deps && graph.has(expr.nodeId)) deps.add(expr.nodeId);\n };\n walkRefs(n.inputs, collect);\n walkRefs(n.params, collect);\n }\n return graph;\n}\n\nfunction walkRefs(value: unknown, cb: (refStr: string, path: string) => void, prefix = \"\"): void {\n if (typeof value === \"string\") {\n if (value.startsWith(REF_PREFIX)) cb(value, prefix);\n return;\n }\n if (Array.isArray(value)) {\n walkArrayRefs(value, cb, prefix);\n return;\n }\n if (value && typeof value === \"object\") {\n walkObjectRefs(value as Record<string, unknown>, cb, prefix);\n }\n}\n\nfunction walkArrayRefs(arr: readonly unknown[], cb: (refStr: string, path: string) => void, prefix: string): void {\n for (let i = 0; i < arr.length; i++) {\n walkRefs(arr[i], cb, prefix ? `${prefix}[${i}]` : `[${i}]`);\n }\n}\n\nfunction walkObjectRefs(\n obj: Record<string, unknown>,\n cb: (refStr: string, path: string) => void,\n prefix: string,\n): void {\n for (const [k, v] of Object.entries(obj)) {\n walkRefs(v, cb, prefix ? `${prefix}.${k}` : k);\n }\n}\n\nfunction walkPromptStrings(value: unknown, cb: (text: string) => void): void {\n if (typeof value === \"string\") {\n cb(value);\n return;\n }\n if (Array.isArray(value)) {\n for (const v of value) walkPromptStrings(v, cb);\n return;\n }\n if (value && typeof value === \"object\") {\n for (const v of Object.values(value as Record<string, unknown>)) {\n walkPromptStrings(v, cb);\n }\n }\n}\n\nfunction listShapeKeys(schema: z.ZodType): string[] | undefined {\n const obj = unwrap(schema);\n if (obj instanceof z.ZodObject) return Object.keys(obj.shape);\n return undefined;\n}\n\nfunction unwrap(schema: z.ZodType): z.ZodType {\n let cur: z.ZodType = schema;\n for (let i = 0; i < 8; i++) {\n const inner = (cur as unknown as { _def?: { innerType?: z.ZodType } })._def?.innerType;\n if (!inner) return cur;\n cur = inner;\n }\n return cur;\n}\n","/**\n * True when `value` is an http(s) URL — the machine-decidable signal that separates a `source:\"url\"`\n * ingest from a `source:\"path\"` one. Shared so the ingest schema's auto-heal, the load-time path\n * resolver, and the validator's advisory all agree on exactly what counts as a URL.\n */\nexport function looksLikeHttpUrl(value: unknown): value is string {\n return typeof value === \"string\" && /^https?:\\/\\//i.test(value.trim());\n}\n","/**\n * Per-model GENERATION PROFILES. Each model we call — video (Seedance, Veo) and\n * image (gpt-image, Gemini, Recraft) — has a documented best-practice prompt\n * structure, length budget, dialogue/audio convention, negative-prompt mechanism,\n * and request-param set. The scaffolder used to emit ONE prompt shape and set none\n * of the param levers; these profiles are the single seam where each model's rules\n * live, read by BOTH the prompt builders and the validator so the two can't drift.\n *\n * Sources (see the session research briefs): fal.ai/learn + BytePlus ModelArk for\n * Seedance; ai.google.dev + cloud.google.com for Veo; OpenAI Cookbook + OpenRouter\n * image docs for gpt-image; ai.google.dev for Gemini image.\n */\nimport { SEEDANCE_DURATIONS } from \"@baker/canvas-contract\";\n\n/** Veo permits generating adult humans from a keyframe — the sanctioned escape from\n * ByteDance's real-person filter; it is also the ONLY legal value for image-to-video\n * in the EU/UK/CH/MENA. Set on every Veo clip. */\nconst VEO_PERSON_GENERATION = \"allow_adult\";\n/** Veo frequently burns in captions/subtitles even when unasked (a known model\n * artifact); the dedicated negative_prompt param is the real suppression lever\n * (an inline \"no subtitles\" line alone is unreliable). Phrased as absences. */\nconst VEO_NEGATIVE_PROMPT =\n \"subtitles, captions, on-screen text, watermark, logo, warped face, distorted hands, extra fingers, low quality\";\n/** Veo's only legal clip durations — NOT the Seedance set. Snapping a Veo clip to a\n * Seedance-only length (5/10/12/15) is a hard provider error. */\nconst VEO_DURATIONS = [4, 6, 8] as const;\n\n/** Kling accepts only 5s or 10s clips; any other length is a hard provider error. */\nconst KLING_DURATIONS = [5, 10] as const;\n/** Kling has a real `negative_prompt` param (forwarded top-level by the backend);\n * phrase as absences, same family as Veo's. */\nconst KLING_NEGATIVE_PROMPT =\n \"warped face, distorted hands, extra fingers, morphing, flicker, on-screen text, watermark, low quality\";\n/** Kling's prompt-adherence dial — higher hugs the prompt (good for a scripted\n * scroll-stopper), lower gives the model more motion freedom. */\nconst KLING_CFG_SCALE = 0.7;\n\n/**\n * A video model's clip-prompt + request-param profile. `dialogueDirective` and the\n * literal `Dialogue: \"…\"` marker it emits are the parse contract `nativeDialogueOf`\n * (and the validator's speech-fit gates) read — both profiles MUST keep that marker.\n */\nexport type ClipPromptProfile = {\n id: \"seedance\" | \"veo\" | \"kling\";\n /** The talking-head directive carrying the verbatim spoken line. */\n dialogueDirective(line: string): string;\n /** Model-specific hard rules appended to every clip prompt (may be empty). */\n extraDirectives: string[];\n /** Affirmative quality/stability directives for models with NO negative_prompt param\n * (Seedance). Emitted as a positive \"keep it stable\" tail, NOT an \"Avoid:\" list: Seedance\n * has no negative field, and inline negation (\"no warped hands\") is weak grammar around a\n * strong activation that tends to SUMMON the very artifact — the fal.ai guide's rule is\n * \"phrase everything positively\" (see seedance-mechanics.md §3). Empty for models that take\n * a real negative_prompt param (Veo, Kling), which parse literal exclusions correctly. */\n stabilityDirectives: string[];\n /** The image-to-video instruction to hold the source frame's framing/palette. */\n keyframeInstruction: string;\n /** Soft word budget for one clip prompt — the validator warns above it. */\n wordBudget: number;\n /** The clip durations this model accepts; the generator snaps to this set. */\n durationSet: readonly number[];\n /** Request params merged onto every `video_generate` node for this model. */\n paramDefaults: Record<string, unknown>;\n};\n\n// Both video profiles now put delivery in PROSE, not [brackets]: the Seedance 2.0\n// guide (and Veo's) carry emotion in the wording around the quoted line; Seedance\n// renders literal brackets and Veo burns them as on-screen text.\nconst SPEAKS_PROSE = (line: string) =>\n `The person speaks to camera; lip-sync follows the dialogue verbatim, with delivery and emotion carried in the wording itself (no bracketed cues). Dialogue: \"${line}\"`;\n\nexport const SEEDANCE_PROFILE: ClipPromptProfile = {\n id: \"seedance\",\n dialogueDirective: SPEAKS_PROSE,\n extraDirectives: [],\n // Seedance has no negative_prompt field. Phrase the anti-artifact intent as the POSITIVE\n // state we want (crisp hands, one stable face, smooth coherent motion, locked identity) —\n // an \"Avoid: warped fingers, morphing faces\" list tends to plant those very artifacts.\n stabilityDirectives: [\n \"hands and fingers crisp and anatomically correct\",\n \"one consistent face and identity across every frame\",\n \"smooth, temporally coherent motion that holds steady frame to frame\",\n ],\n keyframeInstruction: \"Preserve the composition and colors of the first frame; change only the motion described.\",\n // ~120 words is the Seedance quality sweet spot: past it the model starts dropping beats and\n // the attention budget dilutes. The validator warns above this; composite scenes that stack\n // many brief `parts` are the usual offenders.\n wordBudget: 120,\n durationSet: SEEDANCE_DURATIONS,\n paramDefaults: {},\n};\n\nexport const VEO_PROFILE: ClipPromptProfile = {\n id: \"veo\",\n dialogueDirective: SPEAKS_PROSE,\n // Veo's known failure mode: quoted dialogue triggers burned-in subtitles. Belt\n // (inline) and braces (the negative_prompt param, below) — the param is the real lever.\n extraDirectives: [\"No subtitles, no captions, no on-screen text of any kind.\"],\n stabilityDirectives: [], // Veo takes a negative_prompt PARAM instead (paramDefaults).\n keyframeInstruction: \"Describe the transition and camera move between the frames; the frames fix the content.\",\n wordBudget: 200,\n durationSet: VEO_DURATIONS,\n paramDefaults: { person_generation: VEO_PERSON_GENERATION, negative_prompt: VEO_NEGATIVE_PROMPT },\n};\n\nexport const KLING_PROFILE: ClipPromptProfile = {\n id: \"kling\",\n dialogueDirective: SPEAKS_PROSE,\n // Belt (inline) and braces (the negative_prompt param) — the param is the real lever.\n extraDirectives: [\"Single, deliberate camera move — no whip pans or rapid cuts within the clip.\"],\n stabilityDirectives: [], // Kling takes a negative_prompt PARAM instead (paramDefaults).\n keyframeInstruction: \"Preserve the composition and colors of the first frame; animate the motion described.\",\n wordBudget: 200,\n durationSet: KLING_DURATIONS,\n paramDefaults: { negative_prompt: KLING_NEGATIVE_PROMPT, cfg_scale: KLING_CFG_SCALE },\n};\n\n/** The profile for a video model id, matched by family; undefined = unprofiled model. */\nexport function clipProfileFor(modelId: string): ClipPromptProfile | undefined {\n if (/^bytedance\\/seedance/.test(modelId)) return SEEDANCE_PROFILE;\n if (/^google\\/veo/.test(modelId)) return VEO_PROFILE;\n if (/^kwaivgi\\/kling|^kling\\//.test(modelId)) return KLING_PROFILE;\n return undefined;\n}\n\n/**\n * A clip's persuasion INTENT, derived by the scaffolder from the scene's role.\n * The recipe layer keys \"astonishing default\" param overrides off this so an\n * operator doesn't have to know each model's knobs.\n */\nexport type ClipIntent = \"hook\" | \"hero\" | \"cta\" | \"body\";\n\n/**\n * Opinionated per-intent param overrides, merged AFTER a clip's base params so\n * they can intentionally raise the quality dial for the beats that earn it.\n * Only emits params the backend actually forwards for the model — never an inert\n * knob. Currently: hero beats claim the photoreal resolution ceiling; hook beats\n * on Kling max out prompt adherence so the scripted scroll-stopper renders exactly.\n */\nexport function clipParamRecipe(profile: ClipPromptProfile, intent: ClipIntent): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n if (intent === \"hero\") {\n // The hero/reveal beat is where cine quality matters most — pay for 1080p.\n out.resolution = \"1080p\";\n }\n if (intent === \"hook\" && profile.id === \"kling\") {\n out.cfg_scale = 0.85;\n }\n return out;\n}\n\n/** The native line a scaffolded clip prompt asks the video model to speak, when present. */\nexport function nativeDialogueOf(prompt: unknown): string | undefined {\n if (typeof prompt !== \"string\") return undefined;\n const m = prompt.match(/Dialogue: \"(.*)\"/);\n return m?.[1]?.trim() || undefined;\n}\n\n/**\n * An image model's frame-prompt + request-param profile. The motion-brief skeleton\n * is model-agnostic, but constraint PLACEMENT and the realism cue are not: OpenAI's\n * gpt-image weights early text as compositional guidance, so exclusions must come\n * LAST and \"photorealistic\" must be stated explicitly; Gemini reads exclusions fine\n * inline; Recraft renders vector art, so no photoreal cue.\n */\nexport type ImageModelProfile = {\n id: \"gpt-image\" | \"gemini\" | \"recraft\";\n /** Where the clean-plate / no-text exclusions block sits in the prompt. */\n constraintPlacement: \"last\" | \"inline\";\n /** Emit an explicit \"photorealistic\" cue (photoreal models only). */\n photorealCue: boolean;\n /** Request params merged onto every `image_generate` node for this model. */\n paramDefaults: Record<string, unknown>;\n};\n\nexport const GPT_IMAGE_PROFILE: ImageModelProfile = {\n id: \"gpt-image\",\n constraintPlacement: \"last\",\n photorealCue: true,\n // OpenRouter forwards `quality`; gpt-image-2 already processes inputs at high\n // fidelity automatically, so we deliberately do NOT send `input_fidelity`.\n paramDefaults: { quality: \"high\" },\n};\n\nexport const GEMINI_IMAGE_PROFILE: ImageModelProfile = {\n id: \"gemini\",\n constraintPlacement: \"inline\",\n photorealCue: true,\n paramDefaults: { quality: \"high\" },\n};\n\nexport const RECRAFT_IMAGE_PROFILE: ImageModelProfile = {\n id: \"recraft\",\n constraintPlacement: \"inline\",\n photorealCue: false,\n paramDefaults: {},\n};\n\n/** The profile for an image model id, matched by family; undefined = unprofiled model. */\nexport function imageProfileFor(modelId: string): ImageModelProfile | undefined {\n if (/^openai\\/gpt-.*image/.test(modelId)) return GPT_IMAGE_PROFILE;\n if (/^google\\/gemini/.test(modelId)) return GEMINI_IMAGE_PROFILE;\n if (/^recraft\\//.test(modelId)) return RECRAFT_IMAGE_PROFILE;\n return undefined;\n}\n","/**\n * The spine's PER-INPUT ffmpeg fragments — one shared builder/parser so the scaffold\n * (which writes the spine node's args) and the validator (which re-derives each input's\n * on-timeline length from those args) can never drift.\n *\n * The spine absorbs three kinds of per-scene length work that used to be standalone\n * ffmpeg nodes (`s<i>_clip_trim`, `s<i>_seg`, still-hold `s<i>_clip`):\n * - a TRIM: a generated clip (Seedance only emits fixed durations) or a phrase-clip\n * window is cut to its exact scene length inside the spine's own filter chain;\n * - a STILL: a held keyframe / real screenshot loops for the scene length via input\n * flags (`-loop 1 -t <len>`), fit either fill-crop (photography) or pad (a UI\n * screenshot must never be cropped);\n * - the NORMALIZE every input always got (one raster, fps, SAR, timebase).\n * One fewer generational encode per scene, and the graph stops scaling 4-nodes-per-scene.\n */\n\nexport type SpineStillFit = \"fill\" | \"pad\";\n\n/** Per-input spine work, carried on the scaffold's SceneClip. */\nexport type SpineInputWork = {\n /** Cut [offset, offset+len] out of a longer clip inside the spine chain. */\n trim?: { offset_s: number };\n /** The input is a still IMAGE looped for the input length. */\n still?: { fit: SpineStillFit };\n};\n\n/**\n * Input-level flags placed BEFORE this input's `-i`. A still image needs `-loop 1`\n * plus an input-side `-t` so the loop decodes exactly the on-timeline length.\n */\nexport function spineInputFlags(work: SpineInputWork, lenS: number): string[] {\n return work.still ? [\"-loop\", \"1\", \"-t\", lenS.toFixed(3)] : [];\n}\n\n/**\n * The input's filter ops: normalize → trim. Normalize forces ONE raster before the\n * join (concat hard-fails on size/SAR mismatches and silently mis-times on fps/tb),\n * fill-cropped for footage, fit-padded for screens/designed graphics (cropping a UI\n * slices its chrome). The trim runs AFTER normalize so seam-dedup's frame-indexed ops\n * (appended by the caller) always see a 30fps stream.\n */\nexport function spineInputOps(work: SpineInputWork, lenS: number, dims: { w: number; h: number }): string {\n const fit = work.still?.fit ?? \"fill\";\n const scale =\n fit === \"pad\"\n ? `scale=${dims.w}:${dims.h}:force_original_aspect_ratio=decrease,pad=${dims.w}:${dims.h}:(ow-iw)/2:(oh-ih)/2:color=black`\n : `scale=${dims.w}:${dims.h}:force_original_aspect_ratio=increase,crop=${dims.w}:${dims.h}`;\n const normalize = `${scale},format=yuv420p,fps=30,setsar=1,settb=AVTB`;\n if (work.trim) {\n const start = work.trim.offset_s > 0 ? `start=${work.trim.offset_s.toFixed(3)}:` : \"\";\n return `${normalize},trim=${start}duration=${lenS.toFixed(3)},setpts=PTS-STARTPTS`;\n }\n if (work.still) return `${normalize},trim=duration=${lenS.toFixed(3)}`;\n return normalize;\n}\n\n/**\n * Re-derive each spine input's on-timeline length from the spine node's own args —\n * the validator's side of the contract. Returns a per-input-index map; an input with\n * no absorbed length (a clip generated at its exact scene length) is absent, and the\n * caller falls back to sizing the upstream node.\n */\nexport function parseSpineInputLens(args: readonly string[]): Map<number, number> {\n const lens = new Map<number, number>();\n // Input-side `-t` (stills): the flags immediately precede that input's `-i`.\n let inputIndex = 0;\n for (let i = 0; i < args.length; i++) {\n if (args[i] !== \"-i\") continue;\n if (args[i - 2] === \"-t\") {\n const v = Number(args[i - 1]);\n if (Number.isFinite(v)) lens.set(inputIndex, v);\n }\n inputIndex++;\n }\n // Filter-side `trim=` on a `[N:v]…` chain (clips cut inside the spine).\n const graph = args.join(\" \");\n for (const m of graph.matchAll(/\\[(\\d+):v\\][^;[]*?trim=(?:start=[\\d.]+:)?duration=([\\d.]+)/g)) {\n const idx = Number(m[1]);\n const v = Number(m[2]);\n if (Number.isFinite(idx) && Number.isFinite(v)) lens.set(idx, v);\n }\n return lens;\n}\n","import type { z } from \"zod\";\nimport type { AssetRef } from \"../schema/refs.ts\";\nimport type { ExecCtx } from \"./context.ts\";\n\ntype CostEstimate = { credits: number; seconds_estimate: number };\n\nexport type CostFn<P> = (args: { params: P }) => CostEstimate;\n\nexport type ExecuteArgs<I, P> = {\n inputs: I;\n params: P;\n ctx: ExecCtx;\n};\n\n/**\n * Node-supplied extra validation hook. Runs after the node's static Zod\n * schema passes — used by nodes whose param shape depends on external state\n * (e.g. `hyperframe_render` consults the composition's meta.json).\n * Returns issue messages keyed by the dotted param path to surface in\n * `canvas validate` output. Empty array means OK.\n */\ntype ValidateExtraIssue = { path: string; message: string };\nexport type ValidateExtraFn = (args: {\n rawParams: unknown;\n rawInputs: unknown;\n}) => Promise<ValidateExtraIssue[]> | ValidateExtraIssue[];\n\n/**\n * Node-supplied cache-key extras hook. Returns extra fields the executor\n * folds into the cache key alongside `params` — used by nodes whose output\n * depends on external content (e.g. composition directory contents).\n */\nexport type CacheKeyExtrasFn = (args: { params: unknown }) => Promise<Record<string, string>>;\n\n/**\n * Per-output asset-kind declaration. Either a static map (most nodes — each\n * named output produces a fixed kind) or a function of params (e.g. the\n * `ingest` node, whose output kind is decided by `params.expect`).\n *\n * Validators and the dashboard read this to type the output port statically\n * without running the node. Remote nodes also use it at runtime so the\n * delegate ingestor knows how to wrap returned bytes.\n */\nexport type OutputKindsSpec<P> = Record<string, AssetRef[\"kind\"]> | ((params: P) => Record<string, AssetRef[\"kind\"]>);\n\nexport function resolveOutputKinds<P>(\n spec: OutputKindsSpec<P> | undefined,\n params: P,\n): Record<string, AssetRef[\"kind\"]> {\n if (!spec) return {};\n return typeof spec === \"function\" ? spec(params) : spec;\n}\n\nexport type NodeDefinition<I = unknown, P = unknown, O = unknown> = {\n id: string;\n version: string;\n category: string;\n summary: string;\n when_to_use?: string;\n inputs: z.ZodType<I>;\n params: z.ZodType<P>;\n outputs: z.ZodType<O>;\n /** \"local\" runs in-process; \"remote\" delegates to Convex via ctx.client */\n location: \"local\" | \"remote\";\n /**\n * Local node that only forwards asset refs and never reads their bytes\n * (e.g. `collect`). Exempts its upstream producers from the forced R2→disk\n * download local consumers otherwise trigger.\n */\n passthroughRefs?: true;\n cost?: CostFn<P>;\n validateExtra?: ValidateExtraFn;\n cacheKeyExtras?: CacheKeyExtrasFn;\n outputKinds?: OutputKindsSpec<P>;\n execute: (args: ExecuteArgs<I, P>) => Promise<O>;\n};\n\nexport function defineNode<I, P, O>(def: NodeDefinition<I, P, O>): NodeDefinition<I, P, O> {\n return def;\n}\n","/** Damerau-Levenshtein distance with single-edit awareness. */\nfunction distance(a: string, b: string): number {\n const m = a.length;\n const n = b.length;\n if (m === 0) return n;\n if (n === 0) return m;\n const dp = makeDp(m, n);\n for (let i = 1; i <= m; i++) fillRow(dp, a, b, i, n);\n return (dp[m] as number[])[n] ?? 0;\n}\n\nfunction makeDp(m: number, n: number): number[][] {\n const dp: number[][] = Array.from({ length: m + 1 }, () => new Array<number>(n + 1).fill(0));\n for (let i = 0; i <= m; i++) (dp[i] as number[])[0] = i;\n for (let j = 0; j <= n; j++) (dp[0] as number[])[j] = j;\n return dp;\n}\n\nfunction fillRow(dp: number[][], a: string, b: string, i: number, n: number): void {\n const rowI = dp[i] as number[];\n const rowPrev = dp[i - 1] as number[];\n const rowPrev2 = i >= 2 ? (dp[i - 2] as number[]) : undefined;\n for (let j = 1; j <= n; j++) {\n rowI[j] = stepCost(a, b, i, j, rowI, rowPrev, rowPrev2);\n }\n}\n\nfunction stepCost(\n a: string,\n b: string,\n i: number,\n j: number,\n rowI: number[],\n rowPrev: number[],\n rowPrev2: number[] | undefined,\n): number {\n const cost = a.charCodeAt(i - 1) === b.charCodeAt(j - 1) ? 0 : 1;\n const del = (rowPrev[j] ?? 0) + 1;\n const ins = (rowI[j - 1] ?? 0) + 1;\n const sub = (rowPrev[j - 1] ?? 0) + cost;\n let best = Math.min(del, ins, sub);\n if (\n i > 1 &&\n j > 1 &&\n rowPrev2 &&\n a.charCodeAt(i - 1) === b.charCodeAt(j - 2) &&\n a.charCodeAt(i - 2) === b.charCodeAt(j - 1)\n ) {\n best = Math.min(best, (rowPrev2[j - 2] ?? 0) + 1);\n }\n return best;\n}\n\nexport function didYouMean(query: string, candidates: readonly string[], max = 3): string[] {\n if (candidates.length === 0 || !query) return [];\n const threshold = Math.max(1, Math.floor(query.length / 3) + 1);\n const scored: { c: string; d: number }[] = [];\n for (const c of candidates) {\n const d = distance(query.toLowerCase(), c.toLowerCase());\n if (d <= threshold) scored.push({ c, d });\n }\n scored.sort((a, b) => a.d - b.d || a.c.localeCompare(b.c));\n return scored.slice(0, max).map((s) => s.c);\n}\n","import { canonicalize } from \"@baker/canvas-contract\";\nimport type { BackendClient } from \"../client/backend-client.ts\";\nimport { mapWithConcurrency, resolveConcurrency } from \"../lib/concurrency.ts\";\nimport { ulid } from \"../lib/ulid.ts\";\nimport { persistOutputAssetUrls } from \"../nodes/remote/upload.ts\";\nimport { type Canvas, type NodeDecl, parseRefExpr, REF_PREFIX } from \"../schema/canvas.ts\";\nimport { renderTemplate } from \"../schema/prompts.ts\";\nimport type { AssetRef } from \"../schema/refs.ts\";\nimport type { AssetStore } from \"../storage/asset-store.ts\";\nimport type { CacheStore } from \"../storage/cache-store.ts\";\nimport { OutputWriter } from \"../storage/output-writer.ts\";\nimport { computeCacheKey } from \"./cache-key.ts\";\nimport type { ExecCtx, LogFn } from \"./context.ts\";\nimport type { NodeDefinition } from \"./define.ts\";\nimport {\n failureDetail,\n LayerExecutionError,\n type LayerFailure,\n NodeExecutionError,\n type NodeFailureDetail,\n RunAbortedError,\n ValidationError,\n} from \"./errors.ts\";\nimport { type AllOutputs, resolveRefs } from \"./refs.ts\";\nimport type { NodeRegistry } from \"./registry.ts\";\nimport { reachableNodes, subgraph, topologicalLayers } from \"./scheduler.ts\";\nimport { validateCanvas, validateCanvasDeep } from \"./validator.ts\";\n\nexport type RunResult = {\n run_id: string;\n output: AssetRef | AssetRef[] | unknown;\n outputs_by_node: Record<string, Record<string, unknown>>;\n stats: { total_nodes: number; cached_nodes: number; total_credits: number; duration_ms: number };\n outputs_dir: string;\n node_runs: NodeRunRecord[];\n};\n\nexport type NodeRunRecord = {\n node_id: string;\n node_type: string;\n cached: boolean;\n duration_ms: number;\n credits: number;\n};\n\n/**\n * Live run telemetry: the plan (post-prune node list + dependency edges) fires\n * once before any node executes, then start/settled/failed per node. Consumers\n * stream these into run-history progress snapshots; a throwing consumer is\n * swallowed — telemetry must never fail a paid run.\n */\nexport type RunProgressEvent =\n | { kind: \"plan\"; nodes: Array<{ node_id: string; node_type: string; deps: string[]; params: unknown }> }\n | { kind: \"node_start\"; node_id: string }\n | { kind: \"node_settled\"; run: NodeRunRecord; outputs: Record<string, unknown> }\n | { kind: \"node_failed\"; node_id: string; error: NodeFailureDetail };\n\ntype RunOptions = {\n signal?: AbortSignal;\n run_id?: string;\n cache_policy?: \"read_write\" | \"bypass\" | \"read_only\";\n /** Max nodes of one layer in flight at once; invalid or missing → 8 (DEFAULT_CONCURRENCY). */\n concurrency?: number;\n /**\n * Credit ceiling (`--max-credits`). Enforced pre-flight against the deep\n * validator's estimate (nothing billed) and at layer boundaries against\n * actual spend — a boundary is the only point with no async job in flight,\n * so aborting there strands nothing. Cached nodes cost 0, so a capped run\n * retried with a higher cap loses no completed work.\n */\n max_credits?: number;\n /**\n * Node ids to force fresh for THIS run only (the `--regenerate` flag). Folds\n * the run id into each named node's cache key so it re-renders regardless of\n * the content cache, without editing the canvas. Persistent regeneration uses\n * the per-node `regenerate` field instead.\n */\n regenerate?: ReadonlySet<string>;\n onProgress?: (event: RunProgressEvent) => void;\n};\n\ntype EngineOptions = {\n registry: NodeRegistry;\n client: BackendClient;\n assets: AssetStore;\n cache: CacheStore;\n outputsDir: string;\n log?: LogFn;\n /**\n * Stamp durable canvas-assets URLs onto fresh node outputs before they are\n * cached — the precondition for remote cache portability and run-history\n * records. Best-effort: a failed upload logs a warning and keeps the entry\n * local-only, never fails the node.\n */\n persistAssets?: boolean;\n};\n\nexport class Engine {\n private readonly registry: NodeRegistry;\n private readonly client: BackendClient;\n private readonly assets: AssetStore;\n private readonly cache: CacheStore;\n private readonly outputsDir: string;\n private readonly log: LogFn;\n private readonly persistAssets: boolean;\n\n constructor(opts: EngineOptions) {\n this.registry = opts.registry;\n this.client = opts.client;\n this.assets = opts.assets;\n this.cache = opts.cache;\n this.outputsDir = opts.outputsDir;\n this.log = opts.log ?? (() => undefined);\n this.persistAssets = opts.persistAssets ?? false;\n }\n\n validate(canvas: unknown) {\n return validateCanvas(canvas, this.registry);\n }\n\n /** Async variant — runs every node's `validateExtra` hook in addition to the shallow checks. */\n validateDeep(canvas: unknown) {\n return validateCanvasDeep(canvas, this.registry);\n }\n\n async run(input: unknown, opts: RunOptions = {}): Promise<RunResult> {\n // Always run the deep validator before any node executes. This catches\n // composition-meta mistakes (bad param shape, missing required param,\n // unknown @baker composition) upfront — before paying for any remote node.\n // Without this, a typo in the final hyperframe_render call would only\n // surface after all 14 video_generate clips had spent credits.\n const validation = await this.validateDeep(input);\n if (!validation.ok) throw new ValidationError(validation.issues);\n if (opts.max_credits !== undefined && validation.estimatedCredits > opts.max_credits) {\n throw new RunAbortedError(\n \"cost_cap\",\n `estimated ${validation.estimatedCredits} credits exceeds the ${opts.max_credits}-credit cap — nothing was billed; raise --max-credits or shrink the canvas`,\n );\n }\n const canvas = validation.canvas;\n\n const runId = opts.run_id ?? `r_${ulid()}`;\n const writer = new OutputWriter({ outputsDir: this.outputsDir, runId });\n await writer.ensure();\n\n this.log(`[validate] ok (${canvas.nodes.length} nodes, est. ${validation.estimatedCredits} credits)`);\n // Advisory warnings never block the run, but a billed render should still print\n // them (a missing element reference, a scene span past the model's cap) so the\n // operator sees them without a separate `validate` pass.\n for (const w of validation.warnings ?? []) {\n this.log(`[warn ] ${w.code}${w.node_id ? ` (${w.node_id})` : \"\"}: ${w.message}`);\n }\n\n const t0 = Date.now();\n const outputs: AllOutputs = {};\n const counters = { cachedNodes: 0, totalCredits: 0 };\n const nodeRuns: NodeRunRecord[] = [];\n\n const graph = this.pruneToOutput(canvas, buildGraph(canvas));\n const needsBytes = computeNeedsLocalBytes(canvas, graph, this.registry);\n this.emitProgress(opts, {\n kind: \"plan\",\n nodes: [...graph.entries()].map(([id, deps]) => {\n const node = canvas.nodes.find((n) => n.id === id);\n return { node_id: id, node_type: node?.type ?? \"unknown\", deps: [...deps], params: node?.params };\n }),\n });\n\n await this.runLayers(canvas, graph, outputs, runId, writer, opts, counters, nodeRuns, needsBytes);\n\n const output = pickFinalOutput(canvas, outputs);\n const stats = {\n total_nodes: canvas.nodes.length,\n cached_nodes: counters.cachedNodes,\n total_credits: counters.totalCredits,\n duration_ms: Date.now() - t0,\n };\n\n await writer.writeManifest(\"manifest\", {\n run_id: runId,\n canvas,\n outputs_by_node: outputs,\n output,\n stats,\n node_runs: nodeRuns,\n started_at: t0,\n completed_at: t0 + stats.duration_ms,\n });\n await this.writeFinal(writer, output);\n\n this.log(\n `[done ] ${stats.cached_nodes}/${stats.total_nodes} cached, ${stats.total_credits} credits, ${stats.duration_ms}ms`,\n );\n this.log(`outputs in: ${writer.runDir}`);\n\n return { run_id: runId, output, outputs_by_node: outputs, stats, outputs_dir: writer.runDir, node_runs: nodeRuns };\n }\n\n private async runLayers(\n canvas: Canvas,\n graph: Map<string, Set<string>>,\n outputs: AllOutputs,\n runId: string,\n writer: OutputWriter,\n opts: RunOptions,\n counters: { cachedNodes: number; totalCredits: number },\n nodeRuns: NodeRunRecord[],\n needsBytes: ReadonlySet<string>,\n ): Promise<void> {\n const layers = topologicalLayers(graph);\n const limit = resolveConcurrency(opts.concurrency);\n for (const layer of layers) {\n if (opts.signal?.aborted) throw new RunAbortedError(\"signal\", \"run aborted before layer dispatch\");\n if (opts.max_credits !== undefined && counters.totalCredits > opts.max_credits) {\n throw new RunAbortedError(\n \"cost_cap\",\n `spent ${counters.totalCredits} credits, over the ${opts.max_credits}-credit cap — completed nodes are cached; raise --max-credits to continue where this stopped`,\n );\n }\n // Settle the whole layer: a failing node must not abandon in-flight\n // siblings, or their cache writes are lost and repeated runs of a canvas\n // with several flaky nodes never converge.\n const settled = await mapWithConcurrency(layer, limit, (nodeId) => {\n // A signal mid-layer stops DISPATCHING further nodes; already-running\n // siblings still settle so their cache writes land. Skipped nodes never\n // start (no node_start / node_failed) — they stay pending for a resume.\n if (opts.signal?.aborted) {\n return Promise.reject(new RunAbortedError(\"signal\", \"run aborted before node dispatch\"));\n }\n this.emitProgress(opts, { kind: \"node_start\", node_id: nodeId });\n return this.executeOne(canvas, nodeId, outputs, runId, writer, opts, needsBytes.has(nodeId)).then((r) => {\n if (r.cached) counters.cachedNodes++;\n counters.totalCredits += r.credits;\n const node = canvas.nodes.find((n) => n.id === nodeId);\n if (node) {\n const run: NodeRunRecord = {\n node_id: nodeId,\n node_type: node.type,\n cached: r.cached,\n duration_ms: r.durationMs,\n credits: r.credits,\n };\n nodeRuns.push(run);\n this.emitProgress(opts, { kind: \"node_settled\", run, outputs: outputs[nodeId] ?? {} });\n }\n });\n });\n const failures: LayerFailure[] = [];\n settled.forEach((result, i) => {\n const nodeId = layer[i];\n if (result.status === \"rejected\" && nodeId) {\n // Abort-skips are not node failures — the node never dispatched.\n if (result.reason instanceof RunAbortedError) return;\n failures.push({ nodeId, reason: result.reason });\n this.emitProgress(opts, { kind: \"node_failed\", node_id: nodeId, error: failureDetail(result.reason) });\n }\n });\n // An abort outranks same-layer failures: the signal is why the run ended,\n // and per-node outcomes are already captured in the progress snapshot.\n if (opts.signal?.aborted) throw new RunAbortedError(\"signal\", \"run aborted by signal\");\n if (failures.length === 1 && failures[0]) throw failures[0].reason;\n if (failures.length > 1) throw new LayerExecutionError(failures);\n }\n }\n\n /** Progress consumers are observers only — an exception there must never fail the run. */\n private emitProgress(opts: RunOptions, event: RunProgressEvent): void {\n if (!opts.onProgress) return;\n try {\n opts.onProgress(event);\n } catch {\n // deliberately swallowed\n }\n }\n\n /**\n * Dead-node elimination: when the canvas declares an `output`, execute only the\n * nodes that output transitively depends on. Orphaned nodes (left by an edit or\n * a rewire) otherwise still run, bill, and abort the run on their own failure.\n * No declared output ⇒ intent is ambiguous, so run everything (back-compat).\n */\n private pruneToOutput(canvas: Canvas, graph: Map<string, Set<string>>): Map<string, Set<string>> {\n const rootId = canvas.output?.node;\n if (!rootId || !graph.has(rootId)) return graph;\n const keep = reachableNodes(graph, [rootId]);\n if (keep.size === graph.size) return graph;\n const dropped = [...graph.keys()].filter((id) => !keep.has(id));\n this.log(`[prune ] skipping ${dropped.length} node(s) unreachable from output: ${dropped.join(\", \")}`);\n return subgraph(graph, keep);\n }\n\n private async writeFinal(writer: OutputWriter, output: unknown): Promise<void> {\n if (output === undefined) return;\n if (isAssetRefArray(output)) {\n for (let i = 0; i < output.length; i++) {\n const ref = output[i];\n if (ref) await writer.writeAsset(`_final__${i}`, ref);\n }\n return;\n }\n if (isAssetRef(output)) {\n await writer.writeAsset(\"_final\", output);\n return;\n }\n await writer.writeManifest(\"_final\", output);\n }\n\n private async executeOne(\n canvas: Canvas,\n nodeId: string,\n outputs: AllOutputs,\n runId: string,\n writer: OutputWriter,\n opts: RunOptions,\n downloadOutputs: boolean,\n ): Promise<{ cached: boolean; credits: number; durationMs: number }> {\n const node = canvas.nodes.find((n) => n.id === nodeId);\n if (!node) throw new Error(`executor: missing node ${nodeId}`);\n const def = this.registry.get(node.type);\n if (!def) throw new Error(`executor: missing registry entry for type ${node.type}`);\n\n const regenerateToken = resolveRegenerateToken(node, opts.regenerate, runId);\n const prepared = await prepareForExecution(node, outputs, def, canvas.cache_salt, regenerateToken, this.assets);\n const policy = opts.cache_policy ?? \"read_write\";\n\n if (policy !== \"bypass\") {\n const cacheT0 = Date.now();\n const hit = await this.cache.get(prepared.cacheKey);\n if (hit) {\n outputs[node.id] = hit.outputs;\n await this.materializeNodeOutputs(node.id, hit.outputs, writer);\n this.log(`[exec ] ${node.id.padEnd(20)} ${node.type.padEnd(20)} cached`);\n return { cached: true, credits: 0, durationMs: Date.now() - cacheT0 };\n }\n }\n\n const t0 = Date.now();\n const ctx: ExecCtx = {\n canvasRunId: runId,\n nodeId: node.id,\n nodeType: node.type,\n cacheKey: prepared.cacheKey,\n downloadOutputs,\n client: this.client,\n assets: this.assets,\n log: this.log,\n signal: opts.signal,\n };\n // Fail-safe: a local node needs its input bytes on disk. `computeNeedsLocalBytes`\n // guarantees its producers were downloaded, but if an edge was missed\n // (e.g. an unrecognized ref shape), materialize any URL-only input on demand\n // rather than letting the local runner throw on the missing path. A\n // passthrough-ref node (collect) never reads bytes, so it stays URL-only.\n const preparedForExec = needsLocalMaterialization(def)\n ? { ...prepared, resolvedInputs: await this.materializeLocalInputs(prepared.resolvedInputs) }\n : prepared;\n const { parsedInputs, parsedParams } = parseNodeArgs(def, preparedForExec, node.id, node.type);\n const result = await invokeExecute(def, parsedInputs, parsedParams, ctx, node.id, node.type);\n const elapsed = Date.now() - t0;\n const credits = def.cost ? def.cost({ params: parsedParams as never }).credits : 0;\n const outputsObj = result as Record<string, unknown>;\n outputs[node.id] = outputsObj;\n\n // Stamp durable URLs BEFORE the cache write so the entry (and the run\n // record built from outputs_by_node) is rehydratable in any sandbox.\n // URL-only stamping never changes cache keys (inputs hash by sha256,\n // params are normalized to content identity).\n if (this.persistAssets) {\n try {\n await persistOutputAssetUrls(outputsObj, ctx);\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n this.log(`[warn ] ${node.id}: asset persistence failed (${msg}) — outputs stay local-only`);\n }\n }\n\n if (policy === \"read_write\") {\n await this.cache.put({\n cacheKey: prepared.cacheKey,\n nodeType: node.type,\n nodeVersion: def.version,\n outputs: outputsObj,\n refs: collectShas(outputsObj),\n createdAt: Date.now(),\n });\n }\n await this.materializeNodeOutputs(node.id, outputsObj, writer);\n this.log(`[exec ] ${node.id.padEnd(20)} ${node.type.padEnd(20)} fresh (${(elapsed / 1000).toFixed(1)}s)`);\n return { cached: false, credits, durationMs: elapsed };\n }\n\n private async materializeNodeOutputs(\n nodeId: string,\n outputs: Record<string, unknown>,\n writer: OutputWriter,\n ): Promise<void> {\n for (const [name, value] of Object.entries(outputs)) {\n if (isAssetRef(value)) {\n await writer.writeAsset(`${nodeId}__${name}`, value);\n } else if (isAssetRefArray(value)) {\n for (let i = 0; i < value.length; i++) {\n const ref = value[i];\n if (ref) await writer.writeAsset(`${nodeId}__${name}__${i}`, ref);\n }\n } else {\n await writer.writeManifest(`${nodeId}__${name}`, value);\n }\n }\n }\n\n /**\n * Download any URL-only asset ref reachable in a local node's inputs so the\n * bytes are on disk before the local runner stages them. Returns a copy —\n * refs are replaced, never mutated in place, so the producer's cached output\n * (shared object) keeps its URL-only shape.\n */\n private async materializeLocalInputs(inputs: Record<string, unknown>): Promise<Record<string, unknown>> {\n const fix = async (value: unknown): Promise<unknown> => {\n if (Array.isArray(value)) return Promise.all(value.map(fix));\n if (value && typeof value === \"object\") {\n const v = value as Record<string, unknown>;\n if (\n typeof v.kind === \"string\" &&\n typeof v.url === \"string\" &&\n typeof v.sha256 === \"string\" &&\n typeof v.mime === \"string\" &&\n typeof v.path !== \"string\"\n ) {\n this.log(`[warn ] materializing URL-only input on demand (${v.kind}/${v.mime}) — missed graph edge`);\n return this.assets.ingestRemote({\n kind: v.kind as AssetRef[\"kind\"],\n url: v.url,\n sha256: v.sha256,\n mime: v.mime,\n metadata: v.metadata as Record<string, unknown> | undefined,\n });\n }\n const out: Record<string, unknown> = {};\n for (const [k, val] of Object.entries(v)) out[k] = await fix(val);\n return out;\n }\n return value;\n };\n return (await fix(inputs)) as Record<string, unknown>;\n }\n}\n\ntype Prepared = {\n resolvedInputs: Record<string, unknown>;\n renderedParams: unknown;\n cacheKey: string;\n};\n\n/**\n * The cache-busting token for a node, or undefined to leave its content-addressed\n * key untouched. The one-shot `--regenerate` flag wins and folds the run id (fresh\n * every run); otherwise the persistent per-node `regenerate` field is used. Both\n * flow into the cache key as an `extras` entry, so ONLY targeted nodes change keys\n * — every other node keeps its exact prior key and cache hit.\n */\nexport function resolveRegenerateToken(\n node: NodeDecl,\n forced: ReadonlySet<string> | undefined,\n runId: string,\n): string | undefined {\n if (forced?.has(node.id)) return `run:${runId}`;\n if (node.regenerate !== undefined) return `node:${String(node.regenerate)}`;\n return undefined;\n}\n\nasync function prepareForExecution(\n node: NodeDecl,\n outputs: AllOutputs,\n def: NodeDefinition,\n cacheSalt: string | undefined,\n regenerateToken: string | undefined,\n assets: AssetStore,\n): Promise<Prepared> {\n const resolvedInputs = (resolveRefs(node.inputs ?? {}, { outputs }) ?? {}) as Record<string, unknown>;\n const resolvedParams = (resolveRefs(node.params ?? {}, { outputs }) ?? {}) as Record<string, unknown>;\n const slotValues = await hydrateTextSlots(resolvedInputs, assets, node.id, node.type);\n const renderedParams = renderPromptSlotsInValue(resolvedParams, slotValues);\n // Nodes may declare a cacheKeyExtras hook to fold external content into the\n // cache key (e.g. hyperframe_render hashes the composition directory so\n // composition edits invalidate cached renders automatically). A failing hook\n // fails the node: falling back to a params-only key would cache results that\n // ignore external content and silently serve stale outputs later.\n let extras: Record<string, string> | undefined;\n if (def.cacheKeyExtras) {\n try {\n extras = await def.cacheKeyExtras({ params: renderedParams });\n } catch (e) {\n throw new NodeExecutionError(node.id, node.type, { kind: \"local\", cause: e });\n }\n }\n // Fold the regenerate token in as an extra ONLY when present, so nodes without\n // one keep byte-identical cache keys (no mass invalidation on rollout).\n if (regenerateToken !== undefined) {\n extras = { ...(extras ?? {}), __regenerate__: regenerateToken };\n }\n const cacheKey = computeCacheKey({\n node_id: node.type,\n node_version: def.version,\n params: normalizeParamsForCacheKey(renderedParams),\n input_hashes: hashInputs(resolvedInputs),\n cache_salt: cacheSalt,\n extras,\n });\n return { resolvedInputs, renderedParams, cacheKey };\n}\n\nfunction parseNodeArgs(\n def: NodeDefinition,\n prepared: Prepared,\n nodeId: string,\n nodeType: string,\n): { parsedInputs: unknown; parsedParams: unknown } {\n try {\n return {\n parsedInputs: def.inputs.parse(prepared.resolvedInputs),\n parsedParams: def.params.parse(prepared.renderedParams),\n };\n } catch (e) {\n throw new NodeExecutionError(nodeId, nodeType, { kind: \"local\", cause: e });\n }\n}\n\nasync function invokeExecute(\n def: NodeDefinition,\n parsedInputs: unknown,\n parsedParams: unknown,\n ctx: ExecCtx,\n nodeId: string,\n nodeType: string,\n): Promise<unknown> {\n try {\n return await def.execute({ inputs: parsedInputs as never, params: parsedParams as never, ctx });\n } catch (e) {\n if (e instanceof NodeExecutionError) throw e;\n throw new NodeExecutionError(nodeId, nodeType, { kind: \"local\", cause: e });\n }\n}\n\n/** A local node needs its input bytes on disk unless it only forwards refs (collect). */\nfunction needsLocalMaterialization(def: NodeDefinition): boolean {\n return def.location === \"local\" && !def.passthroughRefs;\n}\n\nfunction pickFinalOutput(canvas: Canvas, outputs: AllOutputs): unknown {\n if (canvas.output) {\n const node = outputs[canvas.output.node];\n return node ? node[canvas.output.output] : undefined;\n }\n const last = canvas.nodes[canvas.nodes.length - 1];\n if (!last) return undefined;\n const lastOut = outputs[last.id];\n return lastOut ? Object.values(lastOut)[0] : undefined;\n}\n\n/**\n * Node ids whose outputs a LOCAL (ffmpeg/magick) node consumes and therefore\n * needs on disk. A node NOT in this set can stay URL-only after remote exec —\n * the backend already persisted its bytes to R2 with a durable sha256 URL, so\n * the redundant R2→sandbox download is skipped. `graph` maps node → its upstream\n * deps, so a local node's deps are exactly its byte-needing producers. The run's\n * final output (canvas.output) is a ref pointer, not a graph consumer, so being\n * the final output never forces a download.\n */\nexport function computeNeedsLocalBytes(\n canvas: Canvas,\n graph: Map<string, Set<string>>,\n registry: NodeRegistry,\n): Set<string> {\n const typeById = new Map(canvas.nodes.map((n) => [n.id, n.type]));\n const needs = new Set<string>();\n for (const [consumerId, deps] of graph) {\n const def = registry.get(typeById.get(consumerId) ?? \"\");\n if (def?.location !== \"local\" || def.passthroughRefs) continue;\n for (const dep of deps) needs.add(dep);\n }\n return needs;\n}\n\nfunction buildGraph(canvas: Canvas): Map<string, Set<string>> {\n const graph = new Map<string, Set<string>>();\n for (const n of canvas.nodes) graph.set(n.id, new Set());\n for (const n of canvas.nodes) {\n const collect = (s: string) => {\n if (!s.startsWith(REF_PREFIX)) return;\n const expr = parseRefExpr(s);\n if (!expr || expr.kind !== \"ref\") return;\n if (!graph.has(expr.nodeId)) return;\n const deps = graph.get(n.id);\n if (deps) deps.add(expr.nodeId);\n };\n walkStrings(n.inputs, collect);\n walkStrings(n.params, collect);\n }\n return graph;\n}\n\nfunction walkStrings(value: unknown, cb: (s: string) => void): void {\n if (typeof value === \"string\") {\n cb(value);\n return;\n }\n if (Array.isArray(value)) {\n for (const v of value) walkStrings(v, cb);\n return;\n }\n if (value && typeof value === \"object\") {\n for (const v of Object.values(value as Record<string, unknown>)) walkStrings(v, cb);\n }\n}\n\n/**\n * Reduce each resolved input to a stable identity for the cache key: a ref → its\n * sha256; anything else → a canonical literal with any NESTED refs reduced to\n * `{sha256,kind,mime}` first. Without that normalization, a ref buried inside an\n * object/array input folds its volatile `url`/`path`/`metadata.ingested_at` into\n * the key — the node either never caches (key churns every run) or keeps a stale\n * key when content changes under an unchanged url. Flat inputs (top-level refs,\n * scalars, ref-free literals) key byte-identically to before. Exported for tests.\n */\nexport function hashInputs(inputs: Record<string, unknown>): Record<string, string | string[]> {\n const out: Record<string, string | string[]> = {};\n for (const [k, v] of Object.entries(inputs)) {\n if (Array.isArray(v)) {\n // Preserve every element (and its position): dropping non-asset literals\n // would let two canvases differing only in an array literal share a key.\n out[k] = v.map((el) => extractSha(el) ?? canonicalLiteral(normalizeParamsForCacheKey(el)));\n } else {\n const s = extractSha(v);\n if (s !== null) out[k] = s;\n else out[k] = canonicalLiteral(normalizeParamsForCacheKey(v));\n }\n }\n return out;\n}\n\nfunction extractSha(v: unknown): string | null {\n if (v && typeof v === \"object\" && \"sha256\" in (v as Record<string, unknown>)) {\n const s = (v as { sha256: unknown }).sha256;\n if (typeof s === \"string\") return s;\n }\n return null;\n}\n\n// Params may carry AssetRefs resolved from `$ref:` (e.g. a composition `image`\n// param wired to an upstream asset). Unlike inputs — which `hashInputs` reduces\n// to sha256 — params are folded into the cache key whole, so the AssetRef's\n// volatile fields (`url`, `path`, `metadata.ingested_at`) would change the key\n// every run and defeat caching. Reduce any embedded AssetRef to its stable\n// content identity before keying; the full object is kept for execution.\nexport function normalizeParamsForCacheKey(v: unknown): unknown {\n if (Array.isArray(v)) return v.map(normalizeParamsForCacheKey);\n if (v && typeof v === \"object\") {\n const sha = extractSha(v);\n if (sha !== null) {\n const ref = v as { sha256: string; kind?: unknown; mime?: unknown };\n return { sha256: ref.sha256, kind: ref.kind, mime: ref.mime };\n }\n const out: Record<string, unknown> = {};\n for (const [k, inner] of Object.entries(v as Record<string, unknown>)) {\n out[k] = normalizeParamsForCacheKey(inner);\n }\n return out;\n }\n return v;\n}\n\nfunction canonicalLiteral(v: unknown): string {\n if (v === undefined) return \"u\";\n if (v === null) return \"n\";\n if (typeof v === \"string\") return `s:${v}`;\n if (typeof v === \"number\") return `f:${v}`;\n if (typeof v === \"boolean\") return `b:${v}`;\n // Objects/arrays go through canonicalize (sorted keys, NFC) so the key is\n // stable regardless of property order — raw JSON.stringify is order-dependent.\n return `j:${canonicalize(v)}`;\n}\n\nfunction collectShas(outputs: Record<string, unknown>): string[] {\n const out: string[] = [];\n const walk = (v: unknown): void => {\n if (Array.isArray(v)) {\n v.forEach(walk);\n return;\n }\n if (v && typeof v === \"object\") {\n if (\"sha256\" in v && typeof (v as { sha256: unknown }).sha256 === \"string\") {\n out.push((v as { sha256: string }).sha256);\n }\n for (const inner of Object.values(v as Record<string, unknown>)) walk(inner);\n }\n };\n walk(outputs);\n return [...new Set(out)];\n}\n\nfunction isAssetRef(v: unknown): v is AssetRef {\n return Boolean(\n v && typeof v === \"object\" && \"kind\" in v && typeof (v as { kind: unknown }).kind === \"string\" && \"sha256\" in v,\n );\n}\n\nfunction isAssetRefArray(v: unknown): v is AssetRef[] {\n return Array.isArray(v) && v.length > 0 && v.every(isAssetRef);\n}\n\nfunction renderPromptSlotsInValue(value: unknown, slots: Record<string, unknown>): unknown {\n if (typeof value === \"string\") return renderTemplate(value, stringifySlots(slots));\n if (Array.isArray(value)) return value.map((v) => renderPromptSlotsInValue(v, slots));\n if (value && typeof value === \"object\") {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n out[k] = renderPromptSlotsInValue(v, slots);\n }\n return out;\n }\n return value;\n}\n\n/**\n * Hard cap on text/json content inlined into a prompt slot. Provider prompts\n * comfortably fit hundreds of KB; anything larger is almost certainly a wiring\n * mistake (e.g. pointing a slot at a transcript dump) and would silently eat\n * the model's context, so the node fails instead of truncating.\n */\nconst MAX_INLINE_TEXT_BYTES = 256 * 1024;\n\n/**\n * Replace text/json asset refs in prompt slots with their actual content so\n * `{{slot}}` injects what the upstream node produced. Without this, refs\n * render as compact `[text: <sha8>]` placeholders — fine for binary kinds\n * (image/video/audio), useless for text meant to feed the next prompt.\n */\nasync function hydrateTextSlots(\n slots: Record<string, unknown>,\n assets: AssetStore,\n nodeId: string,\n nodeType: string,\n): Promise<Record<string, unknown>> {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(slots)) {\n out[k] = await hydrateSlotValue(v, assets, nodeId, nodeType);\n }\n return out;\n}\n\nasync function hydrateSlotValue(\n value: unknown,\n assets: AssetStore,\n nodeId: string,\n nodeType: string,\n): Promise<unknown> {\n if (Array.isArray(value)) {\n const out: unknown[] = [];\n for (const v of value) out.push(await hydrateSlotValue(v, assets, nodeId, nodeType));\n return out;\n }\n if (!isAssetRef(value) || (value.kind !== \"text\" && value.kind !== \"json\")) return value;\n let bytes: Buffer;\n try {\n bytes = await assets.readBytes(value.sha256, value.mime);\n } catch (e) {\n // A text/json prompt slot is hydrated by reading its bytes locally, so its\n // producer needs them on disk even when the consumer is a remote node (the\n // `needsLocalBytes` graph rule only tracks local ffmpeg/magick consumers).\n // If the producer was kept URL-only, fetch it on demand — these assets are\n // tiny, so the transfer is cheap.\n if (value.url) {\n try {\n await assets.ingestRemote({ kind: value.kind, url: value.url, sha256: value.sha256, mime: value.mime });\n bytes = await assets.readBytes(value.sha256, value.mime);\n } catch (e2) {\n throw new NodeExecutionError(nodeId, nodeType, { kind: \"local\", cause: e2 });\n }\n } else {\n throw new NodeExecutionError(nodeId, nodeType, { kind: \"local\", cause: e });\n }\n }\n if (bytes.length > MAX_INLINE_TEXT_BYTES) {\n throw new NodeExecutionError(nodeId, nodeType, {\n kind: \"local\",\n cause: new Error(\n `slot asset ${value.sha256.slice(0, 8)} is ${bytes.length} bytes, over the ${MAX_INLINE_TEXT_BYTES}-byte inline prompt limit`,\n ),\n });\n }\n return bytes.toString(\"utf8\");\n}\n\nfunction stringifySlots(slots: Record<string, unknown>): Record<string, string> {\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(slots)) {\n out[k] = stringForSlot(v);\n }\n return out;\n}\n\nfunction stringForSlot(v: unknown): string {\n if (typeof v === \"string\") return v;\n if (v && typeof v === \"object\" && \"kind\" in v && \"sha256\" in v) {\n const ref = v as AssetRef;\n if (ref.kind === \"image\" && \"width\" in ref && \"height\" in ref && ref.width && ref.height) {\n return `[image: ${ref.width}x${ref.height}]`;\n }\n return `[${ref.kind}: ${ref.sha256.slice(0, 8)}]`;\n }\n if (Array.isArray(v)) return v.map(stringForSlot).join(\", \");\n return JSON.stringify(v);\n}\n","import type { NodeDefinition } from \"./define.ts\";\n\nexport class NodeRegistry {\n private readonly byId = new Map<string, NodeDefinition>();\n\n register(def: NodeDefinition): void {\n if (this.byId.has(def.id)) {\n throw new Error(`NodeRegistry: duplicate node id \"${def.id}\"`);\n }\n this.byId.set(def.id, def as NodeDefinition);\n }\n\n registerAll(defs: readonly NodeDefinition[]): void {\n for (const d of defs) this.register(d);\n }\n\n get(id: string): NodeDefinition | undefined {\n return this.byId.get(id);\n }\n\n has(id: string): boolean {\n return this.byId.has(id);\n }\n\n ids(): string[] {\n return [...this.byId.keys()].sort();\n }\n\n all(): NodeDefinition[] {\n return [...this.byId.values()];\n }\n}\n","import { execFile as execFileCb, spawn } from \"node:child_process\";\nimport type { Stats } from \"node:fs\";\nimport { mkdtemp, readdir, readFile, rm, stat } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport path from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { z } from \"zod\";\nimport type { ExecCtx } from \"../engine/context.ts\";\nimport { defineNode } from \"../engine/define.ts\";\nimport { NodeExecutionError } from \"../engine/errors.ts\";\nimport { looksLikeHttpUrl } from \"../lib/url.ts\";\nimport type { AssetKind, AssetRef } from \"../schema/refs.ts\";\nimport { AssetRef as AssetRefSchema } from \"../schema/refs.ts\";\nimport { MAX_ASSET_BYTES } from \"../storage/asset-store.ts\";\nimport { sha256Hex } from \"../storage/sha256.ts\";\nimport { callBackendExec } from \"./remote/delegate.ts\";\nimport { presignAndPut } from \"./remote/upload.ts\";\n\nconst execFile = promisify(execFileCb);\n\n// ---------------------------------------------------------------------------\n// Schema — discriminated union on `source`\n// ---------------------------------------------------------------------------\n\nconst ExpectEnum = z.enum([\"image\", \"video\", \"audio\", \"text\", \"json\", \"font\"]);\n\n/**\n * Heal a `source:\"path\"` ingest whose `path` is actually an http(s) URL into a `source:\"url\"` ingest.\n *\n * The scaffold emits `source:\"path\"` asset slots (it expects a locally-dropped file); an operator\n * routinely fills one with a durable asset URL (`media.withbaker.com/…`) but forgets to flip `source`.\n * Left alone, `path` resolves as a relative filename and the run dies deep at execute with\n * `file_not_found` — AFTER billing has started, and after `validate` reported `ok` (the `path` branch\n * accepts any non-empty string, and validate never stats the disk). The distinction is decidable from\n * the value, so we coerce it here. Runs as a `z.preprocess` in front of the discriminated union, so\n * every caller — `validate`, the deep validator, and `execute` — sees the corrected shape.\n */\nfunction coercePathUrlToUrl(input: unknown): unknown {\n if (!input || typeof input !== \"object\") return input;\n const obj = input as Record<string, unknown>;\n if (obj.source === \"path\" && looksLikeHttpUrl(obj.path)) {\n const { path: _path, ...rest } = obj;\n return { ...rest, source: \"url\", url: (obj.path as string).trim() };\n }\n return input;\n}\n\nconst IngestParams = z.preprocess(\n coercePathUrlToUrl,\n z.discriminatedUnion(\"source\", [\n z\n .object({\n source: z.literal(\"url\"),\n url: z.string().url(),\n expect: ExpectEnum,\n })\n .strict(),\n z\n .object({\n source: z.literal(\"path\"),\n path: z.string().min(1),\n expect: ExpectEnum,\n })\n .strict(),\n ]),\n);\n\nconst IngestInputs = z.object({}).strict();\nconst IngestOutputs = z.object({ asset: AssetRefSchema }).strict();\n\ntype IngestParamsT = z.infer<typeof IngestParams>;\ntype UrlParams = Extract<IngestParamsT, { source: \"url\" }>;\ntype PathParams = Extract<IngestParamsT, { source: \"path\" }>;\n\n// ---------------------------------------------------------------------------\n// Strategy resolution — one branch on source, one switch on expect for URLs\n// ---------------------------------------------------------------------------\n\ntype Strategy = \"direct_fetch\" | \"handinger\" | \"yt_dlp\" | \"local_file\";\n\nconst RAW_TEXT_EXTENSIONS = [\".txt\", \".md\"] as const;\n\nfunction resolveStrategy(params: IngestParamsT): Strategy {\n if (params.source === \"path\") return \"local_file\";\n switch (params.expect) {\n case \"video\":\n case \"audio\":\n return \"yt_dlp\";\n case \"image\":\n case \"json\":\n case \"font\":\n return \"direct_fetch\";\n case \"text\": {\n const p = safePathname(params.url);\n const isRawText = RAW_TEXT_EXTENSIONS.some((ext) => p.endsWith(ext));\n return isRawText ? \"direct_fetch\" : \"handinger\";\n }\n default: {\n params.expect satisfies never;\n throw new Error(`ingest: unhandled expect=${String(params.expect)}`);\n }\n }\n}\n\nfunction safePathname(rawUrl: string): string {\n try {\n return new URL(rawUrl).pathname.toLowerCase();\n } catch {\n return \"\";\n }\n}\n\n// ---------------------------------------------------------------------------\n// Node definition\n// ---------------------------------------------------------------------------\n\nexport const ingestNode = defineNode({\n id: \"ingest\",\n version: \"1.2.0\",\n category: \"io\",\n location: \"local\",\n summary:\n \"Ingest an external URL or a local file into the asset store. Declare the kind you expect (image/video/audio/text/json/font); the node picks the strategy. For source=url: yt-dlp for video/audio (YouTube/TikTok/Vimeo/etc. and direct file URLs), Handinger for HTML/PDF pages → markdown, direct HTTP fetch for binary URLs (images, fonts) and raw .txt/.md. For source=path: read from the local filesystem and upload to R2.\",\n when_to_use:\n 'Use as the on-ramp for any external asset a canvas needs. `expect` makes the output port statically typed so downstream wiring is checked before any byte is fetched. Pick `source: \"url\"` for portable canvas; pick `source: \"path\"` for local files (canvas is not portable across machines without the file). Compose with other nodes for richer pipelines (e.g. `ingest expect=video` → `video_transcribe`).',\n inputs: IngestInputs,\n params: IngestParams,\n outputs: IngestOutputs,\n cost: () => ({ credits: 0, seconds_estimate: 5 }),\n\n // Output kind is declared in params, so validators/UI can type the port\n // statically without running the node.\n outputKinds: (params: IngestParamsT) => ({ asset: params.expect }),\n\n async execute({ params, ctx }) {\n const strategy = resolveStrategy(params);\n const source = params.source === \"url\" ? params.url : params.path;\n ctx.log(`ingest: ${strategy} (${params.expect}) ${source}`);\n const asset = await runStrategy(strategy, params, ctx);\n return { asset };\n },\n});\n\nfunction runStrategy(strategy: Strategy, params: IngestParamsT, ctx: ExecCtx): Promise<AssetRef> {\n if (params.source === \"path\") {\n if (strategy !== \"local_file\") {\n throw new Error(`ingest: invariant — source=path but strategy=${strategy}`);\n }\n return execLocalFile(params, ctx);\n }\n // params.source === \"url\" — narrowed\n switch (strategy) {\n case \"direct_fetch\":\n return execDirectFetch(params, ctx);\n case \"handinger\":\n return execHandinger(params, ctx);\n case \"yt_dlp\":\n return execYtDlp(params, ctx);\n case \"local_file\":\n throw new Error(`ingest: invariant — source=url but strategy=local_file`);\n default: {\n strategy satisfies never;\n throw new Error(`ingest: unhandled strategy=${String(strategy)}`);\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// direct_fetch / handinger — both go through the backend\n// ---------------------------------------------------------------------------\n\nasync function execDirectFetch(params: UrlParams, ctx: ExecCtx): Promise<AssetRef> {\n // Image URLs are fetched and normalized locally rather than delegated to the backend: image-\n // generation models only read jpeg/png/gif/webp and 400 the WHOLE generation on anything else\n // (SVG, AVIF, HEIC, TIFF, BMP). Normalization needs sharp, which can't load in the Convex runtime,\n // so it has to happen here — the same treatment execLocalFile gives a `source: \"path\"` image. Text/\n // json/font URLs still go through the backend (handinger for HTML/PDF, direct fetch otherwise).\n if (params.expect === \"image\") {\n return ingestImageUrl(params.url, ctx);\n }\n const result = await callBackendExec({\n nodeType: \"ingest\",\n nodeVersion: ingestNode.version,\n params: { strategy: \"direct_fetch\", url: params.url, expect: params.expect },\n inputs: {},\n outputKinds: { asset: params.expect },\n ctx,\n });\n return assertAssetOutput(result, params.expect);\n}\n\n/**\n * Fetch an image URL, normalize it to a model-safe raster, and upload. Mirrors execLocalFile so an\n * asset behaves identically whether it's sourced by URL or by path. A non-decodable body (e.g. an\n * HTML error page returned with a 200) surfaces as a clear NodeExecutionError instead of poisoning a\n * downstream generation.\n */\nasync function ingestImageUrl(url: string, ctx: ExecCtx): Promise<AssetRef> {\n const res = await fetch(url);\n if (!res.ok) {\n throw localExecError(ctx, `fetch ${url} → ${res.status}`);\n }\n const ab = await res.arrayBuffer();\n if (ab.byteLength > MAX_ASSET_BYTES) {\n throw localExecError(ctx, `file_too_large: ${url} is ${ab.byteLength} bytes (limit ${MAX_ASSET_BYTES})`);\n }\n let normalized: ModelSafeImage;\n try {\n normalized = await toModelSafeImage(Buffer.from(ab));\n } catch (e) {\n throw localExecError(ctx, `${url}: ${(e as Error).message}`);\n }\n if (normalized.rasterizedFrom) {\n ctx.log(`ingest: normalized ${normalized.rasterizedFrom} URL -> PNG (${normalized.bytes.length}B)`);\n }\n return uploadAndIngest({\n bytes: normalized.bytes,\n kind: \"image\",\n mime: normalized.mime,\n metadata: {\n source_url: url,\n strategy: \"direct_fetch\",\n ingested_at: new Date().toISOString(),\n ...(normalized.rasterizedFrom ? { rasterized_from: normalized.rasterizedFrom } : {}),\n },\n ctx,\n });\n}\n\nasync function execHandinger(params: UrlParams, ctx: ExecCtx): Promise<AssetRef> {\n const result = await callBackendExec({\n nodeType: \"ingest\",\n nodeVersion: ingestNode.version,\n params: { strategy: \"handinger\", url: params.url },\n inputs: {},\n outputKinds: { asset: \"text\" },\n ctx,\n });\n return assertAssetOutput(result, \"text\");\n}\n\nfunction assertAssetOutput(result: Record<string, unknown>, expected: AssetKind): AssetRef {\n const asset = result.asset as AssetRef | undefined;\n if (!asset || typeof asset !== \"object\" || !(\"kind\" in asset)) {\n throw new Error(`ingest: backend returned no asset (got ${JSON.stringify(result)})`);\n }\n if (asset.kind !== expected) {\n throw new Error(`ingest: backend returned kind=${asset.kind} but expected ${expected}`);\n }\n return asset;\n}\n\n// ---------------------------------------------------------------------------\n// local_file — read from disk, sniff mime, upload to R2 via presign\n// ---------------------------------------------------------------------------\n\nfunction resolveLocalPath(input: string): string {\n if (input.startsWith(\"~\")) {\n throw new Error(\n `ingest: ~ path expansion is not supported (got \"${input}\"). Use an absolute path or a cwd-relative path.`,\n );\n }\n if (path.isAbsolute(input)) return input;\n return path.resolve(process.cwd(), input);\n}\n\nconst EXT_TO_MIME: Record<string, string> = {\n png: \"image/png\",\n jpg: \"image/jpeg\",\n jpeg: \"image/jpeg\",\n webp: \"image/webp\",\n gif: \"image/gif\",\n // Non-model-safe rasters `toModelSafeImage` transcodes to PNG at ingest — they\n // must resolve to an image mime here or the kind-check rejects the local file\n // before normalization ever runs.\n avif: \"image/avif\",\n heic: \"image/heic\",\n heif: \"image/heif\",\n tif: \"image/tiff\",\n tiff: \"image/tiff\",\n bmp: \"image/bmp\",\n mp4: \"video/mp4\",\n webm: \"video/webm\",\n mov: \"video/quicktime\",\n m4v: \"video/mp4\",\n mp3: \"audio/mpeg\",\n wav: \"audio/wav\",\n m4a: \"audio/mp4\",\n ogg: \"audio/ogg\",\n flac: \"audio/flac\",\n json: \"application/json\",\n txt: \"text/plain\",\n md: \"text/markdown\",\n markdown: \"text/markdown\",\n html: \"text/html\",\n htm: \"text/html\",\n csv: \"text/csv\",\n ttf: \"font/ttf\",\n otf: \"font/otf\",\n woff: \"font/woff\",\n woff2: \"font/woff2\",\n svg: \"image/svg+xml\",\n};\n\nconst SVG_MIME = \"image/svg+xml\";\n\n// Crispness target for rasterized SVGs. SVGs (brand logos especially) are often authored at small\n// intrinsic sizes — sharp rasterizes at the intrinsic size unless we raise the render density, which\n// would leave a tiny, blurry logo. We measure the intrinsic size and scale the density so the longest\n// edge lands near SVG_TARGET_LONGEST_PX, clamped so a pathological viewBox can't blow up memory.\nconst SVG_TARGET_LONGEST_PX = 2048;\nconst SVG_BASE_DENSITY = 72;\nconst SVG_MAX_DENSITY = 2400;\n\nfunction sniffSvg(buf: Buffer): boolean {\n const head = buf.subarray(0, Math.min(buf.length, 512)).toString(\"utf8\").trimStart();\n return head.startsWith(\"<?xml\") ? head.includes(\"<svg\") : head.startsWith(\"<svg\");\n}\n\nexport function inferMimeFromPath(absPath: string, sniffBytes: Buffer): string {\n const ext = path.extname(absPath).slice(1).toLowerCase();\n const fromExt = EXT_TO_MIME[ext];\n if (fromExt) return fromExt;\n const fromBytes = sniffImageMime(sniffBytes);\n if (fromBytes) return fromBytes;\n if (sniffSvg(sniffBytes)) return SVG_MIME;\n return \"application/octet-stream\";\n}\n\n// Image-generation models can't consume raw SVG markup, so an ingested SVG (e.g. a brand logo) is\n// rasterized to a transparent PNG here. Transparency is kept so the wordmark composites cleanly onto\n// any background downstream.\nexport async function rasterizeSvgToPng(bytes: Buffer): Promise<Buffer> {\n // `sharp` is a native module that can't load in the Convex runtime. This function only runs in the\n // local execLocalFile path (the ingest node is location: \"local\"), so import it lazily — a top-level\n // import would drag the native binary into the Convex bundle and break `convex deploy`.\n const { default: sharp } = await import(\"sharp\");\n const base = await sharp(bytes).metadata();\n const longest = Math.max(base.width ?? 0, base.height ?? 0);\n let density = SVG_BASE_DENSITY;\n if (longest > 0) {\n const scaled = Math.round((SVG_BASE_DENSITY * SVG_TARGET_LONGEST_PX) / longest);\n density = Math.min(SVG_MAX_DENSITY, Math.max(SVG_BASE_DENSITY, scaled));\n }\n return await sharp(bytes, { density }).png({ force: true, palette: false }).toBuffer();\n}\n\n// Image-generation providers (OpenAI, Google, Recraft via OpenRouter) only accept these input\n// formats; a reference in any other format 400s the entire generation with a non-retryable\n// \"not a valid image format\" error.\nconst MODEL_SAFE_IMAGE_MIMES = new Set([\"image/jpeg\", \"image/png\", \"image/gif\", \"image/webp\"]);\n\nexport type ModelSafeImage = { bytes: Buffer; mime: string; rasterizedFrom?: string };\n\n/**\n * Normalize image bytes into a format every image-generation model accepts. Model-safe rasters\n * (jpeg/png/gif/webp) pass through untouched — no re-encode, so quality and animation are preserved.\n * Everything else (SVG, AVIF, HEIC, TIFF, BMP, …) is transcoded to PNG so a downstream reference can\n * never poison a generation. SVG gets the density-aware rasterization (small logos upscaled, alpha\n * kept); other formats go straight through sharp. Throws when the bytes aren't a decodable image at\n * all, so a mis-`expect`ed ingest fails clearly rather than uploading garbage.\n *\n * This lives in the CLI, not the backend, because sharp can't load in the Convex runtime — so the\n * `source: \"url\"` path (backend `direct_fetch`) can't normalize and must route images through here.\n */\nexport async function toModelSafeImage(bytes: Buffer): Promise<ModelSafeImage> {\n const safe = sniffImageMime(bytes);\n if (safe && MODEL_SAFE_IMAGE_MIMES.has(safe)) {\n return { bytes, mime: safe };\n }\n if (sniffSvg(bytes)) {\n return { bytes: await rasterizeSvgToPng(bytes), mime: \"image/png\", rasterizedFrom: \"svg\" };\n }\n const { default: sharp } = await import(\"sharp\");\n try {\n const img = sharp(bytes);\n const format = (await img.metadata()).format;\n const png = await img.png({ force: true }).toBuffer();\n return { bytes: png, mime: \"image/png\", rasterizedFrom: format ?? \"unknown\" };\n } catch (e) {\n throw new Error(`bytes are not a decodable image (${(e as Error).message})`);\n }\n}\n\n/** Whether `buf` carries the exact ASCII string `sig` starting at `offset`. */\nfunction hasAscii(buf: Buffer, offset: number, sig: string): boolean {\n return buf.length >= offset + sig.length && buf.toString(\"ascii\", offset, offset + sig.length) === sig;\n}\n\nconst HEIC_BRANDS = new Set([\"heic\", \"heix\", \"heim\", \"heis\", \"hevc\", \"hevx\", \"mif1\", \"msf1\", \"heif\"]);\n\n/** ISO-BMFF `ftyp` box (bytes 4..8) — the brand at 8..12 splits AVIF from HEIC/HEIF. */\nfunction sniffIsoBmff(buf: Buffer): string | null {\n if (!hasAscii(buf, 4, \"ftyp\")) return null;\n const brand = buf.subarray(8, 12).toString(\"ascii\");\n if (brand === \"avif\" || brand === \"avis\") return \"image/avif\";\n if (HEIC_BRANDS.has(brand)) return \"image/heic\";\n return null;\n}\n\nfunction sniffImageMime(buf: Buffer): string | null {\n if (buf.length < 4) return null;\n if (buf[0] === 0x89 && hasAscii(buf, 1, \"PNG\")) return \"image/png\";\n if (buf[0] === 0xff && buf[1] === 0xd8 && buf[2] === 0xff) return \"image/jpeg\";\n if (hasAscii(buf, 0, \"GIF\")) return \"image/gif\";\n if (hasAscii(buf, 0, \"RIFF\") && hasAscii(buf, 8, \"WEBP\")) return \"image/webp\";\n // TIFF: \"II*\\0\" (little-endian) or \"MM\\0*\" (big-endian).\n if (hasAscii(buf, 0, \"II*\\0\") || hasAscii(buf, 0, \"MM\\0*\")) return \"image/tiff\";\n if (hasAscii(buf, 0, \"BM\")) return \"image/bmp\";\n // Covers HEIC/HEIF/AVIF whose extension is wrong or missing.\n return sniffIsoBmff(buf);\n}\n\n// ISO-BMFF (mp4 / mov / m4v) duration probe. Pure, dependency-free, and runs on\n// the bytes already in memory — so a video ingest can stamp the canonical\n// `VideoRef.duration_ms` without ffprobe (which the engine does not require on\n// PATH). Walks top-level boxes for `moov`, then `mvhd` inside it, and reads the\n// timescale + duration. Returns undefined for anything it can't read (webm, a\n// fragmented/duration-less moov, a truncated header) so the caller degrades to\n// \"duration unknown\" rather than failing the ingest.\n//\n// Box layout: [size:u32 BE][type:ascii4][payload]. size===1 → a u64 `largesize`\n// follows the type; size===0 → the box runs to the end of its parent.\nfunction findBoxPayload(buf: Buffer, start: number, end: number, type: string): { start: number; end: number } | null {\n let offset = start;\n while (offset + 8 <= end) {\n let size = buf.readUInt32BE(offset);\n const boxType = buf.toString(\"ascii\", offset + 4, offset + 8);\n let headerLen = 8;\n if (size === 1) {\n if (offset + 16 > end) return null;\n // largesize is u64; durations here never need >2^53, so Number is safe.\n size = Number(buf.readBigUInt64BE(offset + 8));\n headerLen = 16;\n } else if (size === 0) {\n size = end - offset;\n }\n if (size < headerLen || offset + size > end) return null;\n if (boxType === type) return { start: offset + headerLen, end: offset + size };\n offset += size;\n }\n return null;\n}\n\nconst MVHD_DURATION_UNKNOWN = 0xffffffff;\n\nfunction mp4DurationMs(bytes: Buffer | Uint8Array): number | undefined {\n const buf = Buffer.isBuffer(bytes) ? bytes : Buffer.from(bytes);\n const moov = findBoxPayload(buf, 0, buf.length, \"moov\");\n if (!moov) return undefined;\n const mvhd = findBoxPayload(buf, moov.start, moov.end, \"mvhd\");\n if (!mvhd) return undefined;\n const version = buf[mvhd.start];\n // version byte (1) + flags (3), then v0: creation(4)+modification(4); v1: (8)+(8).\n const tsOffset = mvhd.start + 4 + (version === 1 ? 16 : 8);\n if (version === 1) {\n if (tsOffset + 12 > mvhd.end) return undefined;\n const timescale = buf.readUInt32BE(tsOffset);\n const duration = buf.readBigUInt64BE(tsOffset + 4);\n if (timescale === 0 || duration === 0n) return undefined;\n return Math.round((Number(duration) / timescale) * 1000);\n }\n if (version !== 0) return undefined;\n if (tsOffset + 8 > mvhd.end) return undefined;\n const timescale = buf.readUInt32BE(tsOffset);\n const duration = buf.readUInt32BE(tsOffset + 4);\n if (timescale === 0 || duration === 0 || duration === MVHD_DURATION_UNKNOWN) return undefined;\n return Math.round((duration / timescale) * 1000);\n}\n\nfunction inferKindFromMime(mime: string): AssetKind | null {\n if (mime.startsWith(\"image/\")) return \"image\";\n if (mime.startsWith(\"video/\")) return \"video\";\n if (mime.startsWith(\"audio/\")) return \"audio\";\n if (mime === \"application/json\") return \"json\";\n if (mime.startsWith(\"text/\")) return \"text\";\n if (mime.startsWith(\"font/\")) return \"font\";\n return null;\n}\n\nfunction localExecError(ctx: ExecCtx, message: string): NodeExecutionError {\n return new NodeExecutionError(ctx.nodeId, ctx.nodeType, {\n kind: \"local\",\n cause: new Error(`ingest: ${message}`),\n });\n}\n\nasync function execLocalFile(params: PathParams, ctx: ExecCtx): Promise<AssetRef> {\n const absPath = resolveLocalPath(params.path);\n\n let stats: Stats;\n try {\n stats = await stat(absPath);\n } catch (e) {\n const code = (e as NodeJS.ErrnoException).code;\n if (code === \"ENOENT\") {\n throw localExecError(ctx, `file_not_found: ${absPath}`);\n }\n if (code === \"EACCES\") {\n throw localExecError(ctx, `permission_denied: ${absPath}`);\n }\n throw localExecError(ctx, `stat failed for ${absPath}: ${(e as Error).message}`);\n }\n\n if (!stats.isFile()) {\n throw localExecError(ctx, `not_a_file: ${absPath} (isDirectory=${stats.isDirectory()})`);\n }\n if (stats.size > MAX_ASSET_BYTES) {\n throw localExecError(ctx, `file_too_large: ${absPath} is ${stats.size} bytes (limit ${MAX_ASSET_BYTES})`);\n }\n\n let bytes: Buffer;\n try {\n bytes = await readFile(absPath);\n } catch (e) {\n if ((e as NodeJS.ErrnoException).code === \"EACCES\") {\n throw localExecError(ctx, `permission_denied: ${absPath}`);\n }\n throw localExecError(ctx, `read failed for ${absPath}: ${(e as Error).message}`);\n }\n\n const mime = inferMimeFromPath(absPath, bytes);\n const kind = inferKindFromMime(mime);\n\n if (kind === null) {\n throw localExecError(\n ctx,\n `kind_mismatch: ${absPath} has mime=${mime} which doesn't map to any ingest kind (image/video/audio/text/json/font). If this is a PDF and you want text extraction, host it via URL and use source=\"url\".`,\n );\n }\n if (kind !== params.expect) {\n throw localExecError(ctx, `kind_mismatch: expect=${params.expect} but ${absPath} has mime=${mime} (kind=${kind})`);\n }\n\n ctx.log(`ingest: local file ${stats.size}B mime=${mime}`);\n\n // Normalize any image to a model-safe raster before upload — image-generation models reject SVG,\n // AVIF, HEIC, TIFF, BMP (they read only jpeg/png/gif/webp). The kind check above guarantees\n // expect === \"image\" here; non-image kinds upload verbatim.\n let outBytes = bytes;\n let outMime = mime;\n let rasterizedFrom: string | undefined;\n if (kind === \"image\") {\n const normalized = await toModelSafeImage(bytes);\n outBytes = normalized.bytes;\n outMime = normalized.mime;\n rasterizedFrom = normalized.rasterizedFrom;\n if (rasterizedFrom) ctx.log(`ingest: normalized ${rasterizedFrom} -> PNG (${outBytes.length}B)`);\n }\n\n const durationMs = probeVideoDurationMs(params.expect, outBytes, ctx);\n const ref = await uploadAndIngest({\n bytes: outBytes,\n kind: params.expect,\n mime: outMime,\n metadata: localFileMetadata({ absPath, fileSize: stats.size, mime, durationMs, rasterizedFrom }),\n ctx,\n });\n return withProbedDuration(ref, durationMs);\n}\n\n/**\n * Probe a video's duration from its ISO-BMFF header so downstream nodes (notably\n * video_deconstruct, which sizes its Mux ingest-poll timeout and preflight off\n * the declared duration) don't fall back to their worst-case budgets. Best-effort:\n * undefined for non-video kinds and non-mp4 containers (e.g. webm).\n */\nfunction probeVideoDurationMs(expect: AssetKind, bytes: Buffer, ctx: ExecCtx): number | undefined {\n if (expect !== \"video\") return undefined;\n const durationMs = mp4DurationMs(bytes);\n if (durationMs !== undefined) ctx.log(`ingest: probed video duration ${durationMs}ms`);\n return durationMs;\n}\n\nfunction localFileMetadata(args: {\n absPath: string;\n fileSize: number;\n mime: string;\n durationMs: number | undefined;\n rasterizedFrom: string | undefined;\n}): Record<string, unknown> {\n return {\n source_path: args.absPath,\n strategy: \"local_file\",\n ingested_at: new Date().toISOString(),\n file_size: args.fileSize,\n original_filename: path.basename(args.absPath),\n ...(args.rasterizedFrom ? { rasterized_from: args.rasterizedFrom } : {}),\n ...(args.durationMs !== undefined ? { duration_ms: args.durationMs } : {}),\n };\n}\n\n/**\n * Stamp the canonical top-level VideoRef.duration_ms when known. Consumers read\n * either the field or metadata.duration_ms, so populating both leaves neither\n * convention missing it.\n */\nfunction withProbedDuration(ref: AssetRef, durationMs: number | undefined): AssetRef {\n if (durationMs === undefined || ref.kind !== \"video\") return ref;\n return { ...ref, duration_ms: durationMs };\n}\n\n// ---------------------------------------------------------------------------\n// yt_dlp — runs locally, then uploads to R2 via presign so remote downstream\n// nodes can fetch the asset by URL.\n// ---------------------------------------------------------------------------\n\nconst YT_DLP_BIN = \"yt-dlp\";\nconst YT_DLP_TIMEOUT_MS = 10 * 60 * 1000;\n\nconst YT_DLP_MIME: Record<AssetKind, string> = {\n image: \"image/png\",\n video: \"video/mp4\",\n audio: \"audio/mp4\",\n text: \"text/plain\",\n json: \"application/json\",\n font: \"font/ttf\", // unreachable — resolveStrategy never routes font to yt_dlp\n};\n\nconst YT_DLP_EXT: Record<AssetKind, string> = {\n image: \"png\",\n video: \"mp4\",\n audio: \"m4a\",\n text: \"txt\",\n json: \"json\",\n font: \"ttf\", // unreachable — resolveStrategy never routes font to yt_dlp\n};\n\nasync function execYtDlp(params: UrlParams, ctx: ExecCtx): Promise<AssetRef> {\n if (params.expect !== \"video\" && params.expect !== \"audio\") {\n // resolveStrategy guarantees this, but the runtime branch makes it explicit.\n throw new Error(`ingest: yt_dlp only handles video/audio, got expect=${params.expect}`);\n }\n\n const workDir = await mkdtemp(path.join(tmpdir(), \"ingest-yt-\"));\n try {\n const { filePath, info } = await runYtDlp({\n url: params.url,\n audioOnly: params.expect === \"audio\",\n workDir,\n ctx,\n });\n\n const downloadedStats = await stat(filePath);\n if (downloadedStats.size > MAX_ASSET_BYTES) {\n throw localExecError(\n ctx,\n `file_too_large: yt-dlp output for ${params.url} is ${downloadedStats.size} bytes (limit ${MAX_ASSET_BYTES})`,\n );\n }\n const bytes = await readFile(filePath);\n const kind = params.expect;\n const mime = YT_DLP_MIME[kind];\n const metadata = buildYtDlpMetadata(params.url, info);\n\n return await uploadAndIngest({ bytes, kind, mime, metadata, ctx });\n } finally {\n await rm(workDir, { recursive: true, force: true }).catch((e) => {\n ctx.log(`ingest: tmp cleanup failed (${(e as Error).message})`);\n });\n }\n}\n\ntype YtDlpInfo = Record<string, unknown>;\n\nasync function runYtDlp(args: {\n url: string;\n audioOnly: boolean;\n workDir: string;\n ctx: ExecCtx;\n}): Promise<{ filePath: string; info: YtDlpInfo }> {\n const outTemplate = path.join(args.workDir, \"out.%(ext)s\");\n const infoPath = path.join(args.workDir, \"out.info.json\");\n\n const argv: string[] = [\n args.url,\n \"--no-playlist\",\n \"--no-progress\",\n \"--no-warnings\",\n \"--quiet\",\n \"--write-info-json\",\n \"-o\",\n outTemplate,\n ];\n\n if (args.audioOnly) {\n argv.push(\"-x\", \"--audio-format\", \"m4a\");\n } else {\n argv.push(\"--format\", \"bv*+ba/b\", \"--merge-output-format\", \"mp4\");\n }\n\n args.ctx.log(`ingest: spawning yt-dlp (${args.audioOnly ? \"audio\" : \"video\"})`);\n const { code, stderr } = await spawnAndWait(YT_DLP_BIN, argv, YT_DLP_TIMEOUT_MS);\n if (code !== 0) {\n throw new NodeExecutionError(args.ctx.nodeId, args.ctx.nodeType, {\n kind: \"local\",\n cause: new Error(`yt-dlp exited ${code}\\n${tail(stderr, 40)}`),\n });\n }\n\n const files = await readdir(args.workDir);\n const wanted = args.audioOnly ? \".m4a\" : \".mp4\";\n const downloaded = files.find((f) => f.startsWith(\"out.\") && f.endsWith(wanted));\n if (!downloaded) {\n throw new Error(`ingest: yt-dlp finished but no ${wanted} file in ${args.workDir} (saw: ${files.join(\", \")})`);\n }\n\n let info: YtDlpInfo = {};\n try {\n const raw = await readFile(infoPath, \"utf-8\");\n info = JSON.parse(raw) as YtDlpInfo;\n } catch {\n // info.json is best-effort — yt-dlp sometimes omits it for direct file URLs.\n }\n\n return { filePath: path.join(args.workDir, downloaded), info };\n}\n\nfunction buildYtDlpMetadata(sourceUrl: string, info: YtDlpInfo): Record<string, unknown> {\n const out: Record<string, unknown> = {\n source_url: sourceUrl,\n strategy: \"yt_dlp\",\n ingested_at: new Date().toISOString(),\n };\n if (typeof info.title === \"string\") out.original_title = info.title;\n if (typeof info.uploader === \"string\") out.original_uploader = info.uploader;\n if (typeof info.duration === \"number\") out.original_duration_s = info.duration;\n if (typeof info.webpage_url === \"string\") out.webpage_url = info.webpage_url;\n if (typeof info.width === \"number\") out.width = info.width;\n if (typeof info.height === \"number\") out.height = info.height;\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// R2 upload + local ingest\n// ---------------------------------------------------------------------------\n\nexport async function uploadAndIngest(args: {\n bytes: Buffer;\n kind: AssetKind;\n mime: string;\n metadata: Record<string, unknown>;\n ctx: ExecCtx;\n}): Promise<AssetRef> {\n const sha = sha256Hex(args.bytes);\n const publicUrl = await presignAndPut({ bytes: args.bytes, sha256: sha, mime: args.mime, ctx: args.ctx });\n\n const localRef = await args.ctx.assets.ingestBytes({\n bytes: args.bytes,\n kind: args.kind,\n mime: args.mime,\n metadata: args.metadata,\n });\n // ingestBytes leaves url undefined (LocalAssetStore is local-only). Overlay\n // the public R2 URL so remote downstream nodes can pull this asset.\n return { ...localRef, url: publicUrl } as AssetRef;\n}\n\n// ---------------------------------------------------------------------------\n// Spawn helper (local copy — cli-runner.ts rejects URL args by policy, which\n// directly conflicts with yt-dlp's job)\n// ---------------------------------------------------------------------------\n\ntype SpawnResult = { code: number; stderr: string };\n\nfunction spawnAndWait(bin: string, argv: readonly string[], timeoutMs: number): Promise<SpawnResult> {\n return new Promise((resolve, reject) => {\n const child = spawn(bin, argv, { stdio: [\"ignore\", \"pipe\", \"pipe\"] });\n const stderrChunks: Buffer[] = [];\n let stderrLen = 0;\n const MAX_STDERR = 256 * 1024;\n\n child.stdout.on(\"data\", () => {\n // discard\n });\n child.stderr.on(\"data\", (chunk: Buffer) => {\n if (stderrLen < MAX_STDERR) {\n stderrChunks.push(chunk);\n stderrLen += chunk.length;\n }\n });\n\n const timer = setTimeout(() => {\n child.kill(\"SIGKILL\");\n reject(new Error(`ingest: ${bin} timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n\n child.on(\"error\", (err) => {\n clearTimeout(timer);\n reject(new Error(`ingest: failed to spawn \"${bin}\" — ${err.message}`));\n });\n\n child.on(\"close\", (code) => {\n clearTimeout(timer);\n resolve({ code: code ?? -1, stderr: Buffer.concat(stderrChunks).toString(\"utf8\") });\n });\n });\n}\n\nfunction tail(text: string, maxLines: number): string {\n const lines = text.split(\"\\n\");\n return lines.slice(-maxLines).join(\"\\n\");\n}\n\n// Fold yt-dlp version into the cache key so upgrades bust cache automatically.\nasync function ytDlpVersion(): Promise<string> {\n try {\n const { stdout } = await execFile(YT_DLP_BIN, [\"--version\"], { encoding: \"utf-8\", maxBuffer: 64 * 1024 });\n return stdout.trim();\n } catch {\n return \"yt-dlp:unknown\";\n }\n}\n\n// Attach cacheKeyExtras after definition so the helper can be referenced.\ningestNode.cacheKeyExtras = async ({ params }): Promise<Record<string, string>> => {\n const p = params as { source?: unknown; url?: unknown; path?: unknown; expect?: unknown };\n const extras: Record<string, string> = {};\n\n // For source=path: fold mtime+size into the cache key so editing the file\n // invalidates the cache automatically. Failures (missing file, perms) are\n // silently swallowed — execute will surface them with full context.\n if (p.source === \"path\" && typeof p.path === \"string\") {\n try {\n const abs = resolveLocalPath(p.path);\n const s = await stat(abs);\n extras.local_file_signature = `${s.mtimeMs}:${s.size}`;\n } catch {\n // ignore — execute will fail clearly\n }\n }\n\n // For source=url with yt_dlp strategy: fold tool version so upgrades bust cache.\n if (p.source === \"url\" && (p.expect === \"video\" || p.expect === \"audio\")) {\n extras.yt_dlp_version = await ytDlpVersion();\n }\n\n return extras;\n};\n\n// Exported for unit tests.\nexport const _internal = {\n resolveStrategy,\n resolveLocalPath,\n inferMimeFromPath,\n inferKindFromMime,\n mp4DurationMs,\n buildYtDlpMetadata,\n YT_DLP_EXT,\n YT_DLP_MIME,\n EXT_TO_MIME,\n};\n","import { z } from \"zod\";\nimport { MimeType, Sha256Hex } from \"./primitives.ts\";\n\nconst BaseAssetRef = z.object({\n url: z.string().url().optional(),\n path: z.string().optional(),\n sha256: Sha256Hex,\n mime: MimeType,\n metadata: z.record(z.string(), z.unknown()).optional(),\n});\n\nexport const ImageRef = BaseAssetRef.extend({\n kind: z.literal(\"image\"),\n width: z.number().int().positive().optional(),\n height: z.number().int().positive().optional(),\n});\nexport type ImageRef = z.infer<typeof ImageRef>;\n\nexport const VideoRef = BaseAssetRef.extend({\n kind: z.literal(\"video\"),\n width: z.number().int().positive().optional(),\n height: z.number().int().positive().optional(),\n duration_ms: z.number().nonnegative().optional(),\n});\nexport type VideoRef = z.infer<typeof VideoRef>;\n\nexport const AudioRef = BaseAssetRef.extend({\n kind: z.literal(\"audio\"),\n duration_ms: z.number().nonnegative().optional(),\n});\nexport type AudioRef = z.infer<typeof AudioRef>;\n\nexport const JsonRef = BaseAssetRef.extend({\n kind: z.literal(\"json\"),\n});\nexport type JsonRef = z.infer<typeof JsonRef>;\n\nexport const TextRef = BaseAssetRef.extend({\n kind: z.literal(\"text\"),\n});\nexport type TextRef = z.infer<typeof TextRef>;\n\nexport const FontRef = BaseAssetRef.extend({\n kind: z.literal(\"font\"),\n});\nexport type FontRef = z.infer<typeof FontRef>;\n\nexport const AssetRef = z.discriminatedUnion(\"kind\", [ImageRef, VideoRef, AudioRef, JsonRef, TextRef, FontRef]);\nexport type AssetRef = z.infer<typeof AssetRef>;\n\nexport type AssetKind = AssetRef[\"kind\"];\n","import { z } from \"zod\";\n\nexport const Sha256Hex = z.string().regex(/^[0-9a-f]{64}$/, \"expected 64-char lower-case hex sha-256\");\nexport type Sha256Hex = z.infer<typeof Sha256Hex>;\n\nexport const MimeType = z.string().regex(/^[a-zA-Z0-9!#$&^_.+-]+\\/[a-zA-Z0-9!#$&^_.+-]+$/, \"expected RFC 6838 mime\");\nexport type MimeType = z.infer<typeof MimeType>;\n","import type { RawAssetOutput } from \"../../client/backend-client.ts\";\nimport { BackendHttpError } from \"../../client/http.ts\";\nimport type { ExecCtx } from \"../../engine/context.ts\";\nimport type { NodeDefinition } from \"../../engine/define.ts\";\nimport { resolveOutputKinds } from \"../../engine/define.ts\";\nimport { NodeExecutionError } from \"../../engine/errors.ts\";\nimport type { AssetRef } from \"../../schema/refs.ts\";\nimport { buildRef } from \"../../storage/asset-store.ts\";\nimport { ensureUploaded } from \"./upload.ts\";\n\ntype RemoteSpec<I, P, O> = Omit<NodeDefinition<I, P, O>, \"execute\" | \"location\">;\n\n/**\n * Build a `defineNode`-shaped remote node that POSTs to /api/canvas/nodes/exec\n * and ingests any returned asset bytes locally via ctx.assets.ingestRemote.\n */\nexport function delegated<I, P, O>(spec: RemoteSpec<I, P, O>): NodeDefinition<I, P, O> {\n return {\n ...spec,\n location: \"remote\",\n execute: async ({ inputs, params, ctx }) => {\n return (await callBackendExec({\n nodeType: spec.id,\n nodeVersion: spec.version,\n params,\n inputs,\n outputKinds: resolveOutputKinds(spec.outputKinds, params),\n ctx,\n })) as O;\n },\n };\n}\n\n/**\n * Shared \"POST to /api/canvas/nodes/exec and ingest the returned assets\"\n * pipeline. Used by `delegated()` for remote nodes, and by the `ingest` node\n * which dispatches its `direct_fetch` and `handinger` strategies through the\n * same backend channel even though the node itself is registered as local.\n */\nexport async function callBackendExec(args: {\n nodeType: string;\n nodeVersion: string;\n params: unknown;\n inputs: unknown;\n outputKinds: Record<string, AssetRef[\"kind\"]>;\n ctx: ExecCtx;\n}): Promise<Record<string, unknown>> {\n try {\n const serialized = await serializeInputs(args.inputs, args.ctx);\n // Scoped to the run so a deliberate re-run (e.g. cache bypass) generates\n // fresh, while HTTP-level retries within one execution replay the stored\n // backend response instead of dispatching (and charging) twice.\n const idempotencyKey = args.ctx.cacheKey ? `${args.ctx.canvasRunId}:${args.ctx.cacheKey}` : undefined;\n const res = await args.ctx.client.exec(\n {\n nodeType: args.nodeType,\n nodeVersion: args.nodeVersion,\n params: args.params,\n inputs: serialized,\n idempotency_key: idempotencyKey,\n canvas_run_id: args.ctx.canvasRunId,\n node_id: args.ctx.nodeId,\n },\n args.ctx.signal,\n );\n return await ingestOutputs(res.outputs, args.ctx, args.outputKinds);\n } catch (e) {\n throw mapClientError(args.ctx, e);\n }\n}\n\nasync function serializeInputs(inputs: unknown, ctx: ExecCtx): Promise<Record<string, unknown>> {\n if (!inputs || typeof inputs !== \"object\") return {};\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(inputs as Record<string, unknown>)) {\n out[k] = await stripLocalRefs(v, ctx);\n }\n return out;\n}\n\nasync function stripLocalRefs(value: unknown, ctx: ExecCtx): Promise<unknown> {\n if (Array.isArray(value)) return Promise.all(value.map((v) => stripLocalRefs(v, ctx)));\n if (value && typeof value === \"object\") {\n if (\"kind\" in value && \"sha256\" in value && \"mime\" in value) {\n // A local-node output (ffmpeg/magick via runCli) has `path` but no `url`.\n // Upload it to R2 first so the remote backend can fetch it — otherwise it\n // receives `url: undefined` and rejects the input. Idempotent for refs\n // that already carry a `url` (ingest/remote outputs).\n const ref = await ensureUploaded(value as AssetRef, ctx);\n // Strip local-only `path` and pass through what the backend can consume.\n return {\n kind: ref.kind,\n url: ref.url,\n sha256: ref.sha256,\n mime: ref.mime,\n metadata: ref.metadata,\n };\n }\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) out[k] = await stripLocalRefs(v, ctx);\n return out;\n }\n return value;\n}\n\nasync function ingestOutputs(\n outputs: Record<string, unknown>,\n ctx: ExecCtx,\n kinds: Record<string, AssetRef[\"kind\"]>,\n): Promise<Record<string, unknown>> {\n const result: Record<string, unknown> = {};\n for (const [name, value] of Object.entries(outputs)) {\n const declaredKind = kinds[name];\n result[name] = await ingestValue(value, ctx, declaredKind);\n }\n return result;\n}\n\nasync function ingestValue(value: unknown, ctx: ExecCtx, declaredKind?: AssetRef[\"kind\"]): Promise<unknown> {\n if (Array.isArray(value)) {\n const out: unknown[] = [];\n for (const v of value) out.push(await ingestValue(v, ctx, declaredKind));\n return out;\n }\n if (isRawAsset(value)) {\n const kind = value.kind ?? declaredKind ?? \"json\";\n // No local consumer needs the bytes on disk: the backend already computed\n // the sha256 and persisted a durable R2 URL, so skip the redundant\n // R2→sandbox download and keep the ref URL-only (no local `path`). The run\n // record still works — `isPersistedAssetRef` is true for a canvas-assets URL.\n if (ctx.downloadOutputs === false) {\n // Match the shape `ingestRemote` would have produced (top-level\n // width/height/duration_ms hoisted from metadata) so downstream consumers\n // that read those fields are unaffected — just without the local `path`.\n return buildRef({ kind, sha: value.sha256, mime: value.mime, url: value.url, metadata: value.metadata });\n }\n return ctx.assets.ingestRemote({\n kind,\n url: value.url,\n sha256: value.sha256,\n mime: value.mime,\n metadata: value.metadata,\n });\n }\n return value;\n}\n\nfunction isRawAsset(v: unknown): v is RawAssetOutput {\n return Boolean(\n v &&\n typeof v === \"object\" &&\n \"url\" in v &&\n \"sha256\" in v &&\n \"mime\" in v &&\n typeof (v as { url: unknown }).url === \"string\" &&\n typeof (v as { sha256: unknown }).sha256 === \"string\",\n );\n}\n\nfunction mapClientError(ctx: ExecCtx, e: unknown): Error {\n if (e instanceof BackendHttpError) {\n const d = e.detail;\n if (d.kind === \"provider\") {\n return new NodeExecutionError(ctx.nodeId, ctx.nodeType, {\n kind: \"remote\",\n status: d.status,\n code: d.code,\n message: d.message,\n provider: d.provider,\n // The backend's real classification — providerErr pins the status to 502,\n // so this flag (not the status) is the source of truth for retryability.\n retryable: d.retryable,\n });\n }\n if (d.kind === \"content_policy\") {\n return new NodeExecutionError(ctx.nodeId, ctx.nodeType, {\n kind: \"content_policy\",\n provider: d.provider,\n message: d.message,\n });\n }\n if (d.kind === \"timeout\") {\n return new NodeExecutionError(ctx.nodeId, ctx.nodeType, { kind: \"timeout\", provider: d.provider });\n }\n if (d.kind === \"validation\") {\n return new NodeExecutionError(ctx.nodeId, ctx.nodeType, {\n kind: \"remote\",\n status: d.status,\n code: \"invalid_params\",\n message: d.message,\n });\n }\n if (d.kind === \"unauthorized\") {\n return new NodeExecutionError(ctx.nodeId, ctx.nodeType, {\n kind: \"remote\",\n status: d.status,\n code: \"unauthorized\",\n message: d.message,\n });\n }\n if (d.kind === \"network\") {\n return new NodeExecutionError(ctx.nodeId, ctx.nodeType, { kind: \"network\", cause: d.cause });\n }\n return new NodeExecutionError(ctx.nodeId, ctx.nodeType, {\n kind: \"remote\",\n status: d.status,\n code: \"server_error\",\n message: d.message,\n });\n }\n return new NodeExecutionError(ctx.nodeId, ctx.nodeType, { kind: \"local\", cause: e });\n}\n","import { z } from \"zod\";\nimport { defineNode } from \"../../engine/define.ts\";\nimport type { AssetRef } from \"../../schema/refs.ts\";\nimport { getToolVersion, runCli } from \"./lib/cli-runner.ts\";\n\nconst FFMPEG_BIN = \"ffmpeg\";\n\nconst FORMAT_EXT = { mp3: \"mp3\", wav: \"wav\", m4a: \"m4a\" } as const;\nconst FORMAT_CODEC = { mp3: \"libmp3lame\", wav: \"pcm_s16le\", m4a: \"aac\" } as const;\n\nconst Track = z\n .object({\n /** Input slot name (must match a wired `inputs.<slot>` audio ref). */\n slot: z.string().min(1),\n /** When this track starts on the timeline, seconds from 0. */\n start_s: z.number().min(0),\n /**\n * Optional hard cap on this track's length, seconds. The clip is trimmed BEFORE\n * placement, so a source that runs long (an over-long voice extract, a converted\n * track that came back oversized) cannot bleed into the next track's window.\n */\n duration_s: z.number().positive().optional(),\n /** Optional level adjustment in dB (negative ducks, e.g. a music bed at -12). */\n gain_db: z.number().optional(),\n })\n .strict();\n\n/**\n * Sidechain-duck one track (a music bed) under one or more key tracks (the voice):\n * whenever the key tracks carry signal, the ducked track's level drops, then recovers\n * in the gaps. Makes a music bed sit *dynamically* under speech instead of at a flat\n * level. `threshold` is linear 0–1 (lower = ducks more readily), `ratio` the\n * compression amount, `attack`/`release` in ms.\n */\nconst DuckSpec = z\n .object({\n track: z.string().min(1),\n against: z.array(z.string().min(1)).min(1),\n threshold: z.number().min(0).max(1).optional(),\n ratio: z.number().min(1).max(20).optional(),\n attack: z.number().min(0.01).optional(),\n release: z.number().min(0.01).optional(),\n })\n .strict();\n\nconst AudioTimelineParams = z\n .object({\n tracks: z.array(Track).min(1),\n /** Final track length in ms — pads short / trims long. Defaults to the natural mix length. */\n total_ms: z.number().int().positive().optional(),\n output_format: z.enum([\"mp3\", \"wav\", \"m4a\"]).optional(),\n /** Optional sidechain duck of one track under others (e.g. music under voice). */\n duck: DuckSpec.optional(),\n })\n .strict();\n\ntype AudioTimelineParamsT = z.infer<typeof AudioTimelineParams>;\n\nconst AudioTimelineInputs = z.record(z.string(), z.unknown());\nconst AudioTimelineOutputs = z.object({ audio: z.custom<AssetRef>() }).strict();\n\n/**\n * Build the ffmpeg argv for an audio timeline: one `-i` per track (in order,\n * so track i is ffmpeg input i), an `adelay` (+ optional `volume`) per track\n * to place it, an `amix` to combine them (`normalize=0` preserves the relative\n * levels set via `gain_db`), and an optional `apad`+`atrim` to pin the final\n * length. Pure + deterministic so it unit-tests without ffmpeg.\n */\n/**\n * Sidechain-duck `duck.track` under `duck.against` IN PLACE: split each key label into a\n * mix-copy + key-copy, combine the keys, and compress the ducked track against them.\n * Rewrites the relevant `labelFor` entries (music → ducked, each key → its mix-copy) and\n * appends to `filterChains`. No-op when the named slots aren't present (validated upstream).\n */\nfunction applyDuck(params: AudioTimelineParamsT, labelFor: string[], filterChains: string[]): void {\n const duck = params.duck;\n if (!duck) return;\n const trackIdx = params.tracks.findIndex((t) => t.slot === duck.track);\n const keyIdxs = duck.against.map((s) => params.tracks.findIndex((t) => t.slot === s)).filter((i) => i >= 0);\n if (trackIdx < 0 || keyIdxs.length === 0) return;\n\n const keyLabels: string[] = [];\n for (const ki of keyIdxs) {\n const base = labelFor[ki];\n filterChains.push(`[${base}]asplit=2[${base}m][${base}k]`);\n labelFor[ki] = `${base}m`;\n keyLabels.push(`[${base}k]`);\n }\n let keyOut = keyLabels[0] as string;\n if (keyLabels.length > 1) {\n filterChains.push(`${keyLabels.join(\"\")}amix=inputs=${keyLabels.length}:normalize=0[duckkey]`);\n keyOut = \"[duckkey]\";\n }\n const th = duck.threshold ?? 0.03;\n const ra = duck.ratio ?? 8;\n const at = duck.attack ?? 5;\n const re = duck.release ?? 300;\n filterChains.push(\n `[${labelFor[trackIdx]}]${keyOut}sidechaincompress=threshold=${th}:ratio=${ra}:attack=${at}:release=${re}[ducked]`,\n );\n labelFor[trackIdx] = \"ducked\";\n}\n\nexport function buildAudioTimelineArgs(params: AudioTimelineParamsT): string[] {\n const fmt = params.output_format ?? \"mp3\";\n const inputArgs: string[] = [];\n const filterChains: string[] = [];\n // track index → the filter label that carries it into the final amix. Sidechain\n // ducking rewrites a couple of these (the music label → its ducked copy, each key\n // label → its split mix-copy) without changing the per-track placement chains.\n const labelFor: string[] = [];\n params.tracks.forEach((track, i) => {\n inputArgs.push(\"-i\", `{{in.${track.slot}}}`);\n const delayMs = Math.round(track.start_s * 1000);\n // The cap trims BEFORE the delay so it bounds the clip itself, not the timeline.\n const steps = [\n ...(track.duration_s !== undefined ? [`atrim=0:${track.duration_s}`] : []),\n `adelay=${delayMs}:all=1`,\n ];\n if (track.gain_db !== undefined) steps.push(`volume=${track.gain_db}dB`);\n const label = `a${i}`;\n filterChains.push(`[${i}:a]${steps.join(\",\")}[${label}]`);\n labelFor[i] = label;\n });\n\n applyDuck(params, labelFor, filterChains);\n\n const mixLabels = labelFor.map((l) => `[${l}]`);\n let graph = `${filterChains.join(\";\")};${mixLabels.join(\"\")}amix=inputs=${params.tracks.length}:normalize=0`;\n if (params.total_ms !== undefined) {\n const totalS = params.total_ms / 1000;\n graph += `[mixed];[mixed]apad,atrim=0:${totalS}`;\n }\n graph += \"[out]\";\n\n return [...inputArgs, \"-filter_complex\", graph, \"-map\", \"[out]\", \"-c:a\", FORMAT_CODEC[fmt], \"{{out.audio}}\"];\n}\n\nexport const audioTimelineNode = defineNode({\n id: \"audio_timeline\",\n version: \"1.2.0\",\n category: \"audio\",\n location: \"local\",\n summary:\n \"Place and mix several audio clips onto one timeline: each track starts at a given second (optionally level-adjusted in dB), then they're combined into a single track. Built for laying a music bed plus timed voiceover lines and sound effects under a video.\",\n when_to_use:\n \"Use to assemble a full audio bed from separately-generated clips — e.g. a `music` bed at 0 (ducked via `gain_db: -12`), each scene's `tts` voiceover at its scene start, and `sound_effect` hits at their timestamps. Wire each clip as `inputs.<slot>` (audio AssetRef) and list it in `params.tracks` with `{slot, start_s, duration_s?, gain_db?}` (`duration_s` hard-caps a clip so it can't bleed into the next track's window). Set `total_ms` to pin the final length to the video. Requires `ffmpeg` on PATH.\",\n inputs: AudioTimelineInputs,\n params: AudioTimelineParams,\n outputs: AudioTimelineOutputs,\n // The mixed timeline is an audio asset — declare it so strictly-typed consumers\n // (e.g. audio_voice_convert reading a merged per-speaker track) resolve its kind.\n outputKinds: { audio: \"audio\" },\n cost: () => ({ credits: 0, seconds_estimate: 10 }),\n\n validateExtra({ rawParams, rawInputs }) {\n const issues: Array<{ path: string; message: string }> = [];\n const parsed = AudioTimelineParams.safeParse(rawParams ?? {});\n if (!parsed.success) return issues; // shape errors already surfaced by the param validator\n const inputKeys = new Set(Object.keys((rawInputs as Record<string, unknown>) ?? {}));\n parsed.data.tracks.forEach((track, i) => {\n if (!inputKeys.has(track.slot)) {\n issues.push({\n path: `params.tracks[${i}].slot`,\n message: `track slot \"${track.slot}\" has no matching wired input — add inputs.${track.slot}`,\n });\n }\n });\n const duck = parsed.data.duck;\n if (duck) {\n const slots = new Set(parsed.data.tracks.map((t) => t.slot));\n if (!slots.has(duck.track)) {\n issues.push({ path: \"params.duck.track\", message: `duck.track \"${duck.track}\" is not one of the tracks` });\n }\n duck.against.forEach((s, k) => {\n if (!slots.has(s)) {\n issues.push({ path: `params.duck.against[${k}]`, message: `duck.against \"${s}\" is not one of the tracks` });\n }\n if (s === duck.track) {\n issues.push({ path: `params.duck.against[${k}]`, message: \"a track cannot duck against itself\" });\n }\n });\n }\n return issues;\n },\n\n async cacheKeyExtras() {\n return { ffmpeg_version: await getToolVersion(FFMPEG_BIN) };\n },\n\n async execute({ inputs, params, ctx }) {\n return await runCli({\n bin: FFMPEG_BIN,\n args: buildAudioTimelineArgs(params),\n inputs: inputs as Record<string, AssetRef | AssetRef[]>,\n outputs: { audio: { kind: \"audio\", ext: FORMAT_EXT[params.output_format ?? \"mp3\"] } },\n ctx,\n });\n },\n});\n","import { execFile as execFileCb, spawn } from \"node:child_process\";\nimport { copyFile, mkdtemp, readFile, rm, stat } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport path from \"node:path\";\nimport { promisify } from \"node:util\";\nimport type { ExecCtx } from \"../../../engine/context.ts\";\nimport type { AssetKind, AssetRef } from \"../../../schema/refs.ts\";\n\nconst execFile = promisify(execFileCb);\n\ntype CliOutputSpec = {\n kind: AssetKind;\n ext: string;\n};\n\ntype RunCliArgs = {\n /** Binary to spawn (must be on PATH). */\n bin: string;\n /** argv list with `{{in.<slot>}}` and `{{out.<name>}}` placeholders. */\n args: readonly string[];\n /** Input slots — each becomes `{{in.<slot>}}` (single asset) or `{{in.<slot>.<index>}}` (array). */\n inputs: Record<string, AssetRef | AssetRef[]>;\n /** Output declarations — each becomes `{{out.<name>}}`; engine allocates the path. */\n outputs: Record<string, CliOutputSpec>;\n ctx: ExecCtx;\n /** Process timeout. Default: 10 minutes. */\n timeoutMs?: number;\n};\n\nconst DEFAULT_TIMEOUT_MS = 10 * 60 * 1000;\n\nconst URL_SCHEME_RE = /^[a-zA-Z][a-zA-Z0-9+.-]*:\\/\\//;\n\nconst MIME_BY_EXT: Record<string, string> = {\n png: \"image/png\",\n jpg: \"image/jpeg\",\n jpeg: \"image/jpeg\",\n webp: \"image/webp\",\n gif: \"image/gif\",\n avif: \"image/avif\",\n mp4: \"video/mp4\",\n webm: \"video/webm\",\n mov: \"video/quicktime\",\n mp3: \"audio/mpeg\",\n wav: \"audio/wav\",\n m4a: \"audio/mp4\",\n ogg: \"audio/ogg\",\n flac: \"audio/flac\",\n};\n\nfunction mimeForExt(ext: string): string {\n const clean = ext.startsWith(\".\") ? ext.slice(1) : ext;\n return MIME_BY_EXT[clean.toLowerCase()] ?? \"application/octet-stream\";\n}\n\nfunction extForAssetRef(ref: AssetRef): string {\n // Prefer the on-disk extension if we have a local path; fall back to mime.\n if (ref.path) {\n const e = path.extname(ref.path);\n if (e) return e;\n }\n const reverse: Record<string, string> = {\n \"image/png\": \".png\",\n \"image/jpeg\": \".jpg\",\n \"image/webp\": \".webp\",\n \"video/mp4\": \".mp4\",\n \"video/webm\": \".webm\",\n \"video/quicktime\": \".mov\",\n \"audio/mpeg\": \".mp3\",\n \"audio/wav\": \".wav\",\n \"audio/mp4\": \".m4a\",\n \"audio/ogg\": \".ogg\",\n };\n return reverse[ref.mime] ?? \".bin\";\n}\n\n/**\n * Build the placeholder → absolute-path lookup table for one node invocation.\n * - Single AssetRef inputs register as `in.<slot>`.\n * - Array AssetRef inputs register each element as `in.<slot>.<index>`.\n * - Declared outputs register as `out.<name>`.\n *\n * Returns the lookup table plus the list of staged input paths and allocated\n * output paths so the caller can copy/read them.\n */\ntype Placeholders = {\n lookup: Map<string, string>;\n stagedInputs: { srcPath: string; destPath: string }[];\n outputPaths: { name: string; absPath: string; spec: CliOutputSpec }[];\n};\n\nfunction planArrayInputSlot(\n tmpDir: string,\n slot: string,\n values: AssetRef[],\n lookup: Map<string, string>,\n stagedInputs: Placeholders[\"stagedInputs\"],\n): void {\n for (let i = 0; i < values.length; i++) {\n const ref = values[i];\n if (!ref) continue;\n if (!ref.path) throw new Error(`cli-runner: inputs.${slot}[${i}] has no local path`);\n const dest = path.join(tmpDir, `in_${slot}_${i}${extForAssetRef(ref)}`);\n stagedInputs.push({ srcPath: ref.path, destPath: dest });\n lookup.set(`in.${slot}.${i}`, dest);\n }\n}\n\nfunction planSingleInputSlot(\n tmpDir: string,\n slot: string,\n ref: AssetRef,\n lookup: Map<string, string>,\n stagedInputs: Placeholders[\"stagedInputs\"],\n): void {\n if (!ref.path) throw new Error(`cli-runner: inputs.${slot} has no local path`);\n const dest = path.join(tmpDir, `in_${slot}${extForAssetRef(ref)}`);\n stagedInputs.push({ srcPath: ref.path, destPath: dest });\n lookup.set(`in.${slot}`, dest);\n}\n\nfunction planOutputs(\n tmpDir: string,\n outputs: Record<string, CliOutputSpec>,\n lookup: Map<string, string>,\n): Placeholders[\"outputPaths\"] {\n const outputPaths: Placeholders[\"outputPaths\"] = [];\n for (const [name, spec] of Object.entries(outputs)) {\n const ext = spec.ext.startsWith(\".\") ? spec.ext : `.${spec.ext}`;\n const absPath = path.join(tmpDir, `out_${name}${ext}`);\n outputPaths.push({ name, absPath, spec });\n lookup.set(`out.${name}`, absPath);\n }\n return outputPaths;\n}\n\nfunction planPlaceholders(\n tmpDir: string,\n inputs: Record<string, AssetRef | AssetRef[]>,\n outputs: Record<string, CliOutputSpec>,\n): Placeholders {\n const lookup = new Map<string, string>();\n const stagedInputs: Placeholders[\"stagedInputs\"] = [];\n\n for (const [slot, value] of Object.entries(inputs)) {\n if (Array.isArray(value)) {\n planArrayInputSlot(tmpDir, slot, value, lookup, stagedInputs);\n } else {\n planSingleInputSlot(tmpDir, slot, value, lookup, stagedInputs);\n }\n }\n\n const outputPaths = planOutputs(tmpDir, outputs, lookup);\n return { lookup, stagedInputs, outputPaths };\n}\n\nconst PLACEHOLDER_RE = /\\{\\{\\s*([a-zA-Z0-9_.]+)\\s*\\}\\}/g;\n\n/**\n * Substitute `{{in.X}}` / `{{out.Y}}` placeholders in a single arg string.\n * Returns the new string and the set of placeholder keys it consumed.\n * Throws if a placeholder isn't in the lookup.\n */\nfunction substituteArg(arg: string, lookup: Map<string, string>): string {\n return arg.replace(PLACEHOLDER_RE, (_match, key: string) => {\n const value = lookup.get(key);\n if (value === undefined) {\n throw new Error(\n `cli-runner: unknown placeholder \"{{${key}}}\" — declared inputs/outputs: ${[...lookup.keys()].join(\", \")}`,\n );\n }\n return value;\n });\n}\n\n/**\n * After substitution, reject arg strings that look like raw filesystem paths\n * outside our staging dir, or URL inputs. The threat model is \"trusted local\n * canvas shouldn't accidentally reach outside the engine's content-addressed\n * world.\" Args that resolve to staging-dir paths via placeholders pass cleanly.\n */\nfunction rejectRawPaths(substituted: string, original: string, stagingDir: string): void {\n // URL schemes — block ffmpeg/magick from fetching arbitrary http/file/data inputs.\n if (URL_SCHEME_RE.test(substituted)) {\n throw new Error(\n `cli-runner: URL-style arg \"${original}\" not allowed — ingest the asset upstream (e.g. via the ingest node) and wire it as an input slot.`,\n );\n }\n // Home-relative — never allow.\n if (substituted.startsWith(\"~/\") || substituted === \"~\") {\n throw new Error(`cli-runner: home-relative path \"${original}\" not allowed in args.`);\n }\n // Absolute paths must live under the staging dir.\n if (substituted.startsWith(\"/\")) {\n const resolved = path.resolve(substituted);\n if (!resolved.startsWith(`${stagingDir}${path.sep}`) && resolved !== stagingDir) {\n throw new Error(\n `cli-runner: raw filesystem path \"${original}\" not allowed — declare an input slot and use {{in.<slot>}} instead.`,\n );\n }\n }\n // Relative path tokens — `./foo`, `../foo` — block.\n if (substituted.startsWith(\"./\") || substituted.startsWith(\"../\")) {\n throw new Error(`cli-runner: relative path \"${original}\" not allowed in args.`);\n }\n}\n\nasync function stageInputs(staged: Placeholders[\"stagedInputs\"]): Promise<void> {\n for (const { srcPath, destPath } of staged) {\n await copyFile(srcPath, destPath);\n }\n}\n\ntype SpawnResult = { code: number; stderr: string };\n\nfunction spawnAndWait(bin: string, args: readonly string[], timeoutMs: number): Promise<SpawnResult> {\n return new Promise((resolve, reject) => {\n const child = spawn(bin, args, { stdio: [\"ignore\", \"pipe\", \"pipe\"] });\n const stderrChunks: Buffer[] = [];\n let stderrLen = 0;\n const MAX_STDERR = 256 * 1024;\n\n child.stdout.on(\"data\", () => {\n // Discard stdout — large CLI tools can flood it; we surface stderr on failure.\n });\n child.stderr.on(\"data\", (chunk: Buffer) => {\n if (stderrLen < MAX_STDERR) {\n stderrChunks.push(chunk);\n stderrLen += chunk.length;\n }\n });\n\n const timer = setTimeout(() => {\n child.kill(\"SIGKILL\");\n reject(new Error(`cli-runner: ${bin} timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n\n child.on(\"error\", (err) => {\n clearTimeout(timer);\n reject(new Error(`cli-runner: failed to spawn \"${bin}\" — ${err.message}`));\n });\n\n child.on(\"close\", (code) => {\n clearTimeout(timer);\n const stderr = Buffer.concat(stderrChunks).toString(\"utf8\");\n resolve({ code: code ?? -1, stderr });\n });\n });\n}\n\nfunction tailLines(text: string, maxLines: number): string {\n const lines = text.split(\"\\n\");\n return lines.slice(-maxLines).join(\"\\n\");\n}\n\n/**\n * Run a local CLI binary with engine-staged inputs and engine-allocated outputs.\n *\n * Contract:\n * - `args` are passed as argv (no shell). `{{in.<slot>}}` / `{{out.<name>}}`\n * placeholders are substituted with absolute paths under a per-node tmp dir.\n * - After substitution, raw filesystem paths and URL-style inputs are rejected.\n * - Every declared `outputs` entry must exist and be non-empty after exit.\n * - Outputs are ingested into the asset store as the declared `kind`.\n * - Tmp dir is removed in `finally`.\n */\nexport async function runCli(opts: RunCliArgs): Promise<Record<string, AssetRef>> {\n const { bin, args, inputs, outputs, ctx, timeoutMs = DEFAULT_TIMEOUT_MS } = opts;\n\n const tmpDir = await mkdtemp(path.join(tmpdir(), `cli-${bin.replace(/[^a-z0-9]/gi, \"\")}-`));\n try {\n const { lookup, stagedInputs, outputPaths } = planPlaceholders(tmpDir, inputs, outputs);\n await stageInputs(stagedInputs);\n ctx.log(`staged ${stagedInputs.length} inputs in ${tmpDir}`);\n\n const substituted = args.map((arg) => {\n const next = substituteArg(arg, lookup);\n rejectRawPaths(next, arg, tmpDir);\n return next;\n });\n\n ctx.log(`running ${bin} (${substituted.length} args)`);\n const { code, stderr } = await spawnAndWait(bin, substituted, timeoutMs);\n if (code !== 0) {\n throw new Error(`cli-runner: ${bin} exited ${code}\\n${tailLines(stderr, 40)}`);\n }\n\n const result: Record<string, AssetRef> = {};\n for (const { name, absPath, spec } of outputPaths) {\n const s = await stat(absPath).catch(() => null);\n if (!s?.isFile() || s.size === 0) {\n throw new Error(`cli-runner: declared output \"${name}\" missing or empty at ${absPath}`);\n }\n const bytes = await readFile(absPath);\n const ref = await ctx.assets.ingestBytes({\n bytes: Buffer.from(bytes),\n kind: spec.kind,\n mime: mimeForExt(spec.ext),\n });\n result[name] = ref;\n }\n return result;\n } finally {\n await rm(tmpDir, { recursive: true, force: true }).catch((e) => {\n ctx.log(`cli-runner: tmp cleanup failed (${(e as Error).message})`);\n });\n }\n}\n\n/**\n * Capture the binary's `-version` first line for cache-key inclusion.\n * Memoized per-binary per-process. Bumping the host CLI busts cache automatically.\n */\nconst VERSION_CACHE = new Map<string, string>();\n\nexport async function getToolVersion(bin: string): Promise<string> {\n const cached = VERSION_CACHE.get(bin);\n if (cached !== undefined) return cached;\n try {\n const { stdout } = await execFile(bin, [\"-version\"], { encoding: \"utf-8\", maxBuffer: 1024 * 1024 });\n const firstLine = stdout.split(\"\\n\")[0]?.trim() ?? \"\";\n VERSION_CACHE.set(bin, firstLine);\n return firstLine;\n } catch {\n // Don't fail the run on version probe issues; cache key folds in a stable marker.\n const fallback = `${bin}:unknown`;\n VERSION_CACHE.set(bin, fallback);\n return fallback;\n }\n}\n\n// Exported for tests.\nexport const _internal = {\n planPlaceholders,\n substituteArg,\n rejectRawPaths,\n mimeForExt,\n extForAssetRef,\n};\n","import { z } from \"zod\";\nimport { defineNode } from \"../../engine/define.ts\";\nimport { ImageRef } from \"../../schema/refs.ts\";\n\nexport const collectNode = defineNode({\n id: \"collect\",\n version: \"1.0.0\",\n category: \"data\",\n location: \"local\",\n passthroughRefs: true,\n summary:\n \"Gather images from multiple upstream nodes into one ordered array — the standard terminal for multi-variant canvases whose final output is several images.\",\n when_to_use:\n \"Point the canvas `output` at this node when several independent branches (e.g. one image_generate per scene/variant) must ALL be finals. Wire `inputs.images` as an array of refs like `$ref:gen_billboard_03.images#0` — each final inherits its producer node id as its label (or set `params.labels` to override), so variants stay identifiable in the dashboard and selection.\",\n inputs: z.object({ images: z.array(ImageRef).min(1) }).strict(),\n params: z.object({ labels: z.array(z.string().min(1)).min(1).optional() }).strict(),\n outputs: z.object({ images: z.array(ImageRef).min(1) }).strict(),\n outputKinds: { images: \"image\" },\n cost: () => ({ credits: 0, seconds_estimate: 0 }),\n // Arity is only knowable at validate time when `images` is a literal array;\n // a single `$ref:` string to an upstream array output defers to runtime.\n validateExtra: ({ rawParams, rawInputs }) => {\n const labels = (rawParams as { labels?: unknown } | undefined)?.labels;\n if (!Array.isArray(labels)) return [];\n if (new Set(labels).size !== labels.length) {\n return [{ path: \"params.labels\", message: \"labels must be unique — each names one output variant\" }];\n }\n const images = (rawInputs as { images?: unknown } | undefined)?.images;\n if (Array.isArray(images) && labels.length !== images.length) {\n return [\n {\n path: \"params.labels\",\n message: `labels has ${labels.length} entries but ${images.length} images are wired — provide one label per image`,\n },\n ];\n }\n return [];\n },\n execute: ({ inputs }) => Promise.resolve({ images: inputs.images }),\n});\n","import { z } from \"zod\";\nimport { defineNode } from \"../../engine/define.ts\";\nimport type { AssetRef } from \"../../schema/refs.ts\";\nimport { getToolVersion, runCli } from \"./lib/cli-runner.ts\";\n\nconst FFMPEG_BIN = \"ffmpeg\";\n\nconst OutputDecl = z\n .object({\n kind: z.enum([\"image\", \"video\", \"audio\"]),\n ext: z.string().min(1).max(8),\n })\n .strict();\n\nconst FfmpegParams = z\n .object({\n args: z.array(z.string()).min(1),\n outputs: z.record(z.string(), OutputDecl).default({}),\n })\n .strict();\n\n// Inputs are open — every canvas names its own slots. The cli-runner stages\n// any AssetRef-shaped value (or array of them) into the tmp dir keyed by slot.\nconst FfmpegInputs = z.record(z.string(), z.unknown());\n\n// Outputs are also open — keyed by the same names the canvas declared under\n// `params.outputs`. Each entry is an AssetRef.\nconst FfmpegOutputs = z.record(z.string(), z.custom<AssetRef>());\n\nexport const ffmpegNode = defineNode({\n id: \"ffmpeg\",\n version: \"2.0.0\",\n category: \"video\",\n location: \"local\",\n summary:\n \"Local ffmpeg passthrough. Declare inputs, declare outputs, write the argv you'd type on the command line. Inputs are staged into a tmp dir and reached via `{{in.<slot>}}`; declared outputs are allocated at `{{out.<name>}}` and ingested as assets when the run completes.\",\n when_to_use:\n \"Use whenever you'd reach for ffmpeg on the command line: trim, concat, scale, overlay, extract audio, generate thumbnails, mux/demux. Pass the full argv as `params.args` (no shell — argv array, no string interpolation). \" +\n \"Wire input files via `inputs.<slot>` (single AssetRef) or `inputs.<slot>: [...]` (array, addressed as `{{in.<slot>.0}}`, `{{in.<slot>.1}}`). \" +\n \"Declare every output file under `params.outputs` (name → {kind, ext}); the engine allocates the path, you reference it with `{{out.<name>}}`. \" +\n \"Requires `ffmpeg` on PATH. URL-style inputs (http://, file://) and raw filesystem paths in args are rejected — keep everything in the engine's asset model.\",\n inputs: FfmpegInputs,\n params: FfmpegParams,\n outputs: FfmpegOutputs,\n cost: () => ({ credits: 0, seconds_estimate: 15 }),\n\n async cacheKeyExtras() {\n return { ffmpeg_version: await getToolVersion(FFMPEG_BIN) };\n },\n\n async execute({ inputs, params, ctx }) {\n return await runCli({\n bin: FFMPEG_BIN,\n args: params.args,\n inputs: inputs as Record<string, AssetRef | AssetRef[]>,\n outputs: params.outputs,\n ctx,\n });\n },\n});\n","import { mkdtemp, rm, writeFile } from \"node:fs/promises\";\nimport { createRequire } from \"node:module\";\nimport { tmpdir } from \"node:os\";\nimport path from \"node:path\";\nimport { z } from \"zod\";\nimport { defineNode } from \"../../engine/define.ts\";\nimport { NodeExecutionError } from \"../../engine/errors.ts\";\nimport { FontRef, ImageRef } from \"../../schema/refs.ts\";\nimport { extForMime } from \"../../storage/asset-store.ts\";\nimport { uploadAndIngest } from \"../ingest.ts\";\nimport { stageAsset } from \"./lib/assets.ts\";\n\nconst require_ = createRequire(import.meta.url);\n\nexport const DEFAULT_SPECIMEN = [\n \"The quick brown fox jumps over the lazy dog\",\n \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\",\n \"abcdefghijklmnopqrstuvwxyz\",\n \"0123456789 !?&@#$%().,:;'\\\"-\",\n].join(\"\\n\");\n\nconst FontSpecimenParams = z\n .object({\n text: z.string().min(1).max(2000).optional().default(DEFAULT_SPECIMEN),\n font_size: z.number().int().min(8).max(512).optional().default(72),\n padding: z.number().int().min(0).max(512).optional().default(64),\n line_height: z.number().min(0.8).max(3).optional().default(1.35),\n max_width: z.number().int().min(256).max(4096).optional(),\n })\n .strict();\n\ntype Params = z.infer<typeof FontSpecimenParams>;\n\n// `.loose()` so the exact copy that will appear in the ad can be wired in from\n// an upstream node (e.g. text_generate) and referenced via `{{slot}}` in the\n// `text` param — render the specimen on the real headline, not placeholder text.\nconst FontSpecimenInputs = z.object({ font: FontRef }).loose();\nconst FontSpecimenOutputs = z.object({ image: ImageRef }).strict();\n\n// Retina export, consistent with hyperframe_snapshot.\nconst DEVICE_SCALE_FACTOR = 2;\nconst PAGE_TIMEOUT_MS = 30_000;\n\nfunction escapeHtml(text: string): string {\n return text\n .replaceAll(\"&\", \"&\")\n .replaceAll(\"<\", \"<\")\n .replaceAll(\">\", \">\")\n .replaceAll('\"', \""\")\n .replaceAll(\"'\", \"'\");\n}\n\n/**\n * Self-contained specimen page: the staged font is the ONLY family declared,\n * so a load failure is detectable instead of silently falling back to a\n * system font (which would defeat the node's purpose).\n */\nfunction buildSpecimenHtml(params: Params, fontFilename: string): string {\n const widthRule = params.max_width === undefined ? \"width: max-content;\" : `max-width: ${params.max_width}px;`;\n return `<!doctype html>\n<html>\n<head>\n<meta charset=\"utf-8\">\n<style>\n @font-face {\n font-family: 'SpecimenFont';\n src: url('${fontFilename}');\n }\n html, body { margin: 0; background: #fff; }\n #specimen {\n font-family: 'SpecimenFont';\n color: #000;\n background: #fff;\n font-size: ${params.font_size}px;\n line-height: ${params.line_height};\n padding: ${params.padding}px;\n white-space: pre-wrap;\n overflow-wrap: break-word;\n ${widthRule}\n }\n</style>\n</head>\n<body><div id=\"specimen\">${escapeHtml(params.text)}</div></body>\n</html>\n`;\n}\n\nexport const fontSpecimenNode = defineNode({\n id: \"font_specimen\",\n version: \"1.1.0\",\n category: \"image\",\n location: \"local\",\n summary:\n \"Render specimen text in a given font file to a PNG — black text on a white background — via headless Chromium. \" +\n \"Produces a typeface reference image an image model can replicate.\",\n when_to_use:\n \"Use when a generated image must contain text in a specific brand font: wire `image` into `image_generate`'s `reference` input so the model copies the typeface. \" +\n 'Input is a `font` asset (ttf/otf/woff/woff2) — get one via `ingest` with `expect: \"font\"`. ' +\n \"Default specimen covers a pangram, both alphabets, digits and punctuation; override with `params.text` (e.g. the exact headline to render).\",\n inputs: FontSpecimenInputs,\n params: FontSpecimenParams,\n outputs: FontSpecimenOutputs,\n outputKinds: { image: \"image\" },\n cost: () => ({ credits: 0, seconds_estimate: 5 }),\n\n async execute({ inputs, params, ctx }) {\n const tmp = await mkdtemp(path.join(tmpdir(), \"font-specimen-\"));\n try {\n const fontFilename = `font.${extForMime(inputs.font.mime)}`;\n await stageAsset(inputs.font, tmp, fontFilename);\n\n const entryPath = path.join(tmp, \"index.html\");\n await writeFile(entryPath, buildSpecimenHtml(params, fontFilename), \"utf-8\");\n\n ctx.log(`rendering specimen (${params.font_size}px, ${params.text.split(\"\\n\").length} lines)`);\n\n const pwSpecifier = [\"play\", \"wright\"].join(\"\");\n const playwright = require_(pwSpecifier) as typeof import(\"playwright\");\n const browser = await playwright.chromium.launch({ headless: true });\n try {\n const context = await browser.newContext({\n viewport: { width: 1280, height: 720 },\n deviceScaleFactor: DEVICE_SCALE_FACTOR,\n });\n const page = await context.newPage();\n await page.goto(`file://${entryPath}`, { waitUntil: \"load\", timeout: PAGE_TIMEOUT_MS });\n\n // Fail loudly when Chromium can't parse the font — the page declares\n // no fallback family, but a broken file would otherwise still render\n // with the browser's last-resort font and silently lie downstream.\n const loaded = await page\n .evaluate(async () => {\n const faces = await document.fonts.load(\"16px 'SpecimenFont'\");\n await document.fonts.ready;\n return faces.length;\n })\n .catch(() => 0);\n if (loaded === 0) {\n throw new NodeExecutionError(ctx.nodeId, ctx.nodeType, {\n kind: \"local\",\n cause: new Error(\n `font_specimen: Chromium could not load the font (${inputs.font.mime}) — is the file a valid ttf/otf/woff/woff2?`,\n ),\n });\n }\n\n // A font can load yet cover none of the specimen's characters (e.g. a\n // script-subset woff2 with no Latin glyphs) — Chromium then falls back\n // per character and the specimen would silently show a system font.\n // Detection: a covered char measures identically under both fallback\n // stacks (the font itself renders it); an uncovered char differs\n // (monospace vs serif fallback metrics diverge).\n const { covered, missing } = await page.evaluate((text: string) => {\n const chars = [...new Set(text.replace(/\\s/g, \"\"))];\n const c = document.createElement(\"canvas\").getContext(\"2d\");\n if (!c) return { covered: chars.length, missing: [] as string[] };\n const missingChars: string[] = [];\n for (const ch of chars) {\n c.font = \"64px 'SpecimenFont', monospace\";\n const a = c.measureText(ch).width;\n c.font = \"64px 'SpecimenFont', serif\";\n const b = c.measureText(ch).width;\n if (a !== b) missingChars.push(ch);\n }\n return { covered: chars.length - missingChars.length, missing: missingChars };\n }, params.text);\n if (covered === 0) {\n throw new NodeExecutionError(ctx.nodeId, ctx.nodeType, {\n kind: \"local\",\n cause: new Error(\n \"font_specimen: the font loaded but provides no glyphs for the specimen text — is it a subset for another script? Use a full (e.g. latin) build of the font, or change params.text.\",\n ),\n });\n }\n if (missing.length > 0) {\n ctx.log(`warning: font has no glyphs for ${missing.length} character(s): ${missing.join(\" \")}`);\n }\n\n const specimen = page.locator(\"#specimen\");\n const box = await specimen.boundingBox();\n const bytes = await specimen.screenshot({ type: \"png\", timeout: PAGE_TIMEOUT_MS });\n ctx.log(`captured ${bytes.length} bytes`);\n\n const metadata: Record<string, unknown> = {\n font_sha256: inputs.font.sha256,\n font_mime: inputs.font.mime,\n };\n if (box) {\n metadata.width = Math.round(box.width * DEVICE_SCALE_FACTOR);\n metadata.height = Math.round(box.height * DEVICE_SCALE_FACTOR);\n }\n\n // Upload to R2 (not just the local store): downstream remote nodes\n // (image_generate reference) receive only `url` — see stripLocalRefs.\n const ref = await uploadAndIngest({\n bytes: Buffer.from(bytes),\n kind: \"image\",\n mime: \"image/png\",\n metadata,\n ctx,\n });\n return { image: ref as z.infer<typeof ImageRef> };\n } finally {\n await browser.close();\n }\n } finally {\n await rm(tmp, { recursive: true, force: true }).catch((cleanupErr) => {\n ctx.log(`warning: tmp cleanup failed (${(cleanupErr as Error).message})`);\n });\n }\n },\n});\n\n// Exported for unit tests.\nexport const _internal = {\n FontSpecimenParams,\n buildSpecimenHtml,\n escapeHtml,\n};\n","import { copyFile, readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { AssetRef } from \"../../../schema/refs.ts\";\n\n// Shape we accept: any AssetRef-ish value with at least a kind+mime and either\n// path or url. We don't import the Zod refs here so this helper stays usable\n// from anywhere without circulars.\nexport type StageableRef = { kind: string; mime: string; path?: string; url?: string };\n\n/**\n * Copy a local asset into `destDir` under `filename` (or, when `filename` is\n * omitted, `<key><ext>` derived from the ref's mime). Throws if the ref has no\n * local path — callers must materialise upstream assets before staging.\n */\nexport async function stageAsset(ref: StageableRef, destDir: string, filename: string): Promise<string> {\n if (!ref.path) {\n throw new Error(`stageAsset: ref (${ref.kind}/${ref.mime}) has no local path`);\n }\n const dest = path.join(destDir, filename);\n await copyFile(ref.path, dest);\n return dest;\n}\n\n/**\n * Returns an AssetRef as a URL string browser code can consume.\n * Prefers `ref.url`; falls back to a base64 `data:` URL built from `ref.path`.\n */\nexport async function refToUrl(ref: Pick<AssetRef, \"mime\" | \"path\" | \"url\">): Promise<string> {\n if (ref.url) return ref.url;\n if (!ref.path) {\n throw new Error(\"refToUrl: AssetRef has neither url nor path\");\n }\n const bytes = await readFile(ref.path);\n return `data:${ref.mime};base64,${bytes.toString(\"base64\")}`;\n}\n\nconst ASSET_KINDS: ReadonlySet<string> = new Set([\"image\", \"video\", \"audio\", \"json\", \"text\", \"font\"]);\n\nexport function isAssetRefLike(value: unknown): value is AssetRef {\n if (!value || typeof value !== \"object\") return false;\n const v = value as Record<string, unknown>;\n return (\n typeof v.kind === \"string\" &&\n ASSET_KINDS.has(v.kind) &&\n typeof v.mime === \"string\" &&\n typeof v.sha256 === \"string\" &&\n (typeof v.url === \"string\" || typeof v.path === \"string\")\n );\n}\n","import { execFile } from \"node:child_process\";\nimport { copyFile, mkdtemp, readFile, rm, stat, writeFile } from \"node:fs/promises\";\nimport { createRequire } from \"node:module\";\nimport { cpus, tmpdir } from \"node:os\";\nimport path from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { z } from \"zod\";\nimport { hashCompositionDir } from \"../../engine/composition-hash.ts\";\nimport {\n buildParamsSchema,\n type CompositionMeta,\n defaultFilenameForInput,\n loadCompositionMeta,\n} from \"../../engine/composition-meta.ts\";\nimport type { ExecCtx } from \"../../engine/context.ts\";\nimport { defineNode } from \"../../engine/define.ts\";\nimport type { AssetRef } from \"../../schema/refs.ts\";\nimport { isAssetRefLike, refToUrl, type StageableRef, stageAsset } from \"./lib/assets.ts\";\nimport { lintStructuralIssues, runHyperframesCheck } from \"./lib/hyperframe-check.ts\";\nimport { mapKnownHyperframesError } from \"./lib/hyperframe-errors.ts\";\nimport { ensureHyperframesMetaJson } from \"./lib/hyperframe-meta.ts\";\nimport { substituteVariables } from \"./lib/templating.ts\";\n\nconst execFileAsync = promisify(execFile);\nconst require_ = createRequire(import.meta.url);\n\n// Runtime knobs are owned by the canvas-engine — we always render at max\n// quality, mp4, on the controlled E2B sandbox (see\n// `packages/e2b-template/src/template.ts`). The composition's own params\n// (`words_per_group`, `transcript`, etc.) ride alongside via `.catchall` and\n// are validated against the composition's meta.json by `validateExtra`.\nconst HyperframeParams = z\n .object({\n composition: z.string().min(1),\n // Output container. mp4 (default) for delivery; webm/mov render WITH\n // transparency (alpha) when the composition background is transparent —\n // use for motion-graphic overlays dropped into Premiere/AE/Nuke.\n format: z.enum([\"mp4\", \"webm\", \"mov\"]).optional().default(\"mp4\"),\n timeout_ms: z\n .number()\n .int()\n .positive()\n .optional()\n .default(10 * 60 * 1000),\n })\n .catchall(z.unknown());\n\n// Inputs are dynamic — meta.json declares which keys this composition\n// expects. The node accepts any keyed AssetRef and validates against meta\n// at execute time.\nconst HyperframeInputs = z.record(z.string(), z.custom<AssetRef>()).optional().default({});\n\nconst HyperframeOutputs = z\n .object({\n video: z.custom<AssetRef>(),\n })\n .strict();\n\nconst NODE_OWNED_PARAM_KEYS = new Set([\"composition\", \"format\", \"timeout_ms\"]);\n\nconst MIME_BY_FORMAT: Record<\"mp4\" | \"webm\" | \"mov\", string> = {\n mp4: \"video/mp4\",\n webm: \"video/webm\",\n mov: \"video/quicktime\",\n};\n\n// Engine-injected: the substitution pass fills these from input asset duration\n// (and the composition's default_duration). Authors must not declare them.\nconst ENGINE_INJECTED_TOKENS = new Set([\"duration\"]);\n\ntype Params = z.infer<typeof HyperframeParams>;\n\nexport const hyperframeRenderNode = defineNode({\n id: \"hyperframe_render\",\n version: \"6.1.0\",\n category: \"video\",\n location: \"local\",\n summary:\n \"Render an mp4 by composing an HTML/CSS/GSAP composition over upstream assets. Point `params.composition` at a directory containing `index.html` + `meta.json`. All variables are passed as primitives in `params` and substituted into the composition before render.\",\n when_to_use:\n \"Use to add captions, lower-thirds, branded overlays, title cards, or any HTML-driven graphic over a video. \" +\n \"Point `params.composition` at a directory containing `index.html` + `meta.json`. \" +\n \"Inputs are keyed by the composition's `meta.json.inputs` map — wire `inputs.<key> = $ref:<node>.<output>`. \" +\n \"Output resolution/fps come from the composition's `meta.json`; quality and worker count are fixed by the engine. \" +\n \"Set `params.format` to `webm` or `mov` for a transparent (alpha) overlay to composite in another editor; defaults to `mp4`. \" +\n \"Runs a pre-render `hyperframes lint`/`inspect` gate (overflow/structural errors block; contrast warns).\",\n inputs: HyperframeInputs,\n params: HyperframeParams,\n outputs: HyperframeOutputs,\n cost: () => ({ credits: 0, seconds_estimate: 30 }),\n\n validateExtra: ({ rawParams }) => validateComposition(rawParams),\n\n cacheKeyExtras: async ({ params }) => {\n const out: Record<string, string> = {};\n const composition = (params as { composition?: unknown }).composition;\n if (typeof composition !== \"string\") return out;\n const dir = await resolveCompositionDir(composition).catch(() => null);\n if (!dir) return out;\n out.composition_content_sha = await hashCompositionDir(dir);\n return out;\n },\n\n async execute({ inputs, params, ctx }) {\n const compositionDir = await resolveCompositionDir(params.composition);\n const meta = await loadCompositionMeta(compositionDir);\n const compositionParams = validateAndParseDynamicParams(meta, params);\n\n const tmp = await mkdtemp(path.join(tmpdir(), \"hf-render-\"));\n try {\n await copyComposition(compositionDir, tmp);\n await vendorGsap(tmp, ctx);\n\n const stagedDuration = await stageInputs(tmp, inputs, meta, ctx);\n const duration = stagedDuration ?? meta.default_duration;\n\n const substitutionValues = await buildSubstitutionValues(compositionParams, meta, duration);\n await substituteCompositionFiles(tmp, substitutionValues);\n await ensureHyperframesMetaJson(tmp, ctx.nodeId, meta, duration);\n\n // Pre-render quality gate on the SUBSTITUTED composition: lint + inspect.\n // Overflow/structural errors block; contrast + deferred-asset advisories\n // only warn. Degrades gracefully if the tool is unavailable.\n await runHyperframesCheck({ dir: tmp, nodeId: \"hyperframe_render\", ctx, timeoutMs: params.timeout_ms });\n\n const outputPath = path.join(tmp, `output.${params.format}`);\n\n await runRender({ tmp, outputPath, params, meta, ctx });\n\n const bytes = await readFile(outputPath);\n ctx.log(`rendered ${bytes.length} bytes`);\n const ref = await ctx.assets.ingestBytes({\n bytes: Buffer.from(bytes),\n kind: \"video\",\n mime: MIME_BY_FORMAT[params.format],\n metadata: {\n width: meta.width,\n height: meta.height,\n fps: meta.fps,\n duration_ms: Math.round(duration * 1000),\n },\n });\n return { video: ref };\n } finally {\n await rm(tmp, { recursive: true, force: true }).catch((e) => {\n ctx.log(`warning: tmp cleanup failed (${(e as Error).message})`);\n });\n }\n },\n});\n\n// ---------------------------------------------------------------------------\n// Composition resolution + dynamic param validation\n// ---------------------------------------------------------------------------\n\nexport async function resolveCompositionDir(composition: string): Promise<string> {\n const compositionPath = path.isAbsolute(composition) ? composition : path.resolve(process.cwd(), composition);\n const s = await stat(compositionPath);\n if (s.isDirectory()) return compositionPath;\n return path.dirname(compositionPath);\n}\n\n/**\n * `validateExtra` hook: meta-param validation PLUS a predictive structural lint.\n * Running `hyperframes lint` here (degrades gracefully when the binary is absent)\n * surfaces the gate's structural blockers — untimed background media, timed\n * elements missing `class=\"clip\"`, non-inline caption transcripts — at validate\n * time, BEFORE any billed clip. These are exactly the failures that aborted the\n * Barkibu run after it had paid for 16 generative nodes.\n */\nasync function validateComposition(rawParams: unknown): Promise<{ path: string; message: string }[]> {\n const issues = await validateCompositionParams(rawParams);\n const composition = (rawParams as { composition?: unknown })?.composition;\n if (typeof composition !== \"string\") return issues;\n const dir = await resolveCompositionDir(composition).catch(() => null);\n if (!dir) return issues;\n const structural = await lintStructuralIssues(dir, 20_000);\n for (const s of structural) {\n issues.push({\n path: \"params.composition\",\n message: `pre-render gate would fail: [${s.code}] ${s.message}`,\n });\n }\n return issues;\n}\n\n/**\n * Validate raw params against the composition's meta.json.\n * Returns issue list (empty = ok). Used by `validateExtra` so canvas\n * validate catches bad params before any render runs.\n */\nexport async function validateCompositionParams(rawParams: unknown): Promise<{ path: string; message: string }[]> {\n const issues: { path: string; message: string }[] = [];\n if (!rawParams || typeof rawParams !== \"object\") return issues;\n const params = rawParams as Record<string, unknown>;\n const composition = params.composition;\n if (typeof composition !== \"string\") return issues; // static schema will have flagged it\n\n let dir: string;\n try {\n dir = await resolveCompositionDir(composition);\n } catch (e) {\n issues.push({ path: \"params.composition\", message: (e as Error).message });\n return issues;\n }\n\n let meta: CompositionMeta;\n try {\n meta = await loadCompositionMeta(dir);\n } catch (e) {\n issues.push({ path: \"params.composition\", message: (e as Error).message });\n return issues;\n }\n\n // Pick out only the dynamic (composition-declared) params for the meta-schema check.\n const dynamic: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(params)) {\n if (NODE_OWNED_PARAM_KEYS.has(k)) continue;\n dynamic[k] = v;\n }\n for (const key of Object.keys(dynamic)) {\n if (ENGINE_INJECTED_TOKENS.has(key)) {\n issues.push({\n path: `params.${key}`,\n message: `\"${key}\" is reserved (auto-injected by the renderer from input duration); remove from params`,\n });\n }\n }\n const schema = buildParamsSchema(meta);\n const parsed = schema.safeParse(dynamic);\n if (!parsed.success) {\n for (const issue of parsed.error.issues) {\n const tail = issue.path.join(\".\");\n issues.push({\n path: `params.${tail}`,\n message: issue.message,\n });\n }\n }\n return issues;\n}\n\nfunction validateAndParseDynamicParams(meta: CompositionMeta, params: Params): Record<string, unknown> {\n const dynamic: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(params)) {\n if (NODE_OWNED_PARAM_KEYS.has(k)) continue;\n dynamic[k] = v;\n }\n const schema = buildParamsSchema(meta);\n const parsed = schema.safeParse(dynamic);\n if (!parsed.success) {\n const summary = parsed.error.issues.map((i) => `params.${i.path.join(\".\")}: ${i.message}`).join(\"; \");\n throw new Error(`hyperframe_render: composition param validation failed — ${summary}`);\n }\n return parsed.data;\n}\n\n// ---------------------------------------------------------------------------\n// Asset staging\n// ---------------------------------------------------------------------------\n\nasync function copyComposition(srcDir: string, destDir: string): Promise<void> {\n const { cp } = await import(\"node:fs/promises\");\n await cp(srcDir, destDir, {\n recursive: true,\n filter: (src) => {\n const name = path.basename(src);\n if (name === \".cache\" || name === \"node_modules\" || name === \".git\") return false;\n return true;\n },\n });\n}\n\nasync function vendorGsap(tmp: string, ctx: ExecCtx): Promise<void> {\n try {\n const gsapMin = require_.resolve(\"gsap/dist/gsap.min.js\");\n await copyFile(gsapMin, path.join(tmp, \"gsap.min.js\"));\n } catch (e) {\n ctx.log(`warning: could not vendor gsap.min.js (${(e as Error).message}); compositions must self-supply`);\n }\n}\n\n/**\n * Stage every input referenced in canvas `inputs` against the composition's\n * declared `meta.inputs` map. Throws on:\n * - missing required input\n * - input kind mismatch (canvas passes an image where video is declared)\n * - undeclared input key\n *\n * Returns the duration of the primary input asset (when a video) so the\n * engine can substitute `{{duration}}`. Falls back to meta.default_duration.\n */\nasync function stageInputs(\n tmp: string,\n inputs: Record<string, AssetRef>,\n meta: CompositionMeta,\n ctx: ExecCtx,\n): Promise<number | null> {\n assertInputsMatchMeta(inputs, meta, \"hyperframe_render\");\n let primaryDuration: number | null = null;\n for (const [key, ref] of Object.entries(inputs ?? {})) {\n const spec = meta.inputs[key];\n if (!spec) continue;\n const filename = spec.staged_as ?? defaultFilenameForInput(key, spec.kind);\n await stageAsset(ref as StageableRef, tmp, filename);\n ctx.log(`staged ${spec.kind} → ${filename}`);\n if (spec.kind === \"video\" && primaryDuration === null) {\n primaryDuration = await probeDurationSeconds(path.join(tmp, filename));\n }\n }\n return primaryDuration;\n}\n\n/**\n * Shared input-vs-meta check used by both hyperframe nodes. Throws on:\n * - undeclared input keys (typo / stale canvas)\n * - missing required inputs\n * - kind mismatch (canvas passes an image where video is declared)\n */\nexport function assertInputsMatchMeta(\n inputs: Record<string, AssetRef> | undefined,\n meta: CompositionMeta,\n nodeId: string,\n): void {\n const declaredKeys = new Set(Object.keys(meta.inputs));\n const providedKeys = new Set(Object.keys(inputs ?? {}));\n for (const key of providedKeys) {\n if (!declaredKeys.has(key)) {\n const declared = [...declaredKeys].join(\", \") || \"<none>\";\n throw new Error(`${nodeId}: inputs.${key} is not declared in composition meta.json (declares: ${declared})`);\n }\n }\n for (const [key, spec] of Object.entries(meta.inputs)) {\n if (spec.required && !providedKeys.has(key)) {\n throw new Error(`${nodeId}: inputs.${key} is required (kind=${spec.kind})`);\n }\n }\n for (const [key, ref] of Object.entries(inputs ?? {})) {\n const spec = meta.inputs[key];\n if (!spec) continue;\n if (ref.kind !== spec.kind) {\n throw new Error(`${nodeId}: inputs.${key} expected kind \"${spec.kind}\", got \"${ref.kind}\"`);\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Substitution\n// ---------------------------------------------------------------------------\n\nasync function buildSubstitutionValues(\n compositionParams: Record<string, unknown>,\n meta: CompositionMeta,\n duration: number,\n): Promise<Record<string, unknown>> {\n const out: Record<string, unknown> = {};\n for (const [name, value] of Object.entries(compositionParams)) {\n const spec = meta.params[name];\n if (spec?.kind === \"image\") {\n out[name] = await coerceImageParam(value);\n continue;\n }\n out[name] = value;\n }\n out.duration = duration.toFixed(3);\n return out;\n}\n\nfunction coerceImageParam(value: unknown): Promise<string> {\n if (typeof value === \"string\") return Promise.resolve(value);\n if (isAssetRefLike(value)) return refToUrl(value);\n throw new Error(\"hyperframe_render: image param must be a URL string or AssetRef\");\n}\n\nasync function substituteCompositionFiles(tmp: string, values: Record<string, unknown>): Promise<void> {\n // Substitute in index.html (the only file Hyperframes loads). Embedded\n // <style>/<script> live inside index.html so a single pass handles all of them.\n const entryPath = path.join(tmp, \"index.html\");\n const original = await readFile(entryPath, \"utf-8\");\n const { output, missing } = substituteVariables(original, values);\n if (missing.length > 0) {\n throw new Error(\n `hyperframe_render: composition references undefined variables: ${missing.map((m) => `{{${m}}}`).join(\", \")}. ` +\n `Add to params or to meta.json's params with a default.`,\n );\n }\n await writeFile(entryPath, output, \"utf-8\");\n}\n\n// ---------------------------------------------------------------------------\n// Render shell-out\n// ---------------------------------------------------------------------------\n\n// Cap workers at 4 on the controlled sandbox — Hyperframes spins up one\n// headless Chrome per worker and the e2b instance is typically a 4-vCPU box.\nconst MAX_WORKERS = 4;\n\nfunction workerCount(): number {\n return Math.max(1, Math.min(MAX_WORKERS, cpus().length));\n}\n\nasync function runRender(opts: {\n tmp: string;\n outputPath: string;\n params: Params;\n meta: CompositionMeta;\n ctx: ExecCtx;\n}): Promise<void> {\n const { tmp, outputPath, params, meta, ctx } = opts;\n const args = buildRenderArgs(tmp, outputPath, meta, params.format);\n ctx.log(`rendering ${meta.width}x${meta.height}@${meta.fps}fps ${params.format} from ${path.basename(tmp)}`);\n try {\n await execFileAsync(\"npx\", args, { timeout: params.timeout_ms, maxBuffer: 64 * 1024 * 1024 });\n } catch (e) {\n const stderr = (e as { stderr?: string }).stderr ?? \"\";\n const stdout = (e as { stdout?: string }).stdout ?? \"\";\n const detail = stderr || stdout || (e as Error).message;\n const friendly = mapKnownHyperframesError(detail);\n throw new Error(`hyperframe_render: render failed\\n${friendly ?? detail.slice(0, 4000)}`);\n }\n}\n\nexport function buildRenderArgs(tmp: string, outputPath: string, meta: CompositionMeta, format: string): string[] {\n return [\n \"hyperframes\",\n \"render\",\n tmp,\n \"--output\",\n outputPath,\n \"--fps\",\n String(meta.fps),\n \"--quality\",\n \"high\",\n \"--format\",\n format,\n \"--workers\",\n String(workerCount()),\n ];\n}\n\nasync function probeDurationSeconds(filePath: string): Promise<number> {\n const { stdout } = await execFileAsync(\n \"ffprobe\",\n [\"-v\", \"error\", \"-show_entries\", \"format=duration\", \"-of\", \"csv=p=0\", filePath],\n { encoding: \"utf-8\" },\n );\n const seconds = Number.parseFloat(stdout.trim());\n if (!Number.isFinite(seconds)) {\n throw new Error(`hyperframe_render: ffprobe returned invalid duration: ${stdout}`);\n }\n return seconds;\n}\n","import { readdir, readFile, stat } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { sha256Hex } from \"../storage/sha256.ts\";\n\n// Skip transient/build artefacts when hashing — these aren't part of the\n// composition's source-of-truth and would either thrash the cache (.cache,\n// node_modules) or pollute the hash with editor noise (.DS_Store, .swp).\nconst SKIP_DIRS: ReadonlySet<string> = new Set([\".cache\", \".git\", \"node_modules\", \"dist\", \"build\", \".next\", \".turbo\"]);\n\nfunction isSkippedName(name: string): boolean {\n if (name.startsWith(\".\")) return true; // .DS_Store, dotfiles\n return SKIP_DIRS.has(name);\n}\n\ntype FileEntry = { relPath: string; contentSha: string };\n\n/**\n * Compute a deterministic content-addressed hash of every relevant file under\n * `dir`. Hash layout:\n *\n * sha256(\"<rel/path>\\0<file-sha256>\\n<rel/path>\\0<file-sha256>\\n...\")\n *\n * Entries are sorted by relative path so the result is stable regardless of\n * filesystem-walk order. Returns a hex sha256 string.\n *\n * Used by the executor to fold composition content into the cache key — any\n * edit to a tracked file invalidates the hyperframe_render cache entry.\n */\nexport async function hashCompositionDir(dir: string): Promise<string> {\n const entries = await collectFiles(dir, dir);\n entries.sort((a, b) => a.relPath.localeCompare(b.relPath));\n const manifest = entries.map((e) => `${e.relPath}\\0${e.contentSha}`).join(\"\\n\");\n return sha256Hex(manifest);\n}\n\nasync function collectFiles(root: string, current: string): Promise<FileEntry[]> {\n const out: FileEntry[] = [];\n const names = await readdir(current);\n for (const name of names) {\n if (isSkippedName(name)) continue;\n const abs = path.join(current, name);\n const s = await stat(abs);\n if (s.isDirectory()) {\n out.push(...(await collectFiles(root, abs)));\n continue;\n }\n if (!s.isFile()) continue;\n const bytes = await readFile(abs);\n const relPath = path.relative(root, abs).split(path.sep).join(\"/\");\n out.push({ relPath, contentSha: sha256Hex(bytes) });\n }\n return out;\n}\n","import { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { z } from \"zod\";\n\n// One source of truth per composition: meta.json.\n//\n// The composition declares its inputs (videos/images/audios it expects staged\n// into the render directory) and params (everything you can pass via {{var}}).\n// The hyperframe_render and hyperframe_snapshot nodes load this file, build a\n// per-call Zod schema, and validate the canvas's `params` against it.\n\nconst InputKind = z.enum([\"video\", \"image\", \"audio\", \"json\"]);\n\nconst InputSpec = z\n .object({\n kind: InputKind,\n required: z.boolean().optional().default(false),\n // Filename the composition's HTML references (e.g. `input.mp4`, `logo.png`).\n // Defaults to `<key><ext>` derived from the kind.\n staged_as: z.string().min(1).optional(),\n description: z.string().optional(),\n })\n .strict();\n\nconst ParamSpecBase = {\n required: z.boolean().optional().default(false),\n description: z.string().optional(),\n};\n\nconst StringParam = z\n .object({\n ...ParamSpecBase,\n kind: z.literal(\"string\"),\n default: z.string().optional(),\n enum: z.array(z.string()).optional(),\n })\n .strict();\n\nconst IntegerParam = z\n .object({\n ...ParamSpecBase,\n kind: z.literal(\"integer\"),\n default: z.number().int().optional(),\n min: z.number().int().optional(),\n max: z.number().int().optional(),\n })\n .strict();\n\nconst NumberParam = z\n .object({\n ...ParamSpecBase,\n kind: z.literal(\"number\"),\n default: z.number().optional(),\n min: z.number().optional(),\n max: z.number().optional(),\n })\n .strict();\n\nconst BooleanParam = z\n .object({\n ...ParamSpecBase,\n kind: z.literal(\"boolean\"),\n default: z.boolean().optional(),\n })\n .strict();\n\nconst ColorParam = z\n .object({\n ...ParamSpecBase,\n kind: z.literal(\"color\"),\n default: z.string().optional(),\n })\n .strict();\n\nconst ImageParam = z\n .object({\n ...ParamSpecBase,\n kind: z.literal(\"image\"),\n default: z.string().optional(),\n })\n .strict();\n\nconst JsonParam = z\n .object({\n ...ParamSpecBase,\n kind: z.literal(\"json\"),\n schema: z.unknown().optional(),\n default: z.unknown().optional(),\n })\n .strict();\n\nconst ParamSpec = z.discriminatedUnion(\"kind\", [\n StringParam,\n IntegerParam,\n NumberParam,\n BooleanParam,\n ColorParam,\n ImageParam,\n JsonParam,\n]);\n\ntype ParamSpec = z.infer<typeof ParamSpec>;\n\nexport const CompositionMetaSchema = z\n .object({\n id: z.string().min(1),\n title: z.string().min(1),\n description: z.string().optional(),\n width: z.number().int().positive(),\n height: z.number().int().positive(),\n fps: z.number().int().positive().default(30),\n default_duration: z.number().positive().default(10),\n inputs: z.record(z.string(), InputSpec).default({}),\n params: z.record(z.string(), ParamSpec).default({}),\n })\n .strict();\n\nexport type CompositionMeta = z.infer<typeof CompositionMetaSchema>;\n\nexport async function loadCompositionMeta(compositionDir: string): Promise<CompositionMeta> {\n const metaPath = path.join(compositionDir, \"meta.json\");\n let raw: string;\n try {\n raw = await readFile(metaPath, \"utf-8\");\n } catch (e) {\n throw new Error(`composition meta: cannot read ${metaPath} (${(e as Error).message})`);\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (e) {\n throw new Error(`composition meta: ${metaPath} is not valid JSON (${(e as Error).message})`);\n }\n const result = CompositionMetaSchema.safeParse(parsed);\n if (!result.success) {\n const summary = result.error.issues.map((i) => `${i.path.join(\".\")}: ${i.message}`).join(\"; \");\n throw new Error(`composition meta: ${metaPath} schema error — ${summary}`);\n }\n return result.data;\n}\n\n/**\n * Build a Zod schema for the params declared in `meta.json`. Used to validate\n * the canvas's `params` payload at validate-time and execute-time.\n *\n * Output schema is a `z.object().strict()` — unknown keys are rejected so\n * typos surface immediately. Params with a `default` are made optional and\n * Zod fills the default; required params without defaults must be provided.\n */\nexport function buildParamsSchema(meta: CompositionMeta): z.ZodObject {\n const shape: Record<string, z.ZodType> = {};\n for (const [name, spec] of Object.entries(meta.params)) {\n shape[name] = buildParamFieldSchema(name, spec);\n }\n return z.object(shape).strict();\n}\n\nfunction buildParamFieldSchema(name: string, spec: ParamSpec): z.ZodType {\n switch (spec.kind) {\n case \"string\": {\n const s: z.ZodType = spec.enum && spec.enum.length > 0 ? z.enum(spec.enum as [string, ...string[]]) : z.string();\n return finalize(s, spec.default, spec.required);\n }\n case \"integer\": {\n let s: z.ZodNumber = z.number().int();\n if (spec.min !== undefined) s = s.min(spec.min);\n if (spec.max !== undefined) s = s.max(spec.max);\n return finalize(s, spec.default, spec.required);\n }\n case \"number\": {\n let s: z.ZodNumber = z.number();\n if (spec.min !== undefined) s = s.min(spec.min);\n if (spec.max !== undefined) s = s.max(spec.max);\n return finalize(s, spec.default, spec.required);\n }\n case \"boolean\":\n return finalize(z.boolean(), spec.default, spec.required);\n case \"color\": {\n const s = z.string().regex(/^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/, {\n message: `param \"${name}\": must be a 3/6/8-digit hex color (e.g. \"#ff0066\")`,\n });\n return finalize(s, spec.default, spec.required);\n }\n case \"image\":\n // Accept a URL string or an AssetRef-shaped object — node coerces to URL\n // string before substitution.\n return finalize(z.union([z.string().min(1), z.record(z.string(), z.unknown())]), spec.default, spec.required);\n case \"json\":\n return finalize(\n z.unknown().refine((v) => v !== undefined, { message: `param \"${name}\" is required` }),\n spec.default,\n spec.required,\n );\n default: {\n const _exhaustive: never = spec;\n throw new Error(`buildParamFieldSchema: unknown kind ${(_exhaustive as { kind: string }).kind}`);\n }\n }\n}\n\nfunction finalize(schema: z.ZodType, dflt: unknown, required: boolean | undefined): z.ZodType {\n if (dflt !== undefined) return schema.optional().default(dflt as never);\n if (required === false) return schema.optional();\n return schema;\n}\n\n/** Default filename for an input — the composition can override via `staged_as`. */\nexport function defaultFilenameForInput(key: string, kind: \"video\" | \"image\" | \"audio\" | \"json\"): string {\n if (kind === \"video\") return `${key}.mp4`;\n if (kind === \"audio\") return `${key}.mp3`;\n if (kind === \"json\") return `${key}.json`;\n return `${key}.png`;\n}\n","import { execFile } from \"node:child_process\";\nimport { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { promisify } from \"node:util\";\n\n// Pre-render quality gate. Runs Hyperframes' own `lint` (composition mistakes:\n// missing ids, undeclared variables, bad structure, low contrast, …) and\n// `inspect` (text/container overflow across the timeline) on the SUBSTITUTED\n// composition in the tmp render dir, before the billable render.\n//\n// Severity policy (see the plan): overflow + structural lint errors HARD-BLOCK;\n// contrast and deferred-asset advisories WARN ONLY (low contrast can be a valid\n// brand choice; the agent drops brand fonts/assets after scaffolding). If the\n// `hyperframes` binary or these subcommands are unavailable, the gate degrades\n// gracefully — it logs and lets the render proceed rather than failing a valid\n// render on a missing tool.\n\nconst execFileAsync = promisify(execFile);\n\n// Internal-only types — exported functions return them by inference, so they\n// don't need to be exported themselves (keeps knip's unused-export gate clean).\ntype CheckSeverity = \"blocking\" | \"warning\";\ntype CheckFinding = {\n source: \"lint\" | \"inspect\";\n code: string;\n message: string;\n severity: CheckSeverity;\n};\ntype CheckResult = { blocking: CheckFinding[]; warnings: CheckFinding[] };\n\n// Advisory in Baker's deferred-asset pipeline — never hard-block on these even\n// at lint severity \"error\". The agent supplies brand fonts/assets and tunes\n// contrast AFTER scaffolding, so blocking here would fail legitimate creative.\n// Add a code/keyword here to downgrade a finding from blocking to warning.\n//\n// • contrast / wcag / missing_local_asset / font-* — deferred-asset advisories.\n// • transcript_not_inline — our caption track legitimately reads the transcript\n// from a STAGED `transcript.json` input (a real file at render time); the\n// gate's inline-array preference is a Studio-editing nicety, not a render\n// requirement, so fetch() works and must not block.\n// • text_occluded — the static check can't run GSAP, so it reads every\n// animate-in caption/overlay (hidden until its beat by design) as occluded.\n// A genuine occlusion still surfaces as a warning + on read-the-output-back.\nconst NEVER_BLOCK: RegExp[] = [\n /contrast/i,\n /\\bwcag\\b/i,\n /missing_local_asset/i,\n /font[_-]?family/i,\n /font[_-]?face/i,\n /transcript[_-]?not[_-]?inline/i,\n /text[_-]?occluded/i,\n];\n\n// Stderr/message fragments that mean the command itself could not run (vs. the\n// command running and reporting findings). These degrade gracefully.\nconst UNAVAILABLE = /unknown command|command not found|not found|Did you mean|Unknown argument|ENOENT/i;\n\nfunction isAdvisory(code: string, message: string): boolean {\n const hay = `${code} ${message}`;\n return NEVER_BLOCK.some((re) => re.test(hay));\n}\n\n/** Parse JSON that may be preceded by non-JSON guard lines (e.g. `[StaticGuard] …`). */\nexport function parseCheckJson(raw: string): unknown {\n if (!raw) return null;\n const trimmed = raw.trim();\n try {\n return JSON.parse(trimmed);\n } catch {\n // fall through to brace extraction\n }\n const start = trimmed.indexOf(\"{\");\n const end = trimmed.lastIndexOf(\"}\");\n if (start >= 0 && end > start) {\n try {\n return JSON.parse(trimmed.slice(start, end + 1));\n } catch {\n return null;\n }\n }\n return null;\n}\n\nexport function classifyLint(json: unknown): CheckFinding[] {\n const out: CheckFinding[] = [];\n const findings = (json as { findings?: unknown })?.findings;\n if (!Array.isArray(findings)) return out;\n for (const f of findings) {\n const rec = f as { code?: unknown; message?: unknown; severity?: unknown };\n const code = String(rec?.code ?? \"\");\n const message = String(rec?.message ?? \"\");\n const severity = String(rec?.severity ?? \"info\");\n const blocking = severity === \"error\" && !isAdvisory(code, message);\n out.push({ source: \"lint\", code, message, severity: blocking ? \"blocking\" : \"warning\" });\n }\n return out;\n}\n\nexport function classifyInspect(json: unknown): CheckFinding[] {\n const out: CheckFinding[] = [];\n const obj = json as { issues?: unknown; ok?: unknown };\n const issues = obj?.issues;\n if (!Array.isArray(issues)) return out;\n for (const iss of issues) {\n const rec = iss as { code?: unknown; type?: unknown; message?: unknown; detail?: unknown; severity?: unknown };\n const code = String(rec?.code ?? rec?.type ?? \"overflow\");\n const message = String(rec?.message ?? rec?.detail ?? JSON.stringify(iss));\n // Overflow clips/clobbers the creative → block on errors. Lesser severities\n // (or unscored issues when the run as a whole passed) only warn.\n const severity = rec?.severity ? String(rec.severity) : obj?.ok === false ? \"error\" : \"warning\";\n out.push({ source: \"inspect\", code, message, severity: severity === \"error\" ? \"blocking\" : \"warning\" });\n }\n return out;\n}\n\nexport function classifyCheckOutput(lintRaw: string, inspectRaw: string): CheckResult {\n const findings = [...classifyLint(parseCheckJson(lintRaw)), ...classifyInspect(parseCheckJson(inspectRaw))];\n return {\n blocking: findings.filter((f) => f.severity === \"blocking\"),\n warnings: findings.filter((f) => f.severity === \"warning\"),\n };\n}\n\nexport function buildLintArgs(dir: string): string[] {\n return [\"hyperframes\", \"lint\", dir, \"--json\"];\n}\n\n// Validate runs OUTSIDE the render (no billed clips yet) and on dev boxes that\n// have no `hyperframes` binary. `--no-install` makes npx fast-fail (ENOENT →\n// degrade) instead of attempting a network download, so validate stays free and\n// flake-proof; in the e2b sandbox the globally-pinned binary still resolves.\nfunction buildLintArgsNoInstall(dir: string): string[] {\n return [\"--no-install\", \"hyperframes\", \"lint\", dir, \"--json\"];\n}\n\n// High-confidence STRUCTURAL gate blockers — the ones that fail a render\n// deterministically regardless of inputs/timing: an untimed background media\n// element (`media_missing_data_start`) and a timed element missing `class=\"clip\"`\n// (which the renderer would then show for the WHOLE composition). These are the\n// failures that killed the Barkibu run AFTER it had billed 11 stills + 5 clips, so\n// validate surfaces ONLY these to predict the gate up front. Deliberately excluded:\n// the linter's input-dependent/advisory findings (contrast, text_occluded, overflow),\n// which need a real render to judge and false-positive on animated-in content; and\n// `caption_transcript_not_inline`, since the transcript is a staged input file at\n// render time, not a real blocker (see NEVER_BLOCK).\nconst VALIDATE_STRUCTURAL_CODES = /media_missing_data_start|timed_element_missing_clip_class/i;\n\nexport function filterStructuralFindings(\n findings: { code: string; message: string }[],\n): { code: string; message: string }[] {\n return findings.filter((f) => VALIDATE_STRUCTURAL_CODES.test(f.code));\n}\n\n/**\n * Validate-time predictive lint. Runs `hyperframes lint` on the composition dir\n * and returns ONLY the structural blockers above. Returns `[]` when the tool is\n * unavailable (degrade gracefully, same as the execute-time gate) — so validate\n * never blocks a valid canvas just because the binary is absent off-sandbox.\n */\n// Memoized per process. The predictive validate lint should run only where\n// `hyperframes` is a first-class INSTALLED tool — i.e. the e2b render sandbox,\n// where the template installs it globally (on PATH). We probe the bare binary on\n// PATH (not `npx`, which on a dev box may resolve it from an incidental package\n// cache and then spend ~1.3s PER node linting fixtures during plain validate).\n// Off-sandbox the probe is an instant ENOENT, so validate stays free and the\n// gate degrades to a no-op exactly as the execute-time check does.\nlet hyperframesAvailable: boolean | null = null;\nasync function isHyperframesAvailable(): Promise<boolean> {\n if (hyperframesAvailable !== null) return hyperframesAvailable;\n try {\n await execFileAsync(\"hyperframes\", [\"--version\"], { timeout: 10_000 });\n hyperframesAvailable = true;\n } catch {\n hyperframesAvailable = false;\n }\n return hyperframesAvailable;\n}\n\nexport async function lintStructuralIssues(\n dir: string,\n timeoutMs: number,\n): Promise<{ code: string; message: string }[]> {\n if (!(await isHyperframesAvailable())) return [];\n const lintRaw = await runOne(buildLintArgsNoInstall(dir), timeoutMs);\n if (lintRaw === null) return [];\n const findings = classifyLint(parseCheckJson(lintRaw)).map((f) => ({ code: f.code, message: f.message }));\n return filterStructuralFindings(findings);\n}\n\nexport function buildInspectArgs(dir: string, samples: number): string[] {\n return [\"hyperframes\", \"inspect\", dir, \"--json\", \"--samples\", String(samples)];\n}\n\nexport function buildSnapshotArgs(dir: string, frames: number): string[] {\n // Disable the Gemini `--describe` vision pass so the gate needs no API key or\n // network — we use snapshot purely as a render-path SMOKE TEST for nested\n // compositions (does the embedded block actually render?), not for analysis.\n return [\"hyperframes\", \"snapshot\", dir, \"--frames\", String(frames), \"--describe\", \"false\"];\n}\n\n// A composition that EMBEDS another (a catalog block wired via data-composition-src)\n// can fail in ways lint + inspect + the studio preview ALL miss — the sub-comp's\n// <style>/<script> landing outside its <template>, a host/internal/timeline id\n// mismatch (a ~45s stall, then no animation), or styling the sub-comp root by class\n// instead of #root. Only an actual render exposes these, so when the host wires a\n// LIVE nested block we additionally run `snapshot` (a real headless render of a few\n// frames) as a smoke test. Comments are stripped first so the seeded EXAMPLE slot\n// (a commented-out data-composition-src) never trips it — only an uncommented,\n// wired embed does.\nexport function usesNestedCompositions(indexHtml: string): boolean {\n const withoutComments = indexHtml.replace(/<!--[\\s\\S]*?-->/g, \"\");\n return /data-composition-src\\s*=/.test(withoutComments);\n}\n\n/**\n * Returns the command's stdout (even on a non-zero exit — `lint`/`inspect` exit\n * non-zero when they FIND issues but still print JSON to stdout), or `null` when\n * the command itself is unavailable/failed to run.\n */\nasync function runOne(args: string[], timeoutMs: number): Promise<string | null> {\n try {\n const { stdout } = await execFileAsync(\"npx\", args, { timeout: timeoutMs, maxBuffer: 64 * 1024 * 1024 });\n return stdout;\n } catch (e) {\n const err = e as { stdout?: string; stderr?: string; message?: string };\n if (err.stdout?.includes(\"{\")) return err.stdout; // findings present, JSON on stdout\n const blob = `${err.stderr ?? \"\"} ${err.message ?? \"\"}`;\n if (UNAVAILABLE.test(blob)) return null; // tool missing → degrade gracefully\n return null; // ran but produced nothing parseable → don't block a valid render\n }\n}\n\n/**\n * Run `snapshot` as a render-path smoke test. Unlike lint/inspect it emits no\n * findings JSON — success is exit 0, failure is a throw. We distinguish the tool\n * being absent (degrade gracefully) from the render actually failing (block).\n */\nasync function runSnapshotSmoke(\n args: string[],\n timeoutMs: number,\n): Promise<{ ok: boolean; unavailable: boolean; message: string }> {\n try {\n await execFileAsync(\"npx\", args, { timeout: timeoutMs, maxBuffer: 64 * 1024 * 1024 });\n return { ok: true, unavailable: false, message: \"\" };\n } catch (e) {\n const err = e as { stderr?: string; stdout?: string; message?: string };\n const blob = `${err.stderr ?? \"\"} ${err.message ?? \"\"}`;\n if (UNAVAILABLE.test(blob)) return { ok: false, unavailable: true, message: blob };\n return { ok: false, unavailable: false, message: (err.stderr || err.message || \"snapshot failed\").slice(0, 800) };\n }\n}\n\nexport async function runHyperframesCheck(opts: {\n dir: string;\n nodeId: string;\n ctx: { log: (s: string) => void };\n timeoutMs: number;\n samples?: number;\n}): Promise<void> {\n const { dir, nodeId, ctx, timeoutMs, samples = 5 } = opts;\n const [lintRaw, inspectRaw] = await Promise.all([\n runOne(buildLintArgs(dir), timeoutMs),\n runOne(buildInspectArgs(dir, samples), timeoutMs),\n ]);\n\n if (lintRaw === null && inspectRaw === null) {\n ctx.log(`${nodeId}: hyperframes lint/inspect unavailable — skipping pre-render check`);\n return;\n }\n\n const { blocking, warnings } = classifyCheckOutput(lintRaw ?? \"\", inspectRaw ?? \"\");\n for (const w of warnings) {\n ctx.log(`${nodeId}: hyperframe check warning [${w.source}/${w.code}] ${w.message}`);\n }\n if (blocking.length > 0) {\n const detail = blocking.map((b) => `• [${b.source}/${b.code}] ${b.message}`).join(\"\\n\");\n throw new Error(`${nodeId}: pre-render check failed (${blocking.length} blocking)\\n${detail}`);\n }\n\n // Extra gate for nested compositions: lint/inspect/preview can't see a broken\n // embed, only a real render can (see usesNestedCompositions). Runs after the\n // cheap static checks pass, and only when a live data-composition-src is wired.\n let indexHtml = \"\";\n try {\n indexHtml = await readFile(path.join(dir, \"index.html\"), \"utf-8\");\n } catch {\n indexHtml = \"\";\n }\n if (indexHtml && usesNestedCompositions(indexHtml)) {\n // Snapshot is a real headless render — orders of magnitude slower than the\n // static lint/inspect that just ran (and which already spent `timeoutMs`). Give\n // it its own generous budget so a slow CI/sandbox runner doesn't get a valid\n // composition blocked as a \"smoke test failure\" on a timeout (ETIMEDOUT isn't an\n // UNAVAILABLE signal, so it would otherwise hard-block).\n const snap = await runSnapshotSmoke(buildSnapshotArgs(dir, Math.min(samples, 3)), Math.max(timeoutMs, 120_000));\n if (snap.unavailable) {\n ctx.log(`${nodeId}: hyperframes snapshot unavailable — skipping nested-composition smoke test`);\n } else if (!snap.ok) {\n throw new Error(\n `${nodeId}: nested-composition smoke test failed — an embedded block did not render. ` +\n `Check the host↔block id match, that the block's <style>/<script> live inside its <template>, ` +\n `and that it styles #root (not a class).\\n${snap.message}`,\n );\n } else {\n ctx.log(`${nodeId}: nested-composition smoke test passed`);\n }\n }\n\n ctx.log(`${nodeId}: pre-render check passed (${warnings.length} warning${warnings.length === 1 ? \"\" : \"s\"})`);\n}\n","// Map noisy Hyperframes/ffmpeg/Chromium stderr into actionable messages.\n// Each entry's `match` is tested in order — first hit wins. The matcher\n// returns the friendly message (with a suggested next step) or null when\n// no pattern applies; callers fall back to raw stderr.\n//\n// New patterns: add an entry; the engine doesn't need updating.\n\ntype Pattern = {\n match: RegExp;\n message: (m: RegExpMatchArray) => string;\n};\n\nconst KNOWN_ERROR_PATTERNS: Pattern[] = [\n {\n match: /Variable issue[^\\n]*\\bduration\\b[^\\n]*not declared/i,\n message: () =>\n `Variable \"duration\" cannot be passed in params or declared in the composition — the engine injects it from the input video's duration. Remove \"duration\" from params.`,\n },\n {\n match: /BeginFrame auto-worker calibration timed out/i,\n message: () =>\n `Hyperframes' renderer is overloaded calibrating its frame workers. Try params.quality = \"draft\", params.workers = 2, or split the composition into smaller pieces.`,\n },\n {\n match: /media_missing_id:\\s*<audio>/i,\n message: () =>\n `A <audio> element in the composition is missing an \"id\" attribute. Add id=\"…\" (e.g. id=\"bg-audio\") so Hyperframes can discover it.`,\n },\n {\n match: /media_missing_id:\\s*<video>/i,\n message: () =>\n `A <video> element in the composition is missing an \"id\" attribute. Add id=\"…\" (e.g. id=\"bg\") so Hyperframes can discover it.`,\n },\n {\n match: /Overlapping clips? detected/i,\n message: () =>\n `Two clip elements overlap in time. Shave 1 ms off the previous clip's data-duration to introduce a sub-frame gap, or re-stitch upstream with the ffmpeg node.`,\n },\n {\n match: /ENOENT[^\\n]*gsap\\.min\\.js/i,\n message: () =>\n `Composition references ./gsap.min.js but the file wasn't found in the render directory. The engine vendors gsap from node_modules; ensure 'gsap' is installed in the CLI package, or self-supply gsap.min.js inside your composition directory.`,\n },\n {\n match: /chromium.*could not be launched|Executable doesn't exist/i,\n message: () =>\n `Headless Chrome is missing. Install Playwright Chromium (\\`pnpm exec playwright install chromium\\`) or run with params.docker = true for a sandboxed render.`,\n },\n];\n\nexport function mapKnownHyperframesError(stderr: string): string | null {\n if (!stderr) return null;\n for (const pattern of KNOWN_ERROR_PATTERNS) {\n const m = stderr.match(pattern.match);\n if (m) return `${pattern.message(m)}\\n\\n--- raw output ---\\n${stderr.slice(0, 1500)}`;\n }\n return null;\n}\n","import { writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { CompositionMeta } from \"../../../engine/composition-meta.ts\";\n\n/**\n * Write the top-level `meta.json` Hyperframes itself reads (next to index.html)\n * with {id,name,duration,width,height,fps}. We always overwrite with the\n * engine's values so Hyperframes' interpretation matches ours. Shared by\n * `hyperframe_render` (before render) and `hyperframe_snapshot` (before the\n * pre-render `lint`/`inspect` gate, which reads this file).\n */\nexport async function ensureHyperframesMetaJson(\n tmp: string,\n nodeId: string,\n meta: CompositionMeta,\n duration: number,\n): Promise<void> {\n const metaPath = path.join(tmp, \"meta.json\");\n await writeFile(\n metaPath,\n JSON.stringify(\n {\n id: nodeId,\n name: meta.id,\n duration,\n width: meta.width,\n height: meta.height,\n fps: meta.fps,\n },\n null,\n 2,\n ),\n \"utf-8\",\n );\n}\n","// Single-substitution model used by the composition pipeline.\n//\n// {{var}} in HTML, embedded <style>, embedded <script>\n// ─────► replaced before render by `substituteVariables`\n//\n// String values are inlined as JS-safe literals (`JSON.stringify`-style for\n// numbers, booleans, null, and complex structures; raw text in HTML attribute\n// or text contexts). The engine does the safe stringify — composition authors\n// never call `JSON.parse` again.\n\nconst PATTERN = /\\{\\{\\s*([A-Za-z_][A-Za-z0-9_]*)\\s*\\}\\}/g;\n\n/**\n * Replace every `{{name}}` token in `source` with the JS literal form of\n * `values[name]`. Strings render as their plain text (no surrounding quotes\n * — convenient for both `font-size: {{size_px}}px` and `var X = {{name}};`).\n *\n * Complex values (arrays/objects/numbers/booleans) render via JSON.stringify\n * so the result is a syntactically valid JS literal **and** valid JSON.\n *\n * Missing keys are reported in the returned `missing` array; the engine\n * collects these and surfaces a single aggregated error.\n */\nexport function substituteVariables(\n source: string,\n values: Record<string, unknown>,\n): { output: string; missing: string[]; replaced: string[] } {\n const missing: string[] = [];\n const replaced: string[] = [];\n const seenMissing = new Set<string>();\n const seenReplaced = new Set<string>();\n\n const output = source.replace(PATTERN, (_full, name: string) => {\n if (!Object.hasOwn(values, name)) {\n if (!seenMissing.has(name)) {\n missing.push(name);\n seenMissing.add(name);\n }\n return `{{${name}}}`;\n }\n if (!seenReplaced.has(name)) {\n replaced.push(name);\n seenReplaced.add(name);\n }\n return literalize(values[name]);\n });\n\n return { output, missing, replaced };\n}\n\n/**\n * Render a value as a JS-safe literal embeddable in source code.\n *\n * string → plain text (no quotes — embed inside `\"…\"` if you need a string literal)\n * number → toString() (NaN/Infinity → \"0\")\n * boolean → \"true\" / \"false\"\n * null → \"null\"\n * array/object → JSON.stringify (also valid JS literal)\n * undefined → \"null\"\n *\n * The plain-text behavior for strings is deliberate: most composition uses\n * are HTML attributes or CSS values where surrounding quotes are author-supplied.\n * Authors who need a JS string literal write `\"{{name}}\"` themselves.\n */\nfunction literalize(value: unknown): string {\n if (value === undefined || value === null) return \"null\";\n if (typeof value === \"string\") return value;\n if (typeof value === \"number\") {\n if (!Number.isFinite(value)) return \"0\";\n return String(value);\n }\n if (typeof value === \"boolean\") return value ? \"true\" : \"false\";\n // Arrays, objects: JSON.stringify produces valid JS *and* JSON.\n return JSON.stringify(value);\n}\n\n/**\n * List every `{{name}}` token referenced in `source`. Used by validators to\n * cross-check declared params vs. tokens actually present in the composition.\n */\nexport function extractReferencedTokens(source: string): string[] {\n const out = new Set<string>();\n for (const m of source.matchAll(PATTERN)) {\n const name = m[1];\n if (name) out.add(name);\n }\n return [...out];\n}\n","import { execFile } from \"node:child_process\";\nimport { copyFile, mkdtemp, readFile, rm, writeFile } from \"node:fs/promises\";\nimport { createRequire } from \"node:module\";\nimport { tmpdir } from \"node:os\";\nimport path from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { z } from \"zod\";\nimport { hashCompositionDir } from \"../../engine/composition-hash.ts\";\nimport {\n buildParamsSchema,\n type CompositionMeta,\n defaultFilenameForInput,\n loadCompositionMeta,\n} from \"../../engine/composition-meta.ts\";\nimport { defineNode } from \"../../engine/define.ts\";\nimport type { AssetRef } from \"../../schema/refs.ts\";\nimport { assertInputsMatchMeta, resolveCompositionDir, validateCompositionParams } from \"./hyperframe.ts\";\nimport { isAssetRefLike, refToUrl, type StageableRef, stageAsset } from \"./lib/assets.ts\";\nimport { runHyperframesCheck } from \"./lib/hyperframe-check.ts\";\nimport { mapKnownHyperframesError } from \"./lib/hyperframe-errors.ts\";\nimport { ensureHyperframesMetaJson } from \"./lib/hyperframe-meta.ts\";\nimport { substituteVariables } from \"./lib/templating.ts\";\n\nconst _execFileAsync = promisify(execFile);\nconst require_ = createRequire(import.meta.url);\n\nconst WaitForSpec = z.discriminatedUnion(\"kind\", [\n z.object({ kind: z.literal(\"auto\") }),\n z.object({ kind: z.literal(\"selector\"), value: z.string().min(1) }),\n z.object({ kind: z.literal(\"function\"), value: z.string().min(1) }),\n z.object({ kind: z.literal(\"timeout\"), ms: z.number().int().min(0).max(60_000) }),\n]);\n\n// Output is always rendered at the composition's declared width/height at 2x\n// device-scale (retina) for ad delivery. No knobs for full-page or transparent\n// background — composition controls the canvas size and background.\nconst HyperframeSnapshotParams = z\n .object({\n composition: z.string().min(1),\n wait_for: WaitForSpec.optional().default({ kind: \"auto\" }),\n timeout_ms: z.number().int().positive().optional().default(60_000),\n })\n .catchall(z.unknown());\n\nconst HyperframeSnapshotInputs = z.record(z.string(), z.custom<AssetRef>()).optional().default({});\n\nconst HyperframeSnapshotOutputs = z\n .object({\n image: z.custom<AssetRef>(),\n })\n .strict();\n\nconst NODE_OWNED_PARAM_KEYS = new Set([\"composition\", \"wait_for\", \"timeout_ms\"]);\n\n// Retina export — fixed for ad-creative delivery.\nconst DEVICE_SCALE_FACTOR = 2;\n\ntype Params = z.infer<typeof HyperframeSnapshotParams>;\n\nexport const hyperframeSnapshotNode = defineNode({\n id: \"hyperframe_snapshot\",\n version: \"4.1.0\",\n category: \"image\",\n location: \"local\",\n summary:\n \"Render an HTML/CSS composition to a static PNG via headless Chromium at 2x device-scale (retina). Same composition model as `hyperframe_render` — point `params.composition` at a directory containing `index.html` + `meta.json`.\",\n when_to_use:\n \"Use for static visuals composed from HTML/CSS: UI mockups, branded social posts, text overlays, multi-image grids. \" +\n \"Point `params.composition` at a directory containing `index.html` + `meta.json`. \" +\n \"Inputs are keyed by `meta.json.inputs`. \" +\n \"Output size: composition `meta.json` width/height × 2 (retina). \" +\n '`wait_for` defaults to `\"auto\"` which waits for page `load` + all `<img>` decoded + web fonts ready.',\n inputs: HyperframeSnapshotInputs,\n params: HyperframeSnapshotParams,\n outputs: HyperframeSnapshotOutputs,\n cost: () => ({ credits: 0, seconds_estimate: 3 }),\n\n validateExtra: ({ rawParams }) => validateCompositionParams(rawParams),\n\n cacheKeyExtras: async ({ params }) => {\n const out: Record<string, string> = {};\n const composition = (params as { composition?: unknown }).composition;\n if (typeof composition !== \"string\") return out;\n const dir = await resolveCompositionDir(composition).catch(() => null);\n if (!dir) return out;\n out.composition_content_sha = await hashCompositionDir(dir);\n return out;\n },\n\n async execute({ inputs, params, ctx }) {\n const compositionDir = await resolveCompositionDir(params.composition);\n const meta = await loadCompositionMeta(compositionDir);\n const compositionParams = validateAndParseDynamicParams(meta, params);\n\n const tmp = await mkdtemp(path.join(tmpdir(), \"hf-snap-\"));\n try {\n await copyComposition(compositionDir, tmp);\n await vendorGsap(tmp, ctx);\n await stageInputs(tmp, inputs, meta, ctx);\n\n const substitutionValues = await buildSubstitutionValues(compositionParams, meta);\n await substituteCompositionFiles(tmp, substitutionValues);\n\n // Pre-render quality gate on the SUBSTITUTED composition: lint + inspect.\n // `inspect` reads the top-level meta.json, so write it first. One sample\n // is enough for a still. Overflow/structural errors block; contrast +\n // deferred-asset advisories only warn; missing tool degrades gracefully.\n await ensureHyperframesMetaJson(tmp, ctx.nodeId, meta, meta.default_duration);\n await runHyperframesCheck({\n dir: tmp,\n nodeId: \"hyperframe_snapshot\",\n ctx,\n timeoutMs: params.timeout_ms,\n samples: 1,\n });\n\n const entryPath = path.join(tmp, \"index.html\");\n const entryUrl = `file://${entryPath}`;\n ctx.log(`snapshotting ${meta.width}x${meta.height}@${DEVICE_SCALE_FACTOR}x wait=${params.wait_for.kind}`);\n\n const pwSpecifier = [\"play\", \"wright\"].join(\"\");\n const playwright = require_(pwSpecifier) as typeof import(\"playwright\");\n const { chromium } = playwright;\n const browser = await chromium.launch({ headless: true });\n try {\n const context = await browser.newContext({\n viewport: { width: meta.width, height: meta.height },\n deviceScaleFactor: DEVICE_SCALE_FACTOR,\n });\n const page = await context.newPage();\n await page.goto(entryUrl, { waitUntil: \"load\", timeout: params.timeout_ms });\n\n await waitForReady(page, params.wait_for, params.timeout_ms);\n\n const bytes = await page.screenshot({ type: \"png\" });\n\n ctx.log(`captured ${bytes.length} bytes`);\n const ref = await ctx.assets.ingestBytes({\n bytes: Buffer.from(bytes),\n kind: \"image\",\n mime: \"image/png\",\n metadata: {\n width: meta.width * DEVICE_SCALE_FACTOR,\n height: meta.height * DEVICE_SCALE_FACTOR,\n },\n });\n return { image: ref };\n } finally {\n await browser.close();\n }\n } catch (e) {\n const detail = (e as Error).message;\n const friendly = mapKnownHyperframesError(detail);\n if (friendly) throw new Error(`hyperframe_snapshot: ${friendly}`);\n throw e;\n } finally {\n await rm(tmp, { recursive: true, force: true }).catch((cleanupErr) => {\n ctx.log(`warning: tmp cleanup failed (${(cleanupErr as Error).message})`);\n });\n }\n },\n});\n\nfunction validateAndParseDynamicParams(meta: CompositionMeta, params: Params): Record<string, unknown> {\n const dynamic: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(params)) {\n if (NODE_OWNED_PARAM_KEYS.has(k)) continue;\n dynamic[k] = v;\n }\n const schema = buildParamsSchema(meta);\n const parsed = schema.safeParse(dynamic);\n if (!parsed.success) {\n const summary = parsed.error.issues.map((i) => `params.${i.path.join(\".\")}: ${i.message}`).join(\"; \");\n throw new Error(`hyperframe_snapshot: composition param validation failed — ${summary}`);\n }\n return parsed.data;\n}\n\nasync function copyComposition(srcDir: string, destDir: string): Promise<void> {\n const { cp } = await import(\"node:fs/promises\");\n await cp(srcDir, destDir, {\n recursive: true,\n filter: (src) => {\n const name = path.basename(src);\n if (name === \".cache\" || name === \"node_modules\" || name === \".git\") return false;\n return true;\n },\n });\n}\n\nasync function vendorGsap(tmp: string, ctx: { log: (s: string) => void }): Promise<void> {\n try {\n const gsapMin = require_.resolve(\"gsap/dist/gsap.min.js\");\n await copyFile(gsapMin, path.join(tmp, \"gsap.min.js\"));\n } catch (e) {\n ctx.log(`warning: could not vendor gsap.min.js (${(e as Error).message}); compositions must self-supply`);\n }\n}\n\nasync function stageInputs(\n tmp: string,\n inputs: Record<string, AssetRef>,\n meta: CompositionMeta,\n ctx: { log: (s: string) => void },\n): Promise<void> {\n assertInputsMatchMeta(inputs, meta, \"hyperframe_snapshot\");\n for (const [key, ref] of Object.entries(inputs ?? {})) {\n const spec = meta.inputs[key];\n if (!spec) continue;\n const filename = spec.staged_as ?? defaultFilenameForInput(key, spec.kind);\n await stageAsset(ref as StageableRef, tmp, filename);\n ctx.log(`staged ${spec.kind} → ${filename}`);\n }\n}\n\nasync function buildSubstitutionValues(\n compositionParams: Record<string, unknown>,\n meta: CompositionMeta,\n): Promise<Record<string, unknown>> {\n const out: Record<string, unknown> = {};\n for (const [name, value] of Object.entries(compositionParams)) {\n const spec = meta.params[name];\n if (spec?.kind === \"image\") {\n out[name] = await coerceImageParam(value);\n continue;\n }\n out[name] = value;\n }\n // Snapshots have no real duration; expose a sensible value for compositions\n // shared with hyperframe_render that reference {{duration}}.\n out.duration = meta.default_duration.toFixed(3);\n return out;\n}\n\nfunction coerceImageParam(value: unknown): Promise<string> {\n if (typeof value === \"string\") return Promise.resolve(value);\n if (isAssetRefLike(value)) return refToUrl(value);\n throw new Error(\"hyperframe_snapshot: image param must be a URL string or AssetRef\");\n}\n\nasync function substituteCompositionFiles(tmp: string, values: Record<string, unknown>): Promise<void> {\n const entryPath = path.join(tmp, \"index.html\");\n const original = await readFile(entryPath, \"utf-8\");\n const { output, missing } = substituteVariables(original, values);\n if (missing.length > 0) {\n throw new Error(\n `hyperframe_snapshot: composition references undefined variables: ${missing.map((m) => `{{${m}}}`).join(\", \")}.`,\n );\n }\n await writeFile(entryPath, output, \"utf-8\");\n}\n\nasync function waitForReady(\n page: import(\"playwright\").Page,\n waitFor: Params[\"wait_for\"],\n timeoutMs: number,\n): Promise<void> {\n switch (waitFor.kind) {\n case \"auto\":\n await page.evaluate(async () => {\n const imgs = Array.from(document.images);\n await Promise.all(\n imgs.map((img) =>\n img.complete && img.naturalWidth > 0 ? Promise.resolve() : img.decode().catch(() => undefined),\n ),\n );\n if (document.fonts && typeof document.fonts.ready?.then === \"function\") {\n await document.fonts.ready;\n }\n });\n return;\n case \"selector\":\n await page.waitForSelector(waitFor.value, { timeout: timeoutMs });\n return;\n case \"function\":\n await page.waitForFunction(waitFor.value, undefined, { timeout: timeoutMs });\n return;\n case \"timeout\":\n await page.waitForTimeout(waitFor.ms);\n return;\n default: {\n const _exhaustive: never = waitFor;\n throw new Error(`hyperframe_snapshot: unknown wait_for kind ${(_exhaustive as { kind: string }).kind}`);\n }\n }\n}\n","import { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { z } from \"zod\";\nimport { defineNode } from \"../../engine/define.ts\";\nimport type { AssetRef } from \"../../schema/refs.ts\";\nimport { getToolVersion, runCli } from \"./lib/cli-runner.ts\";\n\nconst execFileAsync = promisify(execFile);\n\nconst OutputDecl = z\n .object({\n kind: z.enum([\"image\", \"video\", \"audio\"]),\n ext: z.string().min(1).max(8),\n })\n .strict();\n\nconst ImageMagickParams = z\n .object({\n args: z.array(z.string()).min(1),\n outputs: z.record(z.string(), OutputDecl).default({}),\n })\n .strict();\n\nconst ImageMagickInputs = z.record(z.string(), z.unknown());\n\nconst ImageMagickOutputs = z.record(z.string(), z.custom<AssetRef>());\n\n/**\n * Resolve which ImageMagick binary to use. Prefer `magick` (v7+); fall back to\n * `convert` (v6). Memoized per process; if neither is on PATH we fail at\n * execute time with a clear message.\n */\nlet resolvedBin: string | undefined;\nasync function resolveBin(): Promise<string> {\n if (resolvedBin) return resolvedBin;\n for (const candidate of [\"magick\", \"convert\"] as const) {\n try {\n await execFileAsync(candidate, [\"-version\"], { encoding: \"utf-8\" });\n resolvedBin = candidate;\n return candidate;\n } catch {\n // try next candidate\n }\n }\n throw new Error(\"imagemagick: neither `magick` nor `convert` found on PATH\");\n}\n\nexport const imagemagickNode = defineNode({\n id: \"imagemagick\",\n version: \"1.0.0\",\n category: \"image\",\n location: \"local\",\n summary:\n \"Local ImageMagick passthrough. Declare inputs, declare outputs, write the argv you'd type on the command line. Inputs are staged into a tmp dir and reached via `{{in.<slot>}}`; declared outputs are allocated at `{{out.<name>}}` and ingested as assets when the run completes.\",\n when_to_use:\n \"Use whenever you'd reach for ImageMagick on the command line: resize, crop, composite, convert formats, annotate, montage, fx. Pass the full argv as `params.args` (no shell — argv array, no string interpolation). \" +\n \"Wire input images via `inputs.<slot>` (single AssetRef) or `inputs.<slot>: [...]` (array, addressed as `{{in.<slot>.0}}`, …). \" +\n \"Declare every output file under `params.outputs` (name → {kind, ext}); the engine allocates the path, you reference it with `{{out.<name>}}`. \" +\n \"Requires `magick` (v7+) or `convert` (v6) on PATH. URL-style inputs and raw filesystem paths in args are rejected — keep everything in the engine's asset model.\",\n inputs: ImageMagickInputs,\n params: ImageMagickParams,\n outputs: ImageMagickOutputs,\n cost: () => ({ credits: 0, seconds_estimate: 3 }),\n\n async cacheKeyExtras() {\n const bin = await resolveBin().catch(() => \"imagemagick:unavailable\");\n return { imagemagick_version: await getToolVersion(bin) };\n },\n\n async execute({ inputs, params, ctx }) {\n const bin = await resolveBin();\n return await runCli({\n bin,\n args: params.args,\n inputs: inputs as Record<string, AssetRef | AssetRef[]>,\n outputs: params.outputs,\n ctx,\n });\n },\n});\n","import { z } from \"zod\";\nimport { defineNode } from \"../../engine/define.ts\";\n\nexport const textNode = defineNode({\n id: \"text\",\n version: \"1.0.0\",\n category: \"data\",\n location: \"local\",\n summary: \"A literal text value. Use for prompts, descriptions, copy.\",\n inputs: z.object({}).strict(),\n params: z.object({ value: z.string() }).strict(),\n outputs: z.object({ text: z.string() }).strict(),\n cost: () => ({ credits: 0, seconds_estimate: 0 }),\n execute: ({ params }) => Promise.resolve({ text: params.value }),\n});\n","import { z } from \"zod\";\nimport { AudioRef, TextRef } from \"../../schema/refs.ts\";\nimport { delegated } from \"./delegate.ts\";\n\nconst AudioVoiceConvertParams = z\n .object({\n model: z.literal(\"elevenlabs/eleven_multilingual_sts_v2\"),\n /** Target voice id. Splice an upstream `voice_select` via `\"{{voice_ref}}\"`. */\n voice: z.string().min(1),\n output_format: z.string().optional(),\n /** Strip the source clip's background noise before re-voicing. */\n remove_background_noise: z.boolean().optional(),\n })\n .strict();\n\nexport const audioVoiceConvertNode = delegated({\n id: \"audio_voice_convert\",\n version: \"1.0.0\",\n category: \"audio\",\n summary:\n \"Voice Changer / speech-to-speech via ElevenLabs (eleven_multilingual_sts_v2). Re-voices an existing audio clip in a TARGET voice while preserving timing/prosody.\",\n when_to_use:\n 'Use to normalize a generator-chosen voice (e.g. a Seedance talking-head clip\\'s native audio) into ONE consistent brand voice across every scene — the cadence is preserved so any lip-sync stays valid. Wire `inputs.voice_ref: $ref:<voice_select>.voice_id` and set `params.voice: \"{{voice_ref}}\"`.',\n inputs: z\n .object({\n audio: AudioRef,\n voice_ref: TextRef.optional(),\n })\n .strict(),\n params: AudioVoiceConvertParams,\n outputs: z.object({ audio: AudioRef }).strict(),\n outputKinds: { audio: \"audio\" },\n cost: () => ({ credits: 1, seconds_estimate: 20 }),\n});\n","import { ELEVENLABS_MAX_TEXT_CHARS, ELEVENLABS_OUTPUT_FORMATS } from \"@baker/canvas-contract\";\nimport { z } from \"zod\";\nimport { AudioRef, JsonRef } from \"../../schema/refs.ts\";\nimport { delegated } from \"./delegate.ts\";\n\nconst DialogueInput = z.object({\n text: z.string().min(1),\n voice_id: z.string().min(1),\n});\n\nconst DIALOGUE_MODELS = [\"elevenlabs/eleven_v3\"] as const;\n\nconst DialogueParams = z\n .object({\n model: z.enum(DIALOGUE_MODELS),\n /**\n * Ordered list of lines, each tagged with the voice that should speak it.\n * Up to 10 unique voice_ids; total text across all lines should stay under\n * ~2000 characters for best quality (ElevenLabs guidance).\n */\n inputs: z.array(DialogueInput).min(1).max(50),\n language_code: z.string().optional(),\n /** ElevenLabs voice/model settings passthrough (e.g. `{ stability: 0.5 }`). */\n settings: z.record(z.string(), z.unknown()).optional(),\n seed: z.number().int().min(0).max(4_294_967_295).optional(),\n apply_text_normalization: z.enum([\"auto\", \"on\", \"off\"]).optional(),\n /**\n * When true, hits `/v1/text-to-dialogue/with-timestamps` and emits a\n * separate `timestamps` output — character-level alignment plus\n * per-voice segment markers usable for captions, lipsync, or\n * beat-matched cuts in ad creatives.\n */\n with_timestamps: z.boolean().optional(),\n output_format: z.enum(ELEVENLABS_OUTPUT_FORMATS).optional(),\n })\n .strict()\n // Above this the backend's $10 cost cap always rejects at dispatch.\n .refine((p) => p.inputs.reduce((sum, line) => sum + line.text.length, 0) <= ELEVENLABS_MAX_TEXT_CHARS, {\n message: `total dialogue text exceeds ${ELEVENLABS_MAX_TEXT_CHARS} characters`,\n path: [\"inputs\"],\n });\n\nexport const dialogueNode = delegated({\n id: \"dialogue\",\n version: \"1.1.0\",\n category: \"audio\",\n summary:\n \"Multi-voice dialogue / VO with ElevenLabs Eleven v3. Each line is tagged with a `voice_id`, so you can render two-character scripts (e.g. ad VO + customer testimonial reaction) in a single call. Setting `with_timestamps: true` adds character-level alignment for caption rendering and lipsync-friendly cuts.\",\n when_to_use:\n \"Use for any ad creative or website video VO that needs more than narration — interviews, two-actor scripts, character ads, testimonial reads. For single-voice flat reads the existing `tts` node is cheaper and simpler; reach for `dialogue` when you need multiple speakers in one stitched track or word-level timing for downstream lipsync / captions.\",\n inputs: z.object({}).loose(),\n params: DialogueParams,\n outputs: z.object({ audio: AudioRef, timestamps: JsonRef.optional() }).strict(),\n outputKinds: { audio: \"audio\", timestamps: \"json\" },\n cost: ({ params }) => {\n const chars = params.inputs.reduce((sum, line) => sum + line.text.length, 0);\n return { credits: Math.max(1, Math.ceil(chars * 0.0015)), seconds_estimate: 8 };\n },\n});\n","import { z } from \"zod\";\nimport { ImageRef } from \"../../schema/refs.ts\";\nimport { delegated } from \"./delegate.ts\";\n\nconst IMAGE_GENERATE_MODELS = [\n \"openai/gpt-image-2\",\n // Legacy — see the registry entry; kept so pre-switch canvases still run.\n \"openai/gpt-5.4-image-2\",\n \"google/gemini-3.1-flash-image-preview\",\n \"google/gemini-3-pro-image-preview\",\n \"recraft/recraft-v4.1-pro-vector\",\n] as const;\n\n// Permissive union of every param accepted by any curated model. The model\n// registry (`@baker/canvas-contract`) is the strict per-model gate — it rejects\n// params that a specific model doesn't support and validates enum values.\nconst ImageGenerateParams = z\n .object({\n model: z.enum(IMAGE_GENERATE_MODELS),\n prompt: z.string().min(1),\n aspect_ratio: z\n .enum([\"1:1\", \"16:9\", \"9:16\", \"4:3\", \"3:4\", \"3:2\", \"2:3\", \"4:5\", \"5:4\", \"21:9\", \"1:4\", \"4:1\", \"1:8\", \"8:1\"])\n .optional(),\n image_size: z.enum([\"0.5K\", \"1K\", \"2K\", \"4K\"]).optional(),\n // Rendering quality. OpenRouter models without a quality knob ignore it; the\n // registry gates which models accept it (gpt-image, Gemini).\n quality: z.enum([\"auto\", \"low\", \"medium\", \"high\"]).optional(),\n // Recraft v4 vector controls, sent as the provider's own `controls` block.\n // Registry rejects them on non-Recraft models.\n strength: z.number().min(0).max(1).optional(),\n rgb_colors: z.array(z.array(z.number().int().min(0).max(255))).optional(),\n background_rgb_color: z.array(z.number().int().min(0).max(255)).optional(),\n })\n .strict();\n\nexport const imageGenerateNode = delegated({\n id: \"image_generate\",\n version: \"2.2.0\",\n category: \"image\",\n summary:\n \"Generate images for ad creatives. Curated model set: GPT Image 2, Gemini 3.1 Flash Image Preview, Gemini 3 Pro Image, Recraft v4.1 Pro Vector. Per-model param support comes from the canvas-engine model registry.\",\n when_to_use:\n \"Use for hero shots, product photography, illustrations, and vector logos. `recraft/recraft-v4.1-pro-vector` for crisp vector / logo work; `openai/gpt-image-2` for photorealistic and in-image text (NOTE: it has no `image_size`, and no 4:5 / 5:4 — route portrait ad formats through Gemini or `image_aspect_adapt`); Gemini variants for fast iteration, extreme ratios, and editing via the `reference` input. `reference` accepts ONE image or an ARRAY of images — wire several to combine references in a single generation (e.g. a subject sheet + a font specimen + the original ad). Every reference is forwarded to the model in array order.\",\n // `reference` is one image or an ordered array of images. The backend forwards\n // each as a separate `image_url` to the provider (OpenRouter accepts many).\n inputs: z.object({ reference: z.union([ImageRef, z.array(ImageRef).min(1)]).optional() }).loose(),\n params: ImageGenerateParams,\n outputs: z.object({ images: z.array(ImageRef).min(1) }).strict(),\n outputKinds: { images: \"image\" },\n cost: () => ({ credits: 5, seconds_estimate: 10 }),\n});\n","import { AD_FORMAT_PLATFORMS, type AdFormatPlatform, resolveAdaptFormats } from \"@baker/canvas-contract\";\nimport { z } from \"zod\";\nimport { ImageRef } from \"../../schema/refs.ts\";\nimport { delegated } from \"./delegate.ts\";\n\nconst ASPECT_ADAPT_MODELS = [\"google/gemini-3-pro-image-preview\", \"google/gemini-3.1-flash-image-preview\"] as const;\n\n// Ad-format ratios only — shared by both models. The extreme banner ratios\n// (1:8, 8:1…) are deliberately excluded: this node adapts ad creatives, and\n// the registry cannot gate array elements per model.\nconst ASPECT_ADAPT_FORMATS = [\"1:1\", \"2:3\", \"3:2\", \"3:4\", \"4:3\", \"4:5\", \"5:4\", \"9:16\", \"16:9\", \"21:9\"] as const;\n\n// The adaptation prompt is baked into the backend handler (consistency-first,\n// direction-aware recomposition); `guidance` appends hints, never replaces it.\n// Targets come from EITHER an explicit `formats` list OR a `platform` preset\n// (Meta / LinkedIn / Google / TikTok / YouTube) that expands to the canonical\n// on-grid set — exactly one of the two, enforced here (the registry can't).\nconst ImageAspectAdaptParams = z\n .object({\n model: z.enum(ASPECT_ADAPT_MODELS),\n formats: z\n .array(z.enum(ASPECT_ADAPT_FORMATS))\n .min(1)\n .max(6)\n .refine((formats) => new Set(formats).size === formats.length, { message: \"formats must be unique\" })\n .optional(),\n platform: z.enum(AD_FORMAT_PLATFORMS).optional(),\n guidance: z.string().min(1).optional(),\n image_size: z.enum([\"0.5K\", \"1K\", \"2K\", \"4K\"]).optional(),\n })\n .strict()\n .refine((p) => (p.formats === undefined) !== (p.platform === undefined), {\n message: \"provide exactly one of `formats` (explicit ratios) or `platform` (a placement preset)\",\n path: [\"formats\"],\n });\n\nexport const imageAspectAdaptNode = delegated({\n id: \"image_aspect_adapt\",\n version: \"1.0.0\",\n category: \"image\",\n summary:\n \"Adapt ONE creative into multiple aspect ratios (Meta: 9:16 stories, 1:1 feed, 4:5, 16:9…) in a single step. Give it either an explicit `formats` list OR a `platform` preset (meta_feed, meta_feed_stories, meta_all, linkedin, google_demandgen, tiktok, youtube) that expands to that platform's canonical set. AI recomposes the layout per format — identical subject, text, logos, colors, and style; the scene is extended/restructured, never stretched or cropped. Formats that already match the source ratio pass through unchanged at zero cost. Outputs are ordered exactly as the resolved format list.\",\n when_to_use:\n \"Use after a hero creative exists (image_generate, ingest, image_search) to fan it out to every placement format — wire the creative into `source` and set EITHER `formats` (exact ratios) OR `platform` (e.g. `meta_feed_stories`). Cost is estimated per format; formats matching the source ratio are free pass-throughs. Off-grid platform targets (e.g. Google 1.91:1) are not rendered here — crop them from the nearest ratio with `baker images crop`. Pick `google/gemini-3.1-flash-image-preview` (Nano Banana flash) while iterating, `google/gemini-3-pro-image-preview` (Nano Banana Pro) for final-quality adaptation.\",\n inputs: z.object({ source: ImageRef }).loose(),\n params: ImageAspectAdaptParams,\n outputs: z.object({ images: z.array(ImageRef).min(1) }).strict(),\n outputKinds: { images: \"image\" },\n cost: ({ params }) => {\n const p = params as { model?: string; formats?: string[]; platform?: AdFormatPlatform } | undefined;\n const count = Math.max(1, resolveAdaptFormats(p ?? {}).length);\n return {\n credits: count * (p?.model === \"google/gemini-3-pro-image-preview\" ? 20 : 5),\n seconds_estimate: 30 + 30 * count,\n };\n },\n});\n","import { z } from \"zod\";\nimport { ImageRef } from \"../../schema/refs.ts\";\nimport { delegated } from \"./delegate.ts\";\n\nconst ImageBackgroundRemoveParams = z\n .object({\n model: z.literal(\"fal/birefnet-v2\").optional().default(\"fal/birefnet-v2\"),\n model_variant: z\n .enum([\"General Use (Light)\", \"General Use (Heavy)\", \"Matting\", \"Portrait\", \"DIS\", \"HRSOD\", \"COD\"])\n .optional()\n .default(\"General Use (Light)\"),\n operating_resolution: z.enum([\"1024x1024\", \"2048x2048\", \"2304x2304\"]).optional(),\n mask_only: z.boolean().optional().default(false),\n })\n .strict();\n\nexport const imageBackgroundRemoveNode = delegated({\n id: \"image_background_remove\",\n version: \"1.0.0\",\n category: \"image\",\n summary:\n \"Remove the background from an image and return a transparent PNG (or the segmentation mask). Powered by fal.ai `fal-ai/birefnet/v2`.\",\n when_to_use:\n \"Use to extract subjects from photos for use as overlays in hyperframe compositions, product shots, or compositing pipelines. \" +\n \"Set `mask_only:true` to return the binary mask instead of the alpha-cut image.\",\n inputs: z\n .object({\n image: ImageRef,\n })\n .strict(),\n params: ImageBackgroundRemoveParams,\n outputs: z\n .object({\n image: ImageRef,\n mask: ImageRef.optional(),\n })\n .strict(),\n outputKinds: { image: \"image\", mask: \"image\" },\n cost: () => ({ credits: 1, seconds_estimate: 5 }),\n});\n","import { z } from \"zod\";\nimport { ImageRef, JsonRef } from \"../../schema/refs.ts\";\nimport { delegated } from \"./delegate.ts\";\n\nconst IMAGE_DESCRIBE_MODELS = [\"~google/gemini-pro-latest\", \"~google/gemini-flash-latest\"] as const;\n\nexport const imageDescribeNode = delegated({\n id: \"image_describe\",\n version: \"1.3.0\",\n category: \"vision\",\n summary:\n \"Reverse-engineer an image into an exhaustive, replication-grade JSON description: who the advertiser is and what they sell (source_context), composition, non-person subjects with expression/treatment, deeply detailed people, brand-identified logos (named by brand, not appearance), camera optics, lighting, color palette WITH per-color brand-ownership (brand vs borrowed-functional) and purpose, materials, visible text, ad signals (proof badges/CTA/price), the persuasion engine (ad_intent), style, post-processing.\",\n when_to_use:\n 'Use to turn a reference image into a structured blueprint you can inject into downstream prompts via `{{slot}}` — e.g. restyle a competitor ad onto your own product, lock a look across a series, or feed exact palette/lighting into image_generate. Purpose-built for market adaptation: logos are identified by brand (\"Trustpilot\", never \"green star\"), people and animals carry expression/emotion/intent detail, and each color is tagged brand vs borrowed-functional so a recolor can keep the reds/yellows that do a job. The extraction prompt is baked in; use `focus` to emphasise aspects and `context` to pass known provenance (advertiser, category, market) so source_context and color ownership are grounded. Pick `~google/gemini-pro-latest` for the densest extraction (recommended for ad / market-adaptation passes), `~google/gemini-flash-latest` for cheap/fast passes. The output is rich — raise `max_tokens` (e.g. 8000+) for dense ads so the JSON isn\\'t truncated.',\n inputs: z.object({ image: ImageRef }).loose(),\n params: z\n .object({\n model: z.enum(IMAGE_DESCRIBE_MODELS),\n focus: z.string().optional(),\n context: z.string().optional(),\n temperature: z.number().min(0).max(2).optional(),\n max_tokens: z.number().int().positive().optional(),\n })\n .strict(),\n outputs: z.object({ description: JsonRef }).strict(),\n outputKinds: { description: \"json\" },\n cost: () => ({ credits: 2, seconds_estimate: 10 }),\n});\n","import { z } from \"zod\";\nimport { ImageRef } from \"../../schema/refs.ts\";\nimport { delegated } from \"./delegate.ts\";\n\nconst REFERENCE_SHEET_MODELS = [\"google/gemini-3-pro-image-preview\", \"google/gemini-3.1-flash-image-preview\"] as const;\n\n// Permissive union of every param accepted by any curated model. The model\n// registry (`@baker/canvas-contract`) is the strict per-model gate. The sheet\n// prompt itself is baked into the backend handler — `prompt_override` is the\n// only full-bypass lever.\nconst ImageReferenceSheetParams = z\n .object({\n model: z.enum(REFERENCE_SHEET_MODELS),\n subject_description: z.string().min(1),\n // `location` = a set/room shown from several camera ANGLES (not a rotated subject),\n // so a multi-scene shoot keeps one consistent set.\n subject_type: z.enum([\"character\", \"person\", \"product\", \"location\"]),\n views: z.array(z.string().min(1)).min(2).max(8).optional(),\n style: z.string().optional(),\n prompt_override: z.string().min(1).optional(),\n aspect_ratio: z\n .enum([\"1:1\", \"16:9\", \"9:16\", \"4:3\", \"3:4\", \"3:2\", \"2:3\", \"4:5\", \"5:4\", \"21:9\", \"1:4\", \"4:1\", \"1:8\", \"8:1\"])\n .optional(),\n image_size: z.enum([\"0.5K\", \"1K\", \"2K\", \"4K\"]).optional(),\n })\n .strict();\n\nexport const imageReferenceSheetNode = delegated({\n id: \"image_reference_sheet\",\n version: \"1.0.0\",\n category: \"image\",\n summary:\n \"Fuse 1–6 images of a single subject (person, character, product, or location/set) into ONE multi-view reference sheet — a labeled grid in consistent style and lighting: a turnaround (FRONT / SIDE / BACK…) for a person/character/product, or several camera angles of the same room (WIDE / REVERSE / DETAIL…) for a location. Curated models: Gemini 3 Pro Image (best fusion + labels), Gemini 3.1 Flash Image (cheap iteration).\",\n when_to_use:\n \"Use before image_generate / video_generate when a subject must stay consistent across many creatives — wire the `sheet` output into their `reference` input instead of re-describing the subject per prompt. `subject_description` should be the exact wording you reuse downstream. Pick `google/gemini-3-pro-image-preview` for final 6-view sheets at 2K+, `google/gemini-3.1-flash-image-preview` while iterating.\",\n inputs: z.object({ references: z.array(ImageRef).min(1).max(6) }).loose(),\n params: ImageReferenceSheetParams,\n outputs: z.object({ sheet: ImageRef }).strict(),\n outputKinds: { sheet: \"image\" },\n cost: ({ params }) => ({\n credits: (params as { model?: string } | undefined)?.model === \"google/gemini-3-pro-image-preview\" ? 20 : 5,\n seconds_estimate: 30,\n }),\n});\n","import { z } from \"zod\";\nimport { ImageRef } from \"../../schema/refs.ts\";\nimport { delegated } from \"./delegate.ts\";\n\nconst ImageSearchParams = z\n .object({\n prompt: z.string().min(1),\n count: z.number().int().min(1).max(20).default(5),\n })\n .strict();\n\nexport const imageSearchNode = delegated({\n id: \"image_search\",\n version: \"1.0.0\",\n category: \"image\",\n summary:\n \"Agentic image search across Google Images, stock photography (Freepik), and Pinterest. An LLM agent picks the search tools and queries, selects the best matches, and the results are downloaded into canvas assets.\",\n when_to_use:\n \"Use to gather real-world reference or inspiration images for a prompt (e.g. several photos of an australian shepherd) so a later step or the user can pick the best one. Not for creating new imagery — use image_generate for that.\",\n inputs: z.object({}).loose(),\n params: ImageSearchParams,\n outputs: z.object({ images: z.array(ImageRef).min(1) }).strict(),\n outputKinds: { images: \"image\" },\n cost: ({ params }) => ({ credits: Math.ceil(2 + params.count / 2), seconds_estimate: 30 }),\n});\n","import { z } from \"zod\";\nimport { ImageRef, TextRef } from \"../../schema/refs.ts\";\nimport { delegated } from \"./delegate.ts\";\n\nconst IMAGE_SELECT_MODELS = [\"~google/gemini-flash-latest\", \"~google/gemini-pro-latest\"] as const;\n\nexport const imageSelectNode = delegated({\n id: \"image_select\",\n version: \"1.0.0\",\n category: \"vision\",\n summary:\n \"Pick the best `count` images out of 2+ candidates with a vision LLM, judged against a prompt. Outputs a passthrough subset of the input refs (no new pixels) plus the model's comparative reasoning.\",\n when_to_use:\n \"Use after fanning out several image_generate variants (or any pool of 2+ images) to keep only the strongest before expensive downstream steps — video generation, reference sheets, final delivery. `count` fixes the output size, so `images#0`…`images#count-1` are always safe to wire. Pick `~google/gemini-flash-latest` for cheap/fast picks and `~google/gemini-pro-latest` for harder aesthetic judgement.\",\n inputs: z.object({ images: z.array(ImageRef).min(2) }).loose(),\n params: z\n .object({\n model: z.enum(IMAGE_SELECT_MODELS),\n prompt: z.string().min(1),\n count: z.number().int().min(1).default(1),\n temperature: z.number().min(0).max(2).optional(),\n max_tokens: z.number().int().positive().optional(),\n })\n .strict(),\n outputs: z.object({ images: z.array(ImageRef).min(1), reasoning: TextRef }).strict(),\n outputKinds: { images: \"image\", reasoning: \"text\" },\n cost: () => ({ credits: 1, seconds_estimate: 5 }),\n // Arity is only knowable at validate time when `images` is a literal array\n // of refs; a single `$ref:` string to an upstream array output is deferred\n // to the runtime Zod parse and the backend's own arity check.\n validateExtra: ({ rawParams, rawInputs }) => {\n const issues: Array<{ path: string; message: string }> = [];\n const images = (rawInputs as { images?: unknown } | undefined)?.images;\n if (!Array.isArray(images)) return issues;\n if (images.length < 2) {\n issues.push({ path: \"inputs.images\", message: \"image_select needs at least 2 images wired\" });\n }\n const count = (rawParams as { count?: unknown } | undefined)?.count;\n if (typeof count === \"number\" && count > images.length) {\n issues.push({\n path: \"params.count\",\n message: `count ${count} exceeds the ${images.length} images wired into \\`images\\``,\n });\n }\n return issues;\n },\n});\n","import { ELEVENLABS_MAX_MUSIC_LENGTH_MS, ELEVENLABS_OUTPUT_FORMATS } from \"@baker/canvas-contract\";\nimport { z } from \"zod\";\nimport { AudioRef, JsonRef, VideoRef } from \"../../schema/refs.ts\";\nimport { delegated } from \"./delegate.ts\";\n\nconst MUSIC_MODELS = [\"elevenlabs/music-v1\", \"elevenlabs/video-background-music-v1\"] as const;\n\nconst MusicParams = z\n .object({\n model: z.enum(MUSIC_MODELS),\n /** Free-form prompt. Used by `elevenlabs/music-v1` (compose-detailed). */\n prompt: z.string().optional(),\n /**\n * Structured composition plan (intro / hook / verse / outro sections with\n * per-section styles + durations). Mutually exclusive with `prompt`.\n */\n composition_plan: z.record(z.string(), z.unknown()).optional(),\n /** Target length when using `prompt`. 3000–454545ms (capped by the $10 per-node cost limit). */\n music_length_ms: z.number().int().min(3000).max(ELEVENLABS_MAX_MUSIC_LENGTH_MS).optional(),\n seed: z.number().int().optional(),\n /** Prompt mode only — forces an instrumental (no vocals) track. */\n force_instrumental: z.boolean().optional(),\n /** composition_plan only — honor exact section durations. */\n respect_sections_durations: z.boolean().optional(),\n /** Emit word-level timestamps alongside the audio. */\n with_timestamps: z.boolean().optional(),\n /**\n * video-to-music only — short description of the desired score\n * (\"upbeat synth, fast cuts, 80s\") used to bias the model.\n */\n description: z.string().max(1000).optional(),\n /** video-to-music only — up to 10 style tags. */\n tags: z.array(z.string()).max(10).optional(),\n output_format: z.enum(ELEVENLABS_OUTPUT_FORMATS).optional(),\n })\n .strict();\n\nexport const musicNode = delegated({\n id: \"music\",\n version: \"1.1.0\",\n category: \"audio\",\n summary:\n \"Generate music for ad creatives and website video content. `elevenlabs/music-v1` composes from a text prompt or structured composition plan; `elevenlabs/video-background-music-v1` scores an existing video clip provided via `inputs.video`.\",\n when_to_use:\n \"Use to produce background music or a full score for video ads, hero-section reels, or any motion content. Prefer the video-to-music model when you already have a cut and want music timed to it; use compose-detailed when you have only a brief or want section-level control (intro / hook / outro). Pair the resulting audio with `video_generate` or `video_lipsync` at compose time.\",\n inputs: z.object({ video: VideoRef.optional() }).loose(),\n params: MusicParams,\n outputs: z.object({ audio: AudioRef, timestamps: JsonRef.optional() }).strict(),\n outputKinds: { audio: \"audio\", timestamps: \"json\" },\n cost: ({ params }) => {\n const seconds = params.music_length_ms ? Math.ceil(params.music_length_ms / 1000) : 30;\n return { credits: Math.max(1, Math.ceil(seconds * 2.2)), seconds_estimate: seconds + 15 };\n },\n // Per-model semantics the registry can't express: compose needs exactly one\n // of prompt/composition_plan, and a video wired into compose is dead weight.\n validateExtra: ({ rawParams, rawInputs }) => {\n const issues: Array<{ path: string; message: string }> = [];\n const params = (rawParams ?? {}) as { model?: unknown; prompt?: unknown; composition_plan?: unknown };\n if (params.model !== \"elevenlabs/music-v1\") return issues;\n const hasPrompt = params.prompt !== undefined;\n const hasPlan = params.composition_plan !== undefined;\n if (hasPrompt === hasPlan) {\n issues.push({\n path: \"params\",\n message: \"elevenlabs/music-v1 needs exactly one of `prompt` or `composition_plan`\",\n });\n }\n if ((rawInputs as { video?: unknown } | undefined)?.video !== undefined) {\n issues.push({\n path: \"inputs.video\",\n message:\n \"elevenlabs/music-v1 ignores `inputs.video` — use elevenlabs/video-background-music-v1 to score a video\",\n });\n }\n return issues;\n },\n});\n","import { ELEVENLABS_OUTPUT_FORMATS } from \"@baker/canvas-contract\";\nimport { z } from \"zod\";\nimport { AudioRef } from \"../../schema/refs.ts\";\nimport { delegated } from \"./delegate.ts\";\n\nconst SOUND_EFFECT_MODELS = [\"elevenlabs/eleven_text_to_sound_v2\"] as const;\n\nconst SoundEffectParams = z\n .object({\n model: z.enum(SOUND_EFFECT_MODELS),\n /** Prompt describing the SFX (\"metal door slam\", \"soft UI tap\", \"ocean waves\"). */\n text: z.string().min(1),\n /**\n * Target length in seconds. 0.5–30. Leave unset to let the model pick the\n * natural length for the described effect.\n */\n duration_seconds: z.number().min(0.5).max(30).optional(),\n /**\n * 0–1. Higher = stick closer to the prompt at the cost of variety; lower\n * = let the model interpret more freely. Defaults to 0.3 on the provider.\n */\n prompt_influence: z.number().min(0).max(1).optional(),\n /** Only valid on `eleven_text_to_sound_v2` — produce a seamless loop. */\n loop: z.boolean().optional(),\n output_format: z.enum(ELEVENLABS_OUTPUT_FORMATS).optional(),\n })\n .strict();\n\nexport const soundEffectNode = delegated({\n id: \"sound_effect\",\n version: \"1.1.0\",\n category: \"audio\",\n summary:\n \"Generate short sound effects from a text prompt via ElevenLabs Text-to-Sound. Use for whooshes, impacts, UI clicks, ambient beds, or signature stingers in ad creatives and product videos.\",\n when_to_use:\n \"Reach for this when you need a punch-in SFX layered against `video_generate` or `hyperframe_render` output — e.g. a logo whoosh on a hero shot, a click on a CTA cut, a swelling ambient bed under VO. Set `loop: true` for atmospheric beds that need to tile under longer footage; leave `duration_seconds` unset and the model picks a natural length.\",\n inputs: z.object({}).loose(),\n params: SoundEffectParams,\n outputs: z.object({ audio: AudioRef }).strict(),\n outputKinds: { audio: \"audio\" },\n cost: ({ params }) => {\n const seconds = params.duration_seconds ?? 5;\n return { credits: Math.max(1, Math.ceil(seconds * 2.2)), seconds_estimate: seconds + 5 };\n },\n});\n","import { z } from \"zod\";\nimport { TextRef } from \"../../schema/refs.ts\";\nimport { delegated } from \"./delegate.ts\";\n\nconst TEXT_GENERATE_MODELS = [\"~google/gemini-flash-latest\", \"~google/gemini-pro-latest\"] as const;\n\nexport const textGenerateNode = delegated({\n id: \"text_generate\",\n version: \"2.2.0\",\n category: \"language\",\n summary: \"Single-turn LLM text generation via OpenRouter. Returns a text response.\",\n when_to_use:\n 'Use for any short text generation step in a canvas — ad copy, hooks, headlines, JSON outputs for downstream nodes. Pick `~google/gemini-flash-latest` for cheap/fast work and `~google/gemini-pro-latest` for harder reasoning. When the output must be JSON for a downstream `{{slot}}` (e.g. the ad-blueprint transform), set `response_format: \"json_object\"` so the model returns clean JSON with no markdown fences or prose. Set `web_search: true` to let the model search the live web first (OpenRouter `:online`) — useful when the transform must adapt copy to the target brand\\'s real facts (current pricing, the trust signals it actually has) rather than guess.',\n inputs: z.object({}).loose(),\n params: z\n .object({\n model: z.enum(TEXT_GENERATE_MODELS),\n prompt: z.string().min(1),\n system: z.string().optional(),\n response_format: z.enum([\"text\", \"json_object\"]).optional(),\n web_search: z.boolean().optional(),\n temperature: z.number().min(0).max(2).optional(),\n max_tokens: z.number().int().positive().optional(),\n })\n .strict(),\n outputs: z.object({ text: TextRef }).strict(),\n outputKinds: { text: \"text\" },\n cost: () => ({ credits: 1, seconds_estimate: 3 }),\n});\n","import { ELEVENLABS_MAX_TEXT_CHARS, ELEVENLABS_OUTPUT_FORMATS } from \"@baker/canvas-contract\";\nimport { z } from \"zod\";\nimport { AudioRef, JsonRef } from \"../../schema/refs.ts\";\nimport { delegated } from \"./delegate.ts\";\n\nconst TTS_MODELS = [\"elevenlabs/eleven_v3\"] as const;\n\n/**\n * ElevenLabs voice settings passthrough. Mirrors the provider's\n * `voice_settings` object.\n */\nconst TtsVoiceSettings = z\n .object({\n stability: z.number().min(0).max(1).optional(),\n similarity_boost: z.number().min(0).max(1).optional(),\n style: z.number().min(0).max(1).optional(),\n use_speaker_boost: z.boolean().optional(),\n speed: z.number().min(0.25).max(4.0).optional(),\n })\n .strict();\n\nconst TtsPronunciationLocator = z\n .object({\n pronunciation_dictionary_id: z.string().min(1),\n version_id: z.string().nullable().optional(),\n })\n .strict();\n\nconst TtsParams = z\n .object({\n model: z.enum(TTS_MODELS),\n text: z.string().min(1).max(ELEVENLABS_MAX_TEXT_CHARS),\n voice: z.string().min(1),\n\n /** Provider output_format (mp3 family only — assets are stored as audio/mpeg). */\n output_format: z.enum(ELEVENLABS_OUTPUT_FORMATS).optional(),\n seed: z.number().int().min(0).max(4_294_967_295).optional(),\n\n // Top-level shortcuts; structured form is `voice_settings`.\n stability: z.number().min(0).max(1).optional(),\n similarity_boost: z.number().min(0).max(1).optional(),\n voice_settings: TtsVoiceSettings.optional(),\n\n /** ISO 639-1 language code. eleven_v3 supports language hints. */\n language_code: z.string().optional(),\n pronunciation_dictionary_locators: z.array(TtsPronunciationLocator).max(3).optional(),\n apply_text_normalization: z.enum([\"auto\", \"on\", \"off\"]).optional(),\n /** Currently Japanese-only. Adds latency. */\n apply_language_text_normalization: z.boolean().optional(),\n\n /**\n * When true, hits `/v1/text-to-speech/{voice_id}/with-timestamps` and\n * adds a `timestamps` output (character-level alignment) for caption\n * rendering, lipsync, and beat-matched cuts.\n */\n with_timestamps: z.boolean().optional(),\n })\n .strict();\n\nexport const ttsNode = delegated({\n id: \"tts\",\n version: \"2.0.0\",\n category: \"audio\",\n summary:\n \"Single-voice text-to-speech via ElevenLabs Eleven v3. Optional character-level timestamps for caption rendering and beat-matched cuts.\",\n when_to_use:\n \"Use for single-speaker VO — ad reads, hero-section narration, product walkthroughs. Reach for `dialogue` when you need multiple voices in one stitched track. Set `with_timestamps: true` when downstream needs character-level alignment (captions, lipsync).\",\n inputs: z.object({}).loose(),\n params: TtsParams,\n outputs: z.object({ audio: AudioRef, timestamps: JsonRef.optional() }).strict(),\n outputKinds: { audio: \"audio\", timestamps: \"json\" },\n cost: ({ params }) => ({\n credits: Math.max(1, Math.ceil(params.text.length * 0.0015)),\n seconds_estimate: params.with_timestamps ? 7 : 5,\n }),\n});\n","import { estimateVideoCredits, VIDEO_GENERATE_MODELS } from \"@baker/canvas-contract\";\nimport { z } from \"zod\";\nimport { ImageRef, VideoRef } from \"../../schema/refs.ts\";\nimport { delegated } from \"./delegate.ts\";\n\n// The accepted model set is the canonical curated roster from the contract — kept\n// in one place so this node schema can never drift from `MODEL_REGISTRY` (which is\n// exactly the drift that let a registered model fail this schema before it).\nconst videoModelEnum = z.enum(VIDEO_GENERATE_MODELS as unknown as [string, ...string[]]);\n\n// Permissive union of every param accepted by any curated model. The registry\n// gates per-model: e.g. Seedance rejects `negative_prompt`, Veo accepts it, Kling\n// takes `cfg_scale`. Enum values for `duration`/`resolution` are also gated there.\nconst VideoGenerateParams = z\n .object({\n model: videoModelEnum,\n prompt: z.string().min(1),\n duration: z.number().int().positive().optional(),\n resolution: z.string().optional(),\n // Union of ratios accepted by at least one curated model (registry gates\n // per-model). 3:2/2:3 are deliberately absent: no registered model takes them.\n aspect_ratio: z.enum([\"16:9\", \"9:16\", \"1:1\", \"4:3\", \"3:4\", \"21:9\", \"9:21\"]).optional(),\n generate_audio: z.boolean().optional(),\n seed: z.number().int().nonnegative().optional(),\n // Veo-only passthroughs (routed via `provider.options.google-vertex.parameters`).\n negative_prompt: z.string().optional(),\n person_generation: z.string().optional(),\n enhance_prompt: z.boolean().optional(),\n conditioning_scale: z.number().optional(),\n // Kling-only passthrough (prompt-adherence dial, sent top-level).\n cfg_scale: z.number().optional(),\n })\n .strict();\n\nexport const videoGenerateNode = delegated({\n id: \"video_generate\",\n version: \"2.0.0\",\n category: \"video\",\n summary:\n \"Generate video for ad creatives. Curated roster: `bytedance/seedance-2.0` (identity/product workhorse, NO photoreal human faces), `google/veo-3.1` (photoreal cine ceiling + the human-face model), `google/veo-3.1-fast` (cheap Veo iteration), `kwaivgi/kling-3.0` (motion-transfer/dynamic). Async with polling.\",\n when_to_use:\n \"Use `bytedance/seedance-2.0` for identity/product output WITHOUT a photoreal human face on camera. Any clip whose frame shows a photoreal human face — a UGC creator, presenter, or testimonial speaker, REAL OR AI-GENERATED — must use `google/veo-3.1`: ByteDance's filter rejects photoreal human faces on Seedance (content_policy_blocked/E005), and a synthetic AI face does NOT clear it. Use `google/veo-3.1-fast` while iterating to keep cost low; `kwaivgi/kling-3.0` for motion-transfer/hyper-dynamic beats. `baker canvas scaffold-video` auto-routes a photoreal cast to Veo; a Seedance clip blocked at runtime also auto-recovers on Veo. Each model gates its own durations/resolutions/aspect ratios in the registry — see the README per-model section.\",\n inputs: z\n .object({\n first_frame: ImageRef.optional(),\n last_frame: ImageRef.optional(),\n reference: ImageRef.optional(),\n /**\n * Reference-to-video: several images the model uses as visual guidance\n * (this person, this product) instead of an exact opening frame. Mutually\n * exclusive with `first_frame` — OpenRouter treats a request carrying both\n * as image-to-video and ignores these, so wire one or the other.\n */\n references: z.array(ImageRef).optional(),\n })\n .loose(),\n params: VideoGenerateParams,\n outputs: z.object({ video: VideoRef }).strict(),\n outputKinds: { video: \"video\" },\n // Priced from the shared contract, so `validate`'s quote and the charge the\n // backend applies come from ONE table. A flat number here under-quoted a\n // 1080p 8s clip by ~10x, and the agent reads this out to the user as \"this\n // will cost N\" before spending it.\n cost: ({ params }) => ({\n credits: estimateVideoCredits({\n model: params.model,\n duration: params.duration,\n resolution: params.resolution,\n // Audio bills at a separate, higher rate on every model that offers it\n // (Veo 3.1 doubles), so omitting it quotes half the real cost.\n generateAudio: params.generate_audio,\n }),\n seconds_estimate: 120,\n }),\n});\n","import { z } from \"zod\";\nimport { VideoRef } from \"../../schema/refs.ts\";\nimport { delegated } from \"./delegate.ts\";\n\nconst VideoBackgroundRemoveParams = z\n .object({\n model: z.literal(\"fal/veed-video-background-removal\").optional().default(\"fal/veed-video-background-removal\"),\n edge_refinement: z.boolean().optional().default(true),\n output_codec: z.enum([\"vp9\", \"h264\"]).optional().default(\"vp9\"),\n })\n .strict();\n\nexport const videoBackgroundRemoveNode = delegated({\n id: \"video_background_remove\",\n version: \"1.0.0\",\n category: \"video\",\n summary:\n \"Remove the background from a video and return a transparent VP9-with-alpha WebM (or H264 RGB+alpha pair). Drops directly into a hyperframe composition as `<video src='...'>` for chroma-keyed picture-in-picture overlays. Powered by fal.ai `veed/video-background-removal/fast`.\",\n when_to_use:\n \"Use when you need a talking-head or subject to float over a custom background in a hyperframe composition. Pair with hyperframe_render(composition: screencast-with-talker) for screencast-with-narrator videos. \" +\n \"Output is `video/webm` with alpha — feed straight into `<video src>` in a composition.\",\n inputs: z\n .object({\n video: VideoRef,\n })\n .strict(),\n params: VideoBackgroundRemoveParams,\n outputs: z.object({ video: VideoRef }).strict(),\n outputKinds: { video: \"video\" },\n // $0.012 per 30 frames (edge refinement on) — assume ~30fps; refine via fal dashboard.\n cost: () => ({ credits: 50, seconds_estimate: 60 }),\n});\n","import { z } from \"zod\";\nimport { ImageRef, JsonRef, VideoRef } from \"../../schema/refs.ts\";\nimport { delegated } from \"./delegate.ts\";\n\nconst VIDEO_DECONSTRUCT_MODELS = [\"~google/gemini-flash-latest\", \"~google/gemini-pro-latest\"] as const;\n\nexport const videoDeconstructNode = delegated({\n id: \"video_deconstruct\",\n version: \"1.4.0\",\n category: \"video\",\n summary:\n 'Deconstruct a video into a replication-grade blueprint: scene boundaries, the real start/end frame of every scene (extracted from the video as images), and an exhaustive JSON analysis — per-scene action detail, camera motion, generation-ready frame/motion prompts, overlay text with full typographic style, floating elements, deeply detailed cast (perceived demographics, ethnicity/skin-tone, styling, market-recasting notes), brand-identified logos (named by brand and what they signal, not by appearance, with on-screen timestamps), dialogue with voice descriptions, music spec, SFX list, plus a word-level transcript. `mode:\"index\"` is the cheap structure-first pass: scene boundaries + global blueprint only (one LLM call, no frames).',\n when_to_use:\n 'Use to reverse-engineer a reference video (e.g. a competitor ad) so a new canvas can reproduce or remix it scene by scene. Agent loop: (1) optionally run `mode:\"index\"` to see the structure cheaply (scene count, boundaries, transcript) before planning; (2) run the full deconstruct; (3) read `analysis` and author the reproduction canvas. The blueprint maps 1:1 onto generation nodes: `analysis.scenes[i]` aligns positionally with `start_frames#i`/`end_frames#i`; per scene, `start_frame_prompt`/`end_frame_prompt` feed image_generate (overlay text is excluded from them by contract — recomposite it from `overlays`), `motion_prompt` + the two frames feed video_generate (first_frame/last_frame), `dialogue[].voice_description` casts tts/dialogue voices, `global.music.music_prompt` feeds music, `sfx[].sound_effect_prompt` feeds sound_effect, and `overlays`/`floating_elements` drive an ffmpeg/hyperframe overlay pass. Long videos (over ~8 min single-shot): run `mode:\"index\"` first, then several full nodes IN PARALLEL each with a `start_s`/`end_s` window (≤480s, snap edges to index scene boundaries), and merge by concatenating `analysis.scenes`; over-length errors include suggested windows. Inject fields into downstream prompts via `{{slot}}`. Pick `~google/gemini-pro-latest` for the densest extraction, `~google/gemini-flash-latest` for cheap/fast passes.',\n inputs: z.object({ video: VideoRef }).loose(),\n params: z\n .object({\n model: z.enum(VIDEO_DECONSTRUCT_MODELS),\n mode: z.enum([\"full\", \"index\"]).optional(),\n language: z.string().min(2).max(8).optional(),\n max_scenes: z.number().int().min(1).max(60).optional(),\n focus: z.string().optional(),\n start_s: z.number().min(0).optional(),\n end_s: z.number().positive().optional(),\n // Real visual shot-cut timestamps (absolute seconds), detected locally with\n // ffmpeg before the deconstruct. The backend SNAPS its LLM scene boundaries\n // onto these and SPLITS any scene that spans one, so a scene's frames never\n // straddle a hard cut. `scaffold-video` populates this; omit for LLM-only cuts.\n shot_cuts: z.array(z.number().min(0)).max(200).optional(),\n // The video model's per-clip ceiling (seconds). A shot longer than this is\n // split into seamless continuation sub-scenes (shared splice frame), so long\n // shots reproduce in full instead of being truncated. `scaffold-video` sets\n // the Seedance ceiling (15); omit to disable length splitting.\n max_clip_s: z.number().positive().max(60).optional(),\n // Transcript provider for the blueprint's dialogue/transcript. Default\n // Groq Whisper; \"deepgram\" routes to Nova-3 so words carry punctuation.\n transcriber: z.enum([\"groq\", \"deepgram\"]).optional(),\n })\n .strict(),\n outputs: z\n .object({\n analysis: JsonRef,\n // Absent in mode:\"index\" (structure only, no Mux frame extraction).\n start_frames: z.array(ImageRef).min(1).optional(),\n end_frames: z.array(ImageRef).min(1).optional(),\n transcript: JsonRef,\n })\n .strict(),\n outputKinds: { analysis: \"json\", start_frames: \"image\", end_frames: \"image\", transcript: \"json\" },\n cost: ({ params }) =>\n (params as { mode?: string }).mode === \"index\"\n ? { credits: 3, seconds_estimate: 60 }\n : { credits: 15, seconds_estimate: 300 },\n});\n","import { z } from \"zod\";\nimport { AudioRef, VideoRef } from \"../../schema/refs.ts\";\nimport { delegated } from \"./delegate.ts\";\n\nconst FalLipsyncParams = z\n .object({\n model: z.literal(\"fal/veed-lipsync\"),\n })\n .strict();\n\nconst VideoLipsyncParams = z.discriminatedUnion(\"model\", [FalLipsyncParams]);\n\nexport const videoLipsyncNode = delegated({\n id: \"video_lipsync\",\n version: \"1.0.0\",\n category: \"video\",\n summary:\n \"Lip-sync a video to an audio track. Currently backed by VEED via fal.ai (`fal/veed-lipsync`). $0.40/min of output.\",\n inputs: z\n .object({\n video: VideoRef,\n audio: AudioRef,\n })\n .strict(),\n params: VideoLipsyncParams,\n outputs: z.object({ video: VideoRef }).strict(),\n outputKinds: { video: \"video\" },\n cost: () => ({ credits: 20, seconds_estimate: 120 }),\n});\n","import { mkdtemp, readFile, rm } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport path from \"node:path\";\nimport { z } from \"zod\";\nimport type { ExecCtx } from \"../../engine/context.ts\";\nimport { defineNode } from \"../../engine/define.ts\";\nimport type { AssetRef } from \"../../schema/refs.ts\";\nimport { AudioRef, VideoRef } from \"../../schema/refs.ts\";\nimport { sha256Hex } from \"../../storage/sha256.ts\";\nimport { probeVideo, runFfmpeg } from \"../local/lib/ffmpeg.ts\";\nimport { callBackendExec } from \"./delegate.ts\";\n\nconst VideoTranscribeParams = z\n .object({\n language: z.string().min(2).max(8).optional(),\n // Provider choice is explicit (no env-based silent branching). Default Groq\n // Whisper; \"deepgram\" routes to Deepgram Nova-3, which additionally emits a\n // `rich` JSON output with punctuated words + paragraph/sentence grouping.\n transcriber: z.enum([\"groq\", \"deepgram\"]).optional(),\n })\n .strict();\n\nconst VideoTranscribeInputs = z\n .object({\n // A video (audio auto-extracted locally) OR a bare audio track. The key stays\n // `video` for back-compat; the backend already accepts audio-kind refs on it —\n // the local extraction path has been shipping one for every video input.\n video: z.union([VideoRef, AudioRef]),\n })\n .strict();\n\nconst VideoTranscribeOutputs = z\n .object({\n transcript: z.custom<AssetRef>(),\n // Only emitted by the Deepgram path: full punctuated words + paragraph /\n // sentence grouping with speaker indices. Absent for the default Groq path.\n rich: z.custom<AssetRef>().optional(),\n })\n .strict();\n\ntype Inputs = z.infer<typeof VideoTranscribeInputs>;\ntype Params = z.infer<typeof VideoTranscribeParams>;\ntype Outputs = z.infer<typeof VideoTranscribeOutputs>;\n\nconst AUDIO_EXTRACT_TIMEOUT_MS = 60_000;\n\nexport const videoTranscribeNode = defineNode<Inputs, Params, Outputs>({\n id: \"video_transcribe\",\n version: \"2.3.0\",\n category: \"language\",\n location: \"local\",\n summary:\n 'Transcribe a video or audio track to a word-level JSON transcript. Default `transcriber:\"groq\"` uses ' +\n 'Groq Whisper Large v3 Turbo ($0.04/hr, 10s min); `transcriber:\"deepgram\"` uses Deepgram Nova-3 ' +\n \"($0.0043/min) and additionally emits a `rich` JSON output with punctuated words + paragraph/sentence \" +\n \"grouping (and speaker indices). \" +\n \"Automatically extracts audio locally (mono 16 kHz MP3) before uploading — reduces payload ~100× \" +\n \"and lifts the effective duration limit well beyond Groq's 100 MB file cap. \" +\n \"The `transcript` output is always an array of {text, start, end} entries ready to feed Hyperframes \" +\n \"caption compositions (Deepgram prefers the punctuated word form).\",\n when_to_use:\n \"Use to generate burned-in captions for a stitched video. Pair with `hyperframe_render` and a captions composition (e.g. `tiktok-captions`) by passing the transcript JSON through `params.variables.transcript`. \" +\n 'Pick `params.language` to filter out non-target speech (e.g. \"es\" for Spanish). ' +\n 'Pick `transcriber:\"deepgram\"` when you want punctuation/paragraphs (read them from the `rich` output) or speaker grouping. ' +\n \"Requires ffmpeg on PATH for audio extraction (falls back to full video upload if unavailable).\",\n inputs: VideoTranscribeInputs,\n params: VideoTranscribeParams,\n outputs: VideoTranscribeOutputs,\n outputKinds: { transcript: \"json\", rich: \"json\" },\n cost: () => ({ credits: 2, seconds_estimate: 30 }),\n\n async execute({ inputs, params, ctx }) {\n const audioInput = await tryExtractAudio(inputs, ctx);\n const effectiveInputs = audioInput ?? inputs;\n\n return (await callBackendExec({\n nodeType: \"video_transcribe\",\n nodeVersion: \"2.3.0\",\n params,\n inputs: effectiveInputs,\n outputKinds: { transcript: \"json\", rich: \"json\" },\n ctx,\n })) as Outputs;\n },\n});\n\nasync function tryExtractAudio(inputs: Inputs, ctx: ExecCtx): Promise<{ video: AssetRef } | null> {\n const video = inputs.video;\n // A bare audio input is already the small transcribable payload — send it as-is.\n if (!video.path || !video.mime?.startsWith(\"video/\")) return null;\n\n let tmpDir: string | undefined;\n try {\n const probe = await probeVideo(video.path);\n if (!probe.has_audio) {\n ctx.log(\"video_transcribe: no audio track detected, sending full video\");\n return null;\n }\n\n tmpDir = await mkdtemp(path.join(tmpdir(), \"vtx-\"));\n const audioPath = path.join(tmpDir, \"audio.mp3\");\n\n ctx.log(\"video_transcribe: extracting audio (mono 16kHz mp3)\");\n await runFfmpeg(\n [\"-i\", video.path, \"-vn\", \"-ac\", \"1\", \"-ar\", \"16000\", \"-b:a\", \"64k\", \"-f\", \"mp3\", \"-y\", audioPath],\n { timeout_ms: AUDIO_EXTRACT_TIMEOUT_MS },\n );\n\n const bytes = await readFile(audioPath);\n if (bytes.byteLength === 0) {\n ctx.log(\"video_transcribe: extracted audio is empty, sending full video\");\n return null;\n }\n\n const sha = sha256Hex(bytes);\n const mime = \"audio/mpeg\";\n const { putUrl, publicUrl } = await ctx.client.presignAssetUpload(sha, mime, ctx.signal);\n\n const putRes = await fetch(putUrl, {\n method: \"PUT\",\n body: new Uint8Array(bytes),\n headers: { \"Content-Type\": mime },\n signal: ctx.signal,\n });\n if (!putRes.ok) {\n ctx.log(`video_transcribe: audio upload failed (${putRes.status}), sending full video`);\n return null;\n }\n\n const localRef = await ctx.assets.ingestBytes({\n bytes,\n kind: \"audio\",\n mime,\n metadata: { extracted_from: video.sha256 },\n });\n\n const sizeMb = (bytes.byteLength / (1024 * 1024)).toFixed(1);\n ctx.log(`video_transcribe: audio extracted (${sizeMb} MB), uploading`);\n\n return {\n video: { ...localRef, url: publicUrl } as AssetRef,\n };\n } catch (e) {\n ctx.log(`video_transcribe: audio extraction failed, sending full video: ${(e as Error).message}`);\n return null;\n } finally {\n if (tmpDir) {\n await rm(tmpDir, { recursive: true, force: true }).catch((_e) => undefined);\n }\n }\n}\n","import { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\n\nconst execFileAsync = promisify(execFile);\n\ntype VideoProbe = {\n duration_seconds: number;\n codec_name: string;\n profile: string | null;\n level: number | null;\n width: number;\n height: number;\n pix_fmt: string | null;\n fps_num: number;\n fps_den: number;\n has_audio: boolean;\n audio_codec: string | null;\n sample_rate: number | null;\n channels: number | null;\n};\n\ntype FfprobeStream = {\n codec_type?: string;\n codec_name?: string;\n profile?: string;\n level?: number;\n width?: number;\n height?: number;\n pix_fmt?: string;\n r_frame_rate?: string;\n avg_frame_rate?: string;\n sample_rate?: string;\n channels?: number;\n};\n\ntype FfprobeFormat = {\n duration?: string;\n};\n\ntype FfprobeJson = {\n streams?: FfprobeStream[];\n format?: FfprobeFormat;\n};\n\nexport async function probeVideo(filePath: string): Promise<VideoProbe> {\n const { stdout } = await execFileAsync(\n \"ffprobe\",\n [\"-v\", \"error\", \"-show_streams\", \"-show_format\", \"-of\", \"json\", filePath],\n { encoding: \"utf-8\", maxBuffer: 8 * 1024 * 1024 },\n );\n return parseProbeJson(stdout, filePath);\n}\n\nfunction parseProbeJson(stdout: string, filePath: string): VideoProbe {\n let parsed: FfprobeJson;\n try {\n parsed = JSON.parse(stdout) as FfprobeJson;\n } catch {\n throw new Error(`ffprobe: unparseable JSON output for ${filePath}`);\n }\n\n const streams = parsed.streams ?? [];\n const video = streams.find((s) => s.codec_type === \"video\");\n if (!video) throw new Error(`ffprobe: no video stream found in ${filePath}`);\n if (typeof video.width !== \"number\" || typeof video.height !== \"number\") {\n throw new Error(`ffprobe: missing video dimensions for ${filePath}`);\n }\n\n const duration = Number.parseFloat(parsed.format?.duration ?? \"\");\n if (!Number.isFinite(duration) || duration <= 0) {\n throw new Error(`ffprobe: invalid duration for ${filePath}: ${parsed.format?.duration}`);\n }\n\n const audio = streams.find((s) => s.codec_type === \"audio\");\n return buildVideoProbe(video, video.width, video.height, audio, duration);\n}\n\nfunction buildVideoProbe(\n video: FfprobeStream,\n width: number,\n height: number,\n audio: FfprobeStream | undefined,\n duration: number,\n): VideoProbe {\n const fps = parseFrameRate(video.r_frame_rate ?? video.avg_frame_rate ?? \"30/1\");\n return {\n duration_seconds: duration,\n codec_name: video.codec_name ?? \"unknown\",\n profile: video.profile ?? null,\n level: typeof video.level === \"number\" ? video.level : null,\n width,\n height,\n pix_fmt: video.pix_fmt ?? null,\n fps_num: fps.num,\n fps_den: fps.den,\n has_audio: audio !== undefined,\n audio_codec: audio?.codec_name ?? null,\n sample_rate: audio?.sample_rate ? Number.parseInt(audio.sample_rate, 10) : null,\n channels: typeof audio?.channels === \"number\" ? audio.channels : null,\n };\n}\n\nfunction parseFrameRate(rate: string): { num: number; den: number } {\n const match = rate.match(/^(\\d+)\\/(\\d+)$/);\n if (match) {\n const num = Number.parseInt(match[1] ?? \"0\", 10);\n const den = Number.parseInt(match[2] ?? \"0\", 10);\n if (den > 0) return { num, den };\n }\n const flat = Number.parseFloat(rate);\n if (Number.isFinite(flat) && flat > 0) return { num: Math.round(flat * 1000), den: 1000 };\n return { num: 30, den: 1 };\n}\n\ntype RunFfmpegOpts = {\n timeout_ms: number;\n log?: (msg: string) => void;\n};\n\nexport async function runFfmpeg(args: readonly string[], opts: RunFfmpegOpts): Promise<void> {\n try {\n await execFileAsync(\"ffmpeg\", args, {\n timeout: opts.timeout_ms,\n maxBuffer: 64 * 1024 * 1024,\n });\n } catch (e) {\n const stderr = (e as { stderr?: string }).stderr ?? \"\";\n const stdout = (e as { stdout?: string }).stdout ?? \"\";\n const detail = stderr || stdout || (e as Error).message;\n throw new Error(`ffmpeg failed:\\n${detail.slice(-4000)}`);\n }\n}\n","import { z } from \"zod\";\nimport { JsonRef, TextRef } from \"../../schema/refs.ts\";\nimport { delegated } from \"./delegate.ts\";\n\nexport const voiceSelectNode = delegated({\n id: \"voice_select\",\n version: \"1.0.0\",\n category: \"audio\",\n summary:\n 'Cast an ElevenLabs voice from a natural-language description (e.g. \"warm, authoritative female narrator, American accent\"). Lists the account\\'s voices and ranks them against the brief, emitting the best `voice_id` as a bare-string text asset plus a ranked `candidates` JSON.',\n when_to_use:\n 'Use to turn a voice description (e.g. from a `video_deconstruct` blueprint\\'s `voice_description`) into a usable ElevenLabs voice id, then feed it into a `tts` node by wiring `inputs.voice_ref: $ref:<this>.voice_id` and setting `params.voice: \"{{voice_ref}}\"` — the engine splices the id in at run time. Review `candidates` (json) to pick a different voice. Optional `gender`/`age`/`accent`/`language` hints sharpen the ranking.',\n inputs: z.object({}).loose(),\n params: z\n .object({\n description: z.string().min(1),\n gender: z.string().optional(),\n age: z.string().optional(),\n accent: z.string().optional(),\n language: z.string().optional(),\n limit: z.number().int().min(1).max(20).optional(),\n })\n .strict(),\n outputs: z.object({ voice_id: TextRef, candidates: JsonRef }).strict(),\n outputKinds: { voice_id: \"text\", candidates: \"json\" },\n cost: () => ({ credits: 0, seconds_estimate: 5 }),\n});\n","import { z } from \"zod\";\nimport type { NodeRegistry } from \"../engine/registry.ts\";\n\ntype CatalogEntry = {\n id: string;\n version: string;\n category: string;\n summary: string;\n when_to_use?: string;\n location: \"local\" | \"remote\";\n inputs: unknown;\n params: unknown;\n outputs: unknown;\n cost_estimate_credits?: number;\n runtime_estimate_seconds?: number;\n};\n\ntype Catalog = {\n schema: \"baker-canvas-catalog/2\";\n generated_at: string;\n categories: Record<string, string[]>;\n entries: CatalogEntry[];\n};\n\nexport function generateCatalog(registry: NodeRegistry, opts: { generatedAt?: string } = {}): Catalog {\n const entries: CatalogEntry[] = registry\n .all()\n .map((def) => {\n const cost = def.cost ? safeCost(def) : undefined;\n return {\n id: def.id,\n version: def.version,\n category: def.category,\n summary: def.summary,\n when_to_use: def.when_to_use,\n location: def.location,\n inputs: z.toJSONSchema(def.inputs, { unrepresentable: \"any\" }),\n params: z.toJSONSchema(def.params, { unrepresentable: \"any\" }),\n outputs: z.toJSONSchema(def.outputs, { unrepresentable: \"any\" }),\n cost_estimate_credits: cost?.credits,\n runtime_estimate_seconds: cost?.seconds_estimate,\n };\n })\n .sort((a, b) => a.id.localeCompare(b.id));\n\n const categories: Record<string, string[]> = {};\n for (const e of entries) {\n let bucket = categories[e.category];\n if (!bucket) {\n bucket = [];\n categories[e.category] = bucket;\n }\n bucket.push(e.id);\n }\n\n return {\n schema: \"baker-canvas-catalog/2\",\n generated_at: opts.generatedAt ?? new Date().toISOString(),\n categories,\n entries,\n };\n}\n\nfunction safeCost(def: { cost?: (args: { params: unknown }) => { credits: number; seconds_estimate: number } }): {\n credits: number;\n seconds_estimate: number;\n} | null {\n if (!def.cost) return null;\n try {\n return def.cost({ params: {} as never });\n } catch {\n return null;\n }\n}\n","import { randomUUID } from \"node:crypto\";\nimport { mkdir, readFile, rename, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nexport type CacheEntry = {\n cacheKey: string;\n nodeType: string;\n nodeVersion: string;\n outputs: Record<string, unknown>;\n refs: string[]; // sha256s referenced (for GC later)\n createdAt: number;\n};\n\nexport interface CacheStore {\n rootDir: string;\n get(cacheKey: string): Promise<CacheEntry | null>;\n put(entry: CacheEntry): Promise<void>;\n}\n\nexport class LocalCacheStore implements CacheStore {\n rootDir: string;\n constructor(rootDir: string) {\n this.rootDir = rootDir;\n }\n\n private filePath(cacheKey: string): string {\n return path.join(this.rootDir, `${cacheKey}.json`);\n }\n\n async get(cacheKey: string): Promise<CacheEntry | null> {\n try {\n const buf = await readFile(this.filePath(cacheKey), \"utf8\");\n return JSON.parse(buf) as CacheEntry;\n } catch (e) {\n if ((e as NodeJS.ErrnoException).code === \"ENOENT\") return null;\n throw e;\n }\n }\n\n async put(entry: CacheEntry): Promise<void> {\n const dest = this.filePath(entry.cacheKey);\n await mkdir(path.dirname(dest), { recursive: true });\n const tmp = `${dest}.tmp-${process.pid}-${randomUUID()}`;\n await writeFile(tmp, JSON.stringify(entry, null, 0));\n await rename(tmp, dest);\n }\n}\n"],"mappings":"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","names":["configure","value","message","tmp","key","res","join","stringify","path","path","message","path","message","cjsModule","cjsModule","distance","sleep","tail","mkdir","unlink","writeFile","path","path","mkdir","writeFile","unlink","readFile","path","z","KLING_DURATIONS","path","readFile","tail","z","readFile","stat","path","z","z","z","z","z","path","timescale","duration","message","stat","readFile","path","stat","readFile","z","execFileCb","spawn","copyFile","mkdtemp","readFile","rm","stat","tmpdir","path","promisify","execFile","spawnAndWait","z","z","z","z","FFMPEG_BIN","z","mkdtemp","rm","writeFile","tmpdir","path","z","copyFile","readFile","path","isAssetRefLike","z","mkdtemp","path","tmpdir","writeFile","rm","execFile","copyFile","mkdtemp","readFile","rm","stat","writeFile","createRequire","tmpdir","path","promisify","z","readdir","readFile","stat","path","readdir","path","stat","readFile","readFile","path","z","execFile","readFile","path","promisify","message","writeFile","path","execFileAsync","promisify","execFile","require_","createRequire","z","mkdtemp","path","tmpdir","stageInputs","readFile","rm","stat","tail","copyFile","isAssetRefLike","writeFile","execFile","copyFile","mkdtemp","readFile","rm","writeFile","createRequire","tmpdir","path","promisify","z","promisify","execFile","require_","createRequire","z","NODE_OWNED_PARAM_KEYS","DEVICE_SCALE_FACTOR","validateAndParseDynamicParams","mkdtemp","path","tmpdir","copyComposition","vendorGsap","stageInputs","buildSubstitutionValues","substituteCompositionFiles","rm","copyFile","coerceImageParam","isAssetRefLike","readFile","writeFile","execFile","promisify","z","execFileAsync","promisify","execFile","OutputDecl","z","z","z","z","z","z","z","z","IMAGE_GENERATE_MODELS","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","mkdtemp","readFile","rm","tmpdir","path","z","execFile","promisify","execFileAsync","z","mkdtemp","path","tmpdir","readFile","rm","z","z","z","randomUUID","mkdir","readFile","rename","writeFile","path","BackendClient","Engine","LocalAssetStore","LocalCacheStore","validateCanvasDeep","generateCatalog","ValidationError","path"]}
|