@milenyumai/film-kit 2.3.3 → 2.3.5

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.
Files changed (44) hide show
  1. package/MODEL_REGISTRY.md +136 -0
  2. package/README.md +26 -2
  3. package/build/index.d.ts +3 -1
  4. package/build/index.js +1 -0
  5. package/build/lib/cli.js +26 -10
  6. package/build/lib/configure.js +16 -17
  7. package/build/lib/defaults.js +10 -0
  8. package/build/lib/film-kit.js +16 -1
  9. package/build/lib/model-registry/index.d.ts +4 -0
  10. package/build/lib/model-registry/index.js +3 -0
  11. package/build/lib/model-registry/registry.d.ts +220 -0
  12. package/build/lib/model-registry/registry.js +191 -0
  13. package/build/lib/model-registry/selectors.d.ts +23 -0
  14. package/build/lib/model-registry/selectors.js +80 -0
  15. package/build/lib/model-registry/types.d.ts +59 -0
  16. package/build/lib/model-registry/types.js +1 -0
  17. package/build/lib/model-registry/validation.d.ts +3 -0
  18. package/build/lib/model-registry/validation.js +42 -0
  19. package/build/lib/storyboard-reference/adapters/base.js +2 -5
  20. package/build/lib/storyboard-reference/adapters/seedance20.js +5 -5
  21. package/build/lib/storyboard-reference/defaults.js +2 -1
  22. package/build/lib/storyboard-reference/index.d.ts +1 -1
  23. package/build/lib/storyboard-reference/output-writer.js +6 -0
  24. package/build/lib/storyboard-reference/prompt-bundle-builder.js +103 -22
  25. package/build/lib/storyboard-reference/request-normalizer.js +6 -4
  26. package/build/lib/storyboard-reference/types.d.ts +25 -0
  27. package/build/lib/storyboard-reference/validators.js +4 -0
  28. package/build/lib/templates.js +1 -1
  29. package/build/lib/types.d.ts +2 -1
  30. package/content/skills/storyboard-reference/SKILL.md +7 -4
  31. package/content/workflows/generate-storyboard.md +7 -6
  32. package/package.json +2 -1
  33. package/packages/gpt-image-smart/content/skills/storyboard-reference/SKILL.md +7 -4
  34. package/packages/gpt-image-smart/content/workflows/generate-storyboard.md +7 -6
  35. package/packages/hybrid/content/skills/storyboard-reference/SKILL.md +7 -4
  36. package/packages/hybrid/content/workflows/generate-storyboard.md +7 -6
  37. package/packages/hybrid-smart/content/skills/storyboard-reference/SKILL.md +7 -4
  38. package/packages/hybrid-smart/content/workflows/generate-storyboard.md +7 -6
  39. package/packages/multi/build/lib/configure.js +4 -4
  40. package/packages/multi/build/lib/templates.js +9 -9
  41. package/packages/multi/content/skills/storyboard-reference/SKILL.md +7 -4
  42. package/packages/multi/content/workflows/generate-storyboard.md +7 -6
  43. package/packages/studio/content/skills/storyboard-reference/SKILL.md +7 -4
  44. package/packages/studio/content/workflows/generate-storyboard.md +7 -6
