@slatesvideo/shared 0.6.11 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth.js +2 -2
- package/dist/clients/cloud.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/manual/content.d.ts +1 -1
- package/dist/manual/content.js +1 -1
- package/dist/operations/index.d.ts +817 -16
- package/dist/operations/index.js +1413 -360
- package/dist/operations/surface.d.ts +4 -1
- package/dist/operations/surface.js +41 -10
- package/dist/prompts/ad-presets.d.ts +77 -0
- package/dist/prompts/ad-presets.js +43 -0
- package/dist/prompts/agent-doctrine.js +27 -5
- package/dist/prompts/banned-tokens.d.ts +4 -29
- package/dist/prompts/banned-tokens.js +29 -204
- package/dist/prompts/craft-cards.js +2 -2
- package/dist/prompts/generation-policy.d.ts +41 -0
- package/dist/prompts/generation-policy.js +53 -0
- package/dist/prompts/guide-retrieval.d.ts +9 -0
- package/dist/prompts/guide-retrieval.js +53 -0
- package/dist/prompts/index.d.ts +1 -0
- package/dist/prompts/index.js +1 -0
- package/dist/prompts/model-capabilities.d.ts +18 -1
- package/dist/prompts/model-capabilities.js +72 -19
- package/dist/prompts/model-facts.d.ts +34 -2
- package/dist/prompts/model-facts.js +66 -5
- package/dist/prompts/partials.generated.js +8 -2
- package/dist/prompts/prompting-tips.d.ts +1 -1
- package/dist/prompts/prompting-tips.js +61 -16
- package/dist/prompts/reference-composer.d.ts +2 -0
- package/dist/prompts/reference-composer.js +51 -50
- package/dist/prompts/script-document.d.ts +165 -0
- package/dist/prompts/script-document.js +11 -0
- package/dist/prompts/shot-grammar.d.ts +4 -4
- package/dist/prompts/shot-grammar.js +3 -3
- package/dist/prompts/shot-spec.d.ts +13 -0
- package/dist/prompts/shot-spec.js +23 -5
- package/dist/skills/content.js +27 -24
- package/exports/slates-chatgpt-images/generated/SKILL.md +107 -0
- package/exports/slates-chatgpt-images/generated/slates-chatgpt-images.skill +0 -0
- package/exports/slates-prompt-builder/generated/SKILL.md +1 -1
- package/exports/slates-prompt-builder/generated/reference-character.md +9 -1
- package/exports/slates-prompt-builder/generated/reference-kling.md +3 -3
- package/exports/slates-prompt-builder/generated/reference-nano-banana.md +22 -10
- package/exports/slates-prompt-builder/generated/reference-seedance.md +4 -4
- package/exports/slates-prompt-builder/generated/slates-prompt-builder-manifest.json +17 -17
- package/exports/slates-prompt-builder/generated/slates-prompt-builder.skill +0 -0
- package/package.json +9 -3
- package/skills/_partials/cinematic-card.md +8 -0
- package/skills/_partials/cinematic-routes-short.md +2 -0
- package/skills/_partials/cinematic-tips-short.md +2 -0
- package/skills/_partials/decision-log.md +1 -13
- package/skills/_partials/image-defaults.md +11 -0
- package/skills/_partials/lens-video-split.md +1 -0
- package/skills/_partials/reference-rules-core.md +1 -1
- package/skills/_partials/sheet-tool-defaults.md +6 -0
- package/skills/slates-character-identity.md +9 -1
- package/skills/slates-chatgpt-images.md +107 -0
- package/skills/slates-cinematic-look.md +237 -0
- package/skills/slates-cost-discipline.md +18 -12
- package/skills/slates-direct-response-ad.md +13 -53
- package/skills/slates-edit-and-iterate.md +1 -1
- package/skills/slates-model-selection.md +20 -14
- package/skills/slates-one-prompt-film.md +19 -77
- package/skills/slates-project-organization.md +7 -3
- package/skills/slates-prompting-flux-2-max.md +15 -4
- package/skills/slates-prompting-gpt-image-2-5.md +41 -28
- package/skills/slates-prompting-inworld-tts.md +174 -174
- package/skills/slates-prompting-kling-v3.md +3 -3
- package/skills/slates-prompting-lip-sync.md +1 -1
- package/skills/slates-prompting-minimax-h3.md +30 -17
- package/skills/slates-prompting-motion-transfer.md +1 -1
- package/skills/slates-prompting-nano-banana-2.md +24 -11
- package/skills/slates-prompting-seedance-2-5.md +7 -6
- package/skills/slates-prompting-seedance.md +5 -5
- package/skills/slates-prompting-seedream-5-lite.md +14 -3
- package/skills/slates-prompting-veo-3.md +1 -1
- package/skills/slates-script-craft.md +45 -0
- package/skills/slates-shot-variety.md +11 -40
- package/skills/slates-storyboard-from-script.md +14 -66
- package/skills/slates-style-prompting.md +4 -4
- package/skills/slates-ugc-influencer-ad.md +32 -309
- package/skills/slates-vision-feedback-loop.md +2 -1
|
@@ -74,9 +74,9 @@ const OMNI_FLASH_ASPECT_RATIOS = ['16:9', '9:16'];
|
|
|
74
74
|
/** Seedance (both seats, and the edit row): six — notably NO `4:5`. */
|
|
75
75
|
const SEEDANCE_ASPECT_RATIOS = ['21:9', '16:9', '4:3', '1:1', '3:4', '9:16'];
|
|
76
76
|
/**
|
|
77
|
-
* MiniMax H3,
|
|
78
|
-
* `minimax/h3/text-to-video` and `minimax/h3-max/text-to-video
|
|
79
|
-
* enums. It happens to be the same six Seedance takes; kept as its OWN constant
|
|
77
|
+
* MiniMax H3, all three seats: six. Read off fal's live OpenAPI 2026-08-27 for
|
|
78
|
+
* `minimax/h3/text-to-video` and `minimax/h3-max/text-to-video`, and 2026-09-29
|
|
79
|
+
* for `minimax/h3-max-turbo/text-to-video` — identical enums. It happens to be the same six Seedance takes; kept as its OWN constant
|
|
80
80
|
* because a provider that adds a ratio adds it to ITS family, and sharing the
|
|
81
81
|
* Seedance constant would silently move H3 the next time ByteDance moves.
|
|
82
82
|
*
|
|
@@ -101,6 +101,7 @@ const MINIMAX_H3_ASPECT_RATIOS = ['21:9', '16:9', '4:3', '1:1', '3:4', '9:16'];
|
|
|
101
101
|
*/
|
|
102
102
|
const LTX_2_5_ASPECT_RATIOS = ['16:9', '9:16'];
|
|
103
103
|
export const GPT_QUALITY_TIERS = ['low', 'medium', 'high', 'xhigh', 'max'];
|
|
104
|
+
export const DEFAULT_GPT_QUALITY = 'high';
|
|
104
105
|
export const GPT_BACKGROUNDS = ['auto', 'transparent', 'opaque'];
|
|
105
106
|
// Product output sizes; schema bounds and metering receipt live in the GPT harvest.
|
|
106
107
|
export const GPT_IMAGE_25_SIZES = {
|
|
@@ -221,6 +222,7 @@ export const AGENT_ROUTE_PROVIDER = 'fal';
|
|
|
221
222
|
export const MODEL_CAPABILITIES = {
|
|
222
223
|
// ── Image models ───────────────────────────────────────────────────────────
|
|
223
224
|
'nano-banana-2': {
|
|
225
|
+
defaultImageResolution: '2k',
|
|
224
226
|
imageResolutions: ['1k', '2k', '4k'],
|
|
225
227
|
// fal's nano-banana-2 schema caps `num_images` at 4 (read 2026-09-09). This
|
|
226
228
|
// is the ONLY model that batches: the MCP's headless path (no projectId) asks
|
|
@@ -231,11 +233,13 @@ export const MODEL_CAPABILITIES = {
|
|
|
231
233
|
maxRefImages: 14,
|
|
232
234
|
},
|
|
233
235
|
'nano-banana-2-lite': {
|
|
236
|
+
defaultImageResolution: '1k',
|
|
234
237
|
imageResolutions: ['1k'],
|
|
235
238
|
aspectRatios: FULL_ASPECT_RATIOS,
|
|
236
239
|
maxRefImages: 4, // fal edit endpoint caps input images at 4
|
|
237
240
|
},
|
|
238
241
|
'nano-banana-pro': {
|
|
242
|
+
defaultImageResolution: '2k',
|
|
239
243
|
imageResolutions: ['1k', '2k', '4k'],
|
|
240
244
|
aspectRatios: FULL_ASPECT_RATIOS,
|
|
241
245
|
maxRefImages: 14,
|
|
@@ -276,30 +280,39 @@ export const MODEL_CAPABILITIES = {
|
|
|
276
280
|
// limits either: the MCP's 4,000-character prompt against fal's 32,000, and
|
|
277
281
|
// image quantity, which is a fan-out and has no provider ceiling at all.
|
|
278
282
|
'gpt-image-2-5-flare': {
|
|
283
|
+
defaultImageResolution: '2k',
|
|
279
284
|
imageResolutions: ['2k', '3k', '4k'],
|
|
280
285
|
aspectRatios: ['1:1', '16:9', '9:16', '4:3', '3:4'],
|
|
281
286
|
maxRefImages: 16,
|
|
282
287
|
},
|
|
283
288
|
'gpt-image-2-5-sunburst': {
|
|
289
|
+
defaultImageResolution: '3k',
|
|
284
290
|
imageResolutions: ['2k', '3k', '4k'],
|
|
285
291
|
aspectRatios: ['1:1', '16:9', '9:16', '4:3', '3:4'],
|
|
286
292
|
maxRefImages: 16,
|
|
287
293
|
},
|
|
288
294
|
'flux-2-max': {
|
|
295
|
+
defaultImageResolution: '1k',
|
|
289
296
|
imageResolutions: ['1k', '2k', '4k'],
|
|
290
297
|
aspectRatios: FULL_ASPECT_RATIOS,
|
|
291
298
|
maxRefImages: 4,
|
|
292
299
|
},
|
|
293
300
|
'seedream-5-lite': {
|
|
301
|
+
defaultImageResolution: '2k',
|
|
294
302
|
imageResolutions: ['2k', '3k', '4k'],
|
|
295
303
|
aspectRatios: FULL_ASPECT_RATIOS,
|
|
296
304
|
maxRefImages: 10,
|
|
297
305
|
},
|
|
298
306
|
// ── Kling video ────────────────────────────────────────────────────────────
|
|
307
|
+
// Standard is 720p and Pro is 1080p; 4K is a separate endpoint shared by all
|
|
308
|
+
// four. Kling's own API: "std: ... The output video resolution is 720P.
|
|
309
|
+
// pro: ... The output video resolution is 1080P." The fal Standard endpoint
|
|
310
|
+
// takes no resolution parameter, and every Standard and Omni render we
|
|
311
|
+
// measured came back 1280x720 (2026-09-29). This row said 1080p until then.
|
|
299
312
|
'kling-v3.0-std': {
|
|
300
313
|
aspectRatios: KLING_DIRECT_ASPECT_RATIOS,
|
|
301
314
|
providerAspectRatios: { fal: KLING_FAL_ASPECT_RATIOS },
|
|
302
|
-
videoResolution: { options: ['
|
|
315
|
+
videoResolution: { options: ['720p', '4k'] },
|
|
303
316
|
// 3, not 5. The op claimed "Kling: 5-15" and refused legal 3-4s takes.
|
|
304
317
|
duration: { min: 3, max: 15, mode: 'continuous' },
|
|
305
318
|
maxIngredientImages: 4,
|
|
@@ -314,7 +327,8 @@ export const MODEL_CAPABILITIES = {
|
|
|
314
327
|
'kling-v3.0-omni': {
|
|
315
328
|
aspectRatios: KLING_DIRECT_ASPECT_RATIOS,
|
|
316
329
|
providerAspectRatios: { fal: KLING_FAL_ASPECT_RATIOS },
|
|
317
|
-
|
|
330
|
+
// O3 Standard: 720p, as Standard above. Omni Pro is the 1080p tier.
|
|
331
|
+
videoResolution: { options: ['720p', '4k'] },
|
|
318
332
|
duration: { min: 3, max: 15, mode: 'continuous' },
|
|
319
333
|
maxIngredientImages: 4,
|
|
320
334
|
},
|
|
@@ -435,10 +449,9 @@ export const MODEL_CAPABILITIES = {
|
|
|
435
449
|
// ['480p','720p','1080p']. There is still NO 4K on 2.5 (2.0 is the only
|
|
436
450
|
// Seedance with one), which is what keeps `is4kVideoKey` version-blind.
|
|
437
451
|
//
|
|
438
|
-
// DEFAULT STAYS 720p, deliberately: a 30s take at 1080p is ~
|
|
439
|
-
// against a 1,000-credit welcome grant
|
|
440
|
-
//
|
|
441
|
-
// defaulting to it are different decisions.
|
|
452
|
+
// DEFAULT STAYS 720p, deliberately: a 30s take at 1080p is ~853 credits
|
|
453
|
+
// against a 1,000-credit welcome grant. Reaching a tier and defaulting to it
|
|
454
|
+
// are different decisions.
|
|
442
455
|
videoResolution: { options: ['480p', '720p', '1080p'], default: '720p' },
|
|
443
456
|
duration: { min: 4, max: 30, mode: 'continuous' },
|
|
444
457
|
maxIngredientImages: 30,
|
|
@@ -472,21 +485,25 @@ export const MODEL_CAPABILITIES = {
|
|
|
472
485
|
// NO multimodal reference caps, deliberately: on an edit row the clip IS the
|
|
473
486
|
// canvas and arrives through `sourceVideo`, not as a reference.
|
|
474
487
|
},
|
|
475
|
-
// ── MiniMax H3 (
|
|
488
|
+
// ── MiniMax H3 (three seats on fal — base and Max added 2026-08-27, Max
|
|
489
|
+
// Turbo 2026-09-29) ─────────────────────────────────────────────────────
|
|
476
490
|
//
|
|
477
|
-
// Every value below is READ OFF fal's live OpenAPI, fetched 2026-08-27
|
|
491
|
+
// Every value below is READ OFF fal's live OpenAPI, fetched 2026-08-27, and
|
|
492
|
+
// re-read 2026-09-29 for the Max 1080p tier and the Turbo row:
|
|
478
493
|
// minimax/h3/{text-to-video,image-to-video,reference-to-video}
|
|
479
494
|
// minimax/h3-max/{text-to-video,image-to-video,reference-to-video}
|
|
495
|
+
// minimax/h3-max-turbo/{text-to-video,image-to-video} (reference-to-video 404s)
|
|
480
496
|
// 🚨 CORRECTED 2026-09-09: `minimax/h3-max/reference-to-video` DOES exist —
|
|
481
497
|
// 9 images, 3 videos, 3 audio. The earlier note here said it 404s; the schema
|
|
482
498
|
// had never been read. Both rows now declare the full omni-reference set, and
|
|
483
499
|
// every cap on the Max row was re-read on the Max endpoint rather than copied
|
|
484
500
|
// down from the base row.
|
|
485
501
|
//
|
|
486
|
-
// 🚨 NEVER PREFIX-MATCH THESE
|
|
487
|
-
// `minimax-h3`,
|
|
488
|
-
//
|
|
489
|
-
//
|
|
502
|
+
// 🚨 NEVER PREFIX-MATCH THESE THREE IDS. `minimax-h3-max-turbo` starts with
|
|
503
|
+
// `minimax-h3-max`, which starts with `minimax-h3`, so any `startsWith`
|
|
504
|
+
// swallows a row into its neighbour's branch — a different ladder AND a
|
|
505
|
+
// different price at the tiers they share. Every lookup downstream is an
|
|
506
|
+
// exact-id map, not a prefix.
|
|
490
507
|
'minimax-h3': {
|
|
491
508
|
// fal reference-to-video schema, 2026-09-09: each audio clip is 2-15s.
|
|
492
509
|
referenceAudioDuration: { min: 2, max: 15 },
|
|
@@ -501,7 +518,7 @@ export const MODEL_CAPABILITIES = {
|
|
|
501
518
|
// trained to output and the one every benchmark quotes; 2K is a 2.2x price
|
|
502
519
|
// step and 4K a 2.7x step, and reaching a tier is a different decision from
|
|
503
520
|
// defaulting to it (same reasoning that keeps Seedance 2.5 on 720p).
|
|
504
|
-
videoResolution: { options: ['480p', '768p', '2k', '4k'], default: '768p' },
|
|
521
|
+
videoResolution: { options: ['480p', '768p', '2k', '4k'], default: '768p', upscaledFrom: { '2k': '768p', '4k': '768p' } },
|
|
505
522
|
// 5, not 4. MiniMax's own model card says 4-15s; fal's schema — which is
|
|
506
523
|
// what our request actually hits — says `minimum: 5`. The endpoint wins.
|
|
507
524
|
duration: { min: 5, max: 15, mode: 'continuous' },
|
|
@@ -548,8 +565,28 @@ export const MODEL_CAPABILITIES = {
|
|
|
548
565
|
// arms — quoted off this endpoint, not inherited.
|
|
549
566
|
maxReferenceVideoSeconds: 15,
|
|
550
567
|
maxReferenceAudioSeconds: 15,
|
|
551
|
-
|
|
568
|
+
// 1080P is on all three h3-max endpoints' enum (fal schema, 2026-09-09 and
|
|
569
|
+
// 2026-09-29), described as "1080P latent refinement from a native 768P
|
|
570
|
+
// source": a refinement, not a native generation and not base H3's
|
|
571
|
+
// 2K/4K upscaler. It was keyed 2026-09-09 and pulled 2026-09-10 because the
|
|
572
|
+
// 1080p video-reference token rate was unpublished; fal now states it
|
|
573
|
+
// (see MINIMAX_MAX_REFERENCE). Default stays 768p, the native tier.
|
|
574
|
+
videoResolution: { options: ['480p', '768p', '1080p'], default: '768p' },
|
|
575
|
+
duration: { min: 5, max: 15, mode: 'continuous' },
|
|
576
|
+
},
|
|
577
|
+
'minimax-h3-max-turbo': {
|
|
578
|
+
aspectRatios: MINIMAX_H3_ASPECT_RATIOS,
|
|
579
|
+
// fal schema for both Turbo endpoints, 2026-09-29: enum
|
|
580
|
+
// ["480P","768P","1080P"], default "768P", the same 1080P "latent
|
|
581
|
+
// refinement from a native 768P source" as the Max row.
|
|
582
|
+
videoResolution: { options: ['480p', '768p', '1080p'], default: '768p' },
|
|
583
|
+
// duration: integer, minimum 5, maximum 15, default 5 (both endpoints).
|
|
552
584
|
duration: { min: 5, max: 15, mode: 'continuous' },
|
|
585
|
+
// NO reference capacity: `minimax/h3-max-turbo/reference-to-video` returns
|
|
586
|
+
// 404 from fal's OpenAPI endpoint (2026-09-29), and neither published
|
|
587
|
+
// endpoint carries a reference array. Start and end frames ride
|
|
588
|
+
// image-to-video and live in MODEL_REGISTRY.features.lastFrame.
|
|
589
|
+
maxIngredientImages: 0,
|
|
553
590
|
},
|
|
554
591
|
// ── LTX-2.5 (both seats on fal — added 2026-08-29) ─────────────────────────
|
|
555
592
|
//
|
|
@@ -706,6 +743,12 @@ export function aspectRatiosFor(model, provider) {
|
|
|
706
743
|
return cap.aspectRatios;
|
|
707
744
|
}
|
|
708
745
|
/** Video resolutions a model accepts. A FIXED model reports exactly its one value. */
|
|
746
|
+
/** The native render an upscaled tier is made from, or undefined for a native tier. */
|
|
747
|
+
export function upscaledFrom(model, resolution) {
|
|
748
|
+
if (!resolution)
|
|
749
|
+
return undefined;
|
|
750
|
+
return MODEL_CAPABILITIES[model]?.videoResolution?.upscaledFrom?.[resolution];
|
|
751
|
+
}
|
|
709
752
|
export function videoResolutionsFor(model) {
|
|
710
753
|
const vr = MODEL_CAPABILITIES[model]?.videoResolution;
|
|
711
754
|
if (!vr)
|
|
@@ -928,14 +971,16 @@ export function describeReferenceImageCaps(models) {
|
|
|
928
971
|
}
|
|
929
972
|
/** H3 Max reference accounting, fal's worked tables read 2026-09-09.
|
|
930
973
|
* https://fal.ai/models/minimax/h3-max/reference-to-video
|
|
931
|
-
* 1080p
|
|
974
|
+
* 1080p: fal's page, read 2026-09-29: "768p and 1080p output use the same
|
|
975
|
+
* reference-video token counts." So 1080p takes the 768p figure; it was absent
|
|
976
|
+
* until fal published that sentence, and must never be inferred from output rates.
|
|
932
977
|
*/
|
|
933
978
|
export const MINIMAX_MAX_REFERENCE = {
|
|
934
979
|
freeTokens: 4096,
|
|
935
980
|
imagePixelsPerToken: 1024,
|
|
936
981
|
normalizedImageEdge: 1024,
|
|
937
982
|
audioTokensPerSecond: 80,
|
|
938
|
-
videoTokensPerSecond: { '480p': 2886, '768p': 7459.2 },
|
|
983
|
+
videoTokensPerSecond: { '480p': 2886, '768p': 7459.2, '1080p': 7459.2 },
|
|
939
984
|
};
|
|
940
985
|
export function minimaxMaxReferenceTokens(input) {
|
|
941
986
|
const rate = MINIMAX_MAX_REFERENCE.videoTokensPerSecond[input.resolution];
|
|
@@ -950,4 +995,12 @@ export function minimaxMaxReferenceTokens(input) {
|
|
|
950
995
|
input.videoSeconds * (rate ?? 0) + input.audioSeconds * MINIMAX_MAX_REFERENCE.audioTokensPerSecond -
|
|
951
996
|
MINIMAX_MAX_REFERENCE.freeTokens));
|
|
952
997
|
}
|
|
998
|
+
/** Quotes and generation use the same model default. */
|
|
999
|
+
export function defaultImageResolutionFor(model) {
|
|
1000
|
+
const c = MODEL_CAPABILITIES[model];
|
|
1001
|
+
if (!c?.defaultImageResolution || !c.imageResolutions?.includes(c.defaultImageResolution)) {
|
|
1002
|
+
throw new Error(`Missing or invalid image default for ${model}`);
|
|
1003
|
+
}
|
|
1004
|
+
return c.defaultImageResolution;
|
|
1005
|
+
}
|
|
953
1006
|
//# sourceMappingURL=model-capabilities.js.map
|
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
/** Connected host, not an API model: capabilities are checked at runtime. */
|
|
2
|
+
export declare const CHATGPT_IMAGE_HOST: {
|
|
3
|
+
readonly id: "chatgpt-account";
|
|
4
|
+
readonly label: "ChatGPT";
|
|
5
|
+
readonly note: "Generate with your connected ChatGPT account";
|
|
6
|
+
readonly usage: "Uses your ChatGPT account limits";
|
|
7
|
+
};
|
|
8
|
+
import { type BuiltInTool } from './generation-policy.js';
|
|
9
|
+
/** Authoring presets only: these do not claim hosted ChatGPT API capabilities. */
|
|
10
|
+
export declare const CHATGPT_FRAMING_RATIOS: import("./model-capabilities.js").AspectRatio[];
|
|
11
|
+
export declare function composeChatGptFraming(prompt: string, aspectRatio?: string): string;
|
|
1
12
|
export interface ModelFact {
|
|
2
13
|
id: string;
|
|
3
14
|
label: string;
|
|
@@ -32,8 +43,14 @@ export interface ModelFact {
|
|
|
32
43
|
* best in the world". 2.0 is the specialist for native 4K and for the same
|
|
33
44
|
* resolution cheaper; Kling is the specialist for cost-effective start-frame,
|
|
34
45
|
* performance and lip-sync work and the only engine behind Motion Transfer and
|
|
35
|
-
* Lip Sync. Recorded in the vault's prompting-ssot.md the same day.
|
|
36
|
-
*
|
|
46
|
+
* Lip Sync. Recorded in the vault's prompting-ssot.md the same day.
|
|
47
|
+
*
|
|
48
|
+
* IMAGE (Eric, 2026-09-15): GPT IMAGE 2.5 SUNBURST IS THE DEFAULT IMAGE MODEL, at
|
|
49
|
+
* `high` and 3k, in agent routing as it has been in the app picker since
|
|
50
|
+
* 2026-09-09. Nano Banana 2 keeps the only headless path, so an image call
|
|
51
|
+
* with no project still runs there. Changing the
|
|
52
|
+
* default lives in this tier field; quality/resolution live in model-capabilities.ts.
|
|
53
|
+
* Consumers and generated skill partials derive them. slates-web reads this to order its model lineup
|
|
37
54
|
* and to fail its build when a niche seat is named more often than the default.
|
|
38
55
|
*/
|
|
39
56
|
tier: 'default' | 'specialist' | 'niche';
|
|
@@ -94,6 +111,21 @@ export declare function seedanceTaskIntentWords(prompt: string): string[];
|
|
|
94
111
|
/** Every model that reads reference video and/or audio, for op descriptions. */
|
|
95
112
|
export declare function multimodalRefModels(): string[];
|
|
96
113
|
export declare const MODEL_FACTS: ModelFact[];
|
|
114
|
+
/**
|
|
115
|
+
* The one `default` seat for a kind on the generate route, READ from `tier`.
|
|
116
|
+
* Anything that needs "the default image model" calls this instead of naming
|
|
117
|
+
* one: the op surface and slates-web both hand-typed nano-banana-2 for six days
|
|
118
|
+
* after the app picker moved to Sunburst.
|
|
119
|
+
*/
|
|
120
|
+
export declare function defaultModelFor(kind: ModelFact['kind']): string;
|
|
121
|
+
/**
|
|
122
|
+
* The seat a built-in tool renders on when its caller names no model. Resolves
|
|
123
|
+
* `TOOL_SEAT` (generation-policy.ts, THE home): `'default-image'` follows the
|
|
124
|
+
* default image seat above, a model id pins the tool. The desktop resolves the
|
|
125
|
+
* same table through its generated mirror, so an op description, the skill
|
|
126
|
+
* partial and the handler that bills cannot name different models.
|
|
127
|
+
*/
|
|
128
|
+
export declare function toolModelFor(tool: BuiltInTool): string;
|
|
97
129
|
/**
|
|
98
130
|
* Routing prose for one lane, generated from the SSOT.
|
|
99
131
|
*
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/** Connected host, not an API model: capabilities are checked at runtime. */
|
|
2
|
+
export const CHATGPT_IMAGE_HOST = {
|
|
3
|
+
id: 'chatgpt-account', label: 'ChatGPT',
|
|
4
|
+
note: 'Generate with your connected ChatGPT account',
|
|
5
|
+
usage: 'Uses your ChatGPT account limits',
|
|
6
|
+
};
|
|
1
7
|
// Per-model prompting facts — routing doctrine and the prompt formula, as
|
|
2
8
|
// KNOWLEDGE (for skills + lead-magnet + op descriptions).
|
|
3
9
|
//
|
|
@@ -26,6 +32,19 @@
|
|
|
26
32
|
// Relative cost claims STAY ("dearer than 2.0 at every shared tier") — that is
|
|
27
33
|
// routing. The figures go, because those are data.
|
|
28
34
|
import { MODEL_CAPABILITIES } from './model-capabilities.js';
|
|
35
|
+
import { DEFAULT_IMAGE_SEAT, TOOL_SEAT } from './generation-policy.js';
|
|
36
|
+
/** Authoring presets only: these do not claim hosted ChatGPT API capabilities. */
|
|
37
|
+
export const CHATGPT_FRAMING_RATIOS = MODEL_CAPABILITIES['gpt-image-2-5-sunburst'].aspectRatios;
|
|
38
|
+
export function composeChatGptFraming(prompt, aspectRatio) {
|
|
39
|
+
if (aspectRatio === undefined)
|
|
40
|
+
return prompt;
|
|
41
|
+
if (!CHATGPT_FRAMING_RATIOS.includes(aspectRatio)) {
|
|
42
|
+
throw new Error('Choose a supported ChatGPT framing preset');
|
|
43
|
+
}
|
|
44
|
+
// Reuse may contain our previous appended request. Replace only this exact suffix.
|
|
45
|
+
const base = prompt.replace(/\n\nRequested output framing: \d+:\d+ aspect ratio\.$/, '');
|
|
46
|
+
return `${base}\n\nRequested output framing: ${aspectRatio} aspect ratio.`;
|
|
47
|
+
}
|
|
29
48
|
/**
|
|
30
49
|
* Reference caps for a fact, read out of the capability SSOT.
|
|
31
50
|
*
|
|
@@ -120,7 +139,7 @@ export const MODEL_FACTS = [
|
|
|
120
139
|
{
|
|
121
140
|
id: 'nano-banana-2',
|
|
122
141
|
route: 'generate',
|
|
123
|
-
tier: '
|
|
142
|
+
tier: 'specialist',
|
|
124
143
|
// Gemini 3.1 FLASH Image — verified against the runtime slug map in
|
|
125
144
|
// slate/src/main/api/google.ts. Nano Banana PRO is a different model
|
|
126
145
|
// (gemini-3-pro-image-preview); do not conflate them.
|
|
@@ -128,7 +147,7 @@ export const MODEL_FACTS = [
|
|
|
128
147
|
kind: 'image',
|
|
129
148
|
// 14 = 10 object-fidelity + 4 character-consistency; the categories don't trade.
|
|
130
149
|
...caps('nano-banana-2'),
|
|
131
|
-
notes: '
|
|
150
|
+
notes: 'The all-rounder and the only image seat with a headless path: holds many subjects coherently in one frame, and the start-frame for legible in-scene text. Knowledge cutoff Jan 2025: anything later needs reference images.',
|
|
132
151
|
},
|
|
133
152
|
{
|
|
134
153
|
id: 'nano-banana-2-lite',
|
|
@@ -160,11 +179,11 @@ export const MODEL_FACTS = [
|
|
|
160
179
|
{
|
|
161
180
|
id: 'gpt-image-2-5-sunburst',
|
|
162
181
|
route: 'generate',
|
|
163
|
-
tier: '
|
|
182
|
+
tier: 'default',
|
|
164
183
|
label: 'GPT Image 2.5 Sunburst',
|
|
165
184
|
kind: 'image',
|
|
166
185
|
...caps('gpt-image-2-5-sunburst'),
|
|
167
|
-
notes: 'THE QUALITY GPT IMAGE SEAT — OpenAI\'s most capable image model, higher quality than GPT Image 2, same price as Flare, deliberately SLOWER. Route here
|
|
186
|
+
notes: 'THE QUALITY GPT IMAGE SEAT — OpenAI\'s most capable image model, higher quality than GPT Image 2, same price as Flare, deliberately SLOWER. Route here unless speed is the point: finals, hero frames, photoreal people, and multi-reference edits where every reference must survive into one frame — its widest lead. Explore on Flare, finish on Sunburst.',
|
|
168
187
|
},
|
|
169
188
|
{
|
|
170
189
|
id: 'flux-2-max',
|
|
@@ -293,7 +312,19 @@ export const MODEL_FACTS = [
|
|
|
293
312
|
// from the base row: "Audio cannot be the only reference input; provide at
|
|
294
313
|
// least one reference image or video with it."
|
|
295
314
|
audioRefNeedsCompanion: true,
|
|
296
|
-
notes: 'THE SPEED SEAT, and the DEARER one at the tier they share — never the cheap H3 and never the default. fal\'s post-train of the H3 weights: MEASURED 2026-08-27 at about 12x faster than base H3 on the same prompt and params, queue to finished file, plus a thin vendor-reported quality edge. It
|
|
315
|
+
notes: 'THE SPEED SEAT, and the DEARER one at the tier they share — never the cheap H3 and never the default. fal\'s post-train of the H3 weights: MEASURED 2026-08-27 at about 12x faster than base H3 on the same prompt and params, queue to finished file, plus a thin vendor-reported quality edge. It tops out at a 1080p refinement of its 768p render. It takes the same omni-reference set as base H3 and animates start and end frames — but not both in one call: its reference endpoint has no start/end-frame fields, where base H3\'s does. Never describe this row as taking no image or reference input. Route here when a fast turnaround on text-to-video or a start-frame shot is worth the premium.',
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
id: 'minimax-h3-max-turbo',
|
|
319
|
+
route: 'generate',
|
|
320
|
+
tier: 'specialist',
|
|
321
|
+
label: 'MiniMax H3 Max Turbo',
|
|
322
|
+
kind: 'video',
|
|
323
|
+
// Added 2026-09-29. No reference caps: fal publishes text-to-video and
|
|
324
|
+
// image-to-video for Turbo and its reference-to-video returns 404, so
|
|
325
|
+
// `caps()` returns nulls and the composer refuses references.
|
|
326
|
+
...caps('minimax-h3-max-turbo'),
|
|
327
|
+
notes: 'THE BUDGET SEAT of the MiniMax family: a second fal post-train of the H3 weights, billed at half H3 Max\'s rate at every tier. Its 1080p is a refinement of the native 768p render, not a native 1080p generation. INPUTS ARE FRAMES, NOT REFERENCES: text-to-video and start/end frames only, with no reference endpoint, so reference-driven consistency goes to H3 Max or base H3. Route here for drafts, volume and cheap coverage, then re-run the keeper on H3 Max or a hero seat.',
|
|
297
328
|
},
|
|
298
329
|
{
|
|
299
330
|
id: 'ltx-2-5',
|
|
@@ -362,7 +393,37 @@ for (const kind of ['image', 'video', 'audio']) {
|
|
|
362
393
|
}
|
|
363
394
|
}
|
|
364
395
|
}
|
|
396
|
+
/**
|
|
397
|
+
* The one `default` seat for a kind on the generate route, READ from `tier`.
|
|
398
|
+
* Anything that needs "the default image model" calls this instead of naming
|
|
399
|
+
* one: the op surface and slates-web both hand-typed nano-banana-2 for six days
|
|
400
|
+
* after the app picker moved to Sunburst.
|
|
401
|
+
*/
|
|
402
|
+
export function defaultModelFor(kind) {
|
|
403
|
+
const fact = MODEL_FACTS.find((f) => f.kind === kind && f.route === 'generate' && f.tier === 'default');
|
|
404
|
+
if (!fact)
|
|
405
|
+
throw new Error(`MODEL_FACTS: no default ${kind} seat on the generate route`);
|
|
406
|
+
return fact.id;
|
|
407
|
+
}
|
|
408
|
+
/**
|
|
409
|
+
* The seat a built-in tool renders on when its caller names no model. Resolves
|
|
410
|
+
* `TOOL_SEAT` (generation-policy.ts, THE home): `'default-image'` follows the
|
|
411
|
+
* default image seat above, a model id pins the tool. The desktop resolves the
|
|
412
|
+
* same table through its generated mirror, so an op description, the skill
|
|
413
|
+
* partial and the handler that bills cannot name different models.
|
|
414
|
+
*/
|
|
415
|
+
export function toolModelFor(tool) {
|
|
416
|
+
const seat = TOOL_SEAT[tool];
|
|
417
|
+
return seat === DEFAULT_IMAGE_SEAT ? defaultModelFor('image') : seat;
|
|
418
|
+
}
|
|
365
419
|
const FACT_BY_ID = new Map(MODEL_FACTS.map((m) => [m.id, m]));
|
|
420
|
+
// A pinned tool seat must be a live image model, or the tool quotes and fires
|
|
421
|
+
// an id nothing can render. Asserted at load, like the one-default-per-kind rule.
|
|
422
|
+
for (const [tool, seat] of Object.entries(TOOL_SEAT)) {
|
|
423
|
+
if (seat !== DEFAULT_IMAGE_SEAT && FACT_BY_ID.get(seat)?.kind !== 'image') {
|
|
424
|
+
throw new Error(`TOOL_SEAT: ${tool} is pinned to "${seat}", which is not an image model in MODEL_FACTS`);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
366
427
|
/**
|
|
367
428
|
* Routing prose for one lane, generated from the SSOT.
|
|
368
429
|
*
|
|
@@ -5,12 +5,18 @@
|
|
|
5
5
|
// per-model skills, so the TS consumers and the markdown consumers can
|
|
6
6
|
// no longer disagree. Edit the partial, not this file, not the skills.
|
|
7
7
|
export const PARTIALS = {
|
|
8
|
-
"
|
|
9
|
-
"
|
|
8
|
+
"cinematic-card": "**For a photographic look, use only what this frame needs.** Image models default to clean, evenly lit and fully exposed. Describe what the camera sees, not just gear or mood:\n- **Inspect every reference first.** Write its grade and imperfections in words: darkness, contrast, muddy or true blacks, colour, softness/noise, subject separation. Never grade cleaner or brighter than the look reference unless asked.\n- **One light system** — `low sun behind her`, `her face falls into deep shadow`, `no light in front of her`.\n- **Visible exposure** — `the sky burns out to white`, `dense, slightly crushed shadows`.\n- **Lens name plus effect** — `200mm telephoto`, `peaks loom huge behind her and melt into soft shapes`.\n- **Name every garment and close the foreground.** Omissions invite reference leakage or invented props.\nBind references inline. A scene reference owns the grade; for a look-only reference, write the new scene's light. References are optional. For owned-frame edits, describe only the change and what stays.\n<!-- slates-only -->Use `slates-cinematic-look` with a technique ID or section query for more.<!-- /slates-only -->",
|
|
9
|
+
"cinematic-routes-short": "Two routes: describe a new frame, or change a frame you own. For a new scene, name references where you use them, write the look reference's grade and imperfections in plain words, then describe one light system, visible exposure, lens plus effect, every garment and a closed foreground. Use only what the shot needs. For your own plate, sheet, photo, footage or Blender render, say only what changes and what stays. Never use a released film frame as the edit base; use it as an art-direction brief for a new scene.",
|
|
10
|
+
"cinematic-tips-short": "Image models tend toward clean, evenly lit, fully exposed pictures. For a filmed look, describe what you see: one light source and its effect, a face almost in silhouette, a sky burned white. Name the lens and its visible effect together. Look at every reference first and describe its own darkness, contrast, colour, softness, noise and subject separation. Keep muddy blacks muddy; never clean up or brighten the reference's grade unless that is the change you want. Name every garment and exactly what is in the foreground. Use only what the shot needs; references are optional.",
|
|
11
|
+
"decision-log": "Record production choices in the editable shot fields. Explain only consequential judgments the user did not specify and no field already records: for example, why a particular light or performance register supports the brief. Do not repeat the shot list in prose or turn this explanation into an approval gate. Follow the separate generation authorization policy before spending.",
|
|
12
|
+
"image-defaults": "**Image default:** gpt-image-2-5-sunburst, quality `high`, 3k. User overrides take priority. Without a project, generation uses the headless Nano Banana 2 seat.\n\n| Model | Default resolution |\n|---|---|\n| nano-banana-2 | 2k |\n| nano-banana-2-lite | 1k |\n| nano-banana-pro | 2k |\n| gpt-image-2-5-flare | 2k |\n| gpt-image-2-5-sunburst | 3k |\n| flux-2-max | 1k |\n| seedream-5-lite | 2k |",
|
|
13
|
+
"lens-video-split": "Named lenses, apertures, film stocks and camera bodies (`85mm f/1.4`, `Kodak Portra 400`, `ARRI Alexa 65`) are an image-model lever. On a video model, translate the look instead of pasting the gear list: `85mm f/1.4, Portra 400` becomes `close-up, shallow depth of field, warm natural colors, cinematic texture, film-grain texture`. ByteDance's Seedance 2.0 guide never mentions fps, shutter angle, f-stop or lens millimetres. Its Seedance 2.5 guide does, once: the visual-style line of its own storyboard example names one camera body and one 35 mm cinema lens. On 2.5 a single line like that is vendor-sanctioned; a stacked gear list still is not.",
|
|
14
|
+
"reference-rules-core": "Identity = a few flat-lit neutral angles; one reference per role, named inline; 2-4 refs not 12; describe environments instead of feeding a grid.\n\n1. **2-4 strong references beat both extremes.** Not 1 (warps toward itself), not 12 (averages worse). Start with 2-3 focused refs — each one adds context AND another variable to balance.\n2. **One reference per ROLE, named in the prompt** — identity / style-grade / environment. The model does **not** infer a reference's role from its position in the list; the inline name carries it. Same-role competitors drift (two \"identity\" refs of different people blend into a third face). Slates resolves `@mentions` / `#tags` into numbered citations. You can also bind references directly in scene prose, naming what each image supplies.\n3. **One identity sheet per character, named inline.** A character's identity is a single asset (dominant portrait + body panels), so attach that one asset rather than a pile of views: **fewer competing renderings of a face is better, because the model cannot tell which one is authoritative and averages them.** Slates cites it as `Marcus (image 1)`. **Do NOT hand-write a \"Reference Image Instructions\" block or role essays** (\"use for identity, ignore the outfit, render a neutral expression\") — that drags the sheet's studio lighting and wardrobe into a scene that asked for neither. The prompt leads; the user's words own wardrobe, expression, lighting, and action.\n4. **Flat-light identity refs.** Prep identity references with flat, even, shadowless lighting on a plain neutral background. A studio-lit or scene-lit character sheet bleeds its lighting into every generation — the failure looks like the subject was green-screen-pasted in front of the location. Reference prep beats prompting here.\n5. **Environment: describe it, don't feed a grid.** Default to describing the location in words and let the model build a space that fits the shot. Reserve an environment reference for a mandatory exact-match, and then use ONE clean establishing image with natural ambient light that reads as the location's real light — never a multi-panel grid fed whole.\n6. **Grids: explore, don't input.** Use grids to explore compositions cheaply, then pick a cell. Never feed a grid back in as a reference — the cells share a split detail budget and were generated jointly, so their flaws propagate.\n7. **Reuse the same refs across every shot** in a sequence. Lock a set and keep it; swapping references mid-sequence causes drift, because the model adapts each reference to the current prompt rather than copying it.\n8. **Legible in-shot text → bake it into a still start frame, never trust text-to-video.** Have an image model render the text, then animate from that locked frame. Video models smear type.\n9. **Working from existing media — describe ONLY what changes.** The source already carries its composition, motion, timing, and performance; re-describing them fights the model. Narrate the delta. (Video lane: restyle your own clip while keeping the performance; delayed-VFX on \"video one\"; marker-object insertion; video-as-reference for a series.)\n10. **Style transforms happen in natural language.** By default the source's artistic medium and visual style are inherited. To change it, add a plain-text instruction (\"anime → real person\"). There are no preset pickers, and there is no style slider.",
|
|
10
15
|
"reference-tips-short": "Name each reference inline; never write role essays. Slates does this for you: `@mention` a subject or environment and it composes `Marcus (image 1) in the cafe (image 2)`, citing them in the exact order it sends them. One canonical identity image avoids competing facial renderings; a \"Reference Image Instructions\" block drags reference lighting into your scene. Start with 2-3 focused refs.",
|
|
11
16
|
"references-read-literally": "> **The general law: the model reads a reference literally.**\n> A reference image is not a suggestion. Whatever is baked into it — lighting, medium, texture, symmetry, competing identities — is read as a **property of the subject** and reproduced downstream. A baked rim light tints every shot made from that sheet. A sheet that looks like a 3D game render gets animated like game footage. Two competing renderings of one face get averaged into a third face.\n\nEvery reference rule below is a corollary of that one sentence, which is why \"prep the reference\" beats \"prompt around the reference\" every time:\n\n- **Flat, plain identity refs** — because scene lighting in the sheet becomes scene lighting in the output (Slates' own receipt: a studio-lit sheet produced a subject that looked green-screen-pasted in front of mountains).\n- **One authoritative rendering per subject** — because the model cannot tell which panel is the real one. ByteDance documents this failure directly: multi-view character assets \"confuse the model's character recognition, causing it to generate duplicate characters of the same appearance.\"\n- **No 3D-game-render look in a reference** — the model recognizes the render mood and inherits its motion character, so the *animation* comes out looking like game footage. This is not a taste rule; it is the same literal-reading mechanism applied to the temporal layer.\n- **Break perfect symmetry** — mirrored faces and dead-square framing read as synthetic, and the model preserves that reading rather than correcting it.\n\n**What this means in practice:** when output is wrong in a way that tracks the *subject* rather than the *scene* — the lighting is wrong the same way in every shot, the face drifts, the material looks synthetic everywhere — fix the reference, not the prompt. Prompting around a baked-in property is the expensive way to lose.",
|
|
12
17
|
"seedance-25-timestamps": "**2.0 does not respond to timestamps and answers only to shot numbers. 2.5 responds to\ninteger-second timestamps.** That is ByteDance's own first line under \"Differences from Seedance\n2.0\", and it is why a 30-second take is usable at all: the length is only worth buying if you can\nsay *when* things happen inside it.\n\nBoth formats are valid on 2.5, and you can mix them — `Shot N` blocks for a storyboard whose\npacing you are happy to leave to the model, timestamps when a beat has to land at a moment.\n\n**Three ways to control time, all first-party:**\n\n| Form | Write it like |\n|---|---|\n| **Interval** | `0-3 seconds… 3-7 seconds… 7-15 seconds` or `[1s-4s]… [4s-8s]… [8s-12s]` |\n| **Time point** | *\"Quick left sideways transition at the 5-second mark.\"* |\n| **Relative** | *\"After 3 seconds, everyone around him shakes their head.\"* · *\"The frame freezes for 1 second after he presses the shutter.\"* |\n\n**The rules that come with them:**\n\n- **One second is the smallest unit.** Integers only — no `2.5s`, no frames.\n- **No gaps in the timeline.** `0-3s… 5-6s…` leaves 3-5s unspecified and the model fills it however\n it likes. Intervals must abut: `0-3s`, `3-7s`, `7-15s`.\n- **Budget the plot to the seconds.** Too little content in a range and the model improvises to\n fill it; too much and you get extra cuts or dropped beats. This is the actual craft of a 30s take.\n- **Never time-code a high-frequency action.** *\"Shake your head three times per second\"* is\n explicitly called out as a misuse — timestamps schedule beats, they don't choreograph frames.\n- **Transitions want both halves:** the moment AND the method — *\"At the 5-second mark, the camera\n transitions leftward with a left wipe into a natural dissolve.\"*\n- **Timestamps work on an EDIT too**, and that is where they earn the most: they scope a change in\n time as well as in content — *\"Change the man's action from drinking coffee to mopping the floor\n from 4-6 seconds in Video 1, and leave the rest of the content unchanged.\"* Without a range, a\n whole-clip instruction is applied to the whole clip.\n\nDo **not** carry this back to 2.0, and do not carry Veo's `[00:00-00:02]` bracket syntax into\neither — 2.0 ignores time entirely, and the cross-model syntax swap is its own known failure.",
|
|
13
18
|
"seedance-25-timestamps-short": "Seedance 2.0 ignores timing and answers only to \"Shot 1 / Shot 2\"; 2.5 acts on whole-second timestamps, and that is what makes a 30-second take controllable rather than just long. Three forms work: intervals (\"0-3 seconds…3-7 seconds\"), a point (\"at the 5-second mark\"), or relative (\"after 3 seconds\"). Whole seconds only, no gaps between intervals, and never to choreograph fast repeated motion. They work on edits too, where a range scopes the change: \"…from 4-6 seconds…\".",
|
|
19
|
+
"sheet-tool-defaults": "**What the sheet tools render on** (you do not pick these; omit `model`):\n\n- **Character identity sheet:** `gpt-image-2-5-sunburst` at 3k, quality `high`, one 16:9 image.\n- **Establishing image:** `gpt-image-2-5-sunburst` at 3k, quality `high`, one 16:9 image.\n\nPrice a sheet for that model at 16:9, with resolution and quality left at their defaults. **Never 4K** — no identity gain at sheet scale, wasted spend.",
|
|
14
20
|
"still-gate": "**A visible defect in the still is already a STOP.** Do not animate it. Fix the frame first, then move to motion — and go to motion only when the crop passes the still scan and you genuinely need movement to confirm an uncertain edge, reflection, or object.\n\nThis is a **cost** rule as much as a craft rule: a 1080p/10s premium video generation costs many multiples of an image re-roll, and video is where a defect stops being fixable. Anything wrong in the still gets worse in motion — soft geometry mushes, broken-but-plausible objects fall apart, oily textures start crawling. **Animating a known-bad frame is the single most expensive mistake in the pipeline.** Re-rolling the image is the cheap move; re-rolling the video is not.",
|
|
15
21
|
"thresholds": "<!-- GENERATED from @slatesvideo/shared — do not edit between the markers.\n Source: CONFIRM_CREDITS, DEVIATION_FACTOR and the audio bounds in\n packages/shared/src/operations/index.ts. Every number here is REFUSED by an\n op when a prompt gets it wrong, which is why none of them is typed by hand\n any more: this block replaced four claims that contradicted the code. -->\n\n**The thresholds, from the code that enforces them:**\n\n- **Confirm gate:** above **17 credits** an op returns `requires_confirm` and will not\n proceed until you re-call with `confirm: true`. Below it, announce the cost once and go.\n- **Deviation pause:** the desktop Studio Agent stops and re-asks when projected generation spend\n exceeds the approved plan by more than **20%**. You do not trigger this; the app does.\n- **Seed Audio duration:** **3–120 seconds.** There is no duration\n parameter on the model — the number you pass is written into the prompt AND is what the user is\n billed. Outside that range the op refuses rather than clamping.\n- **Sound Effects duration:** **1–22 seconds**, billed per second, never left for the\n model to pick.\n\nNever quote a credit figure from memory: `slates_estimate_generation_cost` returns the real one.",
|
|
16
22
|
};
|
|
@@ -16,7 +16,7 @@ export interface PromptingTipsEntry {
|
|
|
16
16
|
/** Footer callout paragraphs. */
|
|
17
17
|
footer?: string[];
|
|
18
18
|
}
|
|
19
|
-
export type PromptingTipsKey = 'seedance' | 'seedance-2-5' | 'seedance-2-5-edit' | 'kling' | 'kling-edit' | 'veo' | 'omni-flash' | 'omni-flash-edit' | 'minimax-h3' | 'ltx-2-5' | 'nano-banana' | 'nano-banana-lite' | 'seed-audio' | 'eleven-sfx' | 'inworld-tts-2';
|
|
19
|
+
export type PromptingTipsKey = 'seedance' | 'seedance-2-5' | 'seedance-2-5-edit' | 'kling' | 'kling-edit' | 'veo' | 'omni-flash' | 'omni-flash-edit' | 'minimax-h3' | 'ltx-2-5' | 'nano-banana' | 'nano-banana-lite' | 'gpt-image-2-5' | 'seed-audio' | 'eleven-sfx' | 'inworld-tts-2';
|
|
20
20
|
export declare const PROMPTING_TIPS: Record<PromptingTipsKey, PromptingTipsEntry>;
|
|
21
21
|
/** Null when no tips exist for the key — callers render an honest fallback. */
|
|
22
22
|
export declare function getPromptingTips(key: string): PromptingTipsEntry | null;
|