@slatesvideo/shared 0.7.1 → 0.7.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/clients/cloud.d.ts +4 -0
- package/dist/clients/cloud.js +11 -3
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/manual/content.d.ts +1 -1
- package/dist/manual/content.js +1 -1
- package/dist/manual/index.d.ts +11 -2
- package/dist/manual/index.js +178 -14
- package/dist/operations/index.d.ts +292 -94
- package/dist/operations/index.js +870 -199
- package/dist/operations/surface.d.ts +6 -2
- package/dist/operations/surface.js +35 -5
- package/dist/prompts/agent-doctrine.d.ts +4 -4
- package/dist/prompts/agent-doctrine.js +18 -29
- package/dist/prompts/generation-policy.d.ts +1 -1
- package/dist/prompts/guide-discovery.d.ts +23 -0
- package/dist/prompts/guide-discovery.js +39 -0
- package/dist/prompts/guide-retrieval.js +1 -1
- package/dist/prompts/model-capabilities.d.ts +8 -9
- package/dist/prompts/model-capabilities.js +11 -51
- package/dist/prompts/model-facts.d.ts +2 -2
- package/dist/prompts/model-facts.js +15 -26
- package/dist/prompts/partials.generated.js +6 -3
- package/dist/prompts/prompting-tips.d.ts +1 -1
- package/dist/prompts/prompting-tips.js +21 -63
- package/dist/prompts/search-terms.d.ts +3 -0
- package/dist/prompts/search-terms.js +24 -0
- package/dist/skills/content.js +36 -37
- package/dist/skills/metadata.d.ts +7 -0
- package/dist/skills/metadata.js +29 -0
- package/exports/slates-chatgpt-images/generated/SKILL.md +7 -1
- package/exports/slates-chatgpt-images/generated/slates-chatgpt-images.skill +0 -0
- package/exports/slates-prompt-builder/generated/SKILL.md +28 -16
- package/exports/slates-prompt-builder/generated/reference-character.md +12 -13
- package/exports/slates-prompt-builder/generated/reference-content-policy.md +2 -2
- package/exports/slates-prompt-builder/generated/reference-gpt-image-2-5.md +191 -0
- package/exports/slates-prompt-builder/generated/reference-kling.md +32 -11
- package/exports/slates-prompt-builder/generated/reference-nano-banana.md +24 -6
- package/exports/slates-prompt-builder/generated/reference-omni-flash.md +65 -0
- package/exports/slates-prompt-builder/generated/reference-seedance-2-5.md +362 -0
- package/exports/slates-prompt-builder/generated/reference-seedance.md +34 -4
- package/exports/slates-prompt-builder/generated/slates-prompt-builder-manifest.json +77 -23
- package/exports/slates-prompt-builder/generated/slates-prompt-builder.skill +0 -0
- package/package.json +2 -1
- package/skills/_partials/blender-action-curves.md +24 -0
- package/skills/_partials/cinematic-card.md +1 -1
- package/skills/_partials/iteration-diagnosis.md +5 -0
- package/skills/_partials/model-routing.md +35 -0
- package/skills/_partials/seedance-25-timestamps.md +2 -2
- package/skills/_partials/still-gate.md +2 -2
- package/skills/_partials/thresholds.md +1 -1
- package/skills/slates-blocking-to-prompt.md +15 -13
- package/skills/slates-camera-language.md +45 -7
- package/skills/slates-character-identity.md +8 -6
- package/skills/slates-chatgpt-images.md +7 -1
- package/skills/slates-cinematic-look.md +1 -1
- package/skills/slates-content-policy.md +4 -6
- package/skills/slates-cost-discipline.md +18 -12
- package/skills/slates-dialogue-blocking.md +6 -6
- package/skills/slates-direct-response-ad.md +1 -1
- package/skills/slates-edit-and-iterate.md +12 -4
- package/skills/slates-model-selection.md +82 -90
- package/skills/slates-one-prompt-film.md +1 -1
- package/skills/slates-previs-blocking.md +44 -13
- package/skills/slates-project-organization.md +2 -2
- package/skills/slates-prompting-elevenlabs.md +4 -4
- package/skills/slates-prompting-flux-2-max.md +2 -3
- package/skills/slates-prompting-gpt-image-2-5.md +2 -2
- package/skills/slates-prompting-inworld-tts.md +1 -1
- package/skills/slates-prompting-kling-v3.md +11 -9
- package/skills/slates-prompting-lip-sync.md +15 -15
- package/skills/slates-prompting-ltx-2-5.md +5 -6
- package/skills/slates-prompting-minimax-h3.md +11 -11
- package/skills/slates-prompting-motion-transfer.md +8 -8
- package/skills/slates-prompting-nano-banana-2.md +8 -4
- package/skills/slates-prompting-omni-flash.md +9 -9
- package/skills/slates-prompting-seed-audio.md +24 -4
- package/skills/slates-prompting-seedance-2-5.md +40 -30
- package/skills/slates-prompting-seedance.md +4 -4
- package/skills/slates-prompting-seedream-5-lite.md +6 -6
- package/skills/slates-restyle-from-blocking.md +2 -2
- package/skills/slates-script-craft.md +1 -1
- package/skills/slates-shot-variety.md +1 -1
- package/skills/slates-storyboard-from-script.md +1 -1
- package/skills/slates-style-prompting.md +8 -6
- package/skills/slates-ugc-influencer-ad.md +1 -1
- package/skills/slates-vision-feedback-loop.md +118 -110
- package/skills/slates-prompting-veo-3.md +0 -224
package/dist/manual/index.d.ts
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import { APP_MANUAL } from './content.js';
|
|
2
2
|
export { APP_MANUAL };
|
|
3
|
-
/**
|
|
4
|
-
|
|
3
|
+
/**
|
|
4
|
+
* A reader over one manual text. The package's own reads go through the shipped manual below; the
|
|
5
|
+
* retrieval check (`scripts/app-manual-retrieval-check.mjs`) reads slate's source manual the same way,
|
|
6
|
+
* before the generator has copied it here.
|
|
7
|
+
*/
|
|
8
|
+
export declare function manualReader(manual: string): {
|
|
9
|
+
index: () => string;
|
|
10
|
+
sections: (query?: string) => string;
|
|
11
|
+
};
|
|
12
|
+
export declare const appManualIndex: () => string;
|
|
13
|
+
export declare const appManualSections: (query?: string) => string;
|
|
5
14
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/manual/index.js
CHANGED
|
@@ -1,20 +1,184 @@
|
|
|
1
1
|
import { APP_MANUAL } from './content.js';
|
|
2
2
|
export { APP_MANUAL };
|
|
3
|
-
/**
|
|
4
|
-
|
|
3
|
+
/** Stop here when two sections are returned together (~1.5k tokens). */
|
|
4
|
+
const PAIR_CAP_CHARS = 6000;
|
|
5
|
+
const STOP = new Set(
|
|
6
|
+
// Question words and filler: "that has no video yet" should not steer toward a heading that says "yet".
|
|
7
|
+
'a an and are as at be by can could do does don doesn for from get got had has have how i in into is isn it its just ll me my of on or re s should t than that the then there this to ve what when where which while who why will with won would you your'.split(' '));
|
|
8
|
+
/**
|
|
9
|
+
* One form per word, so the question's word meets the manual's: "saved", "saves" and "save" are one, as
|
|
10
|
+
* are "running" and "run", "categories" and "category". A light stemmer, not Porter: plural, then -ing or
|
|
11
|
+
* -ed, then a doubled final consonant, then a final e. Both sides go through it, so a crude root is fine.
|
|
12
|
+
*/
|
|
13
|
+
function stem(word) {
|
|
14
|
+
let w = word;
|
|
15
|
+
if (w.length > 4 && w.endsWith('ies'))
|
|
16
|
+
w = `${w.slice(0, -3)}y`;
|
|
17
|
+
else if (w.length > 3 && w.endsWith('s') && !w.endsWith('ss'))
|
|
18
|
+
w = w.slice(0, -1);
|
|
19
|
+
if (w.length > 5 && w.endsWith('ing'))
|
|
20
|
+
w = w.slice(0, -3);
|
|
21
|
+
else if (w.length > 4 && w.endsWith('ed'))
|
|
22
|
+
w = w.slice(0, -2);
|
|
23
|
+
const last = w[w.length - 1];
|
|
24
|
+
if (w.length > 3 && last === w[w.length - 2] && !'lsz'.includes(last) && !/[aeiou0-9]/.test(last))
|
|
25
|
+
w = w.slice(0, -1);
|
|
26
|
+
if (w.length > 3 && w.endsWith('e'))
|
|
27
|
+
w = w.slice(0, -1);
|
|
28
|
+
return w;
|
|
29
|
+
}
|
|
30
|
+
/** Lowercase, split, drop stop words, stem. */
|
|
31
|
+
function terms(text) {
|
|
32
|
+
return (text.toLowerCase().match(/[\p{L}\p{N}]+/gu) ?? []).filter((w) => !STOP.has(w)).map(stem);
|
|
33
|
+
}
|
|
34
|
+
const pairs = (list) => new Set(list.slice(1).map((w, i) => `${list[i]} ${w}`));
|
|
35
|
+
const counts = (list) => {
|
|
36
|
+
const m = new Map();
|
|
37
|
+
for (const w of list)
|
|
38
|
+
m.set(w, (m.get(w) ?? 0) + 1);
|
|
39
|
+
return m;
|
|
40
|
+
};
|
|
41
|
+
const clean = (text) => text.replace(/<!--[\s\S]*?-->\n?/g, '').replace(/\n{3,}/g, '\n\n').trim();
|
|
42
|
+
const bare = (heading) => heading.replace(/^#+\s*/, '').trim();
|
|
43
|
+
/** The manual's sections, parsed once per text. */
|
|
44
|
+
function parse(manual) {
|
|
45
|
+
const start = manual.indexOf('<slates_reference>');
|
|
46
|
+
const end = manual.lastIndexOf('</slates_reference>');
|
|
47
|
+
const body = start >= 0 && end > start ? manual.slice(start + '<slates_reference>'.length, end) : manual;
|
|
48
|
+
const out = [];
|
|
49
|
+
let parent = null;
|
|
50
|
+
let current = null;
|
|
51
|
+
let fenced = false;
|
|
52
|
+
const flush = () => {
|
|
53
|
+
if (!current)
|
|
54
|
+
return;
|
|
55
|
+
const text = clean(current.lines.join('\n'));
|
|
56
|
+
const words = new Map();
|
|
57
|
+
for (const w of terms(text))
|
|
58
|
+
words.set(w, (words.get(w) ?? 0) + 1);
|
|
59
|
+
out.push({
|
|
60
|
+
heading: current.heading,
|
|
61
|
+
parent: current.parent,
|
|
62
|
+
level: current.level,
|
|
63
|
+
body: text,
|
|
64
|
+
words,
|
|
65
|
+
headingWords: counts(terms(current.heading)),
|
|
66
|
+
headingPairs: pairs(terms(current.heading)),
|
|
67
|
+
parentWords: new Set(terms(current.parent ?? '')),
|
|
68
|
+
});
|
|
69
|
+
};
|
|
70
|
+
for (const line of body.split(/\r?\n/)) {
|
|
71
|
+
if (/^\s*```/.test(line))
|
|
72
|
+
fenced = !fenced;
|
|
73
|
+
const m = fenced ? null : /^(#{1,4}) (.+)$/.exec(line);
|
|
74
|
+
// `#` (the version header) and `####` (a sub-point) stay inside the section they sit in.
|
|
75
|
+
if (m && (m[1].length === 2 || m[1].length === 3)) {
|
|
76
|
+
flush();
|
|
77
|
+
const level = m[1].length;
|
|
78
|
+
if (level === 2)
|
|
79
|
+
parent = m[2].trim();
|
|
80
|
+
current = { heading: m[2].trim(), level, parent: level === 3 ? parent : null, lines: [line] };
|
|
81
|
+
}
|
|
82
|
+
else if (current)
|
|
83
|
+
current.lines.push(line);
|
|
84
|
+
}
|
|
85
|
+
flush();
|
|
86
|
+
return out.filter((s) => s.body.replace(/^#+ .*$/m, '').trim().length > 0);
|
|
87
|
+
}
|
|
88
|
+
/** A `###` heading without its trailing synonyms: "Timeline: markers (add a marker, …)" is "Timeline: markers", which asks for it. */
|
|
89
|
+
const shortHeading = (heading) => heading.replace(/\s*\([^)]*\)\s*$/, '').trim() || heading;
|
|
90
|
+
/**
|
|
91
|
+
* The map, step one: every `##` surface on one line with the words it answers. Asking for a surface by
|
|
92
|
+
* the words before its dash returns its opening and its sections (step two); asking with the words of a
|
|
93
|
+
* question returns the one section that answers it. Each step is small.
|
|
94
|
+
*/
|
|
95
|
+
function indexOf(all) {
|
|
96
|
+
const lines = [
|
|
97
|
+
'Slates app manual. Ask with the words of the question for the section that answers it, or ask for a surface by its name (the words before the —) for its list of sections.',
|
|
98
|
+
'',
|
|
99
|
+
];
|
|
100
|
+
for (const s of all)
|
|
101
|
+
if (s.level === 2)
|
|
102
|
+
lines.push(`## ${s.heading}`);
|
|
103
|
+
return lines.join('\n');
|
|
104
|
+
}
|
|
105
|
+
/** A surface's own sections, short, for step two. */
|
|
106
|
+
const sectionList = (all, surface) => all.filter((s) => s.parent === surface.heading).map((s) => shortHeading(s.heading)).join(' · ');
|
|
107
|
+
function score(s, qTerms, idf, phrase) {
|
|
108
|
+
let n = 0;
|
|
109
|
+
for (const t of new Set(qTerms)) {
|
|
110
|
+
const w = idf.get(t) ?? 0;
|
|
111
|
+
if (!w)
|
|
112
|
+
continue;
|
|
113
|
+
// A heading word counts 4, a second mention of it 2 more; the surface's words 1; the body up to 1.5.
|
|
114
|
+
const h = s.headingWords.get(t) ?? 0;
|
|
115
|
+
n += w * ((h ? 4 : 0) + (h > 1 ? 2 : 0) + (s.parentWords.has(t) ? 1 : 0) + Math.min(s.words.get(t) ?? 0, 3) * 0.5);
|
|
116
|
+
}
|
|
117
|
+
// Two question words side by side in the heading ("new project", "video from a picture") are the
|
|
118
|
+
// phrasing the heading was written for.
|
|
119
|
+
for (let i = 1; i < qTerms.length; i++) {
|
|
120
|
+
if (s.headingPairs.has(`${qTerms[i - 1]} ${qTerms[i]}`))
|
|
121
|
+
n += 2 * ((idf.get(qTerms[i - 1]) ?? 0) + (idf.get(qTerms[i]) ?? 0));
|
|
122
|
+
}
|
|
123
|
+
if (phrase.length > 3) {
|
|
124
|
+
if (s.heading.toLowerCase().includes(phrase))
|
|
125
|
+
n += 6;
|
|
126
|
+
else if (s.body.toLowerCase().includes(phrase))
|
|
127
|
+
n += 2;
|
|
128
|
+
}
|
|
129
|
+
return n;
|
|
130
|
+
}
|
|
131
|
+
const withContext = (s) => (s.parent ? `## ${s.parent}\n\n${s.body}` : s.body);
|
|
132
|
+
/**
|
|
133
|
+
* With no query, the whole manual. With a query, the best section (a second when it scores within 15%
|
|
134
|
+
* and both fit ~1.5k tokens), then the next headings to ask for. Whole sections only: never a cut
|
|
135
|
+
* sentence, never an invented step.
|
|
136
|
+
*/
|
|
137
|
+
function sectionsFor(manual, all, query) {
|
|
5
138
|
if (!query?.trim())
|
|
6
|
-
return
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
139
|
+
return manual;
|
|
140
|
+
const q = query.trim().toLowerCase();
|
|
141
|
+
const asked = q.replace(/^#+\s*/, '');
|
|
142
|
+
const exact = all.find((s) => s.heading.toLowerCase() === q || bare(s.heading).toLowerCase() === asked) ??
|
|
143
|
+
// A heading without its synonyms ("Timeline: markers"), or a surface by the words before its dash.
|
|
144
|
+
all.find((s) => s.heading.toLowerCase().replace(/\s*\([^)]*\)\s*$/, '') === asked) ??
|
|
145
|
+
all.find((s) => s.level === 2 && s.heading.split(' — ')[0].toLowerCase() === asked);
|
|
146
|
+
if (exact?.level === 3)
|
|
147
|
+
return withContext(exact);
|
|
148
|
+
if (exact) {
|
|
149
|
+
const list = sectionList(all, exact);
|
|
150
|
+
return list ? `${exact.body}\n\nIts sections (ask for one by name, or with the question's words): ${list}` : exact.body;
|
|
151
|
+
}
|
|
152
|
+
const qTerms = terms(query);
|
|
153
|
+
const df = new Map();
|
|
154
|
+
for (const t of new Set(qTerms))
|
|
155
|
+
df.set(t, all.filter((s) => s.words.has(t) || s.headingWords.has(t)).length);
|
|
156
|
+
const idf = new Map([...df].map(([t, d]) => [t, d ? Math.log(1 + all.length / d) : 0]));
|
|
157
|
+
const ranked = all
|
|
158
|
+
.map((s, index) => ({ s, index, score: score(s, qTerms, idf, q) }))
|
|
159
|
+
.filter((r) => r.score > 0)
|
|
160
|
+
.sort((a, b) => b.score - a.score || a.s.body.length - b.s.body.length || a.index - b.index);
|
|
15
161
|
if (!ranked.length)
|
|
16
|
-
return
|
|
17
|
-
|
|
18
|
-
|
|
162
|
+
return `No manual section matches "${query}". Available headings:\n\n${indexOf(all)}`;
|
|
163
|
+
const [best, second] = ranked;
|
|
164
|
+
const picked = [best];
|
|
165
|
+
if (second && second.score >= best.score * 0.85 && best.s.body.length + second.s.body.length <= PAIR_CAP_CHARS)
|
|
166
|
+
picked.push(second);
|
|
167
|
+
const related = ranked.slice(picked.length, picked.length + 4).map((r) => r.s.heading);
|
|
168
|
+
const text = picked.map((r) => withContext(r.s)).join('\n\n');
|
|
169
|
+
return related.length ? `${text}\n\nRelated sections (ask by heading): ${related.join(' · ')}` : text;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* A reader over one manual text. The package's own reads go through the shipped manual below; the
|
|
173
|
+
* retrieval check (`scripts/app-manual-retrieval-check.mjs`) reads slate's source manual the same way,
|
|
174
|
+
* before the generator has copied it here.
|
|
175
|
+
*/
|
|
176
|
+
export function manualReader(manual) {
|
|
177
|
+
let all = null;
|
|
178
|
+
const parsed = () => (all ??= parse(manual));
|
|
179
|
+
return { index: () => indexOf(parsed()), sections: (query) => sectionsFor(manual, parsed(), query) };
|
|
19
180
|
}
|
|
181
|
+
const shipped = manualReader(APP_MANUAL);
|
|
182
|
+
export const appManualIndex = () => shipped.index();
|
|
183
|
+
export const appManualSections = (query) => shipped.sections(query);
|
|
20
184
|
//# sourceMappingURL=index.js.map
|