@@ -0,0 +1,136 @@
1
+ # Film-Kit Model Registry
2
+
3
+ Film-Kit model metadata is centralized in `src/lib/model-registry/*`.
4
+
5
+ The registry is TypeScript `as const` metadata, not dynamic JSON. It is the canonical source for model identity, lifecycle, preset compatibility, reference-mode compatibility, capabilities, routing role, prompt grammar key, model profile key, and storyboard adapter resolution.
6
+
7
+ Long prompt grammar, runtime profile prose, production guidance, and generated workflow text stay in the existing template, adapter, skill, and model-profile layers.
8
+
9
+ ## Discovery Summary
10
+
11
+ Phase 0 found model ids in four broad surfaces:
12
+
13
+ - Root validation and runtime selection: `src/lib/types.ts`, `src/lib/defaults.ts`, `src/lib/configure.ts`, `src/lib/cli.ts`, and `src/lib/film-kit.ts`.
14
+ - Storyboard-reference routing: `src/lib/storyboard-reference/defaults.ts`, `request-normalizer.ts`, `prompt-bundle-builder.ts`, and `adapters/*`.
15
+ - Internal preset packages: `packages/*/src/lib/*`, where model ids still appear in private preset defaults, templates, and generated runtime prose.
16
+ - Public/user-facing prose and assertions: `README.md`, `content/*`, `packages/*/content/*`, and tests.
17
+
18
+ Phase 1 moved the root runtime, CLI/config validation, `generate-storyboard --models`, storyboard-reference target validation, display-name lookup, default storyboard model list, and adapter resolution onto the registry.
19
+
20
+ Phase 2 intentionally does not import the root registry directly from `packages/*`: package `tsconfig.json` files use `rootDir: src`, and the internal package sources remain private preset implementations. Public usage is guarded through the root dispatcher and root CLI.
21
+
22
+ Remaining hardcoded model names in templates, content, and tests are prompt grammar, generated docs, explicit examples, or compatibility assertions rather than canonical validation sources.
23
+
24
+ ## Files
25
+
26
+ - `src/lib/model-registry/types.ts` defines registry metadata shapes.
27
+ - `src/lib/model-registry/registry.ts` owns the canonical model entries.
28
+ - `src/lib/model-registry/selectors.ts` exposes lookup and selector helpers.
29
+ - `src/lib/model-registry/validation.ts` owns fail-closed model validation.
30
+ - `src/lib/model-registry/index.ts` is the public registry API barrel.
31
+
32
+ ## Public API
33
+
34
+ - `getModel(id)`
35
+ - `requireModel(id)`
36
+ - `listModels()`
37
+ - `listActiveModels()`
38
+ - `listVideoModels()`
39
+ - `listImageModels()`
40
+ - `listActiveVideoModelIds()`
41
+ - `listRunnableVideoModels()`
42
+ - `listRunnableVideoModelIds()`
43
+ - `listModelsForPreset(preset)`
44
+ - `listModelsForReferenceMode(referenceMode)`
45
+ - `isKnownModelId(value)`
46
+ - `isActiveModelId(value)`
47
+ - `isDeprecatedModelId(value)`
48
+ - `isRemovedModelId(value)`
49
+ - `isVideoModelId(value)`
50
+ - `isImageModelId(value)`
51
+ - `isModelSupportedByPreset(modelId, preset)`
52
+ - `getModelAdapterKey(modelId)`
53
+ - `getModelDisplayName(modelId)`
54
+ - `getReplacementModel(modelId)`
55
+ - `assertModelAllowed(modelId, context)`
56
+ - `validateModelAllowed(modelId, context)`
57
+
58
+ ## Lifecycle Rules
59
+
60
+ - `active`: accepted normally.
61
+ - `experimental`: accepted normally, but may be surfaced as internal or preview metadata.
62
+ - `deprecated`: accepted, emits an explicit warning, and should define `replacementModelId` when possible.
63
+ - `removed`: fail-closed. Removed models must never silently fall back.
64
+
65
+ ## Adapter Routing
66
+
67
+ Storyboard-reference video prompt routing resolves through `adapterKey`.
68
+
69
+ - `veo31` -> Veo adapter
70
+ - `seedance20` -> Seedance 2.0 adapter
71
+ - `kling30` -> Kling 3.0 adapter
72
+ - `generic` -> generic adapter, allowed only when the registry entry explicitly selects it
73
+ - `none`, `gptImage2` -> not valid for video storyboard adapter routing
74
+
75
+ Unknown model strings never receive a generic fallback.
76
+
77
+ ## Adding A Video Model
78
+
79
+ 1. Add one entry in `src/lib/model-registry/registry.ts`.
80
+ 2. Choose `modalities: ["video"]`.
81
+ 3. Set `lifecycleStatus`.
82
+ 4. Set `supportedPresets`.
83
+ 5. Set `supportedReferenceModes`.
84
+ 6. Set `supportedAspects`.
85
+ 7. Add `durationRange` or `durationPolicy`.
86
+ 8. Choose an existing `adapterKey` or add a new adapter.
87
+ 9. Set `promptGrammarKey` and `modelProfileKey`.
88
+ 10. Fill `routingRole` and `capabilities`.
89
+ 11. Add registry selector/validation tests.
90
+ 12. Add storyboard adapter routing tests when the model can generate video prompts.
91
+ 13. Update docs/examples only if the model should be publicly visible.
92
+
93
+ Ideal new-video-model diff:
94
+
95
+ - one registry entry
96
+ - one adapter only if no existing adapter fits
97
+ - focused tests
98
+ - docs update when public
99
+
100
+ ## Adding An Image Model
101
+
102
+ 1. Add one registry entry with `modalities: ["image"]`.
103
+ 2. Do not add it to video-only CLI or storyboard video target validation.
104
+ 3. Pick image-aware `supportedPresets`.
105
+ 4. Use `adapterKey: "gptImage2"` only for GPT Image 2 behavior; use `none` or a future image adapter key otherwise.
106
+ 5. Add tests proving it appears in image selectors and not in video selectors.
107
+
108
+ Image models must not widen video model types or `generate-storyboard --models`.
109
+
110
+ ## Deprecating A Model
111
+
112
+ 1. Change `lifecycleStatus` to `deprecated`.
113
+ 2. Add `deprecationMessage`.
114
+ 3. Add `replacementModelId` when there is a direct replacement.
115
+ 4. Keep compatibility metadata only for paths that still work.
116
+ 5. Add tests proving validation emits a warning.
117
+
118
+ Do not silently rewrite deprecated model ids unless a dedicated migration test covers that behavior.
119
+
120
+ ## Removing A Model
121
+
122
+ 1. Change `lifecycleStatus` to `removed`.
123
+ 2. Keep the id in the registry so validation can fail with a clear message.
124
+ 3. Add `deprecationMessage` and `replacementModelId` when possible.
125
+ 4. Clear runtime compatibility if the model must not be routed.
126
+ 5. Add tests proving `assertModelAllowed` fails closed.
127
+
128
+ Removed models must not fall back to active models or generic adapters.
129
+
130
+ ## Phase Boundaries
131
+
132
+ Phase 1 connects the root runtime, CLI/config validation, and storyboard-reference adapter routing to the registry.
133
+
134
+ Phase 2 keeps internal preset packages private. Package source builds use `rootDir: src`, so direct imports from root `src/lib/model-registry` would break package builds or create circular product coupling. Root `configureFilmKit()` and CLI validation are the canonical guardrails for public usage. Internal package prompt/template prose can continue to contain model names as generated runtime content.
135
+
136
+ Phase 3 is this maintenance documentation plus README linkage.
package/README.md CHANGED
@@ -70,6 +70,8 @@ Storyboard-reference prompt generation is also available when you have a charact
70
70
 
