@nodaro/shared 2.8.0 → 2.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/dist/index.cjs +329 -53
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.cts +631 -94
  4. package/dist/index.d.ts +631 -94
  5. package/dist/index.js +297 -53
  6. package/dist/index.js.map +1 -1
  7. package/package.json +1 -1
  8. package/src/__tests__/catalog-projection.test.ts +14 -0
  9. package/src/__tests__/default-video-provider.test.ts +1 -1
  10. package/src/__tests__/llm-models.test.ts +3 -2
  11. package/src/__tests__/organizations-types.test.ts +61 -0
  12. package/src/__tests__/pack-sidecar-localization.test.ts +21 -0
  13. package/src/__tests__/parameter-node-value.test.ts +18 -1
  14. package/src/__tests__/producer-types.test.ts +11 -0
  15. package/src/__tests__/prompt-length-limits.test.ts +7 -3
  16. package/src/__tests__/resolve-pipeline-model.test.ts +4 -4
  17. package/src/__tests__/seedance2-continuation-ref.test.ts +2 -3
  18. package/src/__tests__/video-analysis-catalog-sync.test.ts +1 -1
  19. package/src/__tests__/video-analysis-pricing.test.ts +2 -2
  20. package/src/__tests__/video-mode-for-inputs.test.ts +74 -0
  21. package/src/animals.ts +10 -0
  22. package/src/catalog-projection.ts +48 -0
  23. package/src/combine-transitions.ts +38 -0
  24. package/src/credit-estimators/video-utils.ts +1 -1
  25. package/src/entity-node-fields.ts +147 -0
  26. package/src/featured-entities.ts +1 -1
  27. package/src/furniture.ts +10 -0
  28. package/src/i18n/index.ts +33 -3
  29. package/src/i18n/transitions.ar.ts +6 -0
  30. package/src/i18n/transitions.de.ts +6 -0
  31. package/src/i18n/transitions.es.ts +6 -0
  32. package/src/i18n/transitions.fr.ts +6 -0
  33. package/src/i18n/transitions.he.ts +6 -0
  34. package/src/i18n/transitions.hi.ts +6 -0
  35. package/src/i18n/transitions.ja.ts +6 -0
  36. package/src/i18n/transitions.ko.ts +6 -0
  37. package/src/i18n/transitions.pt-BR.ts +6 -0
  38. package/src/i18n/transitions.ru.ts +6 -0
  39. package/src/i18n/transitions.zh-CN.ts +6 -0
  40. package/src/i18n/types.ts +12 -14
  41. package/src/index.ts +30 -1
  42. package/src/llm-models.ts +4 -0
  43. package/src/model-catalog.ts +19 -0
  44. package/src/model-constants.ts +52 -7
  45. package/src/organizations/index.ts +2 -0
  46. package/src/organizations/types.ts +152 -0
  47. package/src/organizations/views.ts +220 -0
  48. package/src/parameter-node-value.ts +23 -3
  49. package/src/producer-types.ts +10 -0
  50. package/src/smart-cut-windows.ts +8 -17
  51. package/src/suno-track-sources.ts +23 -0
  52. package/src/surround.ts +10 -90
  53. package/src/vehicles.ts +11 -1
  54. package/src/video-analysis-pricing.ts +25 -36
  55. package/src/weapons.ts +11 -1
  56. package/src/workflow-export.ts +41 -0
package/src/i18n/index.ts CHANGED
@@ -30,6 +30,33 @@ function cacheKey(catalog: I18nCatalogId, locale: LocaleId): string {
30
30
  return `${catalog}:${locale}`
31
31
  }
32
32
 
