@nodaro/shared 1.4.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.
- 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,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Models-tab data source: maps each catalog model to the node it creates
|
|
3
|
+
* (`modelToNodeTarget`) and groups node-creatable models into product lines
|
|
4
|
+
* (`buildModelTree`). Consumed by the add-node popup's Models tab. Pure — derives
|
|
5
|
+
* everything from `MODEL_CATALOG` + the provider enums, so models added to the
|
|
6
|
+
* catalog/enums flow through automatically.
|
|
7
|
+
*/
|
|
8
|
+
import { MODEL_CATALOG, type ModelKind, type ModelMode } from "./model-catalog.js"
|
|
9
|
+
import {
|
|
10
|
+
IMAGE_GEN_PROVIDERS, VIDEO_GEN_PROVIDERS, IMAGE_TO_VIDEO_PROVIDERS, TEXT_TO_VIDEO_PROVIDERS,
|
|
11
|
+
UPSCALE_IMAGE_PROVIDERS, VIDEO_UPSCALE_PROVIDERS, MODIFY_IMAGE_PROVIDERS, IMAGE_EDIT_PROVIDERS,
|
|
12
|
+
VIDEO_TO_VIDEO_PROVIDERS, EXTEND_VIDEO_PROVIDERS, MOTION_TRANSFER_PROVIDERS, LIP_SYNC_PROVIDERS,
|
|
13
|
+
FACE_SWAP_PROVIDERS, TTS_PROVIDERS, TEXT_TO_AUDIO_PROVIDERS, TRANSCRIBE_PROVIDERS, MUSIC_PROVIDERS,
|
|
14
|
+
} from "./model-constants.js"
|
|
15
|
+
|
|
16
|
+
export interface ModelNodeTarget {
|
|
17
|
+
nodeType: string
|
|
18
|
+
field?: "provider" | "model"
|
|
19
|
+
value?: string
|
|
20
|
+
}
|
|
21
|
+
export interface ModelTreeVariant extends ModelNodeTarget {
|
|
22
|
+
id: string
|
|
23
|
+
label: string
|
|
24
|
+
kind: ModelKind
|
|
25
|
+
}
|
|
26
|
+
export interface ModelTreeLine {
|
|
27
|
+
series: string
|
|
28
|
+
family: string
|
|
29
|
+
kind: ModelKind
|
|
30
|
+
models: ModelTreeVariant[]
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// A model id that is a valid provider-enum value gets a node + provider preset.
|
|
34
|
+
const ENUM_TARGETS: ReadonlyArray<readonly [readonly string[], string]> = [
|
|
35
|
+
[IMAGE_GEN_PROVIDERS, "generate-image"],
|
|
36
|
+
[VIDEO_GEN_PROVIDERS, "generate-video"],
|
|
37
|
+
[IMAGE_TO_VIDEO_PROVIDERS, "generate-video"],
|
|
38
|
+
[TEXT_TO_VIDEO_PROVIDERS, "generate-video"],
|
|
39
|
+
[UPSCALE_IMAGE_PROVIDERS, "upscale-image"],
|
|
40
|
+
[VIDEO_UPSCALE_PROVIDERS, "video-upscale"],
|
|
41
|
+
[MODIFY_IMAGE_PROVIDERS, "modify-image"],
|
|
42
|
+
[IMAGE_EDIT_PROVIDERS, "modify-image"],
|
|
43
|
+
[VIDEO_TO_VIDEO_PROVIDERS, "video-to-video"],
|
|
44
|
+
[EXTEND_VIDEO_PROVIDERS, "extend-video"],
|
|
45
|
+
[MOTION_TRANSFER_PROVIDERS, "motion-transfer"],
|
|
46
|
+
[LIP_SYNC_PROVIDERS, "lip-sync"],
|
|
47
|
+
[FACE_SWAP_PROVIDERS, "face-swap"],
|
|
48
|
+
[TTS_PROVIDERS, "text-to-speech"],
|
|
49
|
+
[TEXT_TO_AUDIO_PROVIDERS, "text-to-audio"],
|
|
50
|
+
[TRANSCRIBE_PROVIDERS, "transcribe"],
|
|
51
|
+
[MUSIC_PROVIDERS, "suno-generate"],
|
|
52
|
+
]
|
|
53
|
+
|
|
54
|
+
// Fallback by the catalog's own `modes`, for models whose id is NOT a provider-enum
|
|
55
|
+
// value — single-provider utility nodes (voice-design, dubbing, …) and catalog models
|
|
56
|
+
// that no node exposes as a provider option. These create a bare node of the right
|
|
57
|
+
// type (no provider preset — the user picks the model inside the node).
|
|
58
|
+
const MODE_TO_NODE: Readonly<Partial<Record<ModelMode, string>>> = {
|
|
59
|
+
"t2i": "generate-image", "i2i": "modify-image", "edit": "modify-image", "remove-bg": "modify-image",
|
|
60
|
+
"t2v": "generate-video", "i2v": "generate-video", "v2v": "video-to-video", "extend": "extend-video",
|
|
61
|
+
"upscale": "upscale-image", "video-upscale": "video-upscale", "motion-transfer": "motion-transfer",
|
|
62
|
+
"lip-sync": "lip-sync", "tts": "text-to-speech", "sfx": "text-to-audio",
|
|
63
|
+
"music": "suno-generate", "voice-design": "voice-design", "voice-changer": "voice-changer",
|
|
64
|
+
"isolation": "audio-isolation", "dubbing": "dubbing", "forced-alignment": "forced-alignment", "stt": "transcribe",
|
|
65
|
+
"video-analysis": "video-analysis",
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function modelToNodeTarget(modelId: string): ModelNodeTarget | null {
|
|
69
|
+
const entry = MODEL_CATALOG[modelId]
|
|
70
|
+
if (!entry) return null
|
|
71
|
+
// Resolve the target node: a valid provider-enum value wins, else the catalog's modes.
|
|
72
|
+
const enumMatch = ENUM_TARGETS.find(([providers]) => providers.includes(modelId))
|
|
73
|
+
const nodeType = enumMatch?.[1] ?? entry.modes.map((m) => MODE_TO_NODE[m]).find(Boolean)
|
|
74
|
+
if (!nodeType) return null
|
|
75
|
+
// suno-generate stores its model in `data.model` (a V-code carried on the catalog
|
|
76
|
+
// entry as `dataValue`), not as a `provider` id. Every other node takes a `provider`
|
|
77
|
+
// preset when the id is a valid enum value, and a bare node otherwise.
|
|
78
|
+
if (nodeType === "suno-generate") {
|
|
79
|
+
return entry.dataValue ? { nodeType, field: "model", value: entry.dataValue } : { nodeType }
|
|
80
|
+
}
|
|
81
|
+
return enumMatch ? { nodeType, field: "provider", value: modelId } : { nodeType }
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Flat, query-filtered model variants for the add-node search. The single source
|
|
86
|
+
* of truth shared by the Models tab/category browser and every tab's search
|
|
87
|
+
* (image/video/audio narrow by `kind`; models/all/common pass no kind). Filters
|
|
88
|
+
* by label/id substring; a blank query returns `[]`. Derived from
|
|
89
|
+
* `buildModelTree`, so only node-creatable models appear and new catalog entries
|
|
90
|
+
* flow through automatically.
|
|
91
|
+
*/
|
|
92
|
+
// MODEL_CATALOG + the provider enums are static module constants, so the tree
|
|
93
|
+
// never changes at runtime — build it once and reuse for every search keystroke.
|
|
94
|
+
let _modelTree: ModelTreeLine[] | null = null
|
|
95
|
+
function getModelTree(): ModelTreeLine[] {
|
|
96
|
+
return (_modelTree ??= buildModelTree())
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function searchModelVariants(query: string, kind?: ModelKind): ModelTreeVariant[] {
|
|
100
|
+
const q = query.trim().toLowerCase()
|
|
101
|
+
if (!q) return []
|
|
102
|
+
return getModelTree()
|
|
103
|
+
.flatMap((l) => l.models)
|
|
104
|
+
.filter((m) => (!kind || m.kind === kind) && (m.label.toLowerCase().includes(q) || m.id.toLowerCase().includes(q)))
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export function buildModelTree(): ModelTreeLine[] {
|
|
108
|
+
const bySeries = new Map<string, ModelTreeLine>()
|
|
109
|
+
for (const entry of Object.values(MODEL_CATALOG)) {
|
|
110
|
+
const target = modelToNodeTarget(entry.id)
|
|
111
|
+
if (!target || !entry.series) continue
|
|
112
|
+
let line = bySeries.get(entry.series)
|
|
113
|
+
if (!line) {
|
|
114
|
+
line = { series: entry.series, family: entry.family, kind: entry.kind, models: [] }
|
|
115
|
+
bySeries.set(entry.series, line)
|
|
116
|
+
}
|
|
117
|
+
line.models.push({ id: entry.id, label: entry.label, kind: entry.kind, ...target })
|
|
118
|
+
}
|
|
119
|
+
return [...bySeries.values()].sort((a, b) => a.series.localeCompare(b.series))
|
|
120
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Calculate the creator's monetization markup on a base credit cost.
|
|
3
|
+
* Returns the markup amount (not the total).
|
|
4
|
+
*/
|
|
5
|
+
export function calculateMonetizationMarkup(baseCost: number, flatFee: number, percent: number): number {
|
|
6
|
+
if (flatFee <= 0 && percent <= 0) return 0
|
|
7
|
+
return flatFee + Math.ceil(baseCost * percent / 100)
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Calculate the total cost a runner pays (base + markup).
|
|
12
|
+
*/
|
|
13
|
+
export function calculateMonetizedCost(baseCost: number, flatFee: number, percent: number): number {
|
|
14
|
+
return baseCost + calculateMonetizationMarkup(baseCost, flatFee, percent)
|
|
15
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-select helpers for parameter dimensions that allow up to N picks.
|
|
3
|
+
*
|
|
4
|
+
* A dimension's stored value can be:
|
|
5
|
+
* - undefined / "" / [] → no pick
|
|
6
|
+
* - string → single pick (back-compat with single-select fields)
|
|
7
|
+
* - string[] → multi pick (1..N entries)
|
|
8
|
+
*
|
|
9
|
+
* `pickIds` normalizes any of those into a clean string[] (deduped, falsy
|
|
10
|
+
* entries dropped). Pickers cap the array at `maxSelected` (FIFO replacement
|
|
11
|
+
* is the picker's responsibility, not this helper's).
|
|
12
|
+
*
|
|
13
|
+
* Multi-select dimensions today: Person.ethnicity, Mood.mood, Aesthetic.aesthetic.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
export function pickIds(value: unknown): string[] {
|
|
17
|
+
if (typeof value === "string") return value ? [value] : []
|
|
18
|
+
if (!Array.isArray(value)) return []
|
|
19
|
+
const seen = new Set<string>()
|
|
20
|
+
const out: string[] = []
|
|
21
|
+
for (const v of value) {
|
|
22
|
+
if (typeof v !== "string" || !v || seen.has(v)) continue
|
|
23
|
+
seen.add(v)
|
|
24
|
+
out.push(v)
|
|
25
|
+
}
|
|
26
|
+
return out
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Cap a multi-pick array at `maxSelected`, FIFO-replacing the oldest entry
|
|
31
|
+
* when the array is full and a new id is added. Returns a fresh array.
|
|
32
|
+
*/
|
|
33
|
+
export function togglePick(
|
|
34
|
+
current: ReadonlyArray<string>,
|
|
35
|
+
id: string,
|
|
36
|
+
maxSelected: number,
|
|
37
|
+
): string[] {
|
|
38
|
+
if (current.includes(id)) return current.filter((v) => v !== id)
|
|
39
|
+
if (current.length < maxSelected) return [...current, id]
|
|
40
|
+
// FIFO replace: drop oldest, append new
|
|
41
|
+
return [...current.slice(1), id]
|
|
42
|
+
}
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import {
|
|
2
|
+
IMAGE_GEN_PROVIDERS,
|
|
3
|
+
IMAGE_I2I_PROVIDERS,
|
|
4
|
+
IMAGE_EDIT_PROVIDERS,
|
|
5
|
+
UPSCALE_IMAGE_PROVIDERS,
|
|
6
|
+
TEXT_TO_VIDEO_PROVIDERS,
|
|
7
|
+
IMAGE_TO_VIDEO_PROVIDERS,
|
|
8
|
+
VIDEO_GEN_PROVIDERS,
|
|
9
|
+
LIP_SYNC_PROVIDERS,
|
|
10
|
+
TTS_PROVIDERS,
|
|
11
|
+
VOICE_DESIGN_MODELS,
|
|
12
|
+
} from "./model-constants.js"
|
|
13
|
+
import { LLM_MODEL_IDS } from "./llm-models.js"
|
|
14
|
+
|
|
15
|
+
// ──────────────────────────────────────────────────────────────────────────
|
|
16
|
+
// Types
|
|
17
|
+
// ──────────────────────────────────────────────────────────────────────────
|
|
18
|
+
|
|
19
|
+
export type QualityLevel = "low" | "mid" | "high"
|
|
20
|
+
export type SemanticAspectRatio = "auto" | "1:1" | "4:3" | "3:4" | "16:9" | "9:16"
|
|
21
|
+
|
|
22
|
+
export const NODE_DEFAULT_TYPES = [
|
|
23
|
+
// Image
|
|
24
|
+
"generate-image",
|
|
25
|
+
"image-to-image",
|
|
26
|
+
"edit-image",
|
|
27
|
+
"upscale-image",
|
|
28
|
+
// Video
|
|
29
|
+
"text-to-video",
|
|
30
|
+
"image-to-video",
|
|
31
|
+
"generate-video",
|
|
32
|
+
// Composition
|
|
33
|
+
"lip-sync",
|
|
34
|
+
// Audio / Music
|
|
35
|
+
"text-to-speech",
|
|
36
|
+
"generate-music",
|
|
37
|
+
"voice-design",
|
|
38
|
+
// LLM-driven
|
|
39
|
+
"ai-writer",
|
|
40
|
+
"llm-chat",
|
|
41
|
+
"lottie-overlay",
|
|
42
|
+
"3d-title",
|
|
43
|
+
"motion-graphics",
|
|
44
|
+
"image-to-text",
|
|
45
|
+
"qa-check",
|
|
46
|
+
] as const
|
|
47
|
+
|
|
48
|
+
export type NodeDefaultType = (typeof NODE_DEFAULT_TYPES)[number]
|
|
49
|
+
|
|
50
|
+
export const QUALITY_LEVELS: readonly QualityLevel[] = ["low", "mid", "high"] as const
|
|
51
|
+
export const SEMANTIC_ASPECT_RATIOS: readonly SemanticAspectRatio[] = [
|
|
52
|
+
"auto",
|
|
53
|
+
"1:1",
|
|
54
|
+
"4:3",
|
|
55
|
+
"3:4",
|
|
56
|
+
"16:9",
|
|
57
|
+
"9:16",
|
|
58
|
+
] as const
|
|
59
|
+
|
|
60
|
+
// ──────────────────────────────────────────────────────────────────────────
|
|
61
|
+
// Per-node-type registry
|
|
62
|
+
// ──────────────────────────────────────────────────────────────────────────
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Per-node-type metadata: which field on the node carries the admin-set value,
|
|
66
|
+
* the valid value set, and which optional dimensions apply.
|
|
67
|
+
*
|
|
68
|
+
* `field` distinguishes nodes that use `data.provider` (image/video/audio)
|
|
69
|
+
* from nodes that use `data.model` (LLM nodes, voice-design).
|
|
70
|
+
*/
|
|
71
|
+
interface NodeTypeMeta {
|
|
72
|
+
field: "provider" | "model"
|
|
73
|
+
validValues: readonly string[]
|
|
74
|
+
hasQuality: boolean
|
|
75
|
+
hasAspectRatio: boolean
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Music providers per the runtime: enum currently only lists "minimax", but
|
|
79
|
+
// `generate-music.defaultData.provider` is "suno" with a separate `modelVersion`.
|
|
80
|
+
// Until that mismatch is fixed, accept both values for admin defaults.
|
|
81
|
+
const MUSIC_PROVIDERS_FOR_VALIDATION = ["suno", "minimax"] as const
|
|
82
|
+
|
|
83
|
+
const META: Record<NodeDefaultType, NodeTypeMeta> = {
|
|
84
|
+
"generate-image": { field: "provider", validValues: IMAGE_GEN_PROVIDERS, hasQuality: true, hasAspectRatio: true },
|
|
85
|
+
"image-to-image": { field: "provider", validValues: IMAGE_I2I_PROVIDERS, hasQuality: true, hasAspectRatio: true },
|
|
86
|
+
"edit-image": { field: "provider", validValues: IMAGE_EDIT_PROVIDERS, hasQuality: false, hasAspectRatio: false },
|
|
87
|
+
"upscale-image": { field: "provider", validValues: UPSCALE_IMAGE_PROVIDERS, hasQuality: false, hasAspectRatio: false },
|
|
88
|
+
"text-to-video": { field: "provider", validValues: TEXT_TO_VIDEO_PROVIDERS, hasQuality: true, hasAspectRatio: true },
|
|
89
|
+
"image-to-video": { field: "provider", validValues: IMAGE_TO_VIDEO_PROVIDERS, hasQuality: true, hasAspectRatio: true },
|
|
90
|
+
"generate-video": { field: "provider", validValues: VIDEO_GEN_PROVIDERS, hasQuality: true, hasAspectRatio: true },
|
|
91
|
+
"lip-sync": { field: "provider", validValues: LIP_SYNC_PROVIDERS, hasQuality: false, hasAspectRatio: false },
|
|
92
|
+
"text-to-speech": { field: "provider", validValues: TTS_PROVIDERS, hasQuality: false, hasAspectRatio: false },
|
|
93
|
+
"generate-music": { field: "provider", validValues: MUSIC_PROVIDERS_FOR_VALIDATION, hasQuality: false, hasAspectRatio: false },
|
|
94
|
+
"voice-design": { field: "model", validValues: VOICE_DESIGN_MODELS, hasQuality: false, hasAspectRatio: false },
|
|
95
|
+
"ai-writer": { field: "model", validValues: LLM_MODEL_IDS, hasQuality: false, hasAspectRatio: false },
|
|
96
|
+
"llm-chat": { field: "model", validValues: LLM_MODEL_IDS, hasQuality: false, hasAspectRatio: false },
|
|
97
|
+
"lottie-overlay": { field: "model", validValues: LLM_MODEL_IDS, hasQuality: false, hasAspectRatio: false },
|
|
98
|
+
"3d-title": { field: "model", validValues: LLM_MODEL_IDS, hasQuality: false, hasAspectRatio: false },
|
|
99
|
+
"motion-graphics": { field: "model", validValues: LLM_MODEL_IDS, hasQuality: false, hasAspectRatio: false },
|
|
100
|
+
"image-to-text": { field: "model", validValues: LLM_MODEL_IDS, hasQuality: false, hasAspectRatio: false },
|
|
101
|
+
"qa-check": { field: "model", validValues: LLM_MODEL_IDS, hasQuality: false, hasAspectRatio: false },
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export function getTargetField(nodeType: NodeDefaultType): "provider" | "model" {
|
|
105
|
+
return META[nodeType].field
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export function getValidValues(nodeType: NodeDefaultType): readonly string[] {
|
|
109
|
+
return META[nodeType].validValues
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export function supportedDefaultDimensions(nodeType: NodeDefaultType): {
|
|
113
|
+
quality: boolean
|
|
114
|
+
aspectRatio: boolean
|
|
115
|
+
} {
|
|
116
|
+
const m = META[nodeType]
|
|
117
|
+
return { quality: m.hasQuality, aspectRatio: m.hasAspectRatio }
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function validateProviderForNodeType(
|
|
121
|
+
nodeType: NodeDefaultType,
|
|
122
|
+
value: string,
|
|
123
|
+
): string | null {
|
|
124
|
+
const valid = META[nodeType].validValues
|
|
125
|
+
if (!valid.includes(value)) {
|
|
126
|
+
return `value "${value}" is not valid for node type "${nodeType}"`
|
|
127
|
+
}
|
|
128
|
+
return null
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// ──────────────────────────────────────────────────────────────────────────
|
|
132
|
+
// Semantic mappings — quality + aspect ratio per provider
|
|
133
|
+
// ──────────────────────────────────────────────────────────────────────────
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Each provider stores its quality lever on a different field of node data:
|
|
137
|
+
* - `resolution` (1K/2K/4K, 720p/1080p, …) — most image + video providers
|
|
138
|
+
* - `quality` (medium/high, basic/high) — gpt-image, seedream
|
|
139
|
+
*
|
|
140
|
+
* Mapping a semantic level (low/mid/high) to a concrete value is meaningless
|
|
141
|
+
* without knowing WHICH field it belongs to, because writing "medium" into
|
|
142
|
+
* `resolution` (or "2K" into `quality`) trips the route's Zod enum at
|
|
143
|
+
* generate-time. Each entry pairs the field with the per-level values built
|
|
144
|
+
* from frontend/src/components/editor/config-panels/model-options.ts.
|
|
145
|
+
*
|
|
146
|
+
* Providers absent from this table return `undefined` from `mapQuality`,
|
|
147
|
+
* letting the caller fall back to the factory default value.
|
|
148
|
+
*
|
|
149
|
+
* When a provider has fewer than 3 levels, semantic levels collapse onto
|
|
150
|
+
* the closest concrete value (e.g. gpt-image only has medium/high → low maps
|
|
151
|
+
* to medium).
|
|
152
|
+
*/
|
|
153
|
+
export type QualityField = "resolution" | "quality"
|
|
154
|
+
|
|
155
|
+
interface QualityMapping {
|
|
156
|
+
field: QualityField
|
|
157
|
+
values: Partial<Record<QualityLevel, string>>
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const QUALITY_MAP: Record<string, QualityMapping> = {
|
|
161
|
+
// Image gen — resolution-style (1K/2K/4K)
|
|
162
|
+
"nano-banana-pro": { field: "resolution", values: { low: "1K", mid: "2K", high: "4K" } },
|
|
163
|
+
"nano-banana-2": { field: "resolution", values: { low: "1K", mid: "2K", high: "4K" } },
|
|
164
|
+
"flux": { field: "resolution", values: { low: "1K", mid: "2K", high: "2K" } },
|
|
165
|
+
"flux-flex": { field: "resolution", values: { low: "1K", mid: "2K", high: "2K" } },
|
|
166
|
+
"flux-i2i": { field: "resolution", values: { low: "1K", mid: "2K", high: "2K" } },
|
|
167
|
+
"flux-pro-i2i": { field: "resolution", values: { low: "1K", mid: "2K", high: "2K" } },
|
|
168
|
+
"gpt-image-2": { field: "resolution", values: { low: "1K", mid: "2K", high: "4K" } },
|
|
169
|
+
"gpt-image-2-i2i": { field: "resolution", values: { low: "1K", mid: "2K", high: "4K" } },
|
|
170
|
+
// Image gen — quality-style (medium/high or basic/high)
|
|
171
|
+
"gpt-image": { field: "quality", values: { low: "medium", mid: "medium", high: "high" } },
|
|
172
|
+
"gpt-image-i2i": { field: "quality", values: { low: "medium", mid: "medium", high: "high" } },
|
|
173
|
+
"seedream": { field: "quality", values: { low: "basic", mid: "basic", high: "high" } },
|
|
174
|
+
"seedream-edit": { field: "quality", values: { low: "basic", mid: "basic", high: "high" } },
|
|
175
|
+
"seedream-5-lite": { field: "quality", values: { low: "basic", mid: "basic", high: "high" } },
|
|
176
|
+
"seedream-5-lite-i2i": { field: "quality", values: { low: "basic", mid: "basic", high: "high" } },
|
|
177
|
+
// Video gen — resolution-style (720p/1080p)
|
|
178
|
+
"veo3": { field: "resolution", values: { low: "720p", mid: "1080p", high: "1080p" } },
|
|
179
|
+
"veo3.1": { field: "resolution", values: { low: "720p", mid: "1080p", high: "1080p" } },
|
|
180
|
+
"kling": { field: "resolution", values: { low: "720p", mid: "1080p", high: "1080p" } },
|
|
181
|
+
"kling-3.0": { field: "resolution", values: { low: "720p", mid: "1080p", high: "1080p" } },
|
|
182
|
+
"seedance-2": { field: "resolution", values: { low: "720p", mid: "1080p", high: "1080p" } },
|
|
183
|
+
"seedance-2-fast": { field: "resolution", values: { low: "480p", mid: "720p", high: "720p" } },
|
|
184
|
+
"seedance-2-mini": { field: "resolution", values: { low: "480p", mid: "720p", high: "720p" } },
|
|
185
|
+
"wan-2.7-i2v": { field: "resolution", values: { low: "720p", mid: "1080p", high: "1080p" } },
|
|
186
|
+
"wan-2.7-t2v": { field: "resolution", values: { low: "720p", mid: "1080p", high: "1080p" } },
|
|
187
|
+
"happyhorse": { field: "resolution", values: { low: "720p", mid: "1080p", high: "1080p" } },
|
|
188
|
+
"happyhorse-i2v": { field: "resolution", values: { low: "720p", mid: "1080p", high: "1080p" } },
|
|
189
|
+
"happyhorse-ref2v": { field: "resolution", values: { low: "720p", mid: "1080p", high: "1080p" } },
|
|
190
|
+
"happyhorse-edit": { field: "resolution", values: { low: "720p", mid: "1080p", high: "1080p" } },
|
|
191
|
+
"kling-3-omni": { field: "resolution", values: { low: "720p", mid: "1080p", high: "1080p" } },
|
|
192
|
+
"wan-videoedit": { field: "resolution", values: { low: "720p", mid: "1080p", high: "1080p" } },
|
|
193
|
+
// Lightricks LTX 2.3 — 1080p / 2k / 4k (lowercase, matching VIDEO_RESOLUTION_OPTIONS).
|
|
194
|
+
// `field: "resolution"` is mandatory — see Provider Enum Sync pitfall 4.
|
|
195
|
+
"ltx-2.3-pro": { field: "resolution", values: { low: "1080p", mid: "2k", high: "4k" } },
|
|
196
|
+
"ltx-2.3-fast": { field: "resolution", values: { low: "1080p", mid: "2k", high: "4k" } },
|
|
197
|
+
"gemini-omni-video": { field: "resolution", values: { low: "720p", mid: "1080p", high: "4k" } },
|
|
198
|
+
// Grok Imagine Video 1.5 — only 480p/720p (no 1080p tier); high clamps to 720p.
|
|
199
|
+
"grok-imagine-video-1.5": { field: "resolution", values: { low: "480p", mid: "720p", high: "720p" } },
|
|
200
|
+
// Replicate Flux 2 family — MP-based resolution (matching IMAGE_RESOLUTION_OPTIONS["flux-2-*"]).
|
|
201
|
+
// `field: "resolution"` is mandatory — see Provider Enum Sync pitfall 4.
|
|
202
|
+
// mid = provider default: 1 MP for Klein, 2 MP for Pro/Max.
|
|
203
|
+
"flux-2-klein": { field: "resolution", values: { low: "0.5 MP", mid: "1 MP", high: "2 MP" } },
|
|
204
|
+
"flux-2-pro": { field: "resolution", values: { low: "1 MP", mid: "2 MP", high: "4 MP" } },
|
|
205
|
+
"flux-2-max": { field: "resolution", values: { low: "1 MP", mid: "2 MP", high: "4 MP" } },
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const ASPECT_PASSTHROUGH_PROVIDERS = new Set([
|
|
209
|
+
...IMAGE_GEN_PROVIDERS,
|
|
210
|
+
...IMAGE_I2I_PROVIDERS,
|
|
211
|
+
...TEXT_TO_VIDEO_PROVIDERS,
|
|
212
|
+
...IMAGE_TO_VIDEO_PROVIDERS,
|
|
213
|
+
])
|
|
214
|
+
|
|
215
|
+
export interface MappedQuality {
|
|
216
|
+
field: QualityField
|
|
217
|
+
value: string
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
export function mapQuality(provider: string, level: QualityLevel): MappedQuality | undefined {
|
|
221
|
+
const m = QUALITY_MAP[provider]
|
|
222
|
+
const value = m?.values[level]
|
|
223
|
+
return value === undefined ? undefined : { field: m!.field, value }
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
export function mapAspectRatio(
|
|
227
|
+
provider: string,
|
|
228
|
+
ratio: SemanticAspectRatio,
|
|
229
|
+
): string | undefined {
|
|
230
|
+
if (ratio === "auto") return undefined
|
|
231
|
+
if (!ASPECT_PASSTHROUGH_PROVIDERS.has(provider as never)) return ratio
|
|
232
|
+
return ratio
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// ──────────────────────────────────────────────────────────────────────────
|
|
236
|
+
// Linked field derivation
|
|
237
|
+
// ──────────────────────────────────────────────────────────────────────────
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* When admin sets `provider` for a node that has linked fields (e.g.
|
|
241
|
+
* generate-image stores both `provider` AND `model`), derive the linked
|
|
242
|
+
* fields so the resolver writes a coherent snapshot.
|
|
243
|
+
*
|
|
244
|
+
* For unmapped providers, returns `{}` — the runtime config panel applies
|
|
245
|
+
* its own defaulting when needed.
|
|
246
|
+
*/
|
|
247
|
+
const GENERATE_IMAGE_PROVIDER_TO_MODEL: Record<string, string> = {
|
|
248
|
+
"nano-banana": "gemini-2.5-flash-image",
|
|
249
|
+
"nano-banana-pro": "gemini-2.5-flash-image",
|
|
250
|
+
"nano-banana-2": "gemini-2.5-flash-image",
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
export function deriveLinkedFields(
|
|
254
|
+
nodeType: NodeDefaultType,
|
|
255
|
+
value: string,
|
|
256
|
+
): Record<string, unknown> {
|
|
257
|
+
if (nodeType === "generate-image") {
|
|
258
|
+
const model = GENERATE_IMAGE_PROVIDER_TO_MODEL[value]
|
|
259
|
+
return model ? { model } : {}
|
|
260
|
+
}
|
|
261
|
+
return {}
|
|
262
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-node-type list of field names eligible for fieldMappings resolution.
|
|
3
|
+
* Text fields also participate in {} injection when the resolver sees a
|
|
4
|
+
* string value containing {} markers; non-text fields just receive the
|
|
5
|
+
* mapped source's value verbatim.
|
|
6
|
+
*/
|
|
7
|
+
export const NODE_MAPPABLE_FIELDS: Readonly<Record<string, readonly string[]>> = {
|
|
8
|
+
"generate-image": ["prompt", "style", "negativePrompt"],
|
|
9
|
+
"edit-image": ["prompt", "style", "negativePrompt"],
|
|
10
|
+
"image-to-image": ["prompt", "style", "negativePrompt"],
|
|
11
|
+
"modify-image": ["prompt", "style", "negativePrompt"],
|
|
12
|
+
"text-to-video": ["prompt", "negativePrompt"],
|
|
13
|
+
"image-to-video": ["prompt"],
|
|
14
|
+
// Unified t2v/i2v node — replaced the two deprecated keys above (kept only
|
|
15
|
+
// for back-compat with un-migrated workflow JSON). Mirrors text-to-video so
|
|
16
|
+
// fieldMappings/{} injection AND missing-ref detection work on the live node.
|
|
17
|
+
"generate-video": ["prompt", "negativePrompt"],
|
|
18
|
+
"video-analysis": ["analysisFocus", "youtubeUrl"],
|
|
19
|
+
"video-to-video": ["prompt"],
|
|
20
|
+
"text-to-speech": ["directText"],
|
|
21
|
+
"lip-sync": ["prompt"],
|
|
22
|
+
"generate-music": ["prompt", "lyrics", "genre", "mood"],
|
|
23
|
+
"text-to-audio": ["prompt"],
|
|
24
|
+
"suno-generate": ["prompt", "lyrics", "style", "title", "negativeStyle"],
|
|
25
|
+
"suno-cover": ["prompt", "lyrics", "style", "title", "negativeStyle"],
|
|
26
|
+
"suno-extend": ["prompt", "style", "title"],
|
|
27
|
+
"suno-lyrics": ["prompt"],
|
|
28
|
+
"suno-replace-section":["prompt", "tags", "title"],
|
|
29
|
+
"suno-style-boost": ["content"],
|
|
30
|
+
"suno-upload-extend": ["prompt", "style", "title"],
|
|
31
|
+
"suno-mashup": ["style", "title", "negativeStyle"],
|
|
32
|
+
"voice-remix": ["voiceDescription", "text"],
|
|
33
|
+
"voice-design": ["voiceDescription", "text"],
|
|
34
|
+
"forced-alignment": ["transcript"],
|
|
35
|
+
"ai-writer": ["systemPrompt", "userInput"],
|
|
36
|
+
"llm-chat": ["systemPrompt", "userInput"],
|
|
37
|
+
"video-composer": ["compositionPrompt"],
|
|
38
|
+
"after-effects": ["effectPrompt"],
|
|
39
|
+
"lottie-overlay": ["overlayPrompt"],
|
|
40
|
+
"3d-title": ["titlePrompt"],
|
|
41
|
+
"motion-graphics": ["motionPrompt"],
|
|
42
|
+
"generate-script": ["styleGuide"],
|
|
43
|
+
"speech-to-video": ["prompt", "negativePrompt"],
|
|
44
|
+
"extend-video": ["prompt"],
|
|
45
|
+
"motion-transfer": ["prompt"],
|
|
46
|
+
"cinematic-avatar": ["prompt"],
|
|
47
|
+
"image-to-text": ["customPrompt"],
|
|
48
|
+
"instagram-post": ["caption", "title"],
|
|
49
|
+
"tiktok-post": ["caption", "title"],
|
|
50
|
+
"youtube-upload": ["caption", "title"],
|
|
51
|
+
"linkedin-post": ["caption", "title"],
|
|
52
|
+
"x-post": ["caption", "title"],
|
|
53
|
+
"facebook-post": ["caption", "title"],
|
|
54
|
+
"telegram-post": ["caption", "title"],
|
|
55
|
+
"save-to-storage": ["filename"],
|
|
56
|
+
"webhook-output": ["url"],
|
|
57
|
+
"character": ["characterName", "description", "baseOutfit"],
|
|
58
|
+
"face": ["faceName", "description"],
|
|
59
|
+
"object": ["objectName", "description"],
|
|
60
|
+
"creature": ["creatureName", "description"],
|
|
61
|
+
"location": ["locationName", "description"],
|
|
62
|
+
"web-scrape": ["query", "url", "target"],
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** suno-generate secondary text fields exposed as `field-<key>` canvas handles. */
|
|
66
|
+
export const SUNO_FIELD_HANDLE_FIELDS = ["style", "lyrics", "title", "negativeStyle"] as const
|
|
67
|
+
/** Map a `field-<key>` handle id to its data key, or null if not a field handle. */
|
|
68
|
+
export function fieldKeyFromHandle(handleId: string): string | null {
|
|
69
|
+
return handleId.startsWith("field-") ? handleId.slice("field-".length) : null
|
|
70
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { z } from "zod"
|
|
2
|
+
import { extractPresetData } from "./node-preset-extract.js"
|
|
3
|
+
|
|
4
|
+
export const NODE_PRESET_EXPORT_KIND = "nodaro.node-presets" as const
|
|
5
|
+
|
|
6
|
+
export interface ExportedPreset {
|
|
7
|
+
nodeType: string
|
|
8
|
+
name: string
|
|
9
|
+
description?: string
|
|
10
|
+
data: Record<string, unknown>
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface NodePresetExport {
|
|
14
|
+
kind: typeof NODE_PRESET_EXPORT_KIND
|
|
15
|
+
version: 1
|
|
16
|
+
exportedAt: string
|
|
17
|
+
presets: ExportedPreset[]
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const exportedPresetSchema = z.object({
|
|
21
|
+
nodeType: z.string().min(1).max(120),
|
|
22
|
+
name: z.string().min(1).max(120),
|
|
23
|
+
description: z.string().max(500).optional(),
|
|
24
|
+
data: z.record(z.string(), z.unknown()),
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
const envelopeSchema = z.object({
|
|
28
|
+
kind: z.literal(NODE_PRESET_EXPORT_KIND),
|
|
29
|
+
version: z.literal(1),
|
|
30
|
+
exportedAt: z.string().optional().default(""),
|
|
31
|
+
presets: z.array(exportedPresetSchema).max(500),
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
export function buildNodePresetExport(
|
|
35
|
+
presets: ExportedPreset[],
|
|
36
|
+
exportedAtIso: string,
|
|
37
|
+
): NodePresetExport {
|
|
38
|
+
return {
|
|
39
|
+
kind: NODE_PRESET_EXPORT_KIND,
|
|
40
|
+
version: 1,
|
|
41
|
+
exportedAt: exportedAtIso,
|
|
42
|
+
presets: presets.map((p) => ({ ...p, data: extractPresetData(p.data) })),
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Validate an unknown parsed-JSON value as a preset export; throws on invalid. Defensively
|
|
48
|
+
* re-strips runtime keys from each preset's data.
|
|
49
|
+
*/
|
|
50
|
+
export function parseNodePresetExport(input: unknown): NodePresetExport {
|
|
51
|
+
const parsed = envelopeSchema.parse(input)
|
|
52
|
+
return {
|
|
53
|
+
...parsed,
|
|
54
|
+
presets: parsed.presets.map((p) => ({ ...p, data: extractPresetData(p.data) })),
|
|
55
|
+
}
|
|
56
|
+
}
|