71
71
  ## Model Support
72
72
 
73
+ Canonical model metadata lives in `src/lib/model-registry/*`; see [MODEL_REGISTRY.md](./MODEL_REGISTRY.md) for the add/update/deprecate/remove checklist. Public model selection still happens at init time through the root package and CLI.
74
+
73
75
  ### `veo31`
74
76
 
75
77
  - Default single, multi, and studio model
@@ -181,6 +183,7 @@ npx @milenyumai/film-kit generate-storyboard \
181
183
  Outputs:
182
184
 
183
185
  - `outputs/storyboard-reference-plan.json`
186
+ - `outputs/storyboard-prompt.md`
184
187
  - `outputs/reference-prep/CHARACTER-SHEET-*.md`
185
188
  - `outputs/storyboard-prompts/SHOTNN-GPT-IMAGE-2-STORYBOARD.md`
186
189
  - `outputs/prompt-bundles/SHOTNN.bundle.json`
@@ -194,8 +197,10 @@ Rules:
194
197
  - `@character1` is used once to create a 16:9 character sheet prompt with front, back, side, three-quarter, and face close-up views.
195
198
  - GPT Image 2 still prompts use `REFERENCE LOCK`, `Keep same`, `Change only`, and `Avoid` sections so character identity, wardrobe, props, and materials stay immutable unless explicitly changed.
196
199
  - Each `SHOTNN.md` includes a professional `GPT IMAGE 2 STORYBOARD PROMPT`; the generated shot storyboard controls composition, blocking, camera, timing, and editorial phase order only.
197
- - Storyboard prompts use production-board grammar: rough black-and-white pencil panels, strong silhouettes, visible body/camera momentum, and optional color-coded planning annotations. Seedance is instructed to follow the panel order while ignoring arrows, notes, labels, and timestamps in the rendered video.
200
+ - If no external storyboard image exists, Film-Kit still generates the GPT Image 2 storyboard bootstrap prompt and writes it to both `outputs/storyboard-prompts/SHOTNN-GPT-IMAGE-2-STORYBOARD.md` and the convenience alias `outputs/storyboard-prompt.md`.
201
+ - Storyboard prompts use production-board grammar: 16:9 storyboard sheet, rough black-and-white pencil panels, strong silhouettes, visible body/camera momentum, cinematic camera variety, and optional color-coded planning annotations. Seedance is instructed to follow the panel order while ignoring arrows, notes, labels, and timestamps in the rendered video.
198
202
  - Seedance provider-facing tokens map generated character sheets first (`@Image1`, `@Image2`, ...) and the generated shot storyboard next. Legacy lowercase aliases remain documented in runtime text.
203
+ - `SHOTNN.bundle.json` includes `storyboard_creation` metadata with provider, prompt path, alias path, reading order, panel count, Seedance token, annotation policy, and prompt text.
199
204
  - Speaking shots must bind `Audio Plan.activeSpeakerKey` back to project-level `voiceCast`; broken voice bindings fail QA.
200
205
  - Public-figure, celebrity, likeness, logo, trademark, or brand references in the brief, dialogue metadata, or reference metadata are blocked unless safely anonymized first.
