@slatesvideo/shared 0.6.1 → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/clients/blender.d.ts +50 -0
- package/dist/clients/blender.js +195 -0
- package/dist/operations/index.d.ts +24 -0
- package/dist/operations/index.js +244 -1
- package/dist/prompts/reference-composer.d.ts +57 -0
- package/dist/prompts/reference-composer.js +70 -1
- package/dist/skills/content.js +5 -0
- package/package.json +1 -1
- package/skills/slates-blocking-to-prompt.md +250 -0
- package/skills/slates-camera-language.md +196 -0
- package/skills/slates-dialogue-blocking.md +134 -0
- package/skills/slates-previs-blocking.md +153 -0
- package/skills/slates-restyle-from-blocking.md +121 -0
|
@@ -170,12 +170,23 @@ export function composeReferences(rawPrompt, groups, opts = {}) {
|
|
|
170
170
|
topKeys.push(`${noun} ${joinNums(g.videoNums)} ${tail}`);
|
|
171
171
|
}
|
|
172
172
|
}
|
|
173
|
-
// Reference audio ("Audio 1 is a provided reference.")
|
|
173
|
+
// Reference audio ("Audio 1 is a provided reference."), plus THE WORDS when
|
|
174
|
+
// the user has typed them — see ReferenceGroup.spokenText for why the words
|
|
175
|
+
// have to travel as text as well as audio.
|
|
174
176
|
for (const g of numbered) {
|
|
175
177
|
if (g.kind === 'audio-ref' && g.audioNums.length > 0) {
|
|
176
178
|
const noun = g.audioNums.length === 1 ? 'Audio' : 'Audios';
|
|
177
179
|
const tail = g.audioNums.length === 1 ? 'is a provided reference.' : 'are provided references.';
|
|
178
180
|
topKeys.push(`${noun} ${joinNums(g.audioNums)} ${tail}`);
|
|
181
|
+
// Trimmed, never rewritten: the words between the quotes are the user's
|
|
182
|
+
// exactly as typed. The delimiters are CURLY on purpose — a straight
|
|
183
|
+
// quote inside the user's own line then sits beside them without
|
|
184
|
+
// colliding, so nothing has to be escaped and nothing is edited.
|
|
185
|
+
const spoken = (g.spokenText ?? '').trim();
|
|
186
|
+
if (spoken) {
|
|
187
|
+
const lower = g.audioNums.length === 1 ? 'audio' : 'audios';
|
|
188
|
+
topKeys.push(`The words spoken in ${lower} ${joinNums(g.audioNums)} are exactly: “${spoken}”`);
|
|
189
|
+
}
|
|
179
190
|
}
|
|
180
191
|
}
|
|
181
192
|
// 🚨 A PINNED REFERENCE IMAGE GETS NO KEY LINE, DELIBERATELY (2026-08-10).
|
|
@@ -241,6 +252,64 @@ export function composeReferences(rawPrompt, groups, opts = {}) {
|
|
|
241
252
|
unresolvedTokens,
|
|
242
253
|
};
|
|
243
254
|
}
|
|
255
|
+
/**
|
|
256
|
+
* Translate `@character` mentions into Seed Audio's OWN `@AudioN` notation.
|
|
257
|
+
*
|
|
258
|
+
* 🚨 AN ADAPTER, NOT A SECOND COMPOSER — the same relationship
|
|
259
|
+
* `composeKlingEdit` has to `composeReferences`. Seed Audio does not read
|
|
260
|
+
* "audio 1"; it reads `@Audio1`-`@Audio3`, and a clip the prompt never cites is
|
|
261
|
+
* a clip the model ignores. Attaching a voice without citing it would be the
|
|
262
|
+
* silent-drop failure this repo catalogues by name: attach the reference, get
|
|
263
|
+
* no error, get no warning, and get a request that does nothing with it.
|
|
264
|
+
*
|
|
265
|
+
* It emits the SAME grammar the image composer uses — the first mention
|
|
266
|
+
* becomes `Sarah (@Audio1)`, later ones stay `Sarah` — so the NAME still
|
|
267
|
+
* carries the identity and the citation carries the slot. A voice that is
|
|
268
|
+
* attached but never mentioned gets one short key line instead, exactly as an
|
|
269
|
+
* unmentioned character's image does.
|
|
270
|
+
*
|
|
271
|
+
* Everything else is left as authored: an `@token` that is not one of these
|
|
272
|
+
* voices is not ours to touch.
|
|
273
|
+
*
|
|
274
|
+
* A `null` slot means "this position is a clip the caller cites itself" — it
|
|
275
|
+
* holds its @AudioN number and is otherwise ignored.
|
|
276
|
+
*/
|
|
277
|
+
export function composeVoiceCitations(rawPrompt, voices) {
|
|
278
|
+
if (voices.length === 0)
|
|
279
|
+
return rawPrompt;
|
|
280
|
+
const byNorm = new Map();
|
|
281
|
+
voices.forEach((v, i) => {
|
|
282
|
+
if (v?.token)
|
|
283
|
+
byNorm.set(normToken(v.token), { n: i + 1, name: v.name });
|
|
284
|
+
});
|
|
285
|
+
const seen = new Set();
|
|
286
|
+
const body = rawPrompt.replace(/@([\w-]+)/g, (full, tok) => {
|
|
287
|
+
const key = normToken(`@${tok}`);
|
|
288
|
+
const v = byNorm.get(key);
|
|
289
|
+
if (!v)
|
|
290
|
+
return full;
|
|
291
|
+
if (seen.has(key))
|
|
292
|
+
return v.name;
|
|
293
|
+
seen.add(key);
|
|
294
|
+
return `${v.name} (@Audio${v.n})`;
|
|
295
|
+
});
|
|
296
|
+
const keys = [];
|
|
297
|
+
voices.forEach((v, i) => {
|
|
298
|
+
// A null slot is a clip the CALLER already cited itself (the agent route
|
|
299
|
+
// passes its own `audioReferenceAssetIds` this way). It still occupies its
|
|
300
|
+
// @AudioN position — renumbering would repoint every citation a published
|
|
301
|
+
// CLI build wrote — but it is not ours to name.
|
|
302
|
+
if (!v)
|
|
303
|
+
return;
|
|
304
|
+
if (v.token && seen.has(normToken(v.token)))
|
|
305
|
+
return;
|
|
306
|
+
keys.push(`${v.name} is @Audio${i + 1}.`);
|
|
307
|
+
});
|
|
308
|
+
if (keys.length === 0)
|
|
309
|
+
return body;
|
|
310
|
+
const trimmed = body.trim();
|
|
311
|
+
return trimmed ? `${keys.join(' ')}\n\n${trimmed}` : keys.join(' ');
|
|
312
|
+
}
|
|
244
313
|
/** fal cap: max 4 combined element + style-image references per edit request. */
|
|
245
314
|
export const KLING_EDIT_MAX_REFS = 4;
|
|
246
315
|
/**
|