@nodaro/shared 1.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/README.md +32 -0
- package/dist/index.cjs +12506 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +12269 -0
- package/dist/index.d.ts +12269 -0
- package/dist/index.js +11831 -0
- package/dist/index.js.map +1 -0
- package/package.json +54 -0
- package/src/__tests__/__snapshots__/prompt-builder-segments.test.ts.snap +65 -0
- package/src/__tests__/ai-avatar-pricing.test.ts +321 -0
- package/src/__tests__/apply-video-negative-prompt.test.ts +76 -0
- package/src/__tests__/attach-columns.test.ts +28 -0
- package/src/__tests__/audio-crossfade-curves.test.ts +33 -0
- package/src/__tests__/build-model-menu.test.ts +58 -0
- package/src/__tests__/character-aspect-defaults.test.ts +142 -0
- package/src/__tests__/character-mention-slug.test.ts +199 -0
- package/src/__tests__/character-reference-photo-kinds.test.ts +32 -0
- package/src/__tests__/character-usage-mode.test.ts +147 -0
- package/src/__tests__/character-variant-assets.test.ts +142 -0
- package/src/__tests__/character-voice.test.ts +130 -0
- package/src/__tests__/cinematic-avatar-pricing.test.ts +119 -0
- package/src/__tests__/combine-transitions.test.ts +137 -0
- package/src/__tests__/component-types.test.ts +87 -0
- package/src/__tests__/condition-variables.test.ts +98 -0
- package/src/__tests__/credit-identifiers.test.ts +811 -0
- package/src/__tests__/default-video-provider.test.ts +63 -0
- package/src/__tests__/entity-image-handle.test.ts +43 -0
- package/src/__tests__/entity-variants.test.ts +33 -0
- package/src/__tests__/fal-lip-sync-sets.test.ts +31 -0
- package/src/__tests__/featured-entities.test.ts +33 -0
- package/src/__tests__/film-pricing.test.ts +64 -0
- package/src/__tests__/filter-condition.test.ts +285 -0
- package/src/__tests__/freecut-protocol.test.ts +35 -0
- package/src/__tests__/generate-text-items.test.ts +19 -0
- package/src/__tests__/generated-results.test.ts +50 -0
- package/src/__tests__/graph-utils.test.ts +618 -0
- package/src/__tests__/group-aggregation.test.ts +83 -0
- package/src/__tests__/i18n-locale-completeness.test.ts +156 -0
- package/src/__tests__/image-critic-node.test.ts +86 -0
- package/src/__tests__/image-mask-mode.test.ts +16 -0
- package/src/__tests__/image-ref-limit.test.ts +78 -0
- package/src/__tests__/inpaint-region.test.ts +24 -0
- package/src/__tests__/input-field-map-parity.test.ts +30 -0
- package/src/__tests__/json-evaluator.test.ts +289 -0
- package/src/__tests__/json-path.test.ts +64 -0
- package/src/__tests__/lip-sync-pricing.test.ts +142 -0
- package/src/__tests__/list-merge.test.ts +96 -0
- package/src/__tests__/list-sort.test.ts +134 -0
- package/src/__tests__/llm-models.test.ts +445 -0
- package/src/__tests__/location-mention-slug.test.ts +246 -0
- package/src/__tests__/locations-coverage-critic-schema.test.ts +92 -0
- package/src/__tests__/loop-delimiter.test.ts +39 -0
- package/src/__tests__/lottie-slots.test.ts +245 -0
- package/src/__tests__/model-catalog-flux2-resolutions.test.ts +21 -0
- package/src/__tests__/model-constants-location.test.ts +20 -0
- package/src/__tests__/model-constants.test.ts +122 -0
- package/src/__tests__/model-tree.test.ts +86 -0
- package/src/__tests__/no-internal-imports.test.ts +25 -0
- package/src/__tests__/node-default-mappings.test.ts +175 -0
- package/src/__tests__/node-mappable-fields.test.ts +7 -0
- package/src/__tests__/node-preset-export.test.ts +46 -0
- package/src/__tests__/node-preset-extract.test.ts +166 -0
- package/src/__tests__/node-refs-canonical.test.ts +54 -0
- package/src/__tests__/node-refs-combine.test.ts +54 -0
- package/src/__tests__/node-refs.test.ts +187 -0
- package/src/__tests__/node-runtime-keys.test.ts +99 -0
- package/src/__tests__/object-aspect-defaults.test.ts +59 -0
- package/src/__tests__/parameter-node-value.test.ts +137 -0
- package/src/__tests__/pinterest-url.test.ts +35 -0
- package/src/__tests__/pipeline-chat.test.ts +110 -0
- package/src/__tests__/pipeline-validation.test.ts +98 -0
- package/src/__tests__/presentation-utils.test.ts +1137 -0
- package/src/__tests__/producer-types.test.ts +47 -0
- package/src/__tests__/prompt-length-limits.test.ts +156 -0
- package/src/__tests__/provider-directive-defaults.test.ts +46 -0
- package/src/__tests__/reduce-strategy-registry.test.ts +43 -0
- package/src/__tests__/reference-board-templates.test.ts +33 -0
- package/src/__tests__/reference-roles.test.ts +36 -0
- package/src/__tests__/resolve-field-mappings.test.ts +110 -0
- package/src/__tests__/resolve-pipeline-model.test.ts +76 -0
- package/src/__tests__/scene-node-types.test.ts +80 -0
- package/src/__tests__/scraper-actors.test.ts +67 -0
- package/src/__tests__/seedance-2-catalog.test.ts +18 -0
- package/src/__tests__/seedance-2-credit-id.test.ts +23 -0
- package/src/__tests__/seedance-aspects.test.ts +52 -0
- package/src/__tests__/selector.test.ts +1151 -0
- package/src/__tests__/settled-with-limit.test.ts +214 -0
- package/src/__tests__/social-media-specs.test.ts +129 -0
- package/src/__tests__/sub-workflow-validation.test.ts +88 -0
- package/src/__tests__/switchx-pricing.test.ts +28 -0
- package/src/__tests__/to-connected-references.test.ts +153 -0
- package/src/__tests__/utilities.test.ts +541 -0
- package/src/__tests__/video-analysis-pricing.test.ts +58 -0
- package/src/__tests__/video-analysis.test.ts +63 -0
- package/src/__tests__/video-audio-capability.test.ts +204 -0
- package/src/__tests__/video-gen-providers.test.ts +28 -0
- package/src/__tests__/video-mode-aliases.test.ts +150 -0
- package/src/__tests__/video-ref-limits.test.ts +72 -0
- package/src/__tests__/video-utils.test.ts +303 -0
- package/src/__tests__/voice-changer-models.test.ts +33 -0
- package/src/__tests__/workflow-export-strip.test.ts +46 -0
- package/src/ai-avatar-pricing.ts +213 -0
- package/src/ancestor-refs.ts +48 -0
- package/src/animals.ts +231 -0
- package/src/audio-crossfade-curves.ts +73 -0
- package/src/audio-fx-presets.ts +64 -0
- package/src/avatar-payload-validators.ts +214 -0
- package/src/caption-styles.ts +31 -0
- package/src/character-aspect-defaults.ts +102 -0
- package/src/character-facets.ts +37 -0
- package/src/character-mention-slug.ts +166 -0
- package/src/character-usage-mode.ts +109 -0
- package/src/character-variant-assets.ts +121 -0
- package/src/character-voice.ts +151 -0
- package/src/cinematic-avatar-pricing.ts +111 -0
- package/src/clone-utils.ts +46 -0
- package/src/combine-transitions.ts +482 -0
- package/src/community.ts +112 -0
- package/src/component-types.ts +127 -0
- package/src/condition-variables.ts +65 -0
- package/src/credit-estimators/index.ts +15 -0
- package/src/credit-estimators/video-utils.ts +165 -0
- package/src/credit-identifiers.ts +304 -0
- package/src/entity-approval-types.ts +31 -0
- package/src/entity-aspect-defaults.ts +82 -0
- package/src/entity-asset-types.ts +296 -0
- package/src/entity-image-handle.ts +36 -0
- package/src/extra-refs.ts +139 -0
- package/src/featured-entities.ts +136 -0
- package/src/film-pricing.ts +117 -0
- package/src/filter-condition.ts +250 -0
- package/src/flux2-pricing.ts +18 -0
- package/src/freecut-protocol.ts +52 -0
- package/src/furniture.ts +167 -0
- package/src/generate-text-items.ts +15 -0
- package/src/generated-results.ts +63 -0
- package/src/group-aggregation.ts +75 -0
- package/src/hint-graph-types.ts +18 -0
- package/src/i18n/action-fx.ar.ts +89 -0
- package/src/i18n/action-fx.de.ts +89 -0
- package/src/i18n/action-fx.es.ts +89 -0
- package/src/i18n/action-fx.fr.ts +89 -0
- package/src/i18n/action-fx.he.ts +89 -0
- package/src/i18n/action-fx.hi.ts +89 -0
- package/src/i18n/action-fx.ja.ts +89 -0
- package/src/i18n/action-fx.ko.ts +89 -0
- package/src/i18n/action-fx.pt-BR.ts +89 -0
- package/src/i18n/action-fx.ru.ts +89 -0
- package/src/i18n/action-fx.zh-CN.ts +89 -0
- package/src/i18n/aesthetic.ar.ts +170 -0
- package/src/i18n/aesthetic.de.ts +48 -0
- package/src/i18n/aesthetic.es.ts +169 -0
- package/src/i18n/aesthetic.fr.ts +52 -0
- package/src/i18n/aesthetic.he.ts +169 -0
- package/src/i18n/aesthetic.hi.ts +55 -0
- package/src/i18n/aesthetic.ja.ts +165 -0
- package/src/i18n/aesthetic.ko.ts +169 -0
- package/src/i18n/aesthetic.pt-BR.ts +148 -0
- package/src/i18n/aesthetic.ru.ts +155 -0
- package/src/i18n/aesthetic.zh-CN.ts +172 -0
- package/src/i18n/animals.ar.ts +145 -0
- package/src/i18n/animals.de.ts +144 -0
- package/src/i18n/animals.es.ts +158 -0
- package/src/i18n/animals.fr.ts +144 -0
- package/src/i18n/animals.he.ts +155 -0
- package/src/i18n/animals.hi.ts +157 -0
- package/src/i18n/animals.ja.ts +159 -0
- package/src/i18n/animals.ko.ts +159 -0
- package/src/i18n/animals.pt-BR.ts +157 -0
- package/src/i18n/animals.ru.ts +155 -0
- package/src/i18n/animals.zh-CN.ts +155 -0
- package/src/i18n/atmosphere.ar.ts +49 -0
- package/src/i18n/atmosphere.de.ts +47 -0
- package/src/i18n/atmosphere.es.ts +50 -0
- package/src/i18n/atmosphere.fr.ts +47 -0
- package/src/i18n/atmosphere.he.ts +47 -0
- package/src/i18n/atmosphere.hi.ts +49 -0
- package/src/i18n/atmosphere.ja.ts +49 -0
- package/src/i18n/atmosphere.ko.ts +49 -0
- package/src/i18n/atmosphere.pt-BR.ts +49 -0
- package/src/i18n/atmosphere.ru.ts +47 -0
- package/src/i18n/atmosphere.zh-CN.ts +152 -0
- package/src/i18n/backdrop.ar.ts +53 -0
- package/src/i18n/backdrop.de.ts +46 -0
- package/src/i18n/backdrop.es.ts +54 -0
- package/src/i18n/backdrop.fr.ts +52 -0
- package/src/i18n/backdrop.he.ts +51 -0
- package/src/i18n/backdrop.hi.ts +59 -0
- package/src/i18n/backdrop.ja.ts +61 -0
- package/src/i18n/backdrop.ko.ts +59 -0
- package/src/i18n/backdrop.pt-BR.ts +59 -0
- package/src/i18n/backdrop.ru.ts +57 -0
- package/src/i18n/backdrop.zh-CN.ts +57 -0
- package/src/i18n/camera-format.ar.ts +40 -0
- package/src/i18n/camera-format.de.ts +37 -0
- package/src/i18n/camera-format.es.ts +41 -0
- package/src/i18n/camera-format.fr.ts +37 -0
- package/src/i18n/camera-format.he.ts +37 -0
- package/src/i18n/camera-format.hi.ts +42 -0
- package/src/i18n/camera-format.ja.ts +37 -0
- package/src/i18n/camera-format.ko.ts +37 -0
- package/src/i18n/camera-format.pt-BR.ts +46 -0
- package/src/i18n/camera-format.ru.ts +42 -0
- package/src/i18n/camera-format.zh-CN.ts +42 -0
- package/src/i18n/camera-motions.ar.ts +86 -0
- package/src/i18n/camera-motions.de.ts +74 -0
- package/src/i18n/camera-motions.es.ts +86 -0
- package/src/i18n/camera-motions.fr.ts +86 -0
- package/src/i18n/camera-motions.he.ts +86 -0
- package/src/i18n/camera-motions.hi.ts +99 -0
- package/src/i18n/camera-motions.ja.ts +99 -0
- package/src/i18n/camera-motions.ko.ts +99 -0
- package/src/i18n/camera-motions.pt-BR.ts +99 -0
- package/src/i18n/camera-motions.ru.ts +99 -0
- package/src/i18n/camera-motions.zh-CN.ts +99 -0
- package/src/i18n/character-fx.ar.ts +72 -0
- package/src/i18n/character-fx.de.ts +72 -0
- package/src/i18n/character-fx.es.ts +72 -0
- package/src/i18n/character-fx.fr.ts +72 -0
- package/src/i18n/character-fx.he.ts +72 -0
- package/src/i18n/character-fx.hi.ts +72 -0
- package/src/i18n/character-fx.ja.ts +72 -0
- package/src/i18n/character-fx.ko.ts +72 -0
- package/src/i18n/character-fx.pt-BR.ts +72 -0
- package/src/i18n/character-fx.ru.ts +72 -0
- package/src/i18n/character-fx.zh-CN.ts +72 -0
- package/src/i18n/color-look.ar.ts +50 -0
- package/src/i18n/color-look.de.ts +47 -0
- package/src/i18n/color-look.es.ts +50 -0
- package/src/i18n/color-look.fr.ts +50 -0
- package/src/i18n/color-look.he.ts +49 -0
- package/src/i18n/color-look.hi.ts +52 -0
- package/src/i18n/color-look.ja.ts +54 -0
- package/src/i18n/color-look.ko.ts +54 -0
- package/src/i18n/color-look.pt-BR.ts +54 -0
- package/src/i18n/color-look.ru.ts +52 -0
- package/src/i18n/color-look.zh-CN.ts +53 -0
- package/src/i18n/composition-effects.ar.ts +26 -0
- package/src/i18n/composition-effects.de.ts +25 -0
- package/src/i18n/composition-effects.es.ts +27 -0
- package/src/i18n/composition-effects.fr.ts +25 -0
- package/src/i18n/composition-effects.he.ts +25 -0
- package/src/i18n/composition-effects.hi.ts +27 -0
- package/src/i18n/composition-effects.ja.ts +27 -0
- package/src/i18n/composition-effects.ko.ts +27 -0
- package/src/i18n/composition-effects.pt-BR.ts +25 -0
- package/src/i18n/composition-effects.ru.ts +82 -0
- package/src/i18n/composition-effects.zh-CN.ts +25 -0
- package/src/i18n/era.ar.ts +37 -0
- package/src/i18n/era.de.ts +34 -0
- package/src/i18n/era.es.ts +37 -0
- package/src/i18n/era.fr.ts +37 -0
- package/src/i18n/era.he.ts +36 -0
- package/src/i18n/era.hi.ts +39 -0
- package/src/i18n/era.ja.ts +41 -0
- package/src/i18n/era.ko.ts +39 -0
- package/src/i18n/era.pt-BR.ts +41 -0
- package/src/i18n/era.ru.ts +121 -0
- package/src/i18n/era.zh-CN.ts +39 -0
- package/src/i18n/exposure-settings.ar.ts +28 -0
- package/src/i18n/exposure-settings.de.ts +26 -0
- package/src/i18n/exposure-settings.es.ts +28 -0
- package/src/i18n/exposure-settings.fr.ts +29 -0
- package/src/i18n/exposure-settings.he.ts +28 -0
- package/src/i18n/exposure-settings.hi.ts +31 -0
- package/src/i18n/exposure-settings.ja.ts +31 -0
- package/src/i18n/exposure-settings.ko.ts +31 -0
- package/src/i18n/exposure-settings.pt-BR.ts +31 -0
- package/src/i18n/exposure-settings.ru.ts +31 -0
- package/src/i18n/exposure-settings.zh-CN.ts +31 -0
- package/src/i18n/framing.ar.ts +78 -0
- package/src/i18n/framing.de.ts +73 -0
- package/src/i18n/framing.es.ts +78 -0
- package/src/i18n/framing.fr.ts +78 -0
- package/src/i18n/framing.he.ts +77 -0
- package/src/i18n/framing.hi.ts +82 -0
- package/src/i18n/framing.ja.ts +84 -0
- package/src/i18n/framing.ko.ts +82 -0
- package/src/i18n/framing.pt-BR.ts +84 -0
- package/src/i18n/framing.ru.ts +82 -0
- package/src/i18n/framing.zh-CN.ts +82 -0
- package/src/i18n/furniture.ar.ts +92 -0
- package/src/i18n/furniture.de.ts +93 -0
- package/src/i18n/furniture.es.ts +101 -0
- package/src/i18n/furniture.fr.ts +93 -0
- package/src/i18n/furniture.he.ts +101 -0
- package/src/i18n/furniture.hi.ts +101 -0
- package/src/i18n/furniture.ja.ts +101 -0
- package/src/i18n/furniture.ko.ts +101 -0
- package/src/i18n/furniture.pt-BR.ts +101 -0
- package/src/i18n/furniture.ru.ts +101 -0
- package/src/i18n/furniture.zh-CN.ts +101 -0
- package/src/i18n/held-prop.ar.ts +74 -0
- package/src/i18n/held-prop.de.ts +65 -0
- package/src/i18n/held-prop.es.ts +83 -0
- package/src/i18n/held-prop.fr.ts +74 -0
- package/src/i18n/held-prop.he.ts +73 -0
- package/src/i18n/held-prop.hi.ts +82 -0
- package/src/i18n/held-prop.ja.ts +84 -0
- package/src/i18n/held-prop.ko.ts +84 -0
- package/src/i18n/held-prop.pt-BR.ts +84 -0
- package/src/i18n/held-prop.ru.ts +82 -0
- package/src/i18n/held-prop.zh-CN.ts +82 -0
- package/src/i18n/index.ts +208 -0
- package/src/i18n/instrumentation.ar.ts +195 -0
- package/src/i18n/instrumentation.de.ts +195 -0
- package/src/i18n/instrumentation.es.ts +195 -0
- package/src/i18n/instrumentation.fr.ts +195 -0
- package/src/i18n/instrumentation.he.ts +195 -0
- package/src/i18n/instrumentation.hi.ts +195 -0
- package/src/i18n/instrumentation.ja.ts +195 -0
- package/src/i18n/instrumentation.ko.ts +195 -0
- package/src/i18n/instrumentation.pt-BR.ts +195 -0
- package/src/i18n/instrumentation.ru.ts +195 -0
- package/src/i18n/instrumentation.zh-CN.ts +195 -0
- package/src/i18n/lens.ar.ts +24 -0
- package/src/i18n/lens.de.ts +24 -0
- package/src/i18n/lens.es.ts +24 -0
- package/src/i18n/lens.fr.ts +24 -0
- package/src/i18n/lens.he.ts +24 -0
- package/src/i18n/lens.hi.ts +24 -0
- package/src/i18n/lens.ja.ts +24 -0
- package/src/i18n/lens.ko.ts +24 -0
- package/src/i18n/lens.pt-BR.ts +24 -0
- package/src/i18n/lens.ru.ts +25 -0
- package/src/i18n/lens.zh-CN.ts +24 -0
- package/src/i18n/lighting.ar.ts +86 -0
- package/src/i18n/lighting.de.ts +84 -0
- package/src/i18n/lighting.es.ts +89 -0
- package/src/i18n/lighting.fr.ts +84 -0
- package/src/i18n/lighting.he.ts +88 -0
- package/src/i18n/lighting.hi.ts +90 -0
- package/src/i18n/lighting.ja.ts +90 -0
- package/src/i18n/lighting.ko.ts +90 -0
- package/src/i18n/lighting.pt-BR.ts +90 -0
- package/src/i18n/lighting.ru.ts +88 -0
- package/src/i18n/lighting.zh-CN.ts +92 -0
- package/src/i18n/loop-subject.ar.ts +39 -0
- package/src/i18n/loop-subject.de.ts +39 -0
- package/src/i18n/loop-subject.es.ts +39 -0
- package/src/i18n/loop-subject.fr.ts +39 -0
- package/src/i18n/loop-subject.he.ts +39 -0
- package/src/i18n/loop-subject.hi.ts +39 -0
- package/src/i18n/loop-subject.ja.ts +39 -0
- package/src/i18n/loop-subject.ko.ts +39 -0
- package/src/i18n/loop-subject.pt-BR.ts +39 -0
- package/src/i18n/loop-subject.ru.ts +39 -0
- package/src/i18n/loop-subject.zh-CN.ts +39 -0
- package/src/i18n/materials.ar.ts +80 -0
- package/src/i18n/materials.de.ts +80 -0
- package/src/i18n/materials.es.ts +87 -0
- package/src/i18n/materials.fr.ts +80 -0
- package/src/i18n/materials.he.ts +86 -0
- package/src/i18n/materials.hi.ts +86 -0
- package/src/i18n/materials.ja.ts +88 -0
- package/src/i18n/materials.ko.ts +88 -0
- package/src/i18n/materials.pt-BR.ts +88 -0
- package/src/i18n/materials.ru.ts +86 -0
- package/src/i18n/materials.zh-CN.ts +86 -0
- package/src/i18n/mood.ar.ts +61 -0
- package/src/i18n/mood.de.ts +61 -0
- package/src/i18n/mood.es.ts +66 -0
- package/src/i18n/mood.fr.ts +61 -0
- package/src/i18n/mood.he.ts +64 -0
- package/src/i18n/mood.hi.ts +66 -0
- package/src/i18n/mood.ja.ts +66 -0
- package/src/i18n/mood.ko.ts +66 -0
- package/src/i18n/mood.pt-BR.ts +64 -0
- package/src/i18n/mood.ru.ts +64 -0
- package/src/i18n/mood.zh-CN.ts +64 -0
- package/src/i18n/music-genre.ar.ts +302 -0
- package/src/i18n/music-genre.de.ts +302 -0
- package/src/i18n/music-genre.es.ts +302 -0
- package/src/i18n/music-genre.fr.ts +302 -0
- package/src/i18n/music-genre.he.ts +302 -0
- package/src/i18n/music-genre.hi.ts +302 -0
- package/src/i18n/music-genre.ja.ts +302 -0
- package/src/i18n/music-genre.ko.ts +302 -0
- package/src/i18n/music-genre.pt-BR.ts +302 -0
- package/src/i18n/music-genre.ru.ts +302 -0
- package/src/i18n/music-genre.zh-CN.ts +302 -0
- package/src/i18n/music-mood.ar.ts +75 -0
- package/src/i18n/music-mood.de.ts +75 -0
- package/src/i18n/music-mood.es.ts +75 -0
- package/src/i18n/music-mood.fr.ts +75 -0
- package/src/i18n/music-mood.he.ts +75 -0
- package/src/i18n/music-mood.hi.ts +75 -0
- package/src/i18n/music-mood.ja.ts +75 -0
- package/src/i18n/music-mood.ko.ts +75 -0
- package/src/i18n/music-mood.pt-BR.ts +75 -0
- package/src/i18n/music-mood.ru.ts +75 -0
- package/src/i18n/music-mood.zh-CN.ts +75 -0
- package/src/i18n/person.ar.ts +638 -0
- package/src/i18n/person.de.ts +629 -0
- package/src/i18n/person.es.ts +645 -0
- package/src/i18n/person.fr.ts +621 -0
- package/src/i18n/person.he.ts +656 -0
- package/src/i18n/person.hi.ts +654 -0
- package/src/i18n/person.ja.ts +662 -0
- package/src/i18n/person.ko.ts +662 -0
- package/src/i18n/person.pt-BR.ts +656 -0
- package/src/i18n/person.ru.ts +656 -0
- package/src/i18n/person.zh-CN.ts +656 -0
- package/src/i18n/photo-genre.ar.ts +58 -0
- package/src/i18n/photo-genre.de.ts +52 -0
- package/src/i18n/photo-genre.es.ts +64 -0
- package/src/i18n/photo-genre.fr.ts +58 -0
- package/src/i18n/photo-genre.he.ts +62 -0
- package/src/i18n/photo-genre.hi.ts +63 -0
- package/src/i18n/photo-genre.ja.ts +65 -0
- package/src/i18n/photo-genre.ko.ts +63 -0
- package/src/i18n/photo-genre.pt-BR.ts +65 -0
- package/src/i18n/photo-genre.ru.ts +63 -0
- package/src/i18n/photo-genre.zh-CN.ts +63 -0
- package/src/i18n/photographer.ar.ts +75 -0
- package/src/i18n/photographer.de.ts +74 -0
- package/src/i18n/photographer.es.ts +77 -0
- package/src/i18n/photographer.fr.ts +77 -0
- package/src/i18n/photographer.he.ts +78 -0
- package/src/i18n/photographer.hi.ts +80 -0
- package/src/i18n/photographer.ja.ts +84 -0
- package/src/i18n/photographer.ko.ts +84 -0
- package/src/i18n/photographer.pt-BR.ts +83 -0
- package/src/i18n/photographer.ru.ts +78 -0
- package/src/i18n/photographer.zh-CN.ts +78 -0
- package/src/i18n/pose.ar.ts +95 -0
- package/src/i18n/pose.de.ts +96 -0
- package/src/i18n/pose.es.ts +104 -0
- package/src/i18n/pose.fr.ts +96 -0
- package/src/i18n/pose.he.ts +104 -0
- package/src/i18n/pose.hi.ts +104 -0
- package/src/i18n/pose.ja.ts +104 -0
- package/src/i18n/pose.ko.ts +104 -0
- package/src/i18n/pose.pt-BR.ts +104 -0
- package/src/i18n/pose.ru.ts +104 -0
- package/src/i18n/pose.zh-CN.ts +104 -0
- package/src/i18n/post-process-effects.ar.ts +25 -0
- package/src/i18n/post-process-effects.de.ts +24 -0
- package/src/i18n/post-process-effects.es.ts +26 -0
- package/src/i18n/post-process-effects.fr.ts +24 -0
- package/src/i18n/post-process-effects.he.ts +24 -0
- package/src/i18n/post-process-effects.hi.ts +26 -0
- package/src/i18n/post-process-effects.ja.ts +26 -0
- package/src/i18n/post-process-effects.ko.ts +26 -0
- package/src/i18n/post-process-effects.pt-BR.ts +24 -0
- package/src/i18n/post-process-effects.ru.ts +24 -0
- package/src/i18n/post-process-effects.zh-CN.ts +24 -0
- package/src/i18n/render-quality.ar.ts +34 -0
- package/src/i18n/render-quality.de.ts +30 -0
- package/src/i18n/render-quality.es.ts +35 -0
- package/src/i18n/render-quality.fr.ts +34 -0
- package/src/i18n/render-quality.he.ts +33 -0
- package/src/i18n/render-quality.hi.ts +39 -0
- package/src/i18n/render-quality.ja.ts +39 -0
- package/src/i18n/render-quality.ko.ts +39 -0
- package/src/i18n/render-quality.pt-BR.ts +37 -0
- package/src/i18n/render-quality.ru.ts +37 -0
- package/src/i18n/render-quality.zh-CN.ts +37 -0
- package/src/i18n/seasons.ar.ts +10 -0
- package/src/i18n/seasons.de.ts +10 -0
- package/src/i18n/seasons.es.ts +10 -0
- package/src/i18n/seasons.fr.ts +10 -0
- package/src/i18n/seasons.he.ts +10 -0
- package/src/i18n/seasons.hi.ts +10 -0
- package/src/i18n/seasons.ja.ts +10 -0
- package/src/i18n/seasons.ko.ts +10 -0
- package/src/i18n/seasons.pt-BR.ts +10 -0
- package/src/i18n/seasons.ru.ts +10 -0
- package/src/i18n/seasons.zh-CN.ts +10 -0
- package/src/i18n/setting.ar.ts +73 -0
- package/src/i18n/setting.de.ts +73 -0
- package/src/i18n/setting.es.ts +77 -0
- package/src/i18n/setting.fr.ts +73 -0
- package/src/i18n/setting.he.ts +76 -0
- package/src/i18n/setting.hi.ts +76 -0
- package/src/i18n/setting.ja.ts +78 -0
- package/src/i18n/setting.ko.ts +76 -0
- package/src/i18n/setting.pt-BR.ts +78 -0
- package/src/i18n/setting.ru.ts +76 -0
- package/src/i18n/setting.zh-CN.ts +76 -0
- package/src/i18n/style.ar.ts +55 -0
- package/src/i18n/style.de.ts +54 -0
- package/src/i18n/style.es.ts +54 -0
- package/src/i18n/style.fr.ts +54 -0
- package/src/i18n/style.he.ts +54 -0
- package/src/i18n/style.hi.ts +54 -0
- package/src/i18n/style.ja.ts +54 -0
- package/src/i18n/style.ko.ts +54 -0
- package/src/i18n/style.pt-BR.ts +56 -0
- package/src/i18n/style.ru.ts +54 -0
- package/src/i18n/style.zh-CN.ts +54 -0
- package/src/i18n/styling.ar.ts +295 -0
- package/src/i18n/styling.de.ts +285 -0
- package/src/i18n/styling.es.ts +317 -0
- package/src/i18n/styling.fr.ts +285 -0
- package/src/i18n/styling.he.ts +307 -0
- package/src/i18n/styling.hi.ts +323 -0
- package/src/i18n/styling.ja.ts +317 -0
- package/src/i18n/styling.ko.ts +311 -0
- package/src/i18n/styling.pt-BR.ts +301 -0
- package/src/i18n/styling.ru.ts +301 -0
- package/src/i18n/styling.zh-CN.ts +307 -0
- package/src/i18n/temporal.ar.ts +31 -0
- package/src/i18n/temporal.de.ts +24 -0
- package/src/i18n/temporal.es.ts +27 -0
- package/src/i18n/temporal.fr.ts +28 -0
- package/src/i18n/temporal.he.ts +31 -0
- package/src/i18n/temporal.hi.ts +31 -0
- package/src/i18n/temporal.ja.ts +31 -0
- package/src/i18n/temporal.ko.ts +31 -0
- package/src/i18n/temporal.pt-BR.ts +31 -0
- package/src/i18n/temporal.ru.ts +31 -0
- package/src/i18n/temporal.zh-CN.ts +31 -0
- package/src/i18n/transitions.ar.ts +97 -0
- package/src/i18n/transitions.de.ts +97 -0
- package/src/i18n/transitions.es.ts +97 -0
- package/src/i18n/transitions.fr.ts +97 -0
- package/src/i18n/transitions.he.ts +97 -0
- package/src/i18n/transitions.hi.ts +97 -0
- package/src/i18n/transitions.ja.ts +97 -0
- package/src/i18n/transitions.ko.ts +97 -0
- package/src/i18n/transitions.pt-BR.ts +97 -0
- package/src/i18n/transitions.ru.ts +97 -0
- package/src/i18n/transitions.zh-CN.ts +97 -0
- package/src/i18n/types.ts +158 -0
- package/src/i18n/vehicles.ar.ts +137 -0
- package/src/i18n/vehicles.de.ts +125 -0
- package/src/i18n/vehicles.es.ts +138 -0
- package/src/i18n/vehicles.fr.ts +125 -0
- package/src/i18n/vehicles.he.ts +136 -0
- package/src/i18n/vehicles.hi.ts +138 -0
- package/src/i18n/vehicles.ja.ts +138 -0
- package/src/i18n/vehicles.ko.ts +138 -0
- package/src/i18n/vehicles.pt-BR.ts +136 -0
- package/src/i18n/vehicles.ru.ts +136 -0
- package/src/i18n/vehicles.zh-CN.ts +136 -0
- package/src/i18n/voice-character.ar.ts +126 -0
- package/src/i18n/voice-character.de.ts +126 -0
- package/src/i18n/voice-character.es.ts +126 -0
- package/src/i18n/voice-character.fr.ts +126 -0
- package/src/i18n/voice-character.he.ts +126 -0
- package/src/i18n/voice-character.hi.ts +126 -0
- package/src/i18n/voice-character.ja.ts +126 -0
- package/src/i18n/voice-character.ko.ts +126 -0
- package/src/i18n/voice-character.pt-BR.ts +126 -0
- package/src/i18n/voice-character.ru.ts +126 -0
- package/src/i18n/voice-character.zh-CN.ts +126 -0
- package/src/i18n/voice-delivery.ar.ts +77 -0
- package/src/i18n/voice-delivery.de.ts +77 -0
- package/src/i18n/voice-delivery.es.ts +77 -0
- package/src/i18n/voice-delivery.fr.ts +77 -0
- package/src/i18n/voice-delivery.he.ts +77 -0
- package/src/i18n/voice-delivery.hi.ts +77 -0
- package/src/i18n/voice-delivery.ja.ts +77 -0
- package/src/i18n/voice-delivery.ko.ts +77 -0
- package/src/i18n/voice-delivery.pt-BR.ts +77 -0
- package/src/i18n/voice-delivery.ru.ts +77 -0
- package/src/i18n/voice-delivery.zh-CN.ts +77 -0
- package/src/i18n/weapons.ar.ts +115 -0
- package/src/i18n/weapons.de.ts +114 -0
- package/src/i18n/weapons.es.ts +116 -0
- package/src/i18n/weapons.fr.ts +103 -0
- package/src/i18n/weapons.he.ts +114 -0
- package/src/i18n/weapons.hi.ts +116 -0
- package/src/i18n/weapons.ja.ts +116 -0
- package/src/i18n/weapons.ko.ts +116 -0
- package/src/i18n/weapons.pt-BR.ts +114 -0
- package/src/i18n/weapons.ru.ts +114 -0
- package/src/i18n/weapons.zh-CN.ts +114 -0
- package/src/image-critic-node.ts +61 -0
- package/src/image-critic-types.ts +40 -0
- package/src/index.ts +866 -0
- package/src/inject-upstream.ts +15 -0
- package/src/inpaint-region.ts +51 -0
- package/src/json-evaluator.ts +732 -0
- package/src/json-path.ts +52 -0
- package/src/lip-sync-pricing.ts +90 -0
- package/src/list-merge.ts +40 -0
- package/src/list-sort.ts +122 -0
- package/src/list-source-resolver.ts +50 -0
- package/src/llm-models.ts +245 -0
- package/src/location-mention-slug.ts +291 -0
- package/src/location-preset-catalog-map.ts +128 -0
- package/src/loop-delimiter.ts +73 -0
- package/src/lora-routing.ts +95 -0
- package/src/lottie-overlay-catalog.ts +175 -0
- package/src/lottie-slots.ts +309 -0
- package/src/model-catalog.ts +2386 -0
- package/src/model-constants.ts +1910 -0
- package/src/model-tree.ts +120 -0
- package/src/monetization.ts +15 -0
- package/src/multi-pick.ts +42 -0
- package/src/node-default-mappings.ts +262 -0
- package/src/node-mappable-fields.ts +70 -0
- package/src/node-preset-export.ts +56 -0
- package/src/node-preset-extract.ts +147 -0
- package/src/node-refs.ts +253 -0
- package/src/node-runtime-keys.ts +117 -0
- package/src/object-aspect-defaults.ts +72 -0
- package/src/object-picker-types.ts +22 -0
- package/src/parameter-node-value.ts +284 -0
- package/src/pinterest-url.ts +28 -0
- package/src/pipeline-chat.ts +72 -0
- package/src/pipeline-defaults.ts +318 -0
- package/src/pipeline-events.ts +162 -0
- package/src/pipeline-state-types.ts +196 -0
- package/src/pipeline-types.ts +647 -0
- package/src/pipeline-validation.ts +87 -0
- package/src/presentation-types.ts +23 -0
- package/src/presentation-utils.ts +397 -0
- package/src/producer-types.ts +188 -0
- package/src/progress-curve.ts +99 -0
- package/src/provider-directive-defaults.ts +69 -0
- package/src/reduce-strategy-registry.ts +121 -0
- package/src/reference-board-templates.ts +81 -0
- package/src/reference-roles.ts +153 -0
- package/src/reference-sheet/__tests__/board-to-column.test.ts +20 -0
- package/src/reference-sheet/__tests__/catalog.test.ts +50 -0
- package/src/reference-sheet/__tests__/cost.test.ts +38 -0
- package/src/reference-sheet/__tests__/no-drift.test.ts +28 -0
- package/src/reference-sheet/__tests__/panel-plan.test.ts +61 -0
- package/src/reference-sheet/__tests__/panel-prompts.test.ts +17 -0
- package/src/reference-sheet/__tests__/plan-generation.test.ts +72 -0
- package/src/reference-sheet/__tests__/presets.test.ts +54 -0
- package/src/reference-sheet/__tests__/types.test.ts +24 -0
- package/src/reference-sheet/catalog.ts +144 -0
- package/src/reference-sheet/cost.ts +37 -0
- package/src/reference-sheet/credit-id.ts +7 -0
- package/src/reference-sheet/index.ts +8 -0
- package/src/reference-sheet/panel-plan.ts +65 -0
- package/src/reference-sheet/panel-prompts.ts +14 -0
- package/src/reference-sheet/plan-generation.ts +79 -0
- package/src/reference-sheet/presets.ts +77 -0
- package/src/reference-sheet/types.ts +92 -0
- package/src/repeat-types.ts +97 -0
- package/src/resolve-field-mappings.ts +119 -0
- package/src/route-filter.ts +80 -0
- package/src/scene-helper-types.ts +249 -0
- package/src/scene-node-types.ts +281 -0
- package/src/scraper-actors.ts +57 -0
- package/src/scraper-output-schemas.ts +25 -0
- package/src/seasons.ts +45 -0
- package/src/selector.ts +864 -0
- package/src/settled-with-limit.ts +42 -0
- package/src/shot-element.ts +43 -0
- package/src/social-media-specs.ts +121 -0
- package/src/social-post.ts +24 -0
- package/src/sub-workflow-validation.ts +78 -0
- package/src/supported-fonts.ts +40 -0
- package/src/surround.ts +113 -0
- package/src/switchx-pricing.ts +33 -0
- package/src/text-separators.ts +59 -0
- package/src/to-connected-references.ts +77 -0
- package/src/types.ts +272 -0
- package/src/variant-job-id.ts +17 -0
- package/src/vehicles.ts +213 -0
- package/src/video-analysis-pricing.ts +74 -0
- package/src/video-analysis.ts +127 -0
- package/src/video-duration.ts +25 -0
- package/src/voice-changer-models.ts +36 -0
- package/src/voice-matcher-types.ts +37 -0
- package/src/voices.ts +92 -0
- package/src/weapons.ts +190 -0
- package/src/workflow-export.ts +153 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { z } from "zod"
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Body for POST /v1/pipelines/:id/entities/:entity_id/reject.
|
|
5
|
+
* Approve takes no body (optional `edits` future-deferred).
|
|
6
|
+
*/
|
|
7
|
+
export const EntityRejectInputSchema = z.object({
|
|
8
|
+
feedback: z.string().min(1).max(2000),
|
|
9
|
+
})
|
|
10
|
+
export type EntityRejectInput = z.infer<typeof EntityRejectInputSchema>
|
|
11
|
+
|
|
12
|
+
export const ENTITY_STATUSES = [
|
|
13
|
+
"pending",
|
|
14
|
+
"generating",
|
|
15
|
+
"awaiting_approval",
|
|
16
|
+
"approved",
|
|
17
|
+
"rejected",
|
|
18
|
+
"failed",
|
|
19
|
+
// Phase 3 (granular-pipeline-control) — Stage 2 Character Wizard.
|
|
20
|
+
// `pending_description` is the initial state for character entities in
|
|
21
|
+
// manual/guided mode pipelines; the engine waits for the user's Step A
|
|
22
|
+
// approval before generating the portrait. `skipped` is a terminal state
|
|
23
|
+
// for entities the user explicitly opts out of (no generation, excluded
|
|
24
|
+
// from stage-advance gating). Migration: 154_phase_1d3_character_wizard.sql.
|
|
25
|
+
"pending_description",
|
|
26
|
+
"skipped",
|
|
27
|
+
] as const
|
|
28
|
+
export type EntityStatus = (typeof ENTITY_STATUSES)[number]
|
|
29
|
+
|
|
30
|
+
export const ENTITY_TYPES = ["character", "object", "location", "scene"] as const
|
|
31
|
+
export type EntityType = (typeof ENTITY_TYPES)[number]
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
2
|
+
// Entity studio aspect-ratio defaults (location / creature / object)
|
|
3
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
4
|
+
//
|
|
5
|
+
// Character has its own table (`character-aspect-defaults.ts`); this is the
|
|
6
|
+
// equivalent for the other three entity studios. It is the SINGLE source for:
|
|
7
|
+
// 1. the generation request aspect sent to the provider (backend generate-*
|
|
8
|
+
// routes), and
|
|
9
|
+
// 2. the studio card's *fallback* container ratio (frontend), shown until the
|
|
10
|
+
// real media aspect is probed.
|
|
11
|
+
// Keeping both in one place means the framing a user sees can't drift from the
|
|
12
|
+
// framing that was generated.
|
|
13
|
+
//
|
|
14
|
+
// Note: the frontend additionally sizes each card to the REAL decoded media
|
|
15
|
+
// aspect (so a provider that returns a slightly different ratio still displays
|
|
16
|
+
// uncropped). These per-type values are the deterministic placeholder + the
|
|
17
|
+
// value requested at generation time.
|
|
18
|
+
|
|
19
|
+
export type EntityStudioKind = "location" | "creature" | "object"
|
|
20
|
+
|
|
21
|
+
/** Provider "W:H" ratio strings (same vocabulary as the character table). */
|
|
22
|
+
export const ENTITY_ASPECT_DEFAULTS: Record<
|
|
23
|
+
EntityStudioKind,
|
|
24
|
+
Record<string, string>
|
|
25
|
+
> = {
|
|
26
|
+
// Locations are environments → landscape framing everywhere.
|
|
27
|
+
location: {
|
|
28
|
+
timeOfDay: "16:9",
|
|
29
|
+
weather: "16:9",
|
|
30
|
+
seasons: "16:9",
|
|
31
|
+
angles: "16:9",
|
|
32
|
+
lighting: "16:9",
|
|
33
|
+
atmosphereMotions: "16:9",
|
|
34
|
+
},
|
|
35
|
+
// Creatures (animals): turnaround angles & condition variations read square;
|
|
36
|
+
// full-body poses read taller (portrait); motion clips are vertical.
|
|
37
|
+
creature: {
|
|
38
|
+
angles: "1:1",
|
|
39
|
+
poses: "3:4",
|
|
40
|
+
variations: "1:1",
|
|
41
|
+
motion: "9:16",
|
|
42
|
+
},
|
|
43
|
+
// Objects/props: product turnarounds, materials, and condition variants are
|
|
44
|
+
// square; motion clips are vertical.
|
|
45
|
+
object: {
|
|
46
|
+
angles: "1:1",
|
|
47
|
+
materials: "1:1",
|
|
48
|
+
variations: "1:1",
|
|
49
|
+
motion: "9:16",
|
|
50
|
+
},
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const RATIO_RE = /^\d+:\d+$/
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Resolve the provider aspect string for an entity asset generation.
|
|
57
|
+
* Precedence: explicit > node override > per-asset-type default > "1:1".
|
|
58
|
+
* The two "soft" inputs are honored only when they parse as a "W:H" ratio, so a
|
|
59
|
+
* stale value falls through instead of poisoning the request.
|
|
60
|
+
*/
|
|
61
|
+
export function resolveEntityAspect(opts: {
|
|
62
|
+
entity: EntityStudioKind
|
|
63
|
+
assetType: string
|
|
64
|
+
explicit?: string | null
|
|
65
|
+
nodeOverride?: string | null
|
|
66
|
+
}): string {
|
|
67
|
+
if (opts.explicit && RATIO_RE.test(opts.explicit)) return opts.explicit
|
|
68
|
+
if (opts.nodeOverride && RATIO_RE.test(opts.nodeOverride)) return opts.nodeOverride
|
|
69
|
+
return ENTITY_ASPECT_DEFAULTS[opts.entity]?.[opts.assetType] ?? "1:1"
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* "9:16" → 0.5625 (width / height) for a CSS `aspect-ratio` fallback value.
|
|
74
|
+
* Anything that isn't a "W:H" ratio (or has a zero term) → 1 (square).
|
|
75
|
+
*/
|
|
76
|
+
export function aspectRatioToNumber(ratio: string): number {
|
|
77
|
+
const m = /^(\d+):(\d+)$/.exec(ratio.trim())
|
|
78
|
+
if (!m) return 1
|
|
79
|
+
const w = Number(m[1])
|
|
80
|
+
const h = Number(m[2])
|
|
81
|
+
return w > 0 && h > 0 ? w / h : 1
|
|
82
|
+
}
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structural entity vocabulary — asset-type/attach-column tuples, reference
|
|
3
|
+
* photo kinds, styles, labels. Product data visible in the UI and required
|
|
4
|
+
* by SDK consumers; deliberately part of the public Apache surface.
|
|
5
|
+
* (The prompt-BUILDING craft lives in @nodaro/prompts.)
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Prompt builders for entity nodes (character, face, object, location).
|
|
10
|
+
*
|
|
11
|
+
* Single source of truth shared between:
|
|
12
|
+
* - Route handlers: `backend/src/routes/generate-{character,face,object,location}.ts`
|
|
13
|
+
* - Backend orchestrator: `backend/src/services/workflow-engine/payload-builder.ts`
|
|
14
|
+
*
|
|
15
|
+
* The route handlers call these when no client-supplied prompt is provided.
|
|
16
|
+
* The orchestrator calls these to build the same prompt that a single-node
|
|
17
|
+
* HTTP call would produce.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Allowed style values for character / face / object / location entities.
|
|
22
|
+
* Single source of truth: derive Zod enums + TS types from this tuple so the
|
|
23
|
+
* Zod schema, the TS union, the SDK input types, and the CLI flag validator
|
|
24
|
+
* never drift apart.
|
|
25
|
+
*/
|
|
26
|
+
export const CHARACTER_STYLES = ["realistic", "anime", "3d-pixar", "illustration"] as const
|
|
27
|
+
export type EntityStyle = (typeof CHARACTER_STYLES)[number]
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Character asset-type enum — the kinds of variant a user can generate off a
|
|
31
|
+
* character's anchor portrait. Mirrors the literal accepted by
|
|
32
|
+
* `POST /v1/generate-character-asset` (`backend/src/routes/generate-character-asset.ts`)
|
|
33
|
+
* and consumed by the MCP `generate_character` verb (kind="asset") in
|
|
34
|
+
* `backend/src/lib/mcp/tools/verbs-clo.ts`.
|
|
35
|
+
*
|
|
36
|
+
* `angles` is the legacy single-surface alias for `headAngles` — both produce
|
|
37
|
+
* head-and-shoulders portrait framing. `bodyAngles` is the full-body variant.
|
|
38
|
+
* `lighting` is the bucket key (the DB column is `lighting_variations`).
|
|
39
|
+
*/
|
|
40
|
+
export const CHARACTER_ASSET_TYPES = [
|
|
41
|
+
"expressions",
|
|
42
|
+
"poses",
|
|
43
|
+
"lighting",
|
|
44
|
+
"angles",
|
|
45
|
+
"headAngles",
|
|
46
|
+
"bodyAngles",
|
|
47
|
+
"custom",
|
|
48
|
+
] as const
|
|
49
|
+
export type CharacterAssetType = (typeof CHARACTER_ASSET_TYPES)[number]
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* DB columns the character-asset worker may auto-attach to. Required when
|
|
53
|
+
* `assetType === "custom"` (the worker can't infer the bucket from the asset
|
|
54
|
+
* type); for canonical asset types the column is derived automatically.
|
|
55
|
+
*
|
|
56
|
+
* Mirrors the literal accepted by the route's `attachToColumn` Zod field.
|
|
57
|
+
*/
|
|
58
|
+
export const CHARACTER_ATTACH_COLUMNS = [
|
|
59
|
+
"expressions",
|
|
60
|
+
"poses",
|
|
61
|
+
"angles",
|
|
62
|
+
"body_angles",
|
|
63
|
+
"lighting_variations",
|
|
64
|
+
// Reference-sheet buckets (migration 200). `sheets` holds composited
|
|
65
|
+
// reference sheets; `detail_closeups` holds macro close-up panels;
|
|
66
|
+
// `outfit_variations` holds wardrobe panels (character-only — objects and
|
|
67
|
+
// locations don't have an outfit dimension).
|
|
68
|
+
"sheets",
|
|
69
|
+
"detail_closeups",
|
|
70
|
+
"outfit_variations",
|
|
71
|
+
] as const
|
|
72
|
+
export type CharacterAttachColumn = (typeof CHARACTER_ATTACH_COLUMNS)[number]
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Canonical variant presets per character asset type — the SINGLE source of
|
|
76
|
+
* truth shared by the `generate-character-asset` route (Zod validation rejects a
|
|
77
|
+
* non-`custom` variant outside this list) and any client building the asset-set
|
|
78
|
+
* UI (e.g. the Studio character creator), so the two can't drift. `custom` has no
|
|
79
|
+
* preset list (free-form variant).
|
|
80
|
+
*/
|
|
81
|
+
export const CHARACTER_ASSET_VARIANTS = {
|
|
82
|
+
expressions: [
|
|
83
|
+
"neutral",
|
|
84
|
+
"smile",
|
|
85
|
+
"angry",
|
|
86
|
+
"surprised",
|
|
87
|
+
"sad",
|
|
88
|
+
"talking",
|
|
89
|
+
"laughing",
|
|
90
|
+
"disgusted",
|
|
91
|
+
"fearful",
|
|
92
|
+
"smirk",
|
|
93
|
+
"crying",
|
|
94
|
+
],
|
|
95
|
+
poses: [
|
|
96
|
+
"standing",
|
|
97
|
+
"walking",
|
|
98
|
+
"sitting",
|
|
99
|
+
"running",
|
|
100
|
+
"crouching",
|
|
101
|
+
"pointing",
|
|
102
|
+
"fighting stance",
|
|
103
|
+
"jumping",
|
|
104
|
+
"turning",
|
|
105
|
+
],
|
|
106
|
+
lighting: ["daylight", "night", "dramatic"],
|
|
107
|
+
angles: ["front", "3/4 left", "left profile", "right profile", "3/4 right", "back", "above", "below"],
|
|
108
|
+
headAngles: ["front", "3/4 left", "left profile", "right profile", "3/4 right", "above", "below", "back"],
|
|
109
|
+
bodyAngles: ["front", "3/4 left", "left profile", "right profile", "3/4 right", "back", "above", "below"],
|
|
110
|
+
} as const satisfies Partial<Record<CharacterAssetType, readonly string[]>>
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Location asset-type enum — the kinds of variant a user can generate off a
|
|
114
|
+
* location's anchor establishing shot. Mirrors the literal accepted by
|
|
115
|
+
* `POST /v1/generate-location-asset` (`backend/src/routes/generate-location-asset.ts`)
|
|
116
|
+
* and consumed by the MCP `generate_location` verb (kind="asset").
|
|
117
|
+
*
|
|
118
|
+
* `lighting` is the bucket key (the DB column is `lighting`). `custom` is the
|
|
119
|
+
* free-form bucket where callers must supply `attachToColumn` explicitly since
|
|
120
|
+
* the worker can't infer the destination from the asset type.
|
|
121
|
+
*/
|
|
122
|
+
export const LOCATION_ASSET_TYPES = [
|
|
123
|
+
"timeOfDay",
|
|
124
|
+
"weather",
|
|
125
|
+
"seasons",
|
|
126
|
+
"angles",
|
|
127
|
+
"lighting",
|
|
128
|
+
"custom",
|
|
129
|
+
] as const
|
|
130
|
+
export type LocationAssetType = (typeof LOCATION_ASSET_TYPES)[number]
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* DB columns the location-asset worker may auto-attach to. Required when
|
|
134
|
+
* `assetType === "custom"` (the worker can't infer the bucket from the asset
|
|
135
|
+
* type); for canonical asset types the column is derived automatically.
|
|
136
|
+
*
|
|
137
|
+
* Mirrors the literal accepted by the route's `attachToColumn` Zod field.
|
|
138
|
+
*/
|
|
139
|
+
export const LOCATION_ATTACH_COLUMNS = [
|
|
140
|
+
"time_of_day",
|
|
141
|
+
"weather",
|
|
142
|
+
"seasons",
|
|
143
|
+
"angles",
|
|
144
|
+
"lighting",
|
|
145
|
+
"atmosphere_motions",
|
|
146
|
+
// Reference-sheet buckets (migration 200). Locations get `sheets` +
|
|
147
|
+
// `detail_closeups` (no `outfit_variations` — that's character-only).
|
|
148
|
+
"sheets",
|
|
149
|
+
"detail_closeups",
|
|
150
|
+
] as const
|
|
151
|
+
export type LocationAttachColumn = (typeof LOCATION_ATTACH_COLUMNS)[number]
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Canonical variant presets per LOCATION asset type — hoisted from
|
|
155
|
+
* `backend/src/routes/generate-location-asset.ts` (single source of truth shared
|
|
156
|
+
* with the reference-sheet catalog; Plan 04 switches the route to import this).
|
|
157
|
+
*/
|
|
158
|
+
export const LOCATION_ASSET_VARIANTS = {
|
|
159
|
+
timeOfDay: ["dawn", "morning", "noon", "afternoon", "golden hour", "dusk", "blue hour", "night", "midnight"],
|
|
160
|
+
weather: ["clear", "cloudy", "light rain", "heavy rain", "storm", "snow", "blizzard", "fog", "mist"],
|
|
161
|
+
seasons: ["spring", "summer", "autumn", "winter"],
|
|
162
|
+
angles: ["wide", "medium", "closeup", "aerial", "low-angle", "eye-level", "bird's-eye", "dutch tilt"],
|
|
163
|
+
lighting: ["soft natural", "harsh sunlight", "golden", "blue hour", "neon", "candlelit", "cinematic", "dramatic chiaroscuro"],
|
|
164
|
+
} as const satisfies Partial<Record<LocationAssetType, readonly string[]>>
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Reference-photo kind discriminator — the mood-board roles a user can attach
|
|
168
|
+
* to a location row. Single source of truth shared between:
|
|
169
|
+
* - Backend route Zod enum (`backend/src/routes/locations.ts`)
|
|
170
|
+
* - Backend export/import bundle schema (`backend/src/lib/workflow-assets.ts`)
|
|
171
|
+
* - Frontend Studio picker (`reference-photos-section.tsx`)
|
|
172
|
+
* - Frontend `LocationNodeData.referencePhotos.kind` union (`frontend/src/types/nodes.ts`)
|
|
173
|
+
*
|
|
174
|
+
* `other` is the free-form bucket; the rest are user-curated mood-board roles.
|
|
175
|
+
*/
|
|
176
|
+
export const LOCATION_REFERENCE_PHOTO_KINDS = [
|
|
177
|
+
"wide",
|
|
178
|
+
"interior",
|
|
179
|
+
"exterior",
|
|
180
|
+
"detail",
|
|
181
|
+
"moodBoard",
|
|
182
|
+
"other",
|
|
183
|
+
] as const
|
|
184
|
+
export type LocationReferencePhotoKind = (typeof LOCATION_REFERENCE_PHOTO_KINDS)[number]
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Human-friendly label for each photo kind, used in prompt subject lines
|
|
188
|
+
* (`Image N (Old Library — wide-angle reference)`) so the model knows the
|
|
189
|
+
* role of each reference photo at generate time. Kept as a separate map
|
|
190
|
+
* from `LOCATION_REFERENCE_PHOTO_KINDS` so labels can be edited without
|
|
191
|
+
* disturbing the kind enum (which is the schema-of-record).
|
|
192
|
+
*/
|
|
193
|
+
export const LOCATION_REFERENCE_PHOTO_KIND_LABELS: Record<LocationReferencePhotoKind, string> = {
|
|
194
|
+
wide: "wide-angle reference",
|
|
195
|
+
interior: "interior reference",
|
|
196
|
+
exterior: "exterior reference",
|
|
197
|
+
detail: "detail reference",
|
|
198
|
+
moodBoard: "mood-board reference",
|
|
199
|
+
other: "reference",
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
export function locationReferencePhotoKindLabel(kind: LocationReferencePhotoKind): string {
|
|
203
|
+
return LOCATION_REFERENCE_PHOTO_KIND_LABELS[kind]
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Reference-photo kinds captured in the Character Studio identity foundation —
|
|
208
|
+
* the SINGLE schema-of-record for the 7 kinds. Previously duplicated across the
|
|
209
|
+
* `generate-character` + `characters` route Zod enums, `character-reference-set.ts`
|
|
210
|
+
* (backend ranking), and `frontend/src/lib/reference-photo-routing.ts` (UI
|
|
211
|
+
* filtering). All of those now derive from this const (build a Zod enum via
|
|
212
|
+
* `z.enum(CHARACTER_REFERENCE_PHOTO_KINDS)` at the backend edge — this package
|
|
213
|
+
* stays zod-free). Also the shape of the DB `characters.reference_photos[].kind`.
|
|
214
|
+
*
|
|
215
|
+
* `other` is the free-form bucket; the rest are curated identity-foundation roles
|
|
216
|
+
* (frontFace + the four rotation views + a full-body shot).
|
|
217
|
+
*/
|
|
218
|
+
export const CHARACTER_REFERENCE_PHOTO_KINDS = [
|
|
219
|
+
"frontFace",
|
|
220
|
+
"sideLeft",
|
|
221
|
+
"sideRight",
|
|
222
|
+
"threeQuarterLeft",
|
|
223
|
+
"threeQuarterRight",
|
|
224
|
+
"frontBody",
|
|
225
|
+
"other",
|
|
226
|
+
] as const
|
|
227
|
+
export type CharacterReferencePhotoKind = (typeof CHARACTER_REFERENCE_PHOTO_KINDS)[number]
|
|
228
|
+
|
|
229
|
+
/** A single character reference photo: a URL plus its identity-foundation role. */
|
|
230
|
+
export interface CharacterReferencePhoto {
|
|
231
|
+
url: string
|
|
232
|
+
kind: CharacterReferencePhotoKind
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Reserved name the Character Studio auto-assigns when a user clicks Generate
|
|
237
|
+
* before naming the character. Treated as "no name" by prompt builders so the
|
|
238
|
+
* literal string "Untitled character" never leaks into a generation prompt.
|
|
239
|
+
* Frontend stays in sync via `@nodaro/shared`.
|
|
240
|
+
*/
|
|
241
|
+
export const PLACEHOLDER_CHARACTER_NAME = "Untitled character"
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
export const OBJECT_ASSET_TYPES = [
|
|
245
|
+
"angles",
|
|
246
|
+
"materials",
|
|
247
|
+
"variations",
|
|
248
|
+
"motion",
|
|
249
|
+
"custom",
|
|
250
|
+
] as const
|
|
251
|
+
export type ObjectAssetType = (typeof OBJECT_ASSET_TYPES)[number]
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* DB columns the object-asset worker may auto-attach to. Aligns with the
|
|
255
|
+
* `append_object_asset` RPC's CASE/WHEN whitelist (migration 147). Required
|
|
256
|
+
* when `assetType === "custom"`; for canonical asset types the column is
|
|
257
|
+
* derived automatically.
|
|
258
|
+
*/
|
|
259
|
+
export const OBJECT_ATTACH_COLUMNS = [
|
|
260
|
+
"angles",
|
|
261
|
+
"materials",
|
|
262
|
+
"variations",
|
|
263
|
+
"motion_clips",
|
|
264
|
+
// Reference-sheet buckets (migration 200). Objects get `sheets` +
|
|
265
|
+
// `detail_closeups` (no `outfit_variations` — that's character-only).
|
|
266
|
+
"sheets",
|
|
267
|
+
"detail_closeups",
|
|
268
|
+
] as const
|
|
269
|
+
export type ObjectAttachColumn = (typeof OBJECT_ATTACH_COLUMNS)[number]
|
|
270
|
+
|
|
271
|
+
/** Worker-attachable JSONB asset columns on `creatures` (mirrors OBJECT_ATTACH_COLUMNS;
|
|
272
|
+
* `materials`→`poses`). The append_creature_asset RPC (migration 206) whitelists these. */
|
|
273
|
+
export const CREATURE_ATTACH_COLUMNS = [
|
|
274
|
+
"angles", "poses", "variations", "motion_clips", "sheets", "detail_closeups",
|
|
275
|
+
] as const
|
|
276
|
+
export type CreatureAttachColumn = (typeof CREATURE_ATTACH_COLUMNS)[number]
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Canonical variant presets per OBJECT asset type — hoisted from
|
|
280
|
+
* `backend/src/routes/generate-object-asset.ts` so the route, the reference-sheet
|
|
281
|
+
* catalog, and any client share one list and can't drift. (Plan 04 switches the
|
|
282
|
+
* route to import this.) `custom`/`motion` have no preset list.
|
|
283
|
+
*/
|
|
284
|
+
export const OBJECT_ASSET_VARIANTS = {
|
|
285
|
+
angles: ["front", "side", "top", "back", "three-quarter"],
|
|
286
|
+
materials: ["wood", "metal", "glass", "plastic", "fabric", "stone"],
|
|
287
|
+
variations: ["clean", "weathered", "damaged", "ornate", "minimal"],
|
|
288
|
+
} as const satisfies Partial<Record<ObjectAssetType, readonly string[]>>
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Input shape for buildObjectMotionPrompt.
|
|
292
|
+
*
|
|
293
|
+
* Mirrors LocationMotionPromptInput's role. `canonicalDescription` is preferred
|
|
294
|
+
* (LLM-authored from the approved main image) but the helper falls back to
|
|
295
|
+
* category+name if not yet set, and to a generic placeholder if both are absent.
|
|
296
|
+
*/
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Entity node types that expose a plain `image` source handle (emitting the
|
|
3
|
+
* portrait URL) in addition to their identity `*Ref` handle. When a wire leaves
|
|
4
|
+
* the `image` handle, the entity is treated as a plain image PRODUCER
|
|
5
|
+
* (substituted to "upload-image") so it reaches image inputs and lists exactly
|
|
6
|
+
* like generate-image / upload-image, while the `*Ref` handle stays identity.
|
|
7
|
+
*
|
|
8
|
+
* SINGLE SOURCE OF TRUTH — consumed by:
|
|
9
|
+
* - frontend connection validation (drop validator, drag-glow, popover),
|
|
10
|
+
* - frontend run assemblers (execute-node, video-prompt-assembly),
|
|
11
|
+
* - frontend config-panel reference preview builders,
|
|
12
|
+
* - backend payload-builder identity-injection guards.
|
|
13
|
+
* Add future per-handle output-type remaps HERE so every surface inherits them.
|
|
14
|
+
*/
|
|
15
|
+
export const ENTITY_IMAGE_HANDLE_TYPES: ReadonlySet<string> = new Set([
|
|
16
|
+
"character",
|
|
17
|
+
"location",
|
|
18
|
+
"object",
|
|
19
|
+
"creature",
|
|
20
|
+
])
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* The effective output TYPE a given source handle emits. Returns the raw node
|
|
24
|
+
* type for every `(type, handle)` pair EXCEPT an entity `image` handle, which
|
|
25
|
+
* resolves to `"upload-image"` (a plain image producer). Pure — safe for both
|
|
26
|
+
* frontend and backend.
|
|
27
|
+
*/
|
|
28
|
+
export function resolveEffectiveSourceType(
|
|
29
|
+
rawSourceType: string | undefined | null,
|
|
30
|
+
sourceHandleId: string | undefined | null,
|
|
31
|
+
): string {
|
|
32
|
+
if (sourceHandleId === "image" && ENTITY_IMAGE_HANDLE_TYPES.has(rawSourceType ?? "")) {
|
|
33
|
+
return "upload-image"
|
|
34
|
+
}
|
|
35
|
+
return rawSourceType ?? ""
|
|
36
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared helper for materializing user-attached "extra reference images" into
|
|
3
|
+
* `ConnectedReference` entries.
|
|
4
|
+
*
|
|
5
|
+
* Used by both:
|
|
6
|
+
* - frontend `execute-node.ts` (single-node Run + DAG executor path) and
|
|
7
|
+
* - backend `payload-builder.ts` (orchestrator path)
|
|
8
|
+
* so single-node frontend runs and orchestrator-driven runs produce identical
|
|
9
|
+
* `referenceImageUrls` + assembled prompts. See `frontend/src/types/nodes.ts`
|
|
10
|
+
* for the `ExtraRef` interface and `packages/shared/src/prompt-builder.ts`
|
|
11
|
+
* for the directive emission contract (`buildExtraRefDirectives`).
|
|
12
|
+
*
|
|
13
|
+
* Field mapping:
|
|
14
|
+
* - manual upload → source = "manual", description = ref.description
|
|
15
|
+
* - char-variant → source = "wired-character", characterSlug + variantSlug
|
|
16
|
+
* preserved, description = ref.description (used as the
|
|
17
|
+
* bullet's per-image description in directives — overrides
|
|
18
|
+
* `variantDescription` from the character node).
|
|
19
|
+
*
|
|
20
|
+
* Usage-mode resolution: per-ref `usageMode` override → upstream character
|
|
21
|
+
* node's `defaultUsageMode` → global "identical". The resolved mode is stored
|
|
22
|
+
* in `defaultUsageMode` on the resulting `ConnectedReference` so the existing
|
|
23
|
+
* directive emission (`buildExtraRefDirectives`, `buildCanonicalFallback`,
|
|
24
|
+
* `resolveCharacterMentions`) reads it uniformly.
|
|
25
|
+
*
|
|
26
|
+
* Character-node lookup: takes a `lookupCharacterNode` callback so each caller
|
|
27
|
+
* can provide its own (frontend uses Zustand store + edges, backend uses
|
|
28
|
+
* `PayloadBuildContext.nodes` + edges). The callback should return the
|
|
29
|
+
* character node whose name slugifies to `characterSlug`, or undefined if
|
|
30
|
+
* no such character is wired upstream.
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
import { DEFAULT_USAGE_MODE, type UsageMode } from "./character-usage-mode.js"
|
|
34
|
+
import type { ConnectedReference } from "./types.js"
|
|
35
|
+
|
|
36
|
+
/** Shape of an extra-ref entry on node data. Matches `ExtraRef` in the
|
|
37
|
+
* frontend `types/nodes.ts`; duplicated here as a structural interface so
|
|
38
|
+
* the backend (which sees node data as `Record<string, unknown>`) can pass
|
|
39
|
+
* raw JSON through `expandExtraRefsToConnectedReferences`. */
|
|
40
|
+
export interface ExtraRefInput {
|
|
41
|
+
readonly url?: string
|
|
42
|
+
readonly description?: string
|
|
43
|
+
readonly characterSlug?: string
|
|
44
|
+
readonly variantSlug?: string
|
|
45
|
+
readonly variantDisplayName?: string
|
|
46
|
+
readonly usageMode?: UsageMode
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** Hook that returns extra metadata for the upstream Character node backing
|
|
50
|
+
* a given character slug, if any. Used to resolve `defaultUsageMode` and
|
|
51
|
+
* `characterCanonicalDescription`. */
|
|
52
|
+
export interface ExtraRefCharacterContext {
|
|
53
|
+
readonly defaultUsageMode?: UsageMode
|
|
54
|
+
readonly canonicalDescription?: string | null
|
|
55
|
+
readonly displayName?: string
|
|
56
|
+
/** Character node's hybrid `defaultRole` — stamped onto the extra's
|
|
57
|
+
* `ConnectedReference.defaultRole` (only when the extra carries no per-ref
|
|
58
|
+
* `usageMode` override, which would take precedence). */
|
|
59
|
+
readonly defaultRole?: string
|
|
60
|
+
/** Character node's `identityLock`, mapped to the per-reference lock shape
|
|
61
|
+
* (`characterLockToRefLock`) — stamped onto the extra's
|
|
62
|
+
* `ConnectedReference.identityLock`. */
|
|
63
|
+
readonly identityLock?: { enabled: boolean; text?: string }
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Convert a list of `ExtraRef` entries into `ConnectedReference` entries that
|
|
68
|
+
* append to the consumer node's existing `connectedReferences` list. The
|
|
69
|
+
* resulting entries carry `isExtraRef: true` so the shared prompt-builder
|
|
70
|
+
* routes them through the dedicated extra-ref directive emission (which
|
|
71
|
+
* handles "Image N is the same subject as Image M, …" pairing).
|
|
72
|
+
*
|
|
73
|
+
* `lookupCharacterContext(slug)` is called for character-sourced extras to
|
|
74
|
+
* resolve the upstream character node's `defaultUsageMode` and canonical
|
|
75
|
+
* description. Returning `undefined` is safe — the helper falls back to the
|
|
76
|
+
* per-ref `usageMode` override or the global default.
|
|
77
|
+
*/
|
|
78
|
+
export function expandExtraRefsToConnectedReferences(
|
|
79
|
+
extras: ReadonlyArray<ExtraRefInput> | undefined,
|
|
80
|
+
lookupCharacterContext?: (slug: string) => ExtraRefCharacterContext | undefined,
|
|
81
|
+
): ConnectedReference[] {
|
|
82
|
+
if (!extras || extras.length === 0) return []
|
|
83
|
+
const out: ConnectedReference[] = []
|
|
84
|
+
for (let i = 0; i < extras.length; i++) {
|
|
85
|
+
const r = extras[i]
|
|
86
|
+
if (!r || !r.url) continue
|
|
87
|
+
const description = (r.description ?? "").trim()
|
|
88
|
+
if (r.characterSlug) {
|
|
89
|
+
// Character-sourced extra. Resolution chain for the effective mode:
|
|
90
|
+
// per-ref override (r.usageMode) → upstream character node's default →
|
|
91
|
+
// global identical. The character node lookup also gives us the
|
|
92
|
+
// canonical description used by "identical"/"face-pose" mode displays.
|
|
93
|
+
const ctx = lookupCharacterContext?.(r.characterSlug)
|
|
94
|
+
const effectiveMode: UsageMode = r.usageMode ?? ctx?.defaultUsageMode ?? DEFAULT_USAGE_MODE
|
|
95
|
+
const displayName = ctx?.displayName || r.characterSlug
|
|
96
|
+
out.push({
|
|
97
|
+
id: `extra_${i}`,
|
|
98
|
+
defaultName: r.variantDisplayName
|
|
99
|
+
? `${displayName} / ${r.variantDisplayName}`
|
|
100
|
+
: displayName,
|
|
101
|
+
source: "wired-character",
|
|
102
|
+
description,
|
|
103
|
+
url: r.url,
|
|
104
|
+
characterSlug: r.characterSlug,
|
|
105
|
+
variantSlug: r.variantSlug,
|
|
106
|
+
characterCanonicalDescription: ctx?.canonicalDescription ?? null,
|
|
107
|
+
variantDescription: description.length > 0 ? description : null,
|
|
108
|
+
variantDisplayName: r.variantDisplayName,
|
|
109
|
+
defaultUsageMode: effectiveMode,
|
|
110
|
+
// Node-default role (Character Node Role+Lock): stamped ONLY when the
|
|
111
|
+
// extra carries no per-ref `usageMode` override — the override wins
|
|
112
|
+
// (it's already folded into `defaultUsageMode` above, and
|
|
113
|
+
// `resolveDefaultRole` would otherwise let the role beat it).
|
|
114
|
+
defaultRole: r.usageMode ? undefined : ctx?.defaultRole,
|
|
115
|
+
// Node's mapped identity-lock (`characterLockToRefLock`) — orthogonal
|
|
116
|
+
// to the role; the hybrid renderers emit its line via
|
|
117
|
+
// `buildIdentityLockLine`.
|
|
118
|
+
identityLock: ctx?.identityLock,
|
|
119
|
+
isExtraRef: true,
|
|
120
|
+
})
|
|
121
|
+
} else {
|
|
122
|
+
// Manual upload extra. `description` is what the user typed in the
|
|
123
|
+
// per-row textarea; usage mode override applies if set (drives the
|
|
124
|
+
// directive's lock language even for manual refs — covers the "use as
|
|
125
|
+
// style/face only" case for an uploaded photo).
|
|
126
|
+
const effectiveMode: UsageMode | undefined = r.usageMode
|
|
127
|
+
out.push({
|
|
128
|
+
id: `extra_${i}`,
|
|
129
|
+
defaultName: `Image ${i + 1}`,
|
|
130
|
+
source: "manual",
|
|
131
|
+
description,
|
|
132
|
+
url: r.url,
|
|
133
|
+
defaultUsageMode: effectiveMode,
|
|
134
|
+
isExtraRef: true,
|
|
135
|
+
})
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return out
|
|
139
|
+
}
|