201
206
  - Phase budget: 4-6s uses 1-2 phases, 7-10s uses 2-3 phases, and 11-15s uses 3-4 phases.
@@ -214,7 +219,7 @@ CLI flags for direct storyboard bundle generation:
214
219
  | `--models` | Comma-separated target models: `veo31`, `seedance-2.0`, `kling-3.0` |
215
220
  | `--duration` | Duration in seconds per generated shot. Seedance provider range is 4-15 seconds |
216
221
  | `--aspect` | `16:9`, `9:16`, or `1:1` |
217
- | `--storyboard-panel-count-hint` | Optional total panel/phase hint. 5+ phases are split when overload splitting is enabled |
222
+ | `--storyboard-panel-count-hint` | Optional GPT Image 2 storyboard sheet panel count, `1-12`. This does not by itself split SHOT files |
218
223
  | `--max-storyboard-phases` | Upper bound per shot. Default: `4` |
219
224
 
220
225
  ## CLI
@@ -484,6 +489,25 @@ Public root exports:
484
489
  - `FILM_KIT_CONFIG_FILE`
485
490
  - `FILM_KIT_PRESETS`
486
491
  - `LEGACY_CONFIG_FILES`
492
+ - `getModel(id)`
493
+ - `requireModel(id)`
494
+ - `listModels()`
495
+ - `listActiveModels()`
496
+ - `listVideoModels()`
497
+ - `listImageModels()`
498
+ - `listModelsForPreset(preset)`
499
+ - `listModelsForReferenceMode(referenceMode)`
500
+ - `isKnownModelId(value)`
501
+ - `isActiveModelId(value)`
502
+ - `isDeprecatedModelId(value)`
503
+ - `isRemovedModelId(value)`
504
+ - `isVideoModelId(value)`
505
+ - `isImageModelId(value)`
506
+ - `isModelSupportedByPreset(modelId, preset)`
507
+ - `getModelAdapterKey(modelId)`
508
+ - `getReplacementModel(modelId)`
509
+ - `assertModelAllowed(id, context)`
510
+ - `validateModelAllowed(id, context)`
487
511
  - `FilmKitPreset`
488
512
  - `SupportedModel`
489
513
  - `SupportedPlatform`
package/build/index.d.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  export { configureFilmKit, detectFilmKitPreset, FILM_KIT_CONFIG_FILE, FILM_KIT_PRESETS, LEGACY_CONFIG_FILES } from "./lib/film-kit.js";
2
2
  export { configureAgents } from "./lib/configure.js";
3
3
  export { buildStoryboardReferencePromptBundles, normalizeVideoPromptRequest, renderShotMarkdown, writeStoryboardReferenceOutputs } from "./lib/storyboard-reference/index.js";
4
+ export { assertModelAllowed, getModel, getModelAdapterKey, getModelDisplayName, getReplacementModel, isActiveModelId, isDeprecatedModelId, isImageModelId, isKnownModelId, isModelSupportedByPreset, isRemovedModelId, isVideoModelId, listActiveModels, listActiveVideoModelIds, listImageModels, listModels, listModelsForPreset, listModelsForReferenceMode, listRunnableVideoModelIds, listRunnableVideoModels, listVideoModels, requireModel, validateModelAllowed } from "./lib/model-registry/index.js";
4
5
  export type { AgentConfigOptions, ConfigureFilmKitResult, ConfigureResult, FilmKitConfigFile, FilmKitConfigOptions, FilmKitPreset, GptImageFormat, GptImageQuality, GptImageSize, HybridAspectRatio, KlingPreset, NanoBananaImageSize, ReferenceMode, StoryboardReferenceConfig, SupportedModel, SupportedPlatform } from "./lib/types.js";
5
- export type { CharacterReferenceSheetPrompt, ModelPromptOutput, ModelRouteMetadata, PromptBundle, ProviderAssetMappingEntry, ProviderFileLimitReport, ProviderReferenceTokenPolicy, ReferenceAsset, ReferenceAssetRequirement, SeedanceContinuityMode, ShotHandoffNote, StoryboardImagePrompt, StoryboardPhaseBudget, StoryboardReferenceBuildResult, StoryboardReferencePolicy, StoryboardReferenceWriteResult, VideoPromptRequest } from "./lib/storyboard-reference/index.js";
6
+ export type { ActiveModelId, AudioModelId, DeprecatedModelId, ImageModelId, KnownModelId, ModelAdapterKey, ModelAllowedContext, ModelAllowedResult, ModelCapabilities, ModelLifecycleStatus, ModelModality, ModelRegistryEntry, MultimodalModelId, RemovedModelId, VideoModelId } from "./lib/model-registry/index.js";
7
+ export type { CharacterReferenceSheetPrompt, ModelPromptOutput, ModelRouteMetadata, PromptBundle, ProviderAssetMappingEntry, ProviderFileLimitReport, ProviderReferenceTokenPolicy, ReferenceAsset, ReferenceAssetRequirement, SeedanceContinuityMode, ShotHandoffNote, StoryboardCreationMetadata, StoryboardImagePrompt, StoryboardPhaseBudget, StoryboardReferenceBuildResult, StoryboardReferencePolicy, StoryboardReferenceWriteResult, VideoPromptRequest } from "./lib/storyboard-reference/index.js";
package/build/index.js CHANGED
@@ -1,3 +1,4 @@
1
1
  export { configureFilmKit, detectFilmKitPreset, FILM_KIT_CONFIG_FILE, FILM_KIT_PRESETS, LEGACY_CONFIG_FILES } from "./lib/film-kit.js";