33
+ /**
34
+ * Pack-sidecar overlay: localized strings contributed by registered catalog
35
+ * packs (e.g. an extension pack's `sidecars.he`), keyed `<catalog>:<locale>`.
36
+ * Consulted by `getLocalizedEntry` when the file sidecar lacks an id. Empty on
37
+ * mainline. Populated by `@nodaro/prompts` at pack registration — the content
38
+ * (the translated strings) lives in the pack (the deployment overlay), never
39
+ * in this Apache package.
40
+ */
41
+ const packSidecars = new Map<string, LocaleCatalogMap>()
42
+
43
+ export function registerCatalogSidecars(
44
+ catalog: string,
45
+ sidecars: Partial<Record<LocaleId, LocaleCatalogMap>> | undefined,
46
+ ): void {
47
+ if (!sidecars) return
48
+ for (const locale of Object.keys(sidecars) as LocaleId[]) {
49
+ const map = sidecars[locale]
50
+ if (!map) continue
51
+ const key = `${catalog}:${locale}`
52
+ packSidecars.set(key, { ...(packSidecars.get(key) ?? {}), ...map })
53
+ }
54
+ }
55
+
56
+ export function resetCatalogSidecars(): void {
57
+ packSidecars.clear()
58
+ }
59
+
33
60
  /**
34
61
  * Lazy-load a sidecar catalog. Returns `null` if the locale is `en` (no
35
62
  * sidecar — English lives in the canonical catalog file) or if no sidecar
@@ -82,9 +109,12 @@ export function getLocalizedEntry(
82
109
  locale: LocaleId,
83
110
  ): LocalizedEntry | undefined {
84
111
  if (locale === "en") return undefined
85
- const map = cache.get(cacheKey(catalog, locale))
86
- if (!map) return undefined
87
- return map[id]
112
+ const key = cacheKey(catalog, locale)
113
+ const fromFile = cache.get(key)?.[id]
114
+ if (fromFile) return fromFile
115
+ // Fall back to a pack-registered sidecar overlay (G10). File sidecars win;
116
+ // pack sidecars cover ids the deployment overlay added. Empty on mainline.
117
+ return packSidecars.get(key)?.[id]
88
118
  }
89
119
 
90
120
  /**
@@ -7,12 +7,15 @@ const map: LocaleCatalogMap = {
7
7
  "cross-dissolve": { label: "تلاشٍ متقاطع", description: "مزج تدريجي بين اللقطتين" },
8
8
  "fade-to-black": { label: "تلاشٍ إلى الأسود", description: "تظلم تدريجي ثم تظهر اللقطة التالية" },
9
9
  "fade-to-white": { label: "تلاشٍ إلى الأبيض", description: "توهج حتى الأبيض ثم تظهر اللقطة" },
10
+ "snap-to-black": { label: "قطع فوري إلى السواد", description: "قطع فوري إلى سواد كامل للحظة، ثم تدخل اللقطة التالية" },
10
11
  "match-cut": { label: "قطع متطابق", description: "تطابق الشكل أو الحركة بين اللقطتين" },
11
12
  "smash-cut": { label: "قطع مفاجئ", description: "قطع مفاجئ صارخ بين لقطتين متباينتين" },
12
13
  "iris": { label: "انتقال القزحية", description: "دائرة تنغلق ثم تنفتح على اللقطة الجديدة" },
13
14
  "wipe": { label: "مسح خطي", description: "خط يجتاح الإطار ليكشف اللقطة الجديدة" },
14
15
  "roll-transition": { label: "دوران", description: "الإطار يدور 90-180 درجة للانتقال" },
15
16
  "seamless-match": { label: "تطابق سلس", description: "قطع خفي يُموَّه بتطابق الحركة واللون" },
17
+ "whip-pan": { label: "بان سريع", description: "الكاميرا تنعطف جانبًا بسرعة مع ضبابية، واللقطة التالية تتابع الاتجاه نفسه" },
18
+ "jump-cut": { label: "قطع قافز", description: "الإطار نفسه، والزمن يقفز إلى الأمام" },
16
19
 
17
20
  // ── Time ──
18
21
  "fast-forward-day-night": { label: "تسريع (نهار ← ليل)", description: "مرور الزمن من النهار إلى الليل في نفس المشهد" },
@@ -62,6 +65,8 @@ const map: LocaleCatalogMap = {
62
65
  "zoom-into-mouth": { label: "تكبير في الفم", description: "الكاميرا تدخل الفم لتظهر في عالم جديد" },
63
66
  "push-through-glass": { label: "اختراق الزجاج", description: "الكاميرا تخترق لوح زجاج لعالم آخر" },
64
67
  "soul-jump": { label: "قفزة الروح", description: "روح شفافة تخرج وتدخل جسداً جديداً" },
68
+ "mask-transition": { label: "انتقال بالقناع", description: "جسم في المقدمة يحجب الإطار، والكاميرا تعبر العتمة إلى المشهد الجديد" },
69
+ "zoom-through": { label: "تقريب عبر التفصيل", description: "الكاميرا تكبّر تفصيلاً واحدًا حتى ينكشف المشهد الجديد داخله" },
65
70
 
66
71
  // ── Physics ──
67
72
  "explosion-blast": { label: "موجة انفجار", description: "انفجار يجتاح الإطار ويكشف المشهد الجديد" },
@@ -73,6 +78,7 @@ const map: LocaleCatalogMap = {
73
78
  "vehicle-explosion": { label: "انفجار مركبة", description: "مركبة تنفجر واللهب يغطي الإطار ثم يُكشف المشهد" },
74
79
  "jump-match": { label: "قفزة متطابقة", description: "الشخص يقفز وعند الهبوط يكون في مشهد جديد" },
75
80
  "hand-swipe": { label: "مسح اليد", description: "يد تمر أمام العدسة ويتغير المشهد" },
81
+ "action-relay": { label: "قطع على الحركة", description: "الشخصية تغادر الإطار وسط حركة وتكملها في المشهد الجديد" },
76
82
 
77
83
  // ── Light ──
78
84
  "white-flash": { label: "وميض أبيض", description: "الإطار يتوهج أبيض ثم يظهر المشهد الجديد" },
@@ -7,12 +7,15 @@ const map: LocaleCatalogMap = {
7
7
  "cross-dissolve": { label: "Überblendung", description: "Allmähliche Mischung zwischen den Einstellungen" },
8
8
  "fade-to-black": { label: "Abblende auf Schwarz", description: "Dunkelt auf Schwarz ab, zweite Einstellung erscheint" },
9
9
  "fade-to-white": { label: "Abblende auf Weiß", description: "Erstrahlt in Weiß, zweite Einstellung erscheint" },
10
+ "snap-to-black": { label: "Harter Schnitt auf Schwarz", description: "Sofortiger Schnitt auf volles Schwarz für einen Moment, dann die nächste Einstellung" },
10
11
  "match-cut": { label: "Match Cut", description: "Form- oder Bewegungsübereinstimmung zwischen Einstellungen" },
11
12
  "smash-cut": { label: "Smash Cut", description: "Abrupter Schnitt zwischen kontrastierenden Einstellungen" },
12
13
  "iris": { label: "Irisblende", description: "Iris schließt und öffnet sich zur zweiten Einstellung" },
13
14
  "wipe": { label: "Wischblende", description: "Linearer Wisch ersetzt die erste Einstellung" },
14
15
  "roll-transition": { label: "Drehübergang", description: "Bild dreht 90-180°, zweite Einstellung am Ende" },
15
16
  "seamless-match": { label: "Nahtloser Schnitt", description: "Versteckter Schnitt durch angeglichene Bewegung und Farbe" },
17
+ "whip-pan": { label: "Whip Pan", description: "Die Kamera reißt seitwärts in Bewegungsunschärfe, die zweite Einstellung folgt derselben Richtung" },
18
+ "jump-cut": { label: "Jump Cut", description: "Gleiche Einstellung, die Zeit springt vorwärts" },
16
19
 
17
20
  // ── Time ──
18
21
  "fast-forward-day-night": { label: "Zeitraffer Tag → Nacht", description: "Zeitraffer von Tag zu Nacht in derselben Szene" },
@@ -62,6 +65,8 @@ const map: LocaleCatalogMap = {
62
65
  "zoom-into-mouth": { label: "Zoom in den Mund", description: "Die Kamera tritt durch den geöffneten Mund in die neue Welt" },
63
66
  "push-through-glass": { label: "Durch das Glas", description: "Die Kamera durchquert das Glas in die neue Welt" },
64
67
  "soul-jump": { label: "Seelensprung", description: "Eine transluzente Seele verlässt den Körper und betritt den neuen" },
68
+ "mask-transition": { label: "Maskenübergang", description: "Ein Objekt im Vordergrund verdunkelt das Bild, die Kamera fährt hindurch" },
69
+ "zoom-through": { label: "Zoom Hindurch", description: "Die Kamera vergrößert ein Detail, bis die neue Szene darin entsteht" },
65
70
 
66
71
  // ── Physics ──
67
72
  "explosion-blast": { label: "Explosionsdruckwelle", description: "Die Explosion fegt den Rahmen frei, neue Szene erscheint" },
@@ -73,6 +78,7 @@ const map: LocaleCatalogMap = {
73
78
  "vehicle-explosion": { label: "Fahrzeugexplosion", description: "Das Fahrzeug explodiert im Vordergrund, die Szene wechselt" },
74
79
  "jump-match": { label: "Sprung-Schnitt", description: "Das Sujet springt, die Landung verbindet mit der neuen Szene" },
75
80
  "hand-swipe": { label: "Hand-Wisch", description: "Eine Hand wischt über das Objektiv, die Szene wechselt dahinter" },
81
+ "action-relay": { label: "Schnitt auf Bewegung", description: "Das Sujet verlässt das Bild in einer Bewegung und setzt sie in der neuen Szene fort" },
76
82
 
77
83
  // ── Light ──
78
84
  "white-flash": { label: "Weißblitz", description: "Der Rahmen erstrahlt in reinem Weiß" },
@@ -7,12 +7,15 @@ const map: LocaleCatalogMap = {
7
7
  "cross-dissolve": { label: "Disolvencia Cruzada", description: "Mezcla gradual entre planos" },
8
8
  "fade-to-black": { label: "Fundido a Negro", description: "Oscurece a negro, emerge el segundo plano" },
9
9
  "fade-to-white": { label: "Fundido a Blanco", description: "Estalla en blanco, emerge el segundo plano" },
10
+ "snap-to-black": { label: "Corte a Negro", description: "Corte instantáneo a negro por un instante, luego el siguiente plano" },
10
11
  "match-cut": { label: "Corte de Raccord", description: "Coincidencia de forma o movimiento entre planos" },
11
12
  "smash-cut": { label: "Corte Brusco", description: "Corte abrupto entre planos contrastados" },
12
13
  "iris": { label: "Iris", description: "Iris circular cierra y abre en el segundo plano" },
13
14
  "wipe": { label: "Barrido", description: "Barrido lineal reemplaza el primer plano" },
14
15
  "roll-transition": { label: "Rotación", description: "Cuadro gira 90-180°, segundo plano al aterrizar" },
15
16
  "seamless-match": { label: "Corte Invisible", description: "Corte oculto por movimiento y color sincronizados" },
17
+ "whip-pan": { label: "Barrido Rápido", description: "La cámara barre de lado con desenfoque, el siguiente plano sigue esa dirección" },
18
+ "jump-cut": { label: "Corte de Salto", description: "Mismo encuadre, el tiempo salta hacia adelante" },
16
19
 
17
20
  // ── Time ──
18
21
  "fast-forward-day-night": { label: "Time-lapse Día → Noche", description: "Time-lapse de día a noche en la misma escena" },
@@ -62,6 +65,8 @@ const map: LocaleCatalogMap = {
62
65
  "zoom-into-mouth": { label: "Zoom a la Boca", description: "La cámara entra en la boca abierta hacia el nuevo mundo" },
63
66
  "push-through-glass": { label: "Atravesar el Cristal", description: "La cámara atraviesa el cristal hacia el nuevo mundo" },
64
67
  "soul-jump": { label: "Salto del Alma", description: "Un alma translúcida sale del cuerpo y entra en el nuevo" },
68
+ "mask-transition": { label: "Transición de Máscara", description: "Un objeto en primer plano tapa el cuadro y la cámara lo atraviesa" },
69
+ "zoom-through": { label: "Zoom Atravesado", description: "La cámara amplía un detalle hasta que la nueva escena surge dentro" },
65
70
 
66
71
  // ── Physics ──
67
72
  "explosion-blast": { label: "Explosión", description: "Explosión barre el cuadro, emerge la nueva escena" },
@@ -73,6 +78,7 @@ const map: LocaleCatalogMap = {
73
78
  "vehicle-explosion": { label: "Explosión de Vehículo", description: "Vehículo explota en primer plano, la escena cambia" },
74
79
  "jump-match": { label: "Salto Raccord", description: "El sujeto salta, el aterrizaje enlaza con la nueva escena" },
75
80
  "hand-swipe": { label: "Barrido de Mano", description: "Una mano barre la lente, la escena cambia al descubrirse" },
81
+ "action-relay": { label: "Corte por Acción", description: "El sujeto sale de cuadro en una acción y la continúa en la nueva escena" },
76
82
 
77
83
  // ── Light ──
78
84
  "white-flash": { label: "Destello Blanco", description: "El cuadro estalla en blanco puro" },
@@ -7,12 +7,15 @@ const map: LocaleCatalogMap = {
7
7
  "cross-dissolve": { label: "Fondu Enchaîné", description: "Mélange progressif entre les plans" },
8
8
  "fade-to-black": { label: "Fondu au Noir", description: "S'assombrit, le second plan émerge du noir" },
9
9
  "fade-to-white": { label: "Fondu au Blanc", description: "Sature de blanc, le second plan en émerge" },
10
+ "snap-to-black": { label: "Coupe au Noir", description: "Coupe instantanée au noir pendant un temps, puis le plan suivant" },
10
11
  "match-cut": { label: "Coupe sur Raccord", description: "Correspondance de forme ou mouvement entre plans" },
11
12
  "smash-cut": { label: "Coupe Violente", description: "Coupe abrupte entre plans contrastés" },
12
13
  "iris": { label: "Cache Iris", description: "L'iris ferme puis ouvre sur le second plan" },
13
14
  "wipe": { label: "Balayage", description: "Balayage linéaire remplace le premier plan" },
14
15
  "roll-transition": { label: "Rotation", description: "Le cadre pivote 90-180°, second plan à l'arrivée" },
15
16
  "seamless-match": { label: "Coupe Invisible", description: "Coupe masquée par mouvement et couleur synchronisés" },
17
+ "whip-pan": { label: "Filé Panoramique", description: "La caméra file latéralement en flou, le plan suivant garde la direction" },
18
+ "jump-cut": { label: "Jump Cut", description: "Même cadrage, le temps saute en avant" },
16
19
 
17
20
  // ── Time ──
18
21
  "fast-forward-day-night": { label: "Accéléré Jour → Nuit", description: "Accéléré de jour à nuit sur la même scène" },
@@ -62,6 +65,8 @@ const map: LocaleCatalogMap = {
62
65
  "zoom-into-mouth": { label: "Zoom dans la Bouche", description: "La caméra pénètre la bouche ouverte vers le nouveau monde" },
63
66
  "push-through-glass": { label: "Traversée du Verre", description: "La caméra traverse le verre vers le nouveau monde" },
64
67
  "soul-jump": { label: "Saut d'Âme", description: "Une âme translucide quitte le corps et entre dans le nouveau" },
68
+ "mask-transition": { label: "Transition Masquée", description: "Un objet au premier plan masque le cadre, la caméra le traverse" },
69
+ "zoom-through": { label: "Zoom Traversant", description: "La caméra grossit un détail jusqu'à ce que la nouvelle scène s'y déploie" },
65
70
 
66
71
  // ── Physics ──
67
72
  "explosion-blast": { label: "Souffle d'Explosion", description: "L'explosion balaie le cadre, la nouvelle scène émerge" },
@@ -73,6 +78,7 @@ const map: LocaleCatalogMap = {
73
78
  "vehicle-explosion": { label: "Explosion de Véhicule", description: "Le véhicule explose au premier plan, la scène change" },
74
79
  "jump-match": { label: "Raccord de Saut", description: "Le sujet saute, l'atterrissage enchaîne sur la nouvelle scène" },
75
80
  "hand-swipe": { label: "Balayage de Main", description: "Une main balaie l'objectif, la scène change en se dégageant" },
81
+ "action-relay": { label: "Raccord dans le Mouvement", description: "Le sujet sort du cadre sur une action et la poursuit dans la nouvelle scène" },
76
82
 
77
83
  // ── Light ──
78
84
  "white-flash": { label: "Flash Blanc", description: "Le cadre sature en blanc pur" },
@@ -7,12 +7,15 @@ const map: LocaleCatalogMap = {
7
7
  "cross-dissolve": { label: "דיסולב הצלבה", description: "מיזוג הדרגתי בין שתי הסצנות" },
8
8
  "fade-to-black": { label: "דהייה לשחור", description: "חשיכה הדרגתית ואז הסצנה הבאה" },
9
9
  "fade-to-white": { label: "דהייה ללבן", description: "הבהרה עד לבן ואז הסצנה הבאה" },
10
+ "snap-to-black": { label: "חיתוך לשחור", description: "חיתוך מיידי לשחור מלא לרגע, ואז השוט הבא" },
10
11
  "match-cut": { label: "חיתוך התאמה", description: "התאמת צורה או תנועה בין הסצנות" },
11
12
  "smash-cut": { label: "חיתוך חד", description: "חיתוך מפתיע בין סצנות מנוגדות" },
12
13
  "iris": { label: "אירוס", description: "עיגול נסגר ונפתח על הסצנה החדשה" },
13
14
  "wipe": { label: "מחיקה", description: "קו סורק את הפריים וחושף את הסצנה" },
14
15
  "roll-transition": { label: "סיבוב", description: "הפריים מסתובב 90-180 מעלות" },
15
16
  "seamless-match": { label: "התאמה חלקה", description: "חיתוך נסתר בתנועה וצבע תואמים" },
17
+ "whip-pan": { label: "פאן מהיר", description: "המצלמה מסתובבת הצידה במהירות לכדי טשטוש, והשוט הבא ממשיך באותו כיוון" },
18
+ "jump-cut": { label: "ג'אמפ קאט", description: "אותו קאדר, הזמן מדלג קדימה" },
16
19
 
17
20
  // ── Time ──
18
21
  "fast-forward-day-night": { label: "הרצה מהירה (יום ← לילה)", description: "מעבר זמן מהיום ללילה באותה סצנה" },
@@ -62,6 +65,8 @@ const map: LocaleCatalogMap = {
62
65
  "zoom-into-mouth": { label: "זום לתוך פה", description: "המצלמה נכנסת לפה ומגיחה לעולם חדש" },
63
66
  "push-through-glass": { label: "דחיפה דרך זכוכית", description: "המצלמה חודרת לוח זכוכית לעולם אחר" },
64
67
  "soul-jump": { label: "קפיצת נשמה", description: "נשמה שקופה עוזבת גוף אחד ונכנסת לאחר" },
68
+ "mask-transition": { label: "מעבר מסכה", description: "עצם בחזית מכסה את הפריים והמצלמה חוצה את החושך אל הסצנה החדשה" },
69
+ "zoom-through": { label: "זום אל תוך פרט", description: "המצלמה מגדילה פרט אחד עד שהסצנה החדשה נפרשת בתוכו" },
65
70
 
66
71
  // ── Physics ──
67
72
  "explosion-blast": { label: "גל פיצוץ", description: "פיצוץ סורק את הפריים וחושף את הסצנה החדשה" },
@@ -73,6 +78,7 @@ const map: LocaleCatalogMap = {
73
78
  "vehicle-explosion": { label: "פיצוץ רכב", description: "רכב מתפוצץ, להבות מכסות את הפריים, והסצנה מתחלפת" },
74
79
  "jump-match": { label: "קפיצה תואמת", description: "הדמות קופצת ונוחתת בסצנה חדשה" },
75
80
  "hand-swipe": { label: "מחיקת יד", description: "יד עוברת מול העדשה והסצנה משתנה" },
81
+ "action-relay": { label: "חיתוך על תנועה", description: "הדמות יוצאת מהפריים בתנועה וממשיכה אותה בסצנה החדשה" },
76
82
 
77
83
  // ── Light ──
78
84
  "white-flash": { label: "הבזק לבן", description: "הפריים מתמלא לבן ואז מגיחה הסצנה החדשה" },
@@ -7,12 +7,15 @@ const map: LocaleCatalogMap = {
7
7
  "cross-dissolve": { label: "क्रॉस-डिसॉल्व", description: "दोनों दृश्यों के बीच क्रमिक मिश्रण" },
8
8
  "fade-to-black": { label: "काले में फ़ेड", description: "धीरे-धीरे काला होकर नया दृश्य उभरता है" },
9
9
  "fade-to-white": { label: "सफ़ेद में फ़ेड", description: "पूरी तरह सफ़ेद होकर नया दृश्य उभरता है" },
10
+ "snap-to-black": { label: "तुरंत ब्लैक", description: "एक पल के लिए पूरी तरह काला, फिर अगला शॉट" },
10
11
  "match-cut": { label: "मैच कट", description: "दोनों दृश्यों में आकार या गति का मिलान" },
11
12
  "smash-cut": { label: "स्मैश कट", description: "विपरीत दृश्यों के बीच अचानक कट" },
12
13
  "iris": { label: "आइरिस", description: "गोल वृत्त बंद होकर नए दृश्य पर खुलता है" },
13
14
  "wipe": { label: "वाइप", description: "रेखा फ्रेम पार करके नया दृश्य दिखाती है" },
14
15
  "roll-transition": { label: "रोल", description: "फ्रेम 90-180° घूमकर नए दृश्य पर रुकता है" },
15
16
  "seamless-match": { label: "सीमलेस मैच", description: "मिलान गति-रंग से छिपाया गया कट" },
17
+ "whip-pan": { label: "व्हिप पैन", description: "कैमरा तेज़ी से बगल घूमता है और अगला शॉट उसी दिशा में चलता है" },
18
+ "jump-cut": { label: "जंप कट", description: "वही फ्रेमिंग, समय आगे छलांग लगाता है" },
16
19
 
17
20
  // ── Time ──
18
21
  "fast-forward-day-night": { label: "फ़ास्ट-फ़ॉरवर्ड (दिन → रात)", description: "उसी दृश्य में दिन से रात का टाइम-लैप्स" },
@@ -62,6 +65,8 @@ const map: LocaleCatalogMap = {
62
65
  "zoom-into-mouth": { label: "मुँह में ज़ूम", description: "कैमरा मुँह में जाकर नई दुनिया में निकलता है" },
63
66
  "push-through-glass": { label: "काँच से गुज़रना", description: "कैमरा काँच से गुज़रकर नई दुनिया में जाता है" },
64
67
  "soul-jump": { label: "आत्मा की छलाँग", description: "आत्मा एक शरीर से निकलकर दूसरे में जाती है" },
68
+ "mask-transition": { label: "मास्क ट्रांज़िशन", description: "अग्रभूमि की वस्तु फ्रेम को ढक देती है, कैमरा अंधेरे से होकर निकलता है" },
69
+ "zoom-through": { label: "ज़ूम थ्रू", description: "कैमरा एक विवरण को बड़ा करता है और नया दृश्य उसी के भीतर खुलता है" },
65
70
 
66
71
  // ── Physics ──
67
72
  "explosion-blast": { label: "विस्फोट की लहर", description: "विस्फोट फ्रेम पार करता है, नया दृश्य उभरता है" },
@@ -73,6 +78,7 @@ const map: LocaleCatalogMap = {
73
78
  "vehicle-explosion": { label: "वाहन विस्फोट", description: "वाहन फटता है, आग छाती है फ्रेम पर, नया दृश्य दिखता है" },
74
79
  "jump-match": { label: "जंप मैच", description: "पात्र कूदता है, उतरने पर नए दृश्य में होता है" },
75
80
  "hand-swipe": { label: "हाथ का झटका", description: "हाथ लेंस पर झटका देता है, दृश्य बदलता है" },
81
+ "action-relay": { label: "एक्शन मैच कट", description: "विषय गति में फ्रेम से बाहर जाता है और नए दृश्य में वही गति जारी रखता है" },
76
82
 
77
83
  // ── Light ──
78
84
  "white-flash": { label: "सफ़ेद फ़्लैश", description: "फ्रेम सफ़ेद होता है, नया दृश्य उभरता है" },
@@ -7,12 +7,15 @@ const map: LocaleCatalogMap = {
7
7
  "cross-dissolve": { label: "クロスディゾルブ", description: "ショット間の緩やかなブレンド" },
8
8
  "fade-to-black": { label: "暗転", description: "暗転後、次のシーンが浮かび上がる" },
9
9
  "fade-to-white": { label: "ホワイトアウト", description: "白飛び後、次のシーンが現れる" },
10
+ "snap-to-black": { label: "黒への瞬間カット", description: "一瞬で真っ黒になり、間を置いて次のショットへ" },
10
11
  "match-cut": { label: "マッチカット", description: "形や動きを合わせたカット" },
11
12
  "smash-cut": { label: "スマッシュカット", description: "対照的なシーン間の衝撃的な急転" },
12
13
  "iris": { label: "アイリス", description: "円形のアイリスが閉じ、次のシーンで開く" },
13
14
  "wipe": { label: "ワイプ", description: "直線的なワイプで次のシーンへ" },
14
15
  "roll-transition": { label: "ロール", description: "フレームが90〜180°回転して次のシーンへ" },
15
16
  "seamless-match": { label: "シームレスカット", description: "動きと色で隠された完全なシームレスカット" },
17
+ "whip-pan": { label: "ホイップパン", description: "カメラが横に振り切れてブレ、次のショットも同じ方向に流れる" },
18
+ "jump-cut": { label: "ジャンプカット", description: "同じ画角のまま時間が前に飛ぶ" },
16
19
 
17
20
  // ── Time ──
18
21
  "fast-forward-day-night": { label: "日中→夜 早送り", description: "同じ場面の昼から夜へのタイムラプス" },
@@ -62,6 +65,8 @@ const map: LocaleCatalogMap = {
62
65
  "zoom-into-mouth": { label: "口へのズーム", description: "開いた口へ接近し、内側に新しい世界が" },
63
66
  "push-through-glass": { label: "ガラスをすり抜ける", description: "ガラス面をカメラが屈折しながら通り抜ける" },
64
67
  "soul-jump": { label: "魂の跳躍", description: "半透明の魂が体を出て新しい体へ入る" },
68
+ "mask-transition": { label: "マスクトランジション", description: "手前の物体が画面を覆い、その暗闇をカメラが抜けて新しい場面へ" },
69
+ "zoom-through": { label: "ズームスルー", description: "細部を拡大し続け、その中から新しい場面が広がる" },
65
70
 
66
71
  // ── Physics ──
67
72
  "explosion-blast": { label: "爆発", description: "爆発がフレームを吹き飛ばし、新シーンへ" },
@@ -73,6 +78,7 @@ const map: LocaleCatalogMap = {
73
78
  "vehicle-explosion": { label: "車両爆発", description: "前景の車両が爆発し、煙が晴れると新シーン" },
74
79
  "jump-match": { label: "ジャンプマッチ", description: "被写体が跳び、着地が新しいシーンに合致" },
75
80
  "hand-swipe": { label: "手のスワイプ", description: "手がレンズを横切り、遮蔽中にシーン転換" },
81
+ "action-relay": { label: "アクションつなぎ", description: "動作の途中でフレームから出て、新しい場面で同じ動きを続ける" },
76
82
 
77
83
  // ── Light ──
78
84
  "white-flash": { label: "ホワイトフラッシュ", description: "フレームが純白に膨らむ" },
@@ -7,12 +7,15 @@ const map: LocaleCatalogMap = {
7
7
  "cross-dissolve": { label: "크로스 디졸브", description: "샷 간의 점진적인 블렌드" },
8
8
  "fade-to-black": { label: "페이드 투 블랙", description: "화면이 어두워지고 두 번째 장면이 등장" },
9
9
  "fade-to-white": { label: "페이드 투 화이트", description: "화면이 밝아지고 두 번째 장면이 등장" },
10
+ "snap-to-black": { label: "블랙 스냅 컷", description: "즉시 완전한 검은 화면으로 끊었다가 다음 샷으로 전환" },
10
11
  "match-cut": { label: "매치 컷", description: "샷 간 형태나 동작의 시각적 운율" },
11
12
  "smash-cut": { label: "스매시 컷", description: "대조적인 샷 사이의 충격적인 급전환" },
12
13
  "iris": { label: "아이리스", description: "원형 조리개가 닫히고 두 번째 장면에서 열림" },
13
14
  "wipe": { label: "와이프", description: "직선 와이프로 첫 번째 샷을 대체" },
14
15
  "roll-transition": { label: "롤", description: "프레임이 90–180° 회전 후 두 번째 샷이 안정됨" },
15
16
  "seamless-match": { label: "심리스 매치", description: "동작과 색상으로 위장한 보이지 않는 컷" },
17
+ "whip-pan": { label: "휩 팬", description: "카메라가 옆으로 휘몰아치며 흐려지고 다음 샷도 같은 방향으로 이어짐" },
18
+ "jump-cut": { label: "점프 컷", description: "같은 프레이밍에서 시간만 앞으로 건너뜀" },
16
19
 
17
20
  // ── Time ──
18
21
  "fast-forward-day-night": { label: "낮→밤 타임랩스", description: "같은 장면에서 낮에서 밤으로의 타임랩스" },
@@ -62,6 +65,8 @@ const map: LocaleCatalogMap = {
62
65
  "zoom-into-mouth": { label: "입 속으로 줌", description: "열린 입 속으로 밀어 들어가 새 세계로" },
63
66
  "push-through-glass": { label: "유리를 통과", description: "카메라가 유리 면을 굴절하며 통과해 새 세계로" },
64
67
  "soul-jump": { label: "영혼 점프", description: "반투명한 영혼이 몸을 떠나 새 몸으로 들어감" },
68
+ "mask-transition": { label: "마스크 트랜지션", description: "전경의 물체가 화면을 가리고 카메라가 그 어둠을 통과함" },
69
+ "zoom-through": { label: "줌 스루", description: "카메라가 한 디테일을 확대해 그 안에서 새 장면이 펼쳐짐" },
65
70
 
66
71
  // ── Physics ──
67
72
  "explosion-blast": { label: "폭발", description: "폭발이 화면을 쓸어내고 새 장면이 드러남" },
@@ -73,6 +78,7 @@ const map: LocaleCatalogMap = {
73
78
  "vehicle-explosion": { label: "차량 폭발", description: "전경의 차량이 폭발하고 연기 걷히면 새 장면" },
74
79
  "jump-match": { label: "점프 매치", description: "피사체가 점프하고 착지가 새 장면과 연결" },
75
80
  "hand-swipe": { label: "손 스와이프", description: "손이 렌즈를 가리는 사이 장면이 전환됨" },
81
+ "action-relay": { label: "액션 매치 컷", description: "피사체가 동작 중 프레임을 벗어나 새 장면에서 그 동작을 이어감" },
76
82
 
77
83
  // ── Light ──
78
84
  "white-flash": { label: "화이트 플래시", description: "화면이 순백으로 빛남" },
@@ -7,12 +7,15 @@ const map: LocaleCatalogMap = {
7
7
  "cross-dissolve": { label: "Fusão Cruzada", description: "Mistura gradual entre cenas" },
8
8
  "fade-to-black": { label: "Fade para Preto", description: "Escurece ao preto, segunda cena emerge" },
9
9
  "fade-to-white": { label: "Fade para Branco", description: "Clareia ao branco, segunda cena emerge" },
10
+ "snap-to-black": { label: "Corte Seco para Preto", description: "Corte instantâneo ao preto por um instante, depois a próxima cena" },
10
11
  "match-cut": { label: "Corte de Raccord", description: "Correspondência de forma ou movimento entre cenas" },
11
12
  "smash-cut": { label: "Corte Brusco", description: "Corte abrupto entre cenas visualmente contrastantes" },
12
13
  "iris": { label: "Íris", description: "Íris circular fecha e abre na segunda cena" },
13
14
  "wipe": { label: "Varredura", description: "Varredura linear substitui a primeira cena" },
14
15
  "roll-transition": { label: "Rolagem", description: "Quadro gira 90–180°, segunda cena estável" },
15
16
  "seamless-match": { label: "Corte Invisível", description: "Corte oculto disfarçado por movimento e cor" },
17
+ "whip-pan": { label: "Chicote de Câmera", description: "Câmera varre de lado com borrão, a próxima cena segue a mesma direção" },
18
+ "jump-cut": { label: "Jump Cut", description: "Mesmo enquadramento, o tempo salta adiante" },
16
19
 
17
20
  // ── Time ──
18
21
  "fast-forward-day-night": { label: "Dia → Noite (Time-lapse)", description: "Time-lapse do dia para a noite na mesma cena" },
@@ -62,6 +65,8 @@ const map: LocaleCatalogMap = {
62
65
  "zoom-into-mouth": { label: "Zoom na Boca", description: "Push na boca aberta, emerge em novo mundo" },
63
66
  "push-through-glass": { label: "Atravessar o Vidro", description: "Câmera atravessa vidro com refração para nova cena" },
64
67
  "soul-jump": { label: "Salto de Alma", description: "Alma translúcida sai do corpo, entra em novo corpo" },
68
+ "mask-transition": { label: "Transição de Máscara", description: "Objeto em primeiro plano cobre o quadro, câmera atravessa o escuro" },
69
+ "zoom-through": { label: "Zoom Atravessado", description: "Câmera amplia um detalhe até a nova cena surgir dentro dele" },
65
70
 
66
71
  // ── Physics ──
67
72
  "explosion-blast": { label: "Explosão", description: "Explosão limpa o quadro, nova cena emerge" },
@@ -73,6 +78,7 @@ const map: LocaleCatalogMap = {
73
78
  "vehicle-explosion": { label: "Explosão de Veículo", description: "Veículo explode em primeiro plano, cena muda" },
74
79
  "jump-match": { label: "Salto Combinado", description: "Sujeito pula, aterrissagem combina com nova cena" },
75
80
  "hand-swipe": { label: "Varredura de Mão", description: "Mão passa pela lente, cena muda durante a oclusão" },
81
+ "action-relay": { label: "Corte na Ação", description: "Sujeito sai de quadro numa ação e continua o movimento na nova cena" },
76
82
 
77
83
  // ── Light ──
78
84
  "white-flash": { label: "Flash Branco", description: "Quadro clareia ao branco" },
@@ -7,12 +7,15 @@ const map: LocaleCatalogMap = {
7
7
  "cross-dissolve": { label: "Перекрёстный наплыв", description: "Плавное смешение двух сцен" },
8
8
  "fade-to-black": { label: "Затемнение", description: "Постепенное затемнение, затем новая сцена" },
9
9
  "fade-to-white": { label: "Засветка", description: "Осветление до белого, затем новая сцена" },
10
+ "snap-to-black": { label: "Резкий уход в чёрное", description: "Мгновенный переход в чёрное на удар, затем следующий кадр" },
10
11
  "match-cut": { label: "Монтаж по форме", description: "Совпадение формы или движения между сценами" },
11
12
  "smash-cut": { label: "Резкий монтаж", description: "Резкий переход между контрастными сценами" },
12
13
  "iris": { label: "Ирис", description: "Круг закрывается, затем открывается на новой сцене" },
13
14
  "wipe": { label: "Шторка", description: "Линия пересекает кадр, открывая новую сцену" },
14
15
  "roll-transition": { label: "Прокрутка", description: "Кадр вращается на 90-180°, останавливаясь на новой сцене" },
15
16
  "seamless-match": { label: "Незаметный переход", description: "Скрытый монтаж, замаскированный движением и цветом" },
17
+ "whip-pan": { label: "Резкая панорама", description: "Камера резко уходит вбок в смазе, новый кадр движется в ту же сторону" },
18
+ "jump-cut": { label: "Джамп-кат", description: "Та же крупность, время скачком уходит вперёд" },
16
19
 
17
20
  // ── Time ──
18
21
  "fast-forward-day-night": { label: "Ускорение (день → ночь)", description: "Тайм-лапс от дня к ночи в той же сцене" },
@@ -62,6 +65,8 @@ const map: LocaleCatalogMap = {
62
65
  "zoom-into-mouth": { label: "Зум в рот", description: "Камера входит в рот и оказывается в новом мире" },
63
66
  "push-through-glass": { label: "Проход сквозь стекло", description: "Камера проходит сквозь стеклянную панель в другой мир" },
64
67
  "soul-jump": { label: "Прыжок души", description: "Полупрозрачная душа покидает одно тело и входит в другое" },
68
+ "mask-transition": { label: "Переход через маску", description: "Объект на переднем плане перекрывает кадр, камера проходит сквозь темноту" },
69
+ "zoom-through": { label: "Наезд сквозь деталь", description: "Камера укрупняет деталь, пока внутри неё не раскроется новая сцена" },
65
70
 
66
71
  // ── Physics ──
67
72
  "explosion-blast": { label: "Взрывная волна", description: "Взрыв захлёстывает кадр, открывая новую сцену" },
@@ -73,6 +78,7 @@ const map: LocaleCatalogMap = {
73
78
  "vehicle-explosion": { label: "Взрыв транспорта", description: "Машина взрывается, огонь захлёстывает кадр, открывается новая сцена" },
74
79
  "jump-match": { label: "Совпадающий прыжок", description: "Персонаж прыгает и приземляется уже в новой сцене" },
75
80
  "hand-swipe": { label: "Смахивание рукой", description: "Рука проходит перед объективом, сцена меняется" },
81
+ "action-relay": { label: "Монтаж по действию", description: "Герой уходит из кадра на движении и продолжает его в новой сцене" },
76
82
 
77
83
  // ── Light ──
78
84
  "white-flash": { label: "Белая вспышка", description: "Кадр заливается белым, затем появляется новая сцена" },
@@ -7,12 +7,15 @@ const map: LocaleCatalogMap = {
7
7
  "cross-dissolve": { label: "交叉溶解", description: "两个镜头间的渐进融合" },
8
8
  "fade-to-black": { label: "淡出至黑", description: "画面变暗至全黑,第二幕浮现" },
9
9
  "fade-to-white": { label: "淡出至白", description: "画面泛白,第二幕从白光中显现" },
10
+ "snap-to-black": { label: "瞬切黑场", description: "瞬间切入全黑停顿一拍,随后切入下一镜头" },
10
11
  "match-cut": { label: "匹配剪辑", description: "镜头间形状或动作的视觉呼应" },
11
12
  "smash-cut": { label: "撞击剪辑", description: "对比强烈的镜头间的突兀硬切" },
12
13
  "iris": { label: "虹膜转场", description: "圆形虹膜收缩后展开至第二幕" },
13
14
  "wipe": { label: "划像", description: "直线划过替换第一个镜头" },
14
15
  "roll-transition": { label: "滚动转场", description: "画面旋转90–180°,第二幕正立落定" },
15
16
  "seamless-match": { label: "无缝匹配", description: "以运动与色调伪装的隐形剪辑" },
17
+ "whip-pan": { label: "甩镜", description: "镜头横向急甩带出模糊,下一镜头顺着同一方向接上" },
18
+ "jump-cut": { label: "跳切", description: "同一构图,时间向前跳跃" },
16
19
 
17
20
  // ── Time ──
18
21
  "fast-forward-day-night": { label: "快进(日→夜)", description: "同一场景日转夜的延时摄影" },
@@ -62,6 +65,8 @@ const map: LocaleCatalogMap = {
62
65
  "zoom-into-mouth": { label: "推入口腔", description: "推入张开的嘴,进入内部新世界" },
63
66
  "push-through-glass": { label: "穿越玻璃", description: "镜头推过玻璃折射进入新世界" },
64
67
  "soul-jump": { label: "灵魂跃迁", description: "半透明灵魂离体,跃入新身体" },
68
+ "mask-transition": { label: "遮罩转场", description: "前景物体遮黑画面,镜头穿过黑暗进入新场景" },
69
+ "zoom-through": { label: "推进穿越", description: "镜头不断放大一处细节,新场景在其中展开" },
65
70
 
66
71
  // ── Physics ──
67
72
  "explosion-blast": { label: "爆炸", description: "爆炸席卷画面,新场景从烟尘中浮现" },
@@ -73,6 +78,7 @@ const map: LocaleCatalogMap = {
73
78
  "vehicle-explosion": { label: "车辆爆炸", description: "前景车辆爆炸,火焰散去后新场景" },
74
79
  "jump-match": { label: "跳跃匹配", description: "主体起跳,落地衔接新场景" },
75
80
  "hand-swipe": { label: "手掌划过", description: "手掌扫过镜头,遮挡间场景切换" },
81
+ "action-relay": { label: "动作接力剪辑", description: "主体带着动作出画,在新场景中延续同一动作" },
76
82
 
77
83
  // ── Light ──
78
84
  "white-flash": { label: "白色闪光", description: "画面泛出纯白" },
package/src/i18n/types.ts CHANGED
@@ -52,8 +52,6 @@ export interface LanguageDefinition {
52
52
  readonly shortCode: string
53
53
  /** Reading direction. */
