@slatesvideo/shared 0.5.1 → 0.5.3
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/index.d.ts +1 -0
- package/dist/index.js +3 -0
- package/dist/operations/index.d.ts +34 -2
- package/dist/operations/index.js +186 -22
- package/dist/prompts/index.d.ts +1 -0
- package/dist/prompts/index.js +4 -0
- package/dist/prompts/model-facts.js +18 -2
- package/dist/prompts/prompting-tips.d.ts +23 -0
- package/dist/prompts/prompting-tips.js +345 -0
- package/dist/skills/content.js +7 -6
- package/package.json +1 -1
- package/skills/slates-content-policy.md +14 -1
- package/skills/slates-cost-discipline.md +2 -0
- package/skills/slates-model-selection.md +9 -5
- package/skills/slates-one-prompt-film.md +1 -1
- package/skills/slates-prompting-omni-flash.md +44 -0
- package/skills/slates-prompting-seedance.md +1 -1
- package/skills/slates-prompting-veo-3.md +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -5,4 +5,5 @@ export { SKILLS } from './skills/content.js';
|
|
|
5
5
|
export * as operations from './operations/index.js';
|
|
6
6
|
export { ALL_OPERATIONS, VIDEO_MODELS, defaultContext, type Operation, type OperationContext, type OperationResult } from './operations/index.js';
|
|
7
7
|
export { MODEL_FACTS, getModelFact, type ModelFact } from './prompts/model-facts.js';
|
|
8
|
+
export { PROMPTING_TIPS, getPromptingTips, type PromptingTipsEntry, type PromptingTipCard, type PromptingTipsKey } from './prompts/prompting-tips.js';
|
|
8
9
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -8,4 +8,7 @@ export { ALL_OPERATIONS, VIDEO_MODELS, defaultContext } from './operations/index
|
|
|
8
8
|
// prompt derives its MODEL ROUTING doctrine from (kind: image vs video,
|
|
9
9
|
// default/premium/niche notes). Edit model-facts.ts, never prose copies.
|
|
10
10
|
export { MODEL_FACTS, getModelFact } from './prompts/model-facts.js';
|
|
11
|
+
// Per-model prompting tips — the SSOT for the desktop "See prompting tips"
|
|
12
|
+
// modals. The desktop renders these; it never hand-writes tips content.
|
|
13
|
+
export { PROMPTING_TIPS, getPromptingTips } from './prompts/prompting-tips.js';
|
|
11
14
|
//# sourceMappingURL=index.js.map
|
|
@@ -67,6 +67,7 @@ export declare const uploadReferenceImage: Operation<{
|
|
|
67
67
|
projectId: string;
|
|
68
68
|
filePath?: string;
|
|
69
69
|
dataUrl?: string;
|
|
70
|
+
type?: 'image' | 'video';
|
|
70
71
|
}>;
|
|
71
72
|
export declare const listFolders: Operation<{
|
|
72
73
|
projectId: string;
|
|
@@ -169,7 +170,7 @@ export declare const editImage: Operation<{
|
|
|
169
170
|
confirm?: boolean;
|
|
170
171
|
background?: boolean;
|
|
171
172
|
}>;
|
|
172
|
-
export declare const VIDEO_MODELS: readonly ["kling-v3.0-std", "kling-v3.0-pro", "kling-v3.0-omni", "veo-3.1-fast", "veo-3.1-standard", "seedance-2"];
|
|
173
|
+
export declare const VIDEO_MODELS: readonly ["kling-v3.0-std", "kling-v3.0-pro", "kling-v3.0-omni", "veo-3.1-fast", "veo-3.1-standard", "seedance-2", "omni-flash"];
|
|
173
174
|
type VideoModel = (typeof VIDEO_MODELS)[number];
|
|
174
175
|
export declare function videoCostKey(input: {
|
|
175
176
|
model: VideoModel;
|
|
@@ -184,6 +185,7 @@ export declare function videoCostKey(input: {
|
|
|
184
185
|
videoRefSeconds?: number;
|
|
185
186
|
}): string;
|
|
186
187
|
export declare function klingEditCostKey(model: 'kling-v3.0-omni-edit' | 'kling-v3.0-omni-pro-edit', duration: number): string;
|
|
188
|
+
export declare function omniFlashEditCostKey(duration: number): string;
|
|
187
189
|
export declare const generateVideo: Operation<{
|
|
188
190
|
prompt: string;
|
|
189
191
|
model: string;
|
|
@@ -255,13 +257,19 @@ export declare const editVideo: Operation<{
|
|
|
255
257
|
projectId: string;
|
|
256
258
|
sourceVideoAssetId: string;
|
|
257
259
|
prompt: string;
|
|
258
|
-
model?: 'kling-v3.0-omni-edit' | 'kling-v3.0-omni-pro-edit';
|
|
260
|
+
model?: 'kling-v3.0-omni-edit' | 'kling-v3.0-omni-pro-edit' | 'omni-flash-edit';
|
|
259
261
|
characterAssetIds?: string[];
|
|
260
262
|
styleAssetIds?: string[];
|
|
261
263
|
keepAudio?: boolean;
|
|
262
264
|
background?: boolean;
|
|
263
265
|
confirm?: boolean;
|
|
264
266
|
}>;
|
|
267
|
+
export declare const trimVideo: Operation<{
|
|
268
|
+
projectId: string;
|
|
269
|
+
assetId: string;
|
|
270
|
+
inSec?: number;
|
|
271
|
+
outSec: number;
|
|
272
|
+
}>;
|
|
265
273
|
export declare const getGenerationStatus: Operation<{
|
|
266
274
|
generationId: string;
|
|
267
275
|
waitSeconds?: number;
|
|
@@ -289,6 +297,30 @@ export declare const reorderClips: Operation<{
|
|
|
289
297
|
export declare const removeClip: Operation<{
|
|
290
298
|
clipId: string;
|
|
291
299
|
}>;
|
|
300
|
+
export declare const addTimelineTrack: Operation<{
|
|
301
|
+
projectId: string;
|
|
302
|
+
type?: 'video' | 'audio';
|
|
303
|
+
name?: string;
|
|
304
|
+
}>;
|
|
305
|
+
export declare const updateTimelineTrack: Operation<{
|
|
306
|
+
projectId: string;
|
|
307
|
+
trackId: string;
|
|
308
|
+
name?: string;
|
|
309
|
+
muted?: boolean;
|
|
310
|
+
locked?: boolean;
|
|
311
|
+
volume?: number;
|
|
312
|
+
}>;
|
|
313
|
+
export declare const removeTimelineTrack: Operation<{
|
|
314
|
+
projectId: string;
|
|
315
|
+
trackId: string;
|
|
316
|
+
}>;
|
|
317
|
+
export declare const updateTimelineSettings: Operation<{
|
|
318
|
+
projectId: string;
|
|
319
|
+
width?: number;
|
|
320
|
+
height?: number;
|
|
321
|
+
frameRate?: 24 | 30 | 60;
|
|
322
|
+
masterVolume?: number;
|
|
323
|
+
}>;
|
|
292
324
|
export declare const exportVideo: Operation<{
|
|
293
325
|
projectId?: string;
|
|
294
326
|
timelineId?: string;
|
package/dist/operations/index.js
CHANGED
|
@@ -439,12 +439,16 @@ export const getAssetVideoFrames = {
|
|
|
439
439
|
};
|
|
440
440
|
export const uploadReferenceImage = {
|
|
441
441
|
id: 'slates_upload_reference_image',
|
|
442
|
-
description: 'Add a reference image to a Slates project. Pass either filePath (absolute path to a local file) or dataUrl (base64 data: URL) — exactly one.',
|
|
442
|
+
description: 'Add a reference image OR video clip to a Slates project. Pass either filePath (absolute path to a local file) or dataUrl (base64 data: URL) — exactly one. Set type:"video" on a filePath import to bring in a clip (the user\'s own footage to edit/relocate/trim); imported videos are probed on ingest, so duration + dimensions are available immediately. Default type is "image". dataUrl is image-only.',
|
|
443
443
|
input: z
|
|
444
444
|
.object({
|
|
445
445
|
projectId: z.string().uuid(),
|
|
446
446
|
filePath: z.string().optional(),
|
|
447
447
|
dataUrl: z.string().optional(),
|
|
448
|
+
type: z
|
|
449
|
+
.enum(['image', 'video'])
|
|
450
|
+
.optional()
|
|
451
|
+
.describe('Asset kind for a filePath import — "image" (default) or "video". A dataUrl is always an image.'),
|
|
448
452
|
})
|
|
449
453
|
.refine((d) => !!d.filePath !== !!d.dataUrl, {
|
|
450
454
|
message: 'Pass exactly one of filePath or dataUrl',
|
|
@@ -455,10 +459,13 @@ export const uploadReferenceImage = {
|
|
|
455
459
|
const r = await desktop.post('/agent/assets/upload', {
|
|
456
460
|
projectId: input.projectId,
|
|
457
461
|
filePath: input.filePath,
|
|
458
|
-
type: 'image',
|
|
462
|
+
type: input.type ?? 'image',
|
|
459
463
|
});
|
|
460
464
|
return ok(r);
|
|
461
465
|
}
|
|
466
|
+
if (input.type === 'video') {
|
|
467
|
+
throw new Error('dataUrl uploads are image-only — pass a filePath to import a video clip.');
|
|
468
|
+
}
|
|
462
469
|
const r = await desktop.post('/agent/assets/upload-base64', {
|
|
463
470
|
projectId: input.projectId,
|
|
464
471
|
dataUrl: input.dataUrl,
|
|
@@ -1204,6 +1211,7 @@ export const VIDEO_MODELS = [
|
|
|
1204
1211
|
'veo-3.1-fast',
|
|
1205
1212
|
'veo-3.1-standard',
|
|
1206
1213
|
'seedance-2',
|
|
1214
|
+
'omni-flash',
|
|
1207
1215
|
];
|
|
1208
1216
|
// Model → registry cost-key. Each provider's keys ship with their own
|
|
1209
1217
|
// shape (verified against /api/agent/models):
|
|
@@ -1264,6 +1272,11 @@ export function videoCostKey(input) {
|
|
|
1264
1272
|
}
|
|
1265
1273
|
return `${tier}-${input.duration}s${input.sound === true ? '-audio' : ''}`;
|
|
1266
1274
|
}
|
|
1275
|
+
if (input.model === 'omni-flash') {
|
|
1276
|
+
// Mirrors omniFlashCreditKey() in slate/src/shared/pricing.ts — flat 720p
|
|
1277
|
+
// rate, audio native + included, no resolution/audio key dimension.
|
|
1278
|
+
return `omni-flash-${input.duration}s`;
|
|
1279
|
+
}
|
|
1267
1280
|
throw new Error(`Unknown video model: ${input.model}`);
|
|
1268
1281
|
}
|
|
1269
1282
|
// Kling O3 video-to-video edit cost key — mirrors klingEditCreditKey() in
|
|
@@ -1274,6 +1287,12 @@ export function klingEditCostKey(model, duration) {
|
|
|
1274
1287
|
const tier = model === 'kling-v3.0-omni-pro-edit' ? 'kling-v3-omni-pro-edit' : 'kling-v3-omni-edit';
|
|
1275
1288
|
return `${tier}-${duration}s`;
|
|
1276
1289
|
}
|
|
1290
|
+
// Omni Flash video-edit cost key — mirrors omniFlashCreditKey() in
|
|
1291
|
+
// slate/src/shared/pricing.ts (must byte-match; checked by the slates-api
|
|
1292
|
+
// pricing-consistency script). Duration is the CEILED source-clip length.
|
|
1293
|
+
export function omniFlashEditCostKey(duration) {
|
|
1294
|
+
return `omni-flash-edit-${duration}s`;
|
|
1295
|
+
}
|
|
1277
1296
|
/**
|
|
1278
1297
|
* Forgiving model-id resolver. Agents routinely paste registry COST keys
|
|
1279
1298
|
* ("kling-v3-standard-8s", "seedance-2-1080p-8s") into the `model` param —
|
|
@@ -1321,6 +1340,9 @@ function resolveVideoModel(raw) {
|
|
|
1321
1340
|
seedance: 'seedance-2',
|
|
1322
1341
|
'veo-3.1': 'veo-3.1-fast',
|
|
1323
1342
|
'veo-3': 'veo-3.1-fast',
|
|
1343
|
+
'gemini-omni-flash': 'omni-flash',
|
|
1344
|
+
'gemini-omni-flash-preview': 'omni-flash',
|
|
1345
|
+
'omni-flash-preview': 'omni-flash',
|
|
1324
1346
|
};
|
|
1325
1347
|
if (aliases[s]) {
|
|
1326
1348
|
out.model = aliases[s];
|
|
@@ -1339,6 +1361,8 @@ function promptingSkillFor(model) {
|
|
|
1339
1361
|
return 'slates-prompting-veo-3';
|
|
1340
1362
|
if (model.startsWith('seedance'))
|
|
1341
1363
|
return 'slates-prompting-seedance';
|
|
1364
|
+
if (model.startsWith('omni-flash'))
|
|
1365
|
+
return 'slates-prompting-omni-flash';
|
|
1342
1366
|
return 'slates-cost-discipline';
|
|
1343
1367
|
}
|
|
1344
1368
|
export const generateVideo = {
|
|
@@ -1346,14 +1370,14 @@ export const generateVideo = {
|
|
|
1346
1370
|
description: 'Generate video via Slates credits. REQUIRED before calling: read slates-model-selection (the routing doctrine), slates-cost-discipline, and the matching per-model prompting skill (slates-prompting-seedance / slates-prompting-kling-v3 / slates-prompting-veo-3) — video models prompt very differently; load them via slates_get_prompting_guide if no skill files are installed. Read slates-content-policy when the scene involves conflict, creatures, crowds, destruction, weapons, or young characters. projectId, aspectRatio, and duration are required (requires_clarification otherwise). Cost > $0.50 returns requires_confirm — pass confirm=true after explicit user OK. Image-to-video via firstFrameAssetId; first+last frames = Veo/Seedance only; ingredients via ingredientAssetIds (Kling Omni / Seedance). Asset params take UUIDs or badge codes ("IMG-A8").',
|
|
1347
1371
|
input: z.object({
|
|
1348
1372
|
prompt: z.string().min(1).max(4000),
|
|
1349
|
-
model: z.string().describe('One of: kling-v3.0-std | kling-v3.0-pro | kling-v3.0-omni | seedance-2 | veo-3.1-fast | veo-3.1-standard. Pass the BASE id — duration and videoResolution are separate params (registry cost keys like "kling-v3-standard-8s" auto-resolve). Route per the slates-model-selection skill: Kling std = general-purpose DEFAULT, Seedance 2 = premium physics/effects/hero tier, Veo = native-synced-audio niche only (16:9, 4/6/8s) — never the default. All are VIDEO-only. For per-call cost, call slates_estimate_generation_cost — never quote prices from memory.'),
|
|
1373
|
+
model: z.string().describe('One of: kling-v3.0-std | kling-v3.0-pro | kling-v3.0-omni | seedance-2 | veo-3.1-fast | veo-3.1-standard | omni-flash. Pass the BASE id — duration and videoResolution are separate params (registry cost keys like "kling-v3-standard-8s" auto-resolve). Route per the slates-model-selection skill: Kling std = general-purpose DEFAULT, Seedance 2 = premium physics/effects/hero tier, Veo = native-synced-audio niche only (16:9, 4/6/8s) — never the default, omni-flash = cheap 720p tier with audio included (3-10s, 16:9/9:16; t2v, single-start-frame i2v, or up to 7 reference images; no last frame / video / audio refs). All are VIDEO-only. For per-call cost, call slates_estimate_generation_cost — never quote prices from memory.'),
|
|
1350
1374
|
projectId: z.string().uuid().optional().describe('Save into this Slates project. Strongly recommended — the desktop UI shows a progress card live and the asset appears when complete.'),
|
|
1351
1375
|
aspectRatio: z.enum(['1:1', '16:9', '9:16', '4:3', '3:4', '21:9', '9:21', '4:5', '5:4', '2:3', '3:2']).optional().describe('Veo locks to 16:9 — passing anything else will be ignored or fail. Kling/Seedance support all.'),
|
|
1352
|
-
duration: z.number().int().min(
|
|
1376
|
+
duration: z.number().int().min(3).max(15).optional().describe('Seconds. Kling: 5-15. Veo: 4, 6, or 8 only (4K only at 8s). Seedance: 4-15. Omni Flash: 3-10. Default 5 if omitted but always be explicit (cost scales linearly).'),
|
|
1353
1377
|
videoResolution: z.enum(['480p', '720p', '1080p', '4k']).optional().describe('Veo + Seedance. Seedance: 480p/720p/1080p/4K (default 1080p; 4K is native, the most expensive). Veo: 720p/1080p same price, 4K more (8s only).'),
|
|
1354
1378
|
firstFrameAssetId: z.string().optional().describe('Starting frame for image-to-video: asset UUID or badge code ("IMG-A8") — codes resolve against the project at call time, so a code the user just spoke is always safe to pass.'),
|
|
1355
1379
|
lastFrameAssetId: z.string().optional().describe('Ending frame (UUID or badge code). Veo and Seedance only. Pairs with firstFrameAssetId for guided transitions.'),
|
|
1356
|
-
ingredientAssetIds: z.array(z.string()).max(9).optional().describe('Visual reference / ingredient assets (UUIDs or badge codes) for Kling Omni or
|
|
1380
|
+
ingredientAssetIds: z.array(z.string()).max(9).optional().describe('Visual reference / ingredient assets (UUIDs or badge codes) for Kling Omni, Seedance, or Omni Flash. Up to 9 (Seedance), 4 (Kling), or 7 (Omni Flash, combined across all ref params).'),
|
|
1357
1381
|
characterAssetIds: z.array(z.string()).optional().describe('Character sheet assets (UUIDs or badge codes) — keeps a character consistent across the shot.'),
|
|
1358
1382
|
environmentAssetIds: z.array(z.string()).optional().describe('Environment grid assets (UUIDs or badge codes) — keeps a location/setting consistent across the shot.'),
|
|
1359
1383
|
styleAssetIds: z.array(z.string()).optional().describe('Style reference assets (UUIDs or badge codes) — locks the visual style of the shot.'),
|
|
@@ -1412,10 +1436,41 @@ export const generateVideo = {
|
|
|
1412
1436
|
missing,
|
|
1413
1437
|
message: `Missing required field(s): ${missing.join(', ')}. ` +
|
|
1414
1438
|
`Read the slates-cost-discipline + ${promptingSkillFor(input.model)} skills, ` +
|
|
1415
|
-
`or ask the user. Veo locks to 16:9. Kling/Seedance support 1:1 16:9 9:16 4:3 3:4 21:9. ` +
|
|
1416
|
-
`Duration: Kling 5-15s, Veo 4/6/8s (4K only at 8s), Seedance 4-15s. Cost scales linearly with duration.`,
|
|
1439
|
+
`or ask the user. Veo locks to 16:9. Kling/Seedance support 1:1 16:9 9:16 4:3 3:4 21:9. Omni Flash: 16:9/9:16 only. ` +
|
|
1440
|
+
`Duration: Kling 5-15s, Veo 4/6/8s (4K only at 8s), Seedance 4-15s, Omni Flash 3-10s. Cost scales linearly with duration.`,
|
|
1417
1441
|
});
|
|
1418
1442
|
}
|
|
1443
|
+
// Omni Flash: 3-10s, 720p only — t2v, single-start-frame i2v, or ref2v
|
|
1444
|
+
// with up to 7 reference IMAGES. No last frame, no video/audio refs.
|
|
1445
|
+
// Validate up front so the agent gets an actionable message instead of
|
|
1446
|
+
// a registry throw.
|
|
1447
|
+
if (input.model === 'omni-flash') {
|
|
1448
|
+
if (input.duration < 3 || input.duration > 10) {
|
|
1449
|
+
return ok({
|
|
1450
|
+
requires_clarification: true,
|
|
1451
|
+
missing: ['duration'],
|
|
1452
|
+
message: `Omni Flash supports 3-10 seconds (you passed ${input.duration}s). Pick a duration in that range.`,
|
|
1453
|
+
});
|
|
1454
|
+
}
|
|
1455
|
+
if (input.lastFrameAssetId || input.videoReferenceAssetId || input.audioReferenceAssetId) {
|
|
1456
|
+
return ok({
|
|
1457
|
+
requires_clarification: true,
|
|
1458
|
+
missing: [],
|
|
1459
|
+
message: 'Omni Flash takes a prompt, an optional start frame, and up to 7 reference IMAGES — last frames and video/audio references are not supported. Drop those, or switch to seedance-2 (video/audio refs, last frame) or veo (last frame).',
|
|
1460
|
+
});
|
|
1461
|
+
}
|
|
1462
|
+
const refCount = (input.ingredientAssetIds?.length ?? 0) +
|
|
1463
|
+
(input.characterAssetIds?.length ?? 0) +
|
|
1464
|
+
(input.environmentAssetIds?.length ?? 0) +
|
|
1465
|
+
(input.styleAssetIds?.length ?? 0);
|
|
1466
|
+
if (refCount > 7) {
|
|
1467
|
+
return ok({
|
|
1468
|
+
requires_clarification: true,
|
|
1469
|
+
missing: [],
|
|
1470
|
+
message: `Omni Flash takes at most 7 reference images combined (you passed ${refCount}). Trim the list.`,
|
|
1471
|
+
});
|
|
1472
|
+
}
|
|
1473
|
+
}
|
|
1419
1474
|
// Veo exists only at discrete durations 4/6/8s, and 4K only at 8s.
|
|
1420
1475
|
// Validate up front so the agent gets an actionable message instead of
|
|
1421
1476
|
// a generic "Model variant not in registry" throw from the cost lookup.
|
|
@@ -1503,7 +1558,7 @@ export const generateVideo = {
|
|
|
1503
1558
|
const entry = registry.models.find((m) => m.model === costKey);
|
|
1504
1559
|
if (!entry) {
|
|
1505
1560
|
throw new Error(`Model variant not in registry: ${costKey}. ` +
|
|
1506
|
-
`Available video models: ${registry.models.filter((m) => m.model.startsWith('kling') || m.model.startsWith('veo') || m.model.startsWith('seedance')).map((m) => m.model).slice(0, 20).join(', ')}`);
|
|
1561
|
+
`Available video models: ${registry.models.filter((m) => m.model.startsWith('kling') || m.model.startsWith('veo') || m.model.startsWith('seedance') || m.model.startsWith('omni-flash')).map((m) => m.model).slice(0, 20).join(', ')}`);
|
|
1507
1562
|
}
|
|
1508
1563
|
const totalCents = creditCost(entry);
|
|
1509
1564
|
// Pre-flight confirm gate. Fires when:
|
|
@@ -1955,15 +2010,15 @@ export const generateMotionTransfer = {
|
|
|
1955
2010
|
// ── Edit video (Kling O3 video-to-video) ────────────────────────
|
|
1956
2011
|
export const editVideo = {
|
|
1957
2012
|
id: 'slates_edit_video',
|
|
1958
|
-
description: 'Edit an EXISTING video clip with one instruction
|
|
2013
|
+
description: 'Edit an EXISTING video clip with one instruction — character swap, environment change, style transfer — in one pass, no masking. Original motion, camera, and audio are preserved; only what the prompt names changes. Use when a clip is ~90% right (fix it, don\'t re-roll it) or to AI-edit the user\'s own footage. Engines: Kling O3 edit (default; 3–15s clips, 720–3840px, subject/style refs via elements) or omni-flash-edit (Gemini Omni Flash; 3–10s clips, 720p output, PROMPT-ONLY — no refs, cheapest seat). Cost = per second of OUTPUT (≈ clip length, rounded UP to the next second): omni-flash-edit ≈ 19¢/s ≈ kling-v3.0-omni-edit ≈ 19¢/s, kling-v3.0-omni-pro-edit ≈ 25¢/s. Subjects to swap IN go as characterAssetIds (frontal + angle images become Kling elements — Kling models only); style refs as styleAssetIds; max 4 combined. The edited clip saves as a NEW asset linked to its parent (chain edits freely). Routing: Kling edit is the default edit tool (element lock + audio intact); omni-flash-edit for cheap prompt-only footage-synced swaps; prefer Seedance edit/relocate only for style-transfer-heavy jobs — see slates-model-selection. Prompting: slates-prompting-kling-v3 §Edit / slates-prompting-omni-flash.',
|
|
1959
2014
|
input: z.object({
|
|
1960
2015
|
projectId: z.string().uuid().describe('Project the source clip lives in.'),
|
|
1961
|
-
sourceVideoAssetId: z.string().describe('The VIDEO asset to edit — UUID or badge code ("VID-V3", bare "V3"); codes resolve against the project at call time. 3–15s clips
|
|
1962
|
-
prompt: z.string().min(1).max(2500).describe('The change, not the whole scene — e.g. "replace the man with @marcus", "make it a rainy night", "turn the street into a neon Tokyo alley". Mention subjects with @name; the transport compiles them to Kling\'s @ElementN notation.'),
|
|
1963
|
-
model: z.enum(['kling-v3.0-omni-edit', 'kling-v3.0-omni-pro-edit']).optional().describe('Default kling-v3.0-omni-edit. Pro (~25¢/s vs ~19¢/s) only for hero shots where fidelity matters.'),
|
|
1964
|
-
characterAssetIds: z.array(z.string()).max(4).optional().describe('Subject/element image assets to swap IN (UUIDs or badge codes). Each becomes a Kling element (@ElementN).'),
|
|
1965
|
-
styleAssetIds: z.array(z.string()).max(4).optional().describe('Style/appearance reference images (@ImageN). Max 4 combined with characterAssetIds.'),
|
|
1966
|
-
keepAudio: z.boolean().optional().describe('Preserve the original audio track (default true).'),
|
|
2016
|
+
sourceVideoAssetId: z.string().describe('The VIDEO asset to edit — UUID or badge code ("VID-V3", bare "V3"); codes resolve against the project at call time. Kling: 3–15s clips; omni-flash-edit: 3–10s.'),
|
|
2017
|
+
prompt: z.string().min(1).max(2500).describe('The change, not the whole scene — e.g. "replace the man with @marcus", "make it a rainy night", "turn the street into a neon Tokyo alley". Mention subjects with @name; the transport compiles them to Kling\'s @ElementN notation (Kling models). For omni-flash-edit keep it simple and add "Keep everything else the same."'),
|
|
2018
|
+
model: z.enum(['kling-v3.0-omni-edit', 'kling-v3.0-omni-pro-edit', 'omni-flash-edit']).optional().describe('Default kling-v3.0-omni-edit. Pro (~25¢/s vs ~19¢/s) only for hero shots where fidelity matters. omni-flash-edit (~19¢/s, 720p, 3–10s) for prompt-only edits — it takes NO character/style refs.'),
|
|
2019
|
+
characterAssetIds: z.array(z.string()).max(4).optional().describe('Subject/element image assets to swap IN (UUIDs or badge codes). Each becomes a Kling element (@ElementN). KLING MODELS ONLY — rejected on omni-flash-edit.'),
|
|
2020
|
+
styleAssetIds: z.array(z.string()).max(4).optional().describe('Style/appearance reference images (@ImageN). Max 4 combined with characterAssetIds. KLING MODELS ONLY — rejected on omni-flash-edit.'),
|
|
2021
|
+
keepAudio: z.boolean().optional().describe('Preserve the original audio track (default true; Kling models only — omni-flash-edit output carries its own audio).'),
|
|
1967
2022
|
background: z.boolean().optional().describe(BACKGROUND_DESCRIBE),
|
|
1968
2023
|
confirm: z.boolean().optional().describe('Set true to bypass the cost confirm gate after the user OKs the spend.'),
|
|
1969
2024
|
}),
|
|
@@ -1974,6 +2029,12 @@ export const editVideo = {
|
|
|
1974
2029
|
await desktop.requireCapability('background-generation', 'background generation');
|
|
1975
2030
|
}
|
|
1976
2031
|
const model = input.model ?? 'kling-v3.0-omni-edit';
|
|
2032
|
+
const isOmniFlashEdit = model === 'omni-flash-edit';
|
|
2033
|
+
// Kling edit: 3–15s source clips; Omni Flash edit: 3–10s.
|
|
2034
|
+
const maxClipSeconds = isOmniFlashEdit ? 10 : 15;
|
|
2035
|
+
if (isOmniFlashEdit && ((input.characterAssetIds?.length ?? 0) > 0 || (input.styleAssetIds?.length ?? 0) > 0)) {
|
|
2036
|
+
throw new Error('omni-flash-edit is prompt-only — it takes no character/style reference images. Drop the refs, or switch to kling-v3.0-omni-edit which supports elements.');
|
|
2037
|
+
}
|
|
1977
2038
|
// Resolve refs (UUIDs or badge codes) against the project AT CALL TIME.
|
|
1978
2039
|
const refInputs = [
|
|
1979
2040
|
{ ref: input.sourceVideoAssetId, role: 'source clip' },
|
|
@@ -2001,11 +2062,12 @@ export const editVideo = {
|
|
|
2001
2062
|
if (!Number.isFinite(clipSeconds) || clipSeconds <= 0) {
|
|
2002
2063
|
throw new Error('Source clip has no recorded duration — cannot quote the edit. Re-import the clip or pick another.');
|
|
2003
2064
|
}
|
|
2004
|
-
if (clipSeconds >
|
|
2005
|
-
throw new Error(`Source clip is ${clipSeconds.toFixed(1)}s —
|
|
2065
|
+
if (clipSeconds > maxClipSeconds + 0.05 || clipSeconds < 2.95) {
|
|
2066
|
+
throw new Error(`Source clip is ${clipSeconds.toFixed(1)}s — ${model} accepts 3–${maxClipSeconds}s. ` +
|
|
2067
|
+
`Trim it first with slates_trim_video (e.g. inSec 0, outSec ${maxClipSeconds}), then edit the trimmed clip.`);
|
|
2006
2068
|
}
|
|
2007
|
-
const billedSeconds = Math.min(
|
|
2008
|
-
const costKey = klingEditCostKey(model, billedSeconds);
|
|
2069
|
+
const billedSeconds = Math.min(maxClipSeconds, Math.max(3, Math.ceil(clipSeconds - 0.05)));
|
|
2070
|
+
const costKey = isOmniFlashEdit ? omniFlashEditCostKey(billedSeconds) : klingEditCostKey(model, billedSeconds);
|
|
2009
2071
|
const cloud = ctx.cloud();
|
|
2010
2072
|
const registry = await cloud.get('/api/agent/models');
|
|
2011
2073
|
const entry = registry.models.find((m) => m.model === costKey);
|
|
@@ -2078,6 +2140,41 @@ export const editVideo = {
|
|
|
2078
2140
|
};
|
|
2079
2141
|
},
|
|
2080
2142
|
};
|
|
2143
|
+
// ── Trim a video to an exact window (fit-to-model primitive) ────
|
|
2144
|
+
export const trimVideo = {
|
|
2145
|
+
id: 'slates_trim_video',
|
|
2146
|
+
description: 'Trim a video asset to an exact [inSec, outSec] window and save the result as a NEW clip linked to the original (the original is untouched). This is the fit-to-model primitive: an 11s clip will not run on omni-flash-edit (3–10s) or Kling edit (3–15s), and a Seedance video reference must be 2–15s — trim it first, then edit/relocate the trimmed clip. EXACT re-encode (not a keyframe-snapped cut) so the result honors hard duration caps to the frame; any phone rotation flag is baked into the pixels in the same pass. The new clip lands with correct duration/width/height immediately. inSec defaults to 0.',
|
|
2147
|
+
input: z.object({
|
|
2148
|
+
projectId: z.string().uuid().describe('Project the clip lives in.'),
|
|
2149
|
+
assetId: z
|
|
2150
|
+
.string()
|
|
2151
|
+
.describe('The VIDEO asset to trim — UUID or badge code ("VID-V3", bare "V3"); resolves against the project at call time.'),
|
|
2152
|
+
inSec: z.number().min(0).optional().describe('Trim start in seconds (default 0).'),
|
|
2153
|
+
outSec: z.number().positive().describe('Trim end in seconds. Must be greater than inSec.'),
|
|
2154
|
+
}),
|
|
2155
|
+
async run(input, ctx) {
|
|
2156
|
+
const desktop = ctx.desktop();
|
|
2157
|
+
const resolved = await resolveAssetRefs(ctx, input.projectId, [input.assetId]);
|
|
2158
|
+
const assetId = resolved.get(input.assetId)?.id ?? input.assetId;
|
|
2159
|
+
const inSec = input.inSec ?? 0;
|
|
2160
|
+
if (input.outSec - inSec < 0.05) {
|
|
2161
|
+
throw new Error('outSec must be at least ~0.1s after inSec.');
|
|
2162
|
+
}
|
|
2163
|
+
const r = await desktop.post('/agent/assets/trim-video', {
|
|
2164
|
+
assetId,
|
|
2165
|
+
inSec,
|
|
2166
|
+
outSec: input.outSec,
|
|
2167
|
+
});
|
|
2168
|
+
const a = r.asset;
|
|
2169
|
+
const name = a?.code ?? a?.id ?? 'new clip';
|
|
2170
|
+
return {
|
|
2171
|
+
text: `Trimmed clip saved as ${name}${a?.label ? ` — ${a.label}` : ''} ` +
|
|
2172
|
+
`(${(input.outSec - inSec).toFixed(1)}s, ${inSec.toFixed(1)}–${input.outSec.toFixed(1)}s). ` +
|
|
2173
|
+
`Edit or generate from it by its new id/code.`,
|
|
2174
|
+
data: { asset: r.asset },
|
|
2175
|
+
};
|
|
2176
|
+
},
|
|
2177
|
+
};
|
|
2081
2178
|
// ── Generation status (background mode) ─────────────────────────
|
|
2082
2179
|
export const getGenerationStatus = {
|
|
2083
2180
|
id: 'slates_get_generation_status',
|
|
@@ -2163,11 +2260,11 @@ export const getTimeline = {
|
|
|
2163
2260
|
};
|
|
2164
2261
|
export const addClipToTimeline = {
|
|
2165
2262
|
id: 'slates_add_clip_to_timeline',
|
|
2166
|
-
description: "Append a video asset from the project to the project's timeline (or place it at an explicit startFrame). Defaults match the desktop UI:
|
|
2263
|
+
description: "Append a video or audio asset from the project to the project's timeline (or place it at an explicit startFrame). Defaults match the desktop UI: video clips go to the end of the first video track; audio clips (music, voiceover, AI audio) go after the last clip on the first AUDIO track and are mixed under the video on export. An empty timeline auto-adopts the first video clip's resolution and frame rate; later higher-resolution clips raise the canvas. Overlapping video clips resolve top-track-wins. Optionally trim with sourceInFrame/sourceOutFrame (frames at the SOURCE fps). Use slates_get_timeline first to see current clips and pick positions.",
|
|
2167
2264
|
input: z.object({
|
|
2168
2265
|
projectId: z.string().uuid(),
|
|
2169
|
-
assetId: z.string().uuid().describe('Video asset already in the project.'),
|
|
2170
|
-
trackId: z.string().uuid().optional().describe('Target track. Default: the first
|
|
2266
|
+
assetId: z.string().uuid().describe('Video or audio asset already in the project.'),
|
|
2267
|
+
trackId: z.string().uuid().optional().describe('Target track (type must match the asset: video asset → video track, audio asset → audio track). Default: the first track of the matching type.'),
|
|
2171
2268
|
startFrame: z.number().int().min(0).optional().describe('Timeline frame to place the clip at. Default: append after the last clip.'),
|
|
2172
2269
|
sourceInFrame: z.number().int().min(0).optional(),
|
|
2173
2270
|
sourceOutFrame: z.number().int().min(1).optional(),
|
|
@@ -2218,6 +2315,66 @@ export const removeClip = {
|
|
|
2218
2315
|
return ok(await desktop.post('/agent/timeline/remove-clip', input));
|
|
2219
2316
|
},
|
|
2220
2317
|
};
|
|
2318
|
+
export const addTimelineTrack = {
|
|
2319
|
+
id: 'slates_add_timeline_track',
|
|
2320
|
+
description: "Add a track to the project's timeline (default: an audio track, for layering voiceover + music + AI audio). The new track is appended below existing tracks. Returns the new track and the full timeline.",
|
|
2321
|
+
input: z.object({
|
|
2322
|
+
projectId: z.string().uuid(),
|
|
2323
|
+
type: z.enum(['video', 'audio']).optional().describe('Default: audio.'),
|
|
2324
|
+
name: z.string().optional().describe("Default: 'Audio N' / 'Video N'."),
|
|
2325
|
+
}),
|
|
2326
|
+
async run(input, ctx) {
|
|
2327
|
+
const desktop = ctx.desktop();
|
|
2328
|
+
await desktop.requireCapability('timeline-tracks', 'timeline tracks + audio mixing');
|
|
2329
|
+
return ok(await desktop.post('/agent/timeline/add-track', input));
|
|
2330
|
+
},
|
|
2331
|
+
};
|
|
2332
|
+
export const updateTimelineTrack = {
|
|
2333
|
+
id: 'slates_update_timeline_track',
|
|
2334
|
+
description: 'Update a timeline track: rename, mute/unmute, lock/unlock, or set its volume fader (linear gain, -∞ to +12 dB). Track volume applies to both preview and MP4 export — audio-track clips are mixed at this gain; a muted video track still shows video but its embedded audio is silenced.',
|
|
2335
|
+
input: z.object({
|
|
2336
|
+
projectId: z.string().uuid(),
|
|
2337
|
+
trackId: z.string().uuid(),
|
|
2338
|
+
name: z.string().optional(),
|
|
2339
|
+
muted: z.boolean().optional(),
|
|
2340
|
+
locked: z.boolean().optional(),
|
|
2341
|
+
volume: z.number().min(0).max(4).optional().describe('Track fader as LINEAR gain: 0 = -∞ (silent), 1 = 0 dB (unity), ~3.98 = +12 dB (max boost).'),
|
|
2342
|
+
}),
|
|
2343
|
+
async run(input, ctx) {
|
|
2344
|
+
const desktop = ctx.desktop();
|
|
2345
|
+
await desktop.requireCapability('timeline-tracks', 'timeline tracks + audio mixing');
|
|
2346
|
+
return ok(await desktop.post('/agent/timeline/update-track', input));
|
|
2347
|
+
},
|
|
2348
|
+
};
|
|
2349
|
+
export const removeTimelineTrack = {
|
|
2350
|
+
id: 'slates_remove_timeline_track',
|
|
2351
|
+
description: 'Remove an EMPTY timeline track (fails if it still has clips, or if it is the last track of its type).',
|
|
2352
|
+
input: z.object({
|
|
2353
|
+
projectId: z.string().uuid(),
|
|
2354
|
+
trackId: z.string().uuid(),
|
|
2355
|
+
}),
|
|
2356
|
+
async run(input, ctx) {
|
|
2357
|
+
const desktop = ctx.desktop();
|
|
2358
|
+
await desktop.requireCapability('timeline-tracks', 'timeline tracks + audio mixing');
|
|
2359
|
+
return ok(await desktop.post('/agent/timeline/remove-track', input));
|
|
2360
|
+
},
|
|
2361
|
+
};
|
|
2362
|
+
export const updateTimelineSettings = {
|
|
2363
|
+
id: 'slates_update_timeline_settings',
|
|
2364
|
+
description: "Update the project timeline's output settings: resolution, frame rate (24/30/60 — all clips are conformed to it on export), and masterVolume, the output fader (linear gain, -∞ to +12 dB) applied to the final mix in both preview and MP4 export (use it to prevent clipping when stacking loud tracks). Note these are normally auto-managed: the first video clip sets fps + resolution, and higher-res clips raise the canvas. Changing frameRate after clips are placed retimes them — avoid unless the timeline is empty.",
|
|
2365
|
+
input: z.object({
|
|
2366
|
+
projectId: z.string().uuid(),
|
|
2367
|
+
width: z.number().int().min(16).optional(),
|
|
2368
|
+
height: z.number().int().min(16).optional(),
|
|
2369
|
+
frameRate: z.union([z.literal(24), z.literal(30), z.literal(60)]).optional(),
|
|
2370
|
+
masterVolume: z.number().min(0).max(4).optional().describe('Output fader as LINEAR gain: 0 = -∞ (silent), 1 = 0 dB (unity), ~3.98 = +12 dB (max boost).'),
|
|
2371
|
+
}),
|
|
2372
|
+
async run(input, ctx) {
|
|
2373
|
+
const desktop = ctx.desktop();
|
|
2374
|
+
await desktop.requireCapability('timeline-tracks', 'timeline tracks + audio mixing');
|
|
2375
|
+
return ok(await desktop.post('/agent/timeline/update-settings', input));
|
|
2376
|
+
},
|
|
2377
|
+
};
|
|
2221
2378
|
// ── Export ──────────────────────────────────────────────────────
|
|
2222
2379
|
const ABSOLUTE_PATH_RE = /^([A-Za-z]:[\\/]|\/)/;
|
|
2223
2380
|
export const exportVideo = {
|
|
@@ -2584,6 +2741,8 @@ function resolveGuideTopic(topic) {
|
|
|
2584
2741
|
return 'slates-prompting-seedream-5-lite';
|
|
2585
2742
|
if (t.startsWith('veo'))
|
|
2586
2743
|
return 'slates-prompting-veo-3';
|
|
2744
|
+
if (t.startsWith('omni-flash') || t.startsWith('gemini-omni') || t === 'omni flash')
|
|
2745
|
+
return 'slates-prompting-omni-flash';
|
|
2587
2746
|
if (t.startsWith('kling-mc'))
|
|
2588
2747
|
return 'slates-prompting-motion-transfer';
|
|
2589
2748
|
if (t === 'edit-video' || t === 'video-edit' || t === 'edit video' || t === 'video edit')
|
|
@@ -2666,6 +2825,7 @@ export const ALL_OPERATIONS = [
|
|
|
2666
2825
|
generateLipSync,
|
|
2667
2826
|
generateMotionTransfer,
|
|
2668
2827
|
editVideo,
|
|
2828
|
+
trimVideo,
|
|
2669
2829
|
editImage,
|
|
2670
2830
|
getGenerationStatus,
|
|
2671
2831
|
listGenerations,
|
|
@@ -2673,6 +2833,10 @@ export const ALL_OPERATIONS = [
|
|
|
2673
2833
|
addClipToTimeline,
|
|
2674
2834
|
reorderClips,
|
|
2675
2835
|
removeClip,
|
|
2836
|
+
addTimelineTrack,
|
|
2837
|
+
updateTimelineTrack,
|
|
2838
|
+
removeTimelineTrack,
|
|
2839
|
+
updateTimelineSettings,
|
|
2676
2840
|
exportVideo,
|
|
2677
2841
|
exportTimelineXml,
|
|
2678
2842
|
revealFile,
|
package/dist/prompts/index.d.ts
CHANGED
package/dist/prompts/index.js
CHANGED
|
@@ -16,4 +16,8 @@ export * from './style-library.js';
|
|
|
16
16
|
export * from './model-facts.js';
|
|
17
17
|
export * from './character-sheet.js';
|
|
18
18
|
export * from './environment-sheet.js';
|
|
19
|
+
// Exported from the `./prompts` subpath (not just the root barrel) because the
|
|
20
|
+
// desktop RENDERER imports the tips — the root barrel re-exports auth.js
|
|
21
|
+
// (node:fs/os/path), which breaks browser bundling. `./prompts` stays Node-free.
|
|
22
|
+
export * from './prompting-tips.js';
|
|
19
23
|
//# sourceMappingURL=index.js.map
|
|
@@ -58,7 +58,7 @@ export const MODEL_FACTS = [
|
|
|
58
58
|
kind: 'video',
|
|
59
59
|
maxRefImages: null,
|
|
60
60
|
maxIngredients: 9, // ingredient images per video gen
|
|
61
|
-
notes: 'PREMIUM video tier — route here the moment physics, effects, destruction, or scale matter, and for hero shots. VIDEO-ONLY: cannot generate standalone images (use NB2/FLUX.2/Seedream for those). Up to 9 ingredient images. Strong I2V / own-footage restyle. Native 4K. Also the PREMIUM engine inside the Motion Transfer and Lip Sync tools (single-pass: driving video / dialogue are native conditioning signals — better motion fidelity, natural speech, voice cloned from a video source; video references bill input+output seconds).',
|
|
61
|
+
notes: 'PREMIUM video tier — route here the moment physics, effects, destruction, or scale matter, and for hero shots. VIDEO-ONLY: cannot generate standalone images (use NB2/FLUX.2/Seedream for those). Up to 9 ingredient images. Strong I2V / own-footage restyle. Native 4K, but 4K VIDEO is a Pro-only tier gate (base maxes at 1080p; server returns PRO_REQUIRED) — default 1080p unless the user is on Pro. Also the PREMIUM engine inside the Motion Transfer and Lip Sync tools (single-pass: driving video / dialogue are native conditioning signals — better motion fidelity, natural speech, voice cloned from a video source; video references bill input+output seconds).',
|
|
62
62
|
},
|
|
63
63
|
{
|
|
64
64
|
id: 'kling-v3',
|
|
@@ -74,7 +74,7 @@ export const MODEL_FACTS = [
|
|
|
74
74
|
kind: 'video',
|
|
75
75
|
maxRefImages: null,
|
|
76
76
|
maxIngredients: 4, // combined subject elements + style refs per edit
|
|
77
|
-
notes: 'VIDEO-TO-VIDEO EDIT
|
|
77
|
+
notes: 'VIDEO-TO-VIDEO EDIT — the REF-DRIVEN edit tool: takes an EXISTING 3–15s clip and changes what the prompt names, with element/style reference images (@ElementN = frontal + angles) locking subject identity; max 4 combined refs. keep_audio preserves the ORIGINAL audio verbatim (spoken words cannot drift) — but video lips can drift slightly against it, and multi-beat instructions get under-executed (7/09 receipt: missed a second action beat Omni Flash edit landed) — ONE beat per pass. Route here when an edit NEEDS reference images or bit-exact audio; for prompt-only footage-synced VFX, omni-flash-edit won the 7/09 fidelity head-to-head. Billed per second of output (≈ clip length, rounded up). Seedance edit/relocate is the alternative for style-transfer-heavy jobs.',
|
|
78
78
|
},
|
|
79
79
|
{
|
|
80
80
|
id: 'veo-3.1',
|
|
@@ -84,6 +84,22 @@ export const MODEL_FACTS = [
|
|
|
84
84
|
maxIngredients: 3,
|
|
85
85
|
notes: 'NICHE, never the default — pick only when native synchronized audio must generate WITH the video in one gen. 16:9 only, 4/6/8s only. Otherwise Kling (default) or Seedance (physics/premium) win.',
|
|
86
86
|
},
|
|
87
|
+
{
|
|
88
|
+
id: 'omni-flash',
|
|
89
|
+
label: 'Gemini Omni Flash',
|
|
90
|
+
kind: 'video',
|
|
91
|
+
maxRefImages: null,
|
|
92
|
+
maxIngredients: 7, // ref2v image_urls; 7 mirrors Google's own reference limit
|
|
93
|
+
notes: 'CHEAP 720p tier with native synced audio included — t2v, single-start-frame i2v, or reference-to-video with up to 7 reference images. 3-10s, 16:9/9:16 only. No last frame, no video/audio references. VIDEO-ONLY. New seat: quality vs Kling/Seedance unproven pending comparison gens — do not route hero shots here; use it for cheap drafts, audio-in-one-gen at low cost, ref2v character consistency trials, and its edit variant.',
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
id: 'omni-flash-edit',
|
|
97
|
+
label: 'Omni Flash Edit',
|
|
98
|
+
kind: 'video',
|
|
99
|
+
maxRefImages: null,
|
|
100
|
+
maxIngredients: 0, // prompt + source clip ONLY — no element/style refs on this endpoint
|
|
101
|
+
notes: 'VIDEO-TO-VIDEO EDIT, prompt-only — THE EDIT-FIDELITY WINNER (7/09 head-to-head vs Kling edit on real talking footage: lips held perfectly, audio near-identical, both action beats landed). Takes an EXISTING 3-10s clip and changes what the prompt names, footage-synced (prop/effect/environment/lighting swaps). Fidelity is EARNED by prompt discipline: ONE short instruction + "Keep everything else the same." — long descriptive prompts DESTROY it (Google-documented + 7/09 receipt). Never name objects as metaphors ("candle-like" → literal candle). Quirk: occasional tail jitter/doubled last speech beat — trim the tail. NO reference images (identity swaps needing refs → Kling edit); bit-exact audio needs → Kling keep_audio or segment-splice. 720p output, cheapest edit seat (~2/3 of Kling edit Std).',
|
|
102
|
+
},
|
|
87
103
|
];
|
|
88
104
|
const FACT_BY_ID = new Map(MODEL_FACTS.map((m) => [m.id, m]));
|
|
89
105
|
export function getModelFact(id) {
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface PromptingTipCard {
|
|
2
|
+
heading: string;
|
|
3
|
+
/** Monospace example line(s). \n renders as a line break. */
|
|
4
|
+
example?: string;
|
|
5
|
+
note: string;
|
|
6
|
+
/** Render highlighted as a critical/mandatory card. */
|
|
7
|
+
critical?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface PromptingTipsEntry {
|
|
10
|
+
/** Family label for the modal title ("Prompting Tips — {label}"). */
|
|
11
|
+
label: string;
|
|
12
|
+
/** Intro paragraphs above the cards. */
|
|
13
|
+
intro: string[];
|
|
14
|
+
/** Two columns of tip cards. */
|
|
15
|
+
columns: [PromptingTipCard[], PromptingTipCard[]];
|
|
16
|
+
/** Footer callout paragraphs. */
|
|
17
|
+
footer?: string[];
|
|
18
|
+
}
|
|
19
|
+
export type PromptingTipsKey = 'seedance' | 'kling' | 'kling-edit' | 'veo' | 'omni-flash' | 'omni-flash-edit' | 'nano-banana' | 'nano-banana-lite';
|
|
20
|
+
export declare const PROMPTING_TIPS: Record<PromptingTipsKey, PromptingTipsEntry>;
|
|
21
|
+
/** Null when no tips exist for the key — callers render an honest fallback. */
|
|
22
|
+
export declare function getPromptingTips(key: string): PromptingTipsEntry | null;
|
|
23
|
+
//# sourceMappingURL=prompting-tips.d.ts.map
|