2
2
  export { configureAgents } from "./lib/configure.js";
3
3
  export { buildStoryboardReferencePromptBundles, normalizeVideoPromptRequest, renderShotMarkdown, writeStoryboardReferenceOutputs } from "./lib/storyboard-reference/index.js";
4
+ export { assertModelAllowed, getModel, getModelAdapterKey, getModelDisplayName, getReplacementModel, isActiveModelId, isDeprecatedModelId, isImageModelId, isKnownModelId, isModelSupportedByPreset, isRemovedModelId, isVideoModelId, listActiveModels, listActiveVideoModelIds, listImageModels, listModels, listModelsForPreset, listModelsForReferenceMode, listRunnableVideoModelIds, listRunnableVideoModels, listVideoModels, requireModel, validateModelAllowed } from "./lib/model-registry/index.js";
package/build/lib/cli.js CHANGED
@@ -2,7 +2,7 @@ import { FILM_KIT_CONFIG_FILE, FILM_KIT_PRESETS, detectFilmKitPreset, isFilmKitP
2
2
  import { readFile } from "node:fs/promises";
3
3
  import { resolve } from "node:path";
4
4
  import { exists } from "./fs.js";
5
- const SUPPORTED_MODELS = ["veo31", "kling-3.0", "seedance-2.0"];
5
+ import { listActiveVideoModelIds, validateModelAllowed } from "./model-registry/index.js";
6
6
  const SUPPORTED_KLING_PRESETS = ["ultra-realism", "balanced", "custom"];
7
7
  const SUPPORTED_ASPECTS = ["16:9", "9:16", "1:1"];
8
8
  const SUPPORTED_REFERENCE_MODES = ["start-end", "storyboard-reference", "hybrid"];
@@ -87,6 +87,9 @@ const PRESET_ALLOWED_FLAGS = {
87
87
  ])
88
88
  };
89
89
  const COMMON_FLAGS = new Set(["--preset", "--output-dir", "--scenario-hint", "--scenario", "--overwrite", "-f"]);