54
54
  readonly dir: LocaleDirection
55
- /** Optional flag emoji for visual recognition. */
56
- readonly flag: string
57
55
  }
58
56
 
59
57
  /**
@@ -62,18 +60,18 @@ export interface LanguageDefinition {
62
60
  * languages, then RTL languages last.
63
61
  */
64
62
  export const LANGUAGES: ReadonlyArray<LanguageDefinition> = [
65
- { id: "en", englishName: "English", nativeName: "English", shortCode: "EN", dir: "ltr", flag: "🇬🇧" },
66
- { id: "es", englishName: "Spanish", nativeName: "Español", shortCode: "ES", dir: "ltr", flag: "🇪🇸" },
67
- { id: "fr", englishName: "French", nativeName: "Français", shortCode: "FR", dir: "ltr", flag: "🇫🇷" },
68
- { id: "de", englishName: "German", nativeName: "Deutsch", shortCode: "DE", dir: "ltr", flag: "🇩🇪" },
69
- { id: "pt-BR", englishName: "Portuguese (Brazil)", nativeName: "Português", shortCode: "PT", dir: "ltr", flag: "🇧🇷" },
70
- { id: "ru", englishName: "Russian", nativeName: "Русский", shortCode: "RU", dir: "ltr", flag: "🇷🇺" },
71
- { id: "hi", englishName: "Hindi", nativeName: "हिन्दी", shortCode: "HI", dir: "ltr", flag: "🇮🇳" },
72
- { id: "ja", englishName: "Japanese", nativeName: "日本語", shortCode: "JA", dir: "ltr", flag: "🇯🇵" },
73
- { id: "ko", englishName: "Korean", nativeName: "한국어", shortCode: "KO", dir: "ltr", flag: "🇰🇷" },
74
- { id: "zh-CN", englishName: "Chinese (Simplified)", nativeName: "简体中文", shortCode: "ZH", dir: "ltr", flag: "🇨🇳" },
75
- { id: "he", englishName: "Hebrew", nativeName: "עברית", shortCode: "HE", dir: "rtl", flag: "🇮🇱" },
76
- { id: "ar", englishName: "Arabic", nativeName: "العربية", shortCode: "AR", dir: "rtl", flag: "🇸🇦" },
63
+ { id: "en", englishName: "English", nativeName: "English", shortCode: "EN", dir: "ltr" },
64
+ { id: "es", englishName: "Spanish", nativeName: "Español", shortCode: "ES", dir: "ltr" },
65
+ { id: "fr", englishName: "French", nativeName: "Français", shortCode: "FR", dir: "ltr" },
66
+ { id: "de", englishName: "German", nativeName: "Deutsch", shortCode: "DE", dir: "ltr" },
67
+ { id: "pt-BR", englishName: "Portuguese (Brazil)", nativeName: "Português", shortCode: "PT", dir: "ltr" },
68
+ { id: "ru", englishName: "Russian", nativeName: "Русский", shortCode: "RU", dir: "ltr" },
69
+ { id: "hi", englishName: "Hindi", nativeName: "हिन्दी", shortCode: "HI", dir: "ltr" },
70
+ { id: "ja", englishName: "Japanese", nativeName: "日本語", shortCode: "JA", dir: "ltr" },
71
+ { id: "ko", englishName: "Korean", nativeName: "한국어", shortCode: "KO", dir: "ltr" },
72
+ { id: "zh-CN", englishName: "Chinese (Simplified)", nativeName: "简体中文", shortCode: "ZH", dir: "ltr" },
73
+ { id: "he", englishName: "Hebrew", nativeName: "עברית", shortCode: "HE", dir: "rtl" },
74
+ { id: "ar", englishName: "Arabic", nativeName: "العربية", shortCode: "AR", dir: "rtl" },
77
75
  ] as const