90
+ function supportedVideoModelText() {
91
+ return listActiveVideoModelIds().join(", ");
92
+ }
90
93
  function parseIntegerFlag(raw, flag) {
91
94
  const value = Number.parseInt(raw, 10);
92
95
  if (!Number.isInteger(value) || value <= 0) {
@@ -181,10 +184,10 @@ function parseKnownFlags(args) {
181
184
  options.platforms = parsePlatforms(nextValue);
182
185
  break;
183
186
  case "--model":
184
- if (!SUPPORTED_MODELS.includes(nextValue)) {
185
- throw new Error(`Invalid --model value: ${nextValue}. Supported: ${SUPPORTED_MODELS.join(", ")}`);
186
- }
187
- options.model = nextValue;
187
+ options.model = validateModelAllowed(nextValue, {
188
+ requiredModalities: ["video"],
189
+ usage: "--model"
190
+ }).model.id;
188
191
  break;
189
192
  case "--kling-preset":
190
193
  if (!SUPPORTED_KLING_PRESETS.includes(nextValue)) {
@@ -293,9 +296,11 @@ function parseModels(raw) {
293
296
  throw new Error("Invalid --models value. Expected at least one supported model.");
294
297
  }
295
298
  for (const model of models) {
296
- if (!SUPPORTED_MODELS.includes(model)) {
297
- throw new Error(`Invalid --models value: ${model}. Supported: ${SUPPORTED_MODELS.join(", ")}`);
298
- }
299
+ validateModelAllowed(model, {
300
+ requiredModalities: ["video"],
301
+ referenceMode: "storyboard-reference",
302
+ usage: "--models"
303
+ });
299
304
  }
300
305
  return models;
301
306
  }
@@ -472,6 +477,17 @@ export async function parseCliCommand(args, rootDir = process.cwd()) {
472
477
  `You can also commit ${FILM_KIT_CONFIG_FILE} and rerun init.`);
473
478
  }
474
479
  validatePresetFlags(preset, providedFlags);
480
+ if (options.model) {
481
+ const validationContext = {
482
+ preset,
483
+ requiredModalities: ["video"],
484
+ usage: "--model"
485
+ };
486
+ if (options.referenceMode !== undefined) {
487
+ validationContext.referenceMode = options.referenceMode;
488
+ }
489
+ validateModelAllowed(options.model, validationContext);
490
+ }
475
491
  return {
476
492
  command: "init",
477
493
  options: {
@@ -518,7 +534,7 @@ generate-storyboard flags:
518
534
  --character-ref Character identity reference image path or URL (repeatable or comma-separated)
519
535
  --storyboard-ref Optional storyboard guide image path or URL (repeatable or comma-separated)
520
536
  --brief Inline brief text or a path to a brief file
521
- --models Comma-separated models: veo31,seedance-2.0,kling-3.0
537
+ --models Comma-separated models: ${supportedVideoModelText()}
522
538
  --duration Duration in seconds per generated shot
523
539
  --aspect 16:9|9:16|1:1
524
540
  --output-dir Output root (default: ./outputs)
@@ -526,7 +542,7 @@ generate-storyboard flags:
526
542
  --dialogue Repeatable "Speaker: exact line" value
527
543
  --audio-intent SFX/ambience direction
528
544
  --style-intent Visual style direction
529
- --storyboard-panel-count-hint Panel/phase count hint; 5+ panels split into multiple SHOTNN files
545
+ --storyboard-panel-count-hint GPT Image 2 storyboard sheet panel count, 1-12; does not split SHOT files by itself
530
546
  --max-storyboard-phases Upper bound per SHOTNN storyboard phase count
531
547
 
532
548
  Install:
@@ -3,6 +3,7 @@ import { fileURLToPath } from "node:url";
3
3
  import { readdir, readFile, rm } from "node:fs/promises";
4
4
  import { exists, readJsonIfExists, writeText } from "./fs.js";
5
5
  import { resolveOptions } from "./defaults.js";
6
+ import { getModelDisplayName as getRegistryModelDisplayName } from "./model-registry/index.js";
6
7
  import { buildProjectFiles } from "./templates.js";
7
8
  const __filename = fileURLToPath(import.meta.url);
8
9
  const __dirname = dirname(__filename);
@@ -159,6 +160,7 @@ description: Generate storyboard-reference prompt bundles from character referen
159
160
  \`\`\`text
160
161
  ${vars.outputDir}/
161
162
  ├── storyboard-reference-plan.json
163
+ ├── storyboard-prompt.md
162
164
  ├── reference-prep/
163
165
  │ └── CHARACTER-SHEET-*.md
164
166
  ├── storyboard-prompts/
@@ -186,18 +188,21 @@ ${vars.outputDir}/
186
188
  - \`maxStoryboardPhases: ${vars.maxStoryboardPhases}\`
187
189
  - \`voiceCast\` when dialogue or narration exists
188
190
  - \`visual_world\` for camera, lens, lighting, scale, reflection, physics, screen direction, and continuity anchors
189
- 4. Split the scenario into shots by dramatic beat. Use this phase budget:
191
+ 4. Split the scenario into shots by dramatic beat. Use this video phase budget:
190
192
  - 4-6 seconds: 1-2 phases
191
193
  - 7-10 seconds: 2-3 phases
192
194
  - 11-15 seconds: 3-4 phases
193
- - 5+ distinct phases: split into separate \`SHOTNN.md\` files
195
+ - 5+ distinct real video phases, scene changes, or location/action blocks: split into separate \`SHOTNN.md\` files
196
+ - GPT Image 2 storyboard sheets may use 1-12 panels; 5-12 storyboard sheet panels alone do not force a split
194
197
  5. For each shot, write a GPT Image 2 storyboard prompt:
195
198
  - use character sheets as the only identity source
196
199
  - use optional storyboard guides only for staging and timing
200
+ - use raw black-and-white rough pencil storyboard panels, strong silhouettes, visible motion, cinematic camera variety, and color-coded planning annotations
197
201
  - include previous-shot handoff and next-shot handoff
198
202
  - preserve shared \`visual_world\`, lighting, screen direction, and action rhythm
199
203
  6. Build model-ready video prompt bundles:
200
204
  - Seedance: character sheet tokens first, generated shot storyboard token next
205
+ - Seedance: follow storyboard panels left-to-right/top-to-bottom as visual/action/camera source, but never render arrows, labels, annotations, timestamps, or panel borders
201
206
  - Veo: visual planning prompt with full audio direction
202
207
  - Kling: block-structured storyboard route, not a mandatory Start+End frame route
203
208
  7. Keep coverage inside the same \`SHOTNN.md\`; coverage uses storyboard planning prompts and does not request separate start/end still prompts.
@@ -350,13 +355,14 @@ description: Finalize storyboard-reference prompt packages after storyboard QA p
350
355
  ## Validate Files
351
356
 
352
357
  1. \`${vars.outputDir}/storyboard-reference-plan.json\` exists.
353
- 2. \`${vars.outputDir}/reference-prep/\` contains character sheet prompt files.
354
- 3. \`${vars.outputDir}/storyboard-prompts/\` contains per-shot GPT Image 2 storyboard prompts.
355
- 4. \`${vars.outputDir}/prompt-bundles/\` contains model prompt bundles.
356
- 5. Every \`${vars.outputDir}/shots/SHOTNN.md\` contains the required storyboard-reference sections.
357
- 6. Coverage stays in the same \`SHOTNN.md\`.
358
- 7. No generated shot contains forbidden start/end frame sections or exact first-frame reuse instructions.
359
- 8. \`storyboard_reference_status\` and \`storyboard_handoff_status\` are pass.
358
+ 2. \`${vars.outputDir}/storyboard-prompt.md\` exists as the storyboard bootstrap alias.
359
+ 3. \`${vars.outputDir}/reference-prep/\` contains character sheet prompt files.
360
+ 4. \`${vars.outputDir}/storyboard-prompts/\` contains per-shot GPT Image 2 storyboard prompts.
361
+ 5. \`${vars.outputDir}/prompt-bundles/\` contains model prompt bundles with \`storyboard_creation\` metadata.
362
+ 6. Every \`${vars.outputDir}/shots/SHOTNN.md\` contains the required storyboard-reference sections.
363
+ 7. Coverage stays in the same \`SHOTNN.md\`.
364
+ 8. No generated shot contains forbidden start/end frame sections or exact first-frame reuse instructions.
365
+ 9. \`storyboard_reference_status\` and \`storyboard_handoff_status\` are pass.
360
366
 
361
367
  ## Final Summary
362
368
 
@@ -549,13 +555,6 @@ description: Storyboard-reference prompt structure for GPT Image 2 character she
549
555
  Do not emit main-shot \`ILK FRAME\`, \`İLK FRAME\`, \`SON FRAME\`, \`SHOTNN_START\`, \`SHOTNN_END\`, or exact first-frame reuse instructions in storyboard-reference mode.
550
556
  `;
551
557
  }
552
- function getModelDisplayName(model) {
553
- if (model === "kling-3.0")
554
- return "Kling 3.0";
555
- if (model === "seedance-2.0")
556
- return "Seedance 2.0";
557
- return "Google Flow + Veo 3.1";
558
- }
559
558
  function getKlingPresetDisplay(model, klingPreset) {
560
559
  return model === "kling-3.0" ? klingPreset : "n/a (Kling-only)";
561
560
  }
@@ -622,7 +621,7 @@ export async function configureAgents(options = {}) {
622
621
  scenarioHint: resolved.scenarioHint,
623
622
  model: resolved.model,
624
623
  klingPreset: getKlingPresetDisplay(resolved.model, resolved.klingPreset),
625
- modelDisplayName: getModelDisplayName(resolved.model),
624
+ modelDisplayName: getRegistryModelDisplayName(resolved.model),
626
625
  referenceMode: resolved.referenceMode,
627
626
  storyboardReferenceActive,
628
627
  maxStoryboardPhases: resolved.storyboardReferenceMode.maxStoryboardPhases
@@ -1,3 +1,4 @@
1
+ import { validateModelAllowed } from "./model-registry/index.js";
1
2
  const ALL_PLATFORMS = ["cursor", "claude", "copilot", "antigravity", "codex"];
2
3
  const DEFAULT_MODEL = "veo31";
3
4
  const DEFAULT_KLING_PRESET = "ultra-realism";
@@ -31,12 +32,21 @@ export function normalizeStoryboardReferenceConfig(input, referenceMode) {
31
32
  export function resolveOptions(input) {
32
33
  const warnings = [];
33
34
  const model = input.model ?? DEFAULT_MODEL;
35
+ const modelValidationContext = {
36
+ requiredModalities: ["video"],
37
+ usage: "runtime"
38
+ };
39
+ if (input.referenceMode !== undefined) {
40
+ modelValidationContext.referenceMode = input.referenceMode;
41
+ }
42
+ const modelValidation = validateModelAllowed(model, modelValidationContext);
34
43
  const klingPreset = input.klingPreset ?? DEFAULT_KLING_PRESET;
35
44
  const referenceMode = input.referenceMode ?? DEFAULT_REFERENCE_MODE;
36
45
  const storyboardReferenceMode = normalizeStoryboardReferenceConfig(input.storyboardReferenceMode, referenceMode);
37
46
  if (!input.model) {
38
47
  warnings.push("Model not specified. Falling back to veo31. In the next major release, --model will be required.");
39
48
  }
49
+ warnings.push(...modelValidation.warnings);
40
50
  if (referenceMode === "storyboard-reference" && !storyboardReferenceMode.enabled) {
41
51
  warnings.push("referenceMode is storyboard-reference, but storyboardReferenceMode.enabled is false.");
42
52
  }
@@ -3,6 +3,7 @@ import { fileURLToPath } from "node:url";
3
3
  import { configureAgents } from "./configure.js";
4
4
  import { resolveOptions } from "./defaults.js";
5
5
  import { exists, readJsonIfExists, writeText } from "./fs.js";
6
+ import { validateModelAllowed } from "./model-registry/index.js";
6
7
  export const FILM_KIT_CONFIG_FILE = "film-kit.config.json";
7
8
  export const FILM_KIT_PRESETS = [
8
9
  "single",
@@ -370,6 +371,20 @@ export async function configureFilmKit(options = {}) {
370
371
  assignDefined(merged, options);
371
372
  merged.rootDir = rootDir;
372
373
  merged.preset = preset;
374
+ const rootValidationWarnings = [];
375
+ const mergedModel = readString(merged.model);
376
+ if (mergedModel) {
377
+ const validationContext = {
378
+ preset,
379
+ requiredModalities: ["video"],
380
+ usage: "film-kit.config.json model"
381
+ };
382
+ const mergedReferenceMode = readString(merged.referenceMode);
383
+ if (mergedReferenceMode !== undefined) {
384
+ validationContext.referenceMode = mergedReferenceMode;
385
+ }
386
+ rootValidationWarnings.push(...validateModelAllowed(mergedModel, validationContext).warnings);
387
+ }
373
388
  const runtime = await loadPresetRuntime(preset);
374
389
  const resolved = runtime.resolve(pickPresetOptions(preset, merged));
375
390
  if (resolved.referenceMode === undefined && merged.referenceMode !== undefined) {
@@ -382,7 +397,7 @@ export async function configureFilmKit(options = {}) {
382
397
  const result = await runtime.configure(configureOptions);
383
398
  const configPath = join(rootDir, FILM_KIT_CONFIG_FILE);
384
399
  await writeText(configPath, `${JSON.stringify(buildFilmKitConfigFile(preset, resolved), null, 2)}\n`);
385
- const warnings = [...result.warnings];
400
+ const warnings = [...rootValidationWarnings, ...result.warnings];
386
401
  if (legacyMatch) {
387
402
  warnings.push(`Migrated legacy config '${legacyMatch.filename}' to '${FILM_KIT_CONFIG_FILE}'.`);
388
403
  }
@@ -0,0 +1,4 @@
1
+ export { MODEL_REGISTRY, type ActiveModelId, type AudioModelId, type DeprecatedModelId, type ImageModelId, type KnownModelId, type MultimodalModelId, type RemovedModelId, type VideoModelId } from "./registry.js";
2
+ export { getModel, getModelAdapterKey, getModelDisplayName, getReplacementModel, isActiveModelId, isDeprecatedModelId, isImageModelId, isKnownModelId, isModelSupportedByPreset, isRemovedModelId, isVideoModelId, listActiveModels, listActiveVideoModelIds, listImageModels, listModels, listModelsForPreset, listModelsForReferenceMode, listRunnableVideoModelIds, listRunnableVideoModels, listVideoModels, requireModel } from "./selectors.js";
3
+ export { assertModelAllowed, validateModelAllowed } from "./validation.js";
4
+ export type { ModelAdapterKey, ModelAllowedContext, ModelAllowedResult, ModelCapabilities, ModelDurationRange, ModelLifecycleStatus, ModelModality, ModelProfileKey, ModelRegistryAspectRatio, ModelRegistryEntry, ModelRegistryPreset, ModelRegistryReferenceMode, ModelRoutingRole, PromptGrammarKey } from "./types.js";
@@ -0,0 +1,3 @@
1
+ export { MODEL_REGISTRY } from "./registry.js";
2
+ export { getModel, getModelAdapterKey, getModelDisplayName, getReplacementModel, isActiveModelId, isDeprecatedModelId, isImageModelId, isKnownModelId, isModelSupportedByPreset, isRemovedModelId, isVideoModelId, listActiveModels, listActiveVideoModelIds, listImageModels, listModels, listModelsForPreset, listModelsForReferenceMode, listRunnableVideoModelIds, listRunnableVideoModels, listVideoModels, requireModel } from "./selectors.js";
3
+ export { assertModelAllowed, validateModelAllowed } from "./validation.js";