78
76
 
79
77
  export const LOCALE_IDS: ReadonlyArray<LocaleId> = LANGUAGES.map((l) => l.id)
package/src/index.ts CHANGED
@@ -110,6 +110,7 @@ export {
110
110
  VIDEO_MODE_ALIASES,
111
111
  VIDEO_GEN_COLLAPSED_T2V_IDS,
112
112
  resolveVideoProviderForMode,
113
+ resolveVideoModeForInputs,
113
114
  isSeedance2Provider,
114
115
  MINIMAX_H3_PROVIDERS,
115
116
  isMinimaxH3Provider,
@@ -396,7 +397,6 @@ export {
396
397
  TILT_CARRIED_FRACTION,
397
398
  isTiltDirection,
398
399
  defaultCarriedFraction,
399
- buildSurroundFillPrompt,
400
400
  type SurroundDirection,
401
401
  } from "./surround.js"
402
402
 
@@ -511,6 +511,7 @@ export {
511
511
  PARAMETER_NODE_TYPES,
512
512
  HINT_EXEMPT_PARAMETER_TYPES,
513
513
  getParameterValue,
514
+ setRegisteredPersonPackFields,
514
515
  } from "./parameter-node-value.js"
515
516
 
516
517
  export {
@@ -746,6 +747,8 @@ export {
746
747
  getLocaleDirection,
747
748
  ensureLocaleCatalogLoaded,
748
749
  registerSidecarLoaders,
750
+ registerCatalogSidecars,
751
+ resetCatalogSidecars,
749
752
  resolveLabel,
750
753
  resolveDescription,
751
754
  entryMatchesQuery,
@@ -762,6 +765,9 @@ export type {
762
765
  WorkflowExportObject,
763
766
  WorkflowExportCreature,
764
767
  WorkflowExportLocation,
768
+ WorkflowMediaRef,
769
+ WorkflowPortability,
770
+ WorkflowImportReport,
765
771
  } from "./workflow-export.js"
766
772
  export { stripExportContent } from "./workflow-export.js"
767
773
 
@@ -860,6 +866,8 @@ export * from "./reduce-strategy-registry.js"
860
866
  export {
861
867
  COMBINE_TRANSITIONS,
862
868
  COMBINE_TRANSITION_IDS,
869
+ PICKER_TO_COMBINE_TRANSITION,
870
+ resolveSlideshowTransition,
863
871
  COMBINE_TRANSITION_GROUP_ORDER,
864
872
  COMBINE_TRANSITION_GROUP_LABELS,
865
873
  getCombineTransition,
@@ -886,6 +894,8 @@ export {
886
894
  FAN_OUT_EACH_TYPES,
887
895
  } from "./producer-types.js"
888
896
 
897
+ export { SUNO_TRACK_SOURCE_TYPES } from "./suno-track-sources.js"
898
+
889
899
  export {
890
900
  VOICE_CHANGER_MODELS,
891
901
  VOICE_CHANGER_MODEL_IDS,
@@ -953,3 +963,22 @@ export * from "./smart-cut-windows.js"
953
963
 
954
964
  export * from "./entity-asset-types.js"
955
965
  export * from "./hint-graph-types.js"
966
+
967
+ // --- Tag-free /v1/catalogs projection wire shape (the ONLY catalog type in shared) ---
968
+ export * from "./catalog-projection.js"
969
+
970
+ // --- Organizations (second tenancy axis): wire contract only — enums, settings request schemas, error codes ---
971
+ export * from "./organizations/index.js"
972
+
973
+ export {
974
+ ENTITY_DB_ID_FIELD,
975
+ ENTITY_NAME_FIELD,
976
+ ENTITY_TABLE,
977
+ ENTITY_BUCKET_FIELDS,
978
+ ENTITY_KIND_SCALAR_FIELDS,
979
+ ENTITY_SCALAR_FIELDS,
980
+ entityScalarFields,
981
+ entityHydrationColumns,
982
+ } from "./entity-node-fields.js"
983
+ export { ENTITY_NODE_KINDS } from "./entity-node-fields.js"
984
+ export type { EntityNodeKind } from "./entity-node-fields.js"
package/src/llm-models.ts CHANGED
@@ -529,6 +529,9 @@ export type LlmFeature =
529
529
  // feature (not ai-writer, which it used to piggyback on) so the model
530
530
  // default and the tiered credit ids are the strategy's own.
531
531
  | "pick-best-llm"
532
+ // In-app Workflow Copilot turns (backend agent loop; metered, reservation
533
+ // ceiling under `STATIC_CREDIT_COSTS["workflow-copilot"]`).
534
+ | "workflow-copilot"
532
535
 
533
536
  /** Engine-dependent LlmFeature for the motion-graphics node (design §8: every credit-id site must branch on engine). */
534
537
  export function motionGraphicsFeature(engine?: string): LlmFeature {
@@ -553,6 +556,7 @@ export const LLM_FEATURE_DEFAULTS: Record<LlmFeature, string> = {
553
556
  "translate": "gemini-3.6-flash",
554
557
  "image-critic": "claude-sonnet-4.6",
555
558
  "pick-best-llm": "claude-sonnet-4.6",
559
+ "workflow-copilot": "claude-sonnet-5",
556
560
  }
557
561
 
558
562
  /**