slotdeck 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +486 -2
- package/dist/deck/numbers.d.ts +14 -0
- package/dist/deck/numbers.js +48 -0
- package/dist/deck/numbers.js.map +1 -0
- package/dist/deck/spec.d.ts +73 -0
- package/dist/deck/spec.js +21 -0
- package/dist/deck/spec.js.map +1 -0
- package/dist/deck/validate.d.ts +49 -0
- package/dist/deck/validate.js +189 -0
- package/dist/deck/validate.js.map +1 -0
- package/dist/generate.d.ts +53 -0
- package/dist/generate.js +44 -0
- package/dist/generate.js.map +1 -0
- package/dist/index.d.ts +42 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -0
- package/dist/llm/gemini.d.ts +39 -0
- package/dist/llm/gemini.js +147 -0
- package/dist/llm/gemini.js.map +1 -0
- package/dist/llm/provider.d.ts +38 -0
- package/dist/llm/provider.js +2 -0
- package/dist/llm/provider.js.map +1 -0
- package/dist/node.d.ts +3 -0
- package/dist/node.js +31 -0
- package/dist/node.js.map +1 -0
- package/dist/plan/assets.d.ts +28 -0
- package/dist/plan/assets.js +80 -0
- package/dist/plan/assets.js.map +1 -0
- package/dist/plan/catalog.d.ts +106 -0
- package/dist/plan/catalog.js +302 -0
- package/dist/plan/catalog.js.map +1 -0
- package/dist/plan/edit.d.ts +31 -0
- package/dist/plan/edit.js +364 -0
- package/dist/plan/edit.js.map +1 -0
- package/dist/plan/plan.d.ts +106 -0
- package/dist/plan/plan.js +243 -0
- package/dist/plan/plan.js.map +1 -0
- package/dist/plan/write.d.ts +39 -0
- package/dist/plan/write.js +179 -0
- package/dist/plan/write.js.map +1 -0
- package/dist/pptx/package.d.ts +48 -0
- package/dist/pptx/package.js +202 -0
- package/dist/pptx/package.js.map +1 -0
- package/dist/pptx/presentation.d.ts +20 -0
- package/dist/pptx/presentation.js +31 -0
- package/dist/pptx/presentation.js.map +1 -0
- package/dist/pptx/xml.d.ts +23 -0
- package/dist/pptx/xml.js +67 -0
- package/dist/pptx/xml.js.map +1 -0
- package/dist/render/chart.d.ts +18 -0
- package/dist/render/chart.js +158 -0
- package/dist/render/chart.js.map +1 -0
- package/dist/render/extract.d.ts +11 -0
- package/dist/render/extract.js +65 -0
- package/dist/render/extract.js.map +1 -0
- package/dist/render/picture.d.ts +20 -0
- package/dist/render/picture.js +114 -0
- package/dist/render/picture.js.map +1 -0
- package/dist/render/render.d.ts +32 -0
- package/dist/render/render.js +247 -0
- package/dist/render/render.js.map +1 -0
- package/dist/render/repeat.d.ts +15 -0
- package/dist/render/repeat.js +118 -0
- package/dist/render/repeat.js.map +1 -0
- package/dist/render/table.d.ts +12 -0
- package/dist/render/table.js +84 -0
- package/dist/render/table.js.map +1 -0
- package/dist/render/text.d.ts +31 -0
- package/dist/render/text.js +210 -0
- package/dist/render/text.js.map +1 -0
- package/dist/store.d.ts +18 -0
- package/dist/store.js +23 -0
- package/dist/store.js.map +1 -0
- package/dist/template/change.d.ts +138 -0
- package/dist/template/change.js +406 -0
- package/dist/template/change.js.map +1 -0
- package/dist/template/check.d.ts +15 -0
- package/dist/template/check.js +97 -0
- package/dist/template/check.js.map +1 -0
- package/dist/template/draft.d.ts +47 -0
- package/dist/template/draft.js +276 -0
- package/dist/template/draft.js.map +1 -0
- package/dist/template/inspect.d.ts +53 -0
- package/dist/template/inspect.js +157 -0
- package/dist/template/inspect.js.map +1 -0
- package/dist/template/instruct.d.ts +26 -0
- package/dist/template/instruct.js +278 -0
- package/dist/template/instruct.js.map +1 -0
- package/dist/template/manifest.d.ts +226 -0
- package/dist/template/manifest.js +116 -0
- package/dist/template/manifest.js.map +1 -0
- package/dist/template/measure.d.ts +80 -0
- package/dist/template/measure.js +212 -0
- package/dist/template/measure.js.map +1 -0
- package/dist/template/sample.d.ts +17 -0
- package/dist/template/sample.js +96 -0
- package/dist/template/sample.js.map +1 -0
- package/dist/template/view.d.ts +46 -0
- package/dist/template/view.js +38 -0
- package/dist/template/view.js.map +1 -0
- package/dist/tools.d.ts +68 -0
- package/dist/tools.js +266 -0
- package/dist/tools.js.map +1 -0
- package/dist/util/image.d.ts +11 -0
- package/dist/util/image.js +58 -0
- package/dist/util/image.js.map +1 -0
- package/dist/util/png.d.ts +2 -0
- package/dist/util/png.js +50 -0
- package/dist/util/png.js.map +1 -0
- package/package.json +63 -4
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
import { DeckValidationError, validateDeck } from '../deck/validate.js';
|
|
2
|
+
import { unstatedChartValues } from '../deck/numbers.js';
|
|
3
|
+
import { isChartValue, isImageRef } from '../deck/spec.js';
|
|
4
|
+
import { TEXT_SIZES, effectiveSlots, itemCount, itemRange } from '../template/manifest.js';
|
|
5
|
+
import { buildCatalog, describeCatalog, planPattern, readItems } from './catalog.js';
|
|
6
|
+
import { PlanError, asker, directionOf, hasFigures } from './plan.js';
|
|
7
|
+
import { cleanText, suppliesText, systemPrompt, writeSlides } from './write.js';
|
|
8
|
+
function describeValue(value) {
|
|
9
|
+
if (value === undefined || value === null)
|
|
10
|
+
return '';
|
|
11
|
+
if (typeof value === 'string')
|
|
12
|
+
return JSON.stringify(value);
|
|
13
|
+
if (Array.isArray(value))
|
|
14
|
+
return JSON.stringify(value);
|
|
15
|
+
if (!isImageRef(value))
|
|
16
|
+
return `${isChartValue(value) ? 'chart' : 'table'} ${JSON.stringify(value)}`;
|
|
17
|
+
return value.prompt ? `picture of ${JSON.stringify(value.prompt)}` : `picture "${value.asset}"`;
|
|
18
|
+
}
|
|
19
|
+
/** The deck as the model sees it: one line per slide with every slot's content. */
|
|
20
|
+
function describeDeck(deck) {
|
|
21
|
+
return deck.slides
|
|
22
|
+
.map((slide, index) => {
|
|
23
|
+
const slots = Object.entries(slide.slots)
|
|
24
|
+
.map(([name, value]) => `${name}: ${describeValue(value)}`)
|
|
25
|
+
.filter((line) => !line.endsWith(': '))
|
|
26
|
+
.join('; ');
|
|
27
|
+
return `${index + 1}. [${slide.pattern}${slide.items !== undefined ? `, ${slide.items} items` : ''}] ${slots}`;
|
|
28
|
+
})
|
|
29
|
+
.join('\n');
|
|
30
|
+
}
|
|
31
|
+
/** A short label for a slide that is not being rewritten, so the model knows what surrounds its work. */
|
|
32
|
+
function slideLabel(slide) {
|
|
33
|
+
const title = slide.slots.title;
|
|
34
|
+
const text = typeof title === 'string' ? title : Object.values(slide.slots).find((value) => typeof value === 'string');
|
|
35
|
+
return text ? JSON.stringify(text) : '';
|
|
36
|
+
}
|
|
37
|
+
function editPlanSchema(patternIds, slideCount, fieldNames, mostItems) {
|
|
38
|
+
const schema = planSchemaBase(patternIds, slideCount);
|
|
39
|
+
const top = schema.properties;
|
|
40
|
+
top.text_size = {
|
|
41
|
+
type: 'string',
|
|
42
|
+
enum: Object.keys(TEXT_SIZES),
|
|
43
|
+
description: 'Size of body text after the change. Repeat the current size unless the request is about text size.',
|
|
44
|
+
};
|
|
45
|
+
schema.required.push('text_size');
|
|
46
|
+
if (mostItems > 0) {
|
|
47
|
+
const entry = top.slides.items.properties;
|
|
48
|
+
entry.items = {
|
|
49
|
+
type: 'integer',
|
|
50
|
+
minimum: 1,
|
|
51
|
+
maximum: mostItems,
|
|
52
|
+
description: 'For a pattern with a row of items: how many items the slide has after the change. Leave it out for other patterns.',
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
if (fieldNames.length > 0) {
|
|
56
|
+
const properties = schema.properties;
|
|
57
|
+
properties.fields = {
|
|
58
|
+
type: 'object',
|
|
59
|
+
description: 'The deck-level texts after the change. Repeat a value exactly unless the request affects it.',
|
|
60
|
+
properties: Object.fromEntries(fieldNames.map((name) => [name, { type: 'string' }])),
|
|
61
|
+
required: fieldNames,
|
|
62
|
+
};
|
|
63
|
+
schema.required.push('fields');
|
|
64
|
+
}
|
|
65
|
+
return schema;
|
|
66
|
+
}
|
|
67
|
+
function planSchemaBase(patternIds, slideCount) {
|
|
68
|
+
return {
|
|
69
|
+
type: 'object',
|
|
70
|
+
properties: {
|
|
71
|
+
summary: { type: 'string', description: 'One sentence saying what you changed, written for the person who asked, in their language' },
|
|
72
|
+
language: { type: 'string', description: 'BCP 47 tag of the deck language after the change' },
|
|
73
|
+
title: { type: 'string', description: 'Title of the deck after the change' },
|
|
74
|
+
slides: {
|
|
75
|
+
type: 'array',
|
|
76
|
+
minItems: 1,
|
|
77
|
+
items: {
|
|
78
|
+
type: 'object',
|
|
79
|
+
properties: {
|
|
80
|
+
from: { type: 'integer', minimum: 0, maximum: slideCount, description: 'Number of the existing slide this slide is based on; 0 for a new slide' },
|
|
81
|
+
pattern: { type: 'string', enum: patternIds },
|
|
82
|
+
change: { type: 'string', description: 'What to write or change on this slide. Empty when the slide stays exactly as it is.' },
|
|
83
|
+
images: { type: 'boolean', description: 'true only when the pictures or icons of this slide should change' },
|
|
84
|
+
},
|
|
85
|
+
required: ['from', 'pattern', 'change', 'images'],
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
required: ['summary', 'language', 'title', 'slides'],
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Applies an instruction such as "shorten slide 3" or "add a slide about pricing" to a deck.
|
|
94
|
+
*
|
|
95
|
+
* Two model calls: the first decides what the deck looks like after the change (which slides
|
|
96
|
+
* stay, move, go, get rewritten or are new); the second writes only the slides that change.
|
|
97
|
+
* Untouched slides are copied by code, so they cannot drift, and pictures are kept unless the
|
|
98
|
+
* instruction is about them.
|
|
99
|
+
*/
|
|
100
|
+
export async function planEdit(template, deck, instruction, options) {
|
|
101
|
+
const { manifest } = template;
|
|
102
|
+
const layout = options.layout ?? 'strict';
|
|
103
|
+
const fields = options.fields ?? deck.fields ?? {};
|
|
104
|
+
const currentLanguage = deck.language ?? manifest.language ?? 'en';
|
|
105
|
+
const definitions = new Map(manifest.patterns.map((pattern) => [pattern.id, pattern]));
|
|
106
|
+
// What new slides may use. Number patterns need figures from the instruction or the original brief.
|
|
107
|
+
const numbers = options.numberPatterns ?? 'from-brief';
|
|
108
|
+
const figures = numbers === 'always' || (numbers === 'from-brief' && hasFigures(`${instruction} ${deck.brief ?? ''}`));
|
|
109
|
+
const context = {
|
|
110
|
+
layout,
|
|
111
|
+
fields,
|
|
112
|
+
icons: options.icons ?? [],
|
|
113
|
+
assets: options.assets ?? [],
|
|
114
|
+
imageDensity: options.imageDensity ?? 'medium',
|
|
115
|
+
figures,
|
|
116
|
+
textScale: deck.textScale ?? 1,
|
|
117
|
+
};
|
|
118
|
+
const currentSize = (Object.entries(TEXT_SIZES).find(([, factor]) => factor === context.textScale)?.[0] ?? 'normal');
|
|
119
|
+
if (options.patterns)
|
|
120
|
+
context.allow = options.patterns;
|
|
121
|
+
const offer = buildCatalog(manifest, context);
|
|
122
|
+
const offered = new Map(offer.patterns.map((pattern) => [pattern.def.id, pattern]));
|
|
123
|
+
// An existing slide keeps its pattern even if that pattern would not be offered for a new slide.
|
|
124
|
+
const existing = [...new Set(deck.slides.map((slide) => slide.pattern))].filter((id) => definitions.has(id) && !offered.has(id));
|
|
125
|
+
const patternIds = [...offered.keys(), ...existing];
|
|
126
|
+
if (patternIds.length === 0)
|
|
127
|
+
throw new PlanError(`No pattern of template "${manifest.name}" can be used`);
|
|
128
|
+
// 1. Plan the edit.
|
|
129
|
+
// Deck-level texts can change too ("translate the deck"), unless the caller fixes them.
|
|
130
|
+
const fieldNames = options.fields ? [] : Object.keys(fields);
|
|
131
|
+
options.onProgress?.({ stage: 'outline' });
|
|
132
|
+
const planRequest = [
|
|
133
|
+
deck.brief ? `The deck was written from this brief:\n${deck.brief}` : '',
|
|
134
|
+
`The deck as it is now${deck.title ? ` ("${deck.title}")` : ''}, in the language with BCP 47 tag "${currentLanguage}", body text size "${currentSize}":\n${describeDeck(deck)}`,
|
|
135
|
+
fieldNames.length > 0
|
|
136
|
+
? `Deck-level texts, shown on several slides:\n${fieldNames.map((name) => `${name}: ${JSON.stringify(fields[name])}`).join('\n')}`
|
|
137
|
+
: '',
|
|
138
|
+
`Requested change:\n${instruction.trim()}`,
|
|
139
|
+
[
|
|
140
|
+
'Return the slides of the deck after the change, in their new order.',
|
|
141
|
+
'- from: the number of the existing slide a slide is based on, or 0 for a new slide. Leave a slide out to delete it.',
|
|
142
|
+
'- pattern: keep the pattern of an existing slide unless the request calls for a different layout.',
|
|
143
|
+
'- change: what to write or change on that slide. Leave it empty for every slide the request does not touch.',
|
|
144
|
+
'- images: true only when the pictures or icons of that slide should change.',
|
|
145
|
+
'- items: for a pattern with a row of items, the number the slide has after the change.',
|
|
146
|
+
].join('\n'),
|
|
147
|
+
offer.patterns.length > 0 ? `Patterns for new slides ("?" marks an optional slot):\n${describeCatalog(offer, context.textScale)}` : '',
|
|
148
|
+
]
|
|
149
|
+
.filter(Boolean)
|
|
150
|
+
.join('\n\n');
|
|
151
|
+
const readPlan = (answer) => {
|
|
152
|
+
const raw = (answer ?? {});
|
|
153
|
+
const rawFields = (typeof raw.fields === 'object' && raw.fields !== null ? raw.fields : {});
|
|
154
|
+
// A field the model leaves empty keeps its value: a header must not silently disappear.
|
|
155
|
+
const nextFields = Object.fromEntries(fieldNames.map((name) => [name, cleanText(rawFields[name]) || fields[name]]));
|
|
156
|
+
const countProblems = [];
|
|
157
|
+
const entries = (Array.isArray(raw.slides) ? raw.slides : []).map((item, index) => {
|
|
158
|
+
const given = (item ?? {});
|
|
159
|
+
const entry = { from: Number(given.from) || 0, pattern: cleanText(given.pattern), change: cleanText(given.change), images: given.images === true };
|
|
160
|
+
const definition = definitions.get(entry.pattern);
|
|
161
|
+
if (definition?.repeat) {
|
|
162
|
+
// A slide that keeps its layout keeps its number of items unless the plan says otherwise.
|
|
163
|
+
const source = entry.from > 0 ? deck.slides[entry.from - 1] : undefined;
|
|
164
|
+
const count = readItems(definition, given.items ?? (source?.pattern === entry.pattern ? source.items : undefined));
|
|
165
|
+
if (count.problem)
|
|
166
|
+
countProblems.push(`slide ${index + 1}: ${count.problem}`);
|
|
167
|
+
if (count.items !== undefined)
|
|
168
|
+
entry.items = count.items;
|
|
169
|
+
}
|
|
170
|
+
return entry;
|
|
171
|
+
});
|
|
172
|
+
const plan = {
|
|
173
|
+
summary: cleanText(raw.summary),
|
|
174
|
+
language: cleanText(raw.language) || currentLanguage,
|
|
175
|
+
title: cleanText(raw.title),
|
|
176
|
+
textSize: (typeof raw.text_size === 'string' && raw.text_size in TEXT_SIZES ? raw.text_size : currentSize),
|
|
177
|
+
fields: { ...fields, ...nextFields },
|
|
178
|
+
entries,
|
|
179
|
+
};
|
|
180
|
+
if (entries.length === 0)
|
|
181
|
+
return { ...plan, problem: 'the answer contained no slides' };
|
|
182
|
+
if (countProblems.length > 0)
|
|
183
|
+
return { ...plan, problem: countProblems.join('; ') };
|
|
184
|
+
for (const [index, entry] of entries.entries()) {
|
|
185
|
+
const where = `slide ${index + 1}`;
|
|
186
|
+
if (!Number.isInteger(entry.from) || entry.from < 0 || entry.from > deck.slides.length) {
|
|
187
|
+
return { ...plan, problem: `${where}: "from" must be 0 or the number of an existing slide (1 to ${deck.slides.length})` };
|
|
188
|
+
}
|
|
189
|
+
if (!definitions.has(entry.pattern))
|
|
190
|
+
return { ...plan, problem: `${where}: unknown pattern "${entry.pattern}"` };
|
|
191
|
+
const source = entry.from > 0 ? deck.slides[entry.from - 1] : undefined;
|
|
192
|
+
if (source?.pattern !== entry.pattern && !offered.has(entry.pattern)) {
|
|
193
|
+
return { ...plan, problem: `${where}: pattern "${entry.pattern}" cannot be used for a new or re-laid-out slide here` };
|
|
194
|
+
}
|
|
195
|
+
if (!source && !entry.change)
|
|
196
|
+
return { ...plan, problem: `${where}: a new slide needs "change" to say what it shows` };
|
|
197
|
+
}
|
|
198
|
+
return plan;
|
|
199
|
+
};
|
|
200
|
+
const mostItems = Math.max(0, ...patternIds.map((id) => itemRange(definitions.get(id))).map((range) => (range && range.max > range.min ? range.max : 0)));
|
|
201
|
+
const planSchema = editPlanSchema(patternIds, deck.slides.length, fieldNames, mostItems);
|
|
202
|
+
let plan = readPlan(await asker(options.llm, systemPrompt(currentLanguage, 'deck'), options.signal)(planRequest, planSchema));
|
|
203
|
+
if (plan.problem) {
|
|
204
|
+
const retry = `${planRequest}\n\nYour previous answer could not be used: ${plan.problem}. Answer again.`;
|
|
205
|
+
plan = readPlan(await asker(options.llm, systemPrompt(currentLanguage, 'deck'), options.signal)(retry, planSchema));
|
|
206
|
+
if (plan.problem)
|
|
207
|
+
throw new PlanError(`The model did not produce a usable edit plan: ${plan.problem}`);
|
|
208
|
+
}
|
|
209
|
+
const language = plan.language;
|
|
210
|
+
const direction = options.direction ?? (language === currentLanguage ? (deck.direction ?? directionOf(language)) : directionOf(language));
|
|
211
|
+
// A change of language touches every slide, whatever the plan says.
|
|
212
|
+
if (language !== currentLanguage) {
|
|
213
|
+
for (const entry of plan.entries)
|
|
214
|
+
if (!entry.change)
|
|
215
|
+
entry.change = 'Translate into the new deck language.';
|
|
216
|
+
}
|
|
217
|
+
// Larger text fits less: from here on, limits are those of the size the deck will have.
|
|
218
|
+
const textScale = TEXT_SIZES[plan.textSize];
|
|
219
|
+
const resized = textScale !== context.textScale;
|
|
220
|
+
context.textScale = textScale;
|
|
221
|
+
const overflows = (slide) => validateDeck(manifest, { ...deck, textScale, slides: [slide] }, { layout }).some((issue) => /characters|paragraphs/.test(issue.message));
|
|
222
|
+
// 2. Work out, per slide, whether it is copied or written, and what a written slide carries over.
|
|
223
|
+
const jobs = [];
|
|
224
|
+
const kept = new Map();
|
|
225
|
+
plan.entries.forEach((entry, index) => {
|
|
226
|
+
const number = index + 1;
|
|
227
|
+
const source = entry.from > 0 ? deck.slides[entry.from - 1] : undefined;
|
|
228
|
+
const definition = definitions.get(entry.pattern);
|
|
229
|
+
if (source && source.pattern === entry.pattern && !entry.change) {
|
|
230
|
+
// Two things rewrite a slide the plan left alone: a new number of items, and text that no longer fits.
|
|
231
|
+
if (entry.items !== undefined && entry.items !== itemCount(definition, source.items)) {
|
|
232
|
+
entry.change = `Use ${entry.items} ${definition.repeat?.item ?? 'item'}s.`;
|
|
233
|
+
}
|
|
234
|
+
else if (resized && overflows(source)) {
|
|
235
|
+
entry.change = 'Shorten the text to fit the new text size. Keep the meaning.';
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
if (source && source.pattern === entry.pattern && !entry.change) {
|
|
239
|
+
kept.set(number, structuredClone(source));
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
const carried = {};
|
|
243
|
+
if (source && source.pattern === entry.pattern) {
|
|
244
|
+
// Same layout: everything the model is not asked about stays, pictures included unless they are the point.
|
|
245
|
+
for (const slot of effectiveSlots(definition, entry.items)) {
|
|
246
|
+
const value = source.slots[slot.name];
|
|
247
|
+
if (value === undefined)
|
|
248
|
+
continue;
|
|
249
|
+
const policy = slot.empty ?? 'error';
|
|
250
|
+
if ((slot.kind === 'image' && !entry.images) || policy === 'keep' || policy === 'drop')
|
|
251
|
+
carried[slot.name] = value;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
else if (source && !entry.images) {
|
|
255
|
+
// New layout for an existing slide: its photos move over, in order, so they are not generated again.
|
|
256
|
+
const oldDefinition = definitions.get(source.pattern);
|
|
257
|
+
const photos = (oldDefinition?.slots ?? [])
|
|
258
|
+
.filter((slot) => slot.kind === 'image' && slot.imageKind === 'photo')
|
|
259
|
+
.map((slot) => source.slots[slot.name])
|
|
260
|
+
.filter(isImageRef);
|
|
261
|
+
for (const slot of effectiveSlots(definition, entry.items)) {
|
|
262
|
+
if (slot.kind !== 'image' || slot.imageKind !== 'photo')
|
|
263
|
+
continue;
|
|
264
|
+
const photo = photos.shift();
|
|
265
|
+
if (photo)
|
|
266
|
+
carried[slot.name] = photo;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
// A slide that stays in its layout can always be rewritten, even if that layout is not on offer for new slides.
|
|
270
|
+
const own = source && source.pattern === entry.pattern ? { ...context, figures: true, imageDensity: 'high' } : context;
|
|
271
|
+
let planned = planPattern(definition, own, new Set(Object.keys(carried)), entry.items);
|
|
272
|
+
if ('reason' in planned && source && source.pattern === entry.pattern) {
|
|
273
|
+
// Its pictures cannot be replaced with what the caller supplied (say, no icon set): keep them all.
|
|
274
|
+
for (const slot of effectiveSlots(definition, entry.items)) {
|
|
275
|
+
const value = source.slots[slot.name];
|
|
276
|
+
if (slot.kind === 'image' && value !== undefined)
|
|
277
|
+
carried[slot.name] = value;
|
|
278
|
+
}
|
|
279
|
+
planned = planPattern(definition, own, new Set(Object.keys(carried)), entry.items);
|
|
280
|
+
}
|
|
281
|
+
if ('reason' in planned)
|
|
282
|
+
throw new PlanError(`Slide ${number}: pattern "${entry.pattern}" ${planned.reason}`);
|
|
283
|
+
const job = {
|
|
284
|
+
number,
|
|
285
|
+
pattern: planned.pattern,
|
|
286
|
+
purpose: entry.change,
|
|
287
|
+
carried,
|
|
288
|
+
relaid: !!source && source.pattern !== entry.pattern,
|
|
289
|
+
};
|
|
290
|
+
if (source)
|
|
291
|
+
job.source = source;
|
|
292
|
+
jobs.push(job);
|
|
293
|
+
});
|
|
294
|
+
const assemble = (written) => {
|
|
295
|
+
const slides = plan.entries.map((entry, index) => kept.get(index + 1) ?? written.get(index + 1) ?? { pattern: entry.pattern, slots: {} });
|
|
296
|
+
// The request joins the brief: later edits, and the check of chart numbers, see what was asked for.
|
|
297
|
+
const brief = [deck.brief, instruction.trim()].filter(Boolean).join('\n');
|
|
298
|
+
const next = { ...deck, version: 1, language, direction, brief, slides };
|
|
299
|
+
if (textScale === 1)
|
|
300
|
+
delete next.textScale;
|
|
301
|
+
else
|
|
302
|
+
next.textScale = textScale;
|
|
303
|
+
if (plan.title)
|
|
304
|
+
next.title = plan.title;
|
|
305
|
+
if (Object.keys(plan.fields).length > 0)
|
|
306
|
+
next.fields = plan.fields;
|
|
307
|
+
return next;
|
|
308
|
+
};
|
|
309
|
+
if (jobs.length === 0) {
|
|
310
|
+
// Reordering and deleting need no writing.
|
|
311
|
+
return { deck: assemble(new Map()), summary: plan.summary, rewritten: [], warnings: [] };
|
|
312
|
+
}
|
|
313
|
+
// 3. Write the slides that change.
|
|
314
|
+
options.onProgress?.({ stage: 'write', slides: jobs.length });
|
|
315
|
+
const overview = plan.entries
|
|
316
|
+
.map((entry, index) => {
|
|
317
|
+
const number = index + 1;
|
|
318
|
+
const keptSlide = kept.get(number);
|
|
319
|
+
return keptSlide ? `${number}. ${entry.pattern}, unchanged ${slideLabel(keptSlide)}` : `${number}. ${entry.pattern}, to write`;
|
|
320
|
+
})
|
|
321
|
+
.join('\n');
|
|
322
|
+
const tasks = jobs
|
|
323
|
+
.map((job) => {
|
|
324
|
+
const offeredSlots = new Set(job.pattern.slots.map((planned) => planned.slot.name));
|
|
325
|
+
const lines = [`s${job.number} (${job.pattern.def.id}). ${job.source ? 'Change' : 'New slide'}: ${job.purpose}`];
|
|
326
|
+
if (job.source) {
|
|
327
|
+
// Show what is there now. After a layout change the slot names differ, so everything is shown as material.
|
|
328
|
+
const current = Object.entries(job.source.slots).filter(([name, value]) => (job.relaid || offeredSlots.has(name)) && value !== null);
|
|
329
|
+
const shown = Object.fromEntries(current.map(([name, value]) => [name, isImageRef(value) ? (value.prompt ? { prompt: value.prompt, alt: value.alt ?? '' } : value.asset) : value]));
|
|
330
|
+
lines.push(`${job.relaid ? 'Content of the slide it replaces' : 'Current content'}: ${JSON.stringify(shown)}`);
|
|
331
|
+
}
|
|
332
|
+
return lines.join('\n');
|
|
333
|
+
})
|
|
334
|
+
.join('\n\n');
|
|
335
|
+
const request = [
|
|
336
|
+
deck.brief ? `The deck was written from this brief:\n${deck.brief}` : '',
|
|
337
|
+
`Requested change:\n${instruction.trim()}`,
|
|
338
|
+
`The deck after the change:\n${overview}`,
|
|
339
|
+
'Write only the slides below. When a slide has current content, start from it and change only what is asked: keep every other text word for word.',
|
|
340
|
+
tasks,
|
|
341
|
+
...suppliesText(jobs, context),
|
|
342
|
+
'Fill every required property. Leave an optional property out when the slide is better without it.',
|
|
343
|
+
]
|
|
344
|
+
.filter(Boolean)
|
|
345
|
+
.join('\n\n');
|
|
346
|
+
const draft = await writeSlides({
|
|
347
|
+
ask: asker(options.llm, systemPrompt(language, 'deck'), options.signal),
|
|
348
|
+
request,
|
|
349
|
+
jobs,
|
|
350
|
+
context,
|
|
351
|
+
assemble,
|
|
352
|
+
manifest,
|
|
353
|
+
layout,
|
|
354
|
+
maxRepairs: options.maxRepairs ?? 2,
|
|
355
|
+
onRepair: (attempt, issues) => options.onProgress?.({ stage: 'repair', attempt, issues }),
|
|
356
|
+
});
|
|
357
|
+
const errors = draft.issues.filter((issue) => issue.severity === 'error');
|
|
358
|
+
if (errors.length > 0)
|
|
359
|
+
throw new DeckValidationError(errors);
|
|
360
|
+
const rewritten = jobs.map((job) => job.number);
|
|
361
|
+
const unstated = unstatedChartValues(manifest, draft.deck).filter((issue) => rewritten.includes(issue.slide));
|
|
362
|
+
return { deck: draft.deck, summary: plan.summary, rewritten, warnings: [...draft.issues, ...unstated] };
|
|
363
|
+
}
|
|
364
|
+
//# sourceMappingURL=edit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"edit.js","sourceRoot":"","sources":["../../src/plan/edit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExE,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAI3D,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAE3F,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAErF,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEtE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAiChF,SAAS,aAAa,CAAC,KAA4B;IACjD,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,EAAE,CAAC;IACrD,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC5D,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACvD,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;QAAE,OAAO,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;IACrG,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,cAAc,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY,KAAK,CAAC,KAAK,GAAG,CAAC;AAClG,CAAC;AAED,mFAAmF;AACnF,SAAS,YAAY,CAAC,IAAc;IAClC,OAAO,IAAI,CAAC,MAAM;SACf,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;QACpB,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC;aACtC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,KAAK,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;aAC1D,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;aACtC,IAAI,CAAC,IAAI,CAAC,CAAC;QACd,OAAO,GAAG,KAAK,GAAG,CAAC,MAAM,KAAK,CAAC,OAAO,GAAG,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,KAAK,KAAK,EAAE,CAAC;IACjH,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC;AAED,yGAAyG;AACzG,SAAS,UAAU,CAAC,KAAgB;IAClC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC;IAChC,MAAM,IAAI,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAmB,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC;IACxI,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAC1C,CAAC;AAED,SAAS,cAAc,CAAC,UAAoB,EAAE,UAAkB,EAAE,UAAoB,EAAE,SAAiB;IACvG,MAAM,MAAM,GAAG,cAAc,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;IACtD,MAAM,GAAG,GAAG,MAAM,CAAC,UAAwC,CAAC;IAC5D,GAAG,CAAC,SAAS,GAAG;QACd,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC;QAC7B,WAAW,EAAE,oGAAoG;KAClH,CAAC;IACD,MAAM,CAAC,QAAqB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAChD,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;QAClB,MAAM,KAAK,GAAK,GAAG,CAAC,MAAqB,CAAC,KAAoB,CAAC,UAAwC,CAAC;QACxG,KAAK,CAAC,KAAK,GAAG;YACZ,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,CAAC;YACV,OAAO,EAAE,SAAS;YAClB,WAAW,EAAE,oHAAoH;SAClI,CAAC;IACJ,CAAC;IACD,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,MAAM,UAAU,GAAG,MAAM,CAAC,UAAwC,CAAC;QACnE,UAAU,CAAC,MAAM,GAAG;YAClB,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,8FAA8F;YAC3G,UAAU,EAAE,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;YACpF,QAAQ,EAAE,UAAU;SACrB,CAAC;QACD,MAAM,CAAC,QAAqB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC/C,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,cAAc,CAAC,UAAoB,EAAE,UAAkB;IAC9D,OAAO;QACL,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,2FAA2F,EAAE;YACrI,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,kDAAkD,EAAE;YAC7F,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,oCAAoC,EAAE;YAC5E,MAAM,EAAE;gBACN,IAAI,EAAE,OAAO;gBACb,QAAQ,EAAE,CAAC;gBACX,KAAK,EAAE;oBACL,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,IAAI,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,wEAAwE,EAAE;wBACjJ,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE;wBAC7C,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,qFAAqF,EAAE;wBAC9H,MAAM,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,kEAAkE,EAAE;qBAC7G;oBACD,QAAQ,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,CAAC;iBAClD;aACF;SACF;QACD,QAAQ,EAAE,CAAC,SAAS,EAAE,UAAU,EAAE,OAAO,EAAE,QAAQ,CAAC;KACrD,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,QAAkB,EAAE,IAAc,EAAE,WAAmB,EAAE,OAAoB;IAC1G,MAAM,EAAE,QAAQ,EAAE,GAAG,QAAQ,CAAC;IAC9B,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,QAAQ,CAAC;IAC1C,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC;IACnD,MAAM,eAAe,GAAG,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,QAAQ,IAAI,IAAI,CAAC;IACnE,MAAM,WAAW,GAAG,IAAI,GAAG,CAAqB,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IAE3G,oGAAoG;IACpG,MAAM,OAAO,GAAG,OAAO,CAAC,cAAc,IAAI,YAAY,CAAC;IACvD,MAAM,OAAO,GAAG,OAAO,KAAK,QAAQ,IAAI,CAAC,OAAO,KAAK,YAAY,IAAI,UAAU,CAAC,GAAG,WAAW,IAAI,IAAI,CAAC,KAAK,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;IACvH,MAAM,OAAO,GAAmB;QAC9B,MAAM;QACN,MAAM;QACN,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,EAAE;QAC1B,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,EAAE;QAC5B,YAAY,EAAE,OAAO,CAAC,YAAY,IAAI,QAAQ;QAC9C,OAAO;QACP,SAAS,EAAE,IAAI,CAAC,SAAS,IAAI,CAAC;KAC/B,CAAC;IACF,MAAM,WAAW,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAa,CAAC;IACjI,IAAI,OAAO,CAAC,QAAQ;QAAE,OAAO,CAAC,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC;IACvD,MAAM,KAAK,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC9C,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IACpF,iGAAiG;IACjG,MAAM,QAAQ,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IACjI,MAAM,UAAU,GAAG,CAAC,GAAG,OAAO,CAAC,IAAI,EAAE,EAAE,GAAG,QAAQ,CAAC,CAAC;IACpD,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,SAAS,CAAC,2BAA2B,QAAQ,CAAC,IAAI,eAAe,CAAC,CAAC;IAE1G,oBAAoB;IACpB,wFAAwF;IACxF,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC7D,OAAO,CAAC,UAAU,EAAE,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;IAC3C,MAAM,WAAW,GAAG;QAClB,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,0CAA0C,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE;QACxE,wBAAwB,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,sCAAsC,eAAe,sBAAsB,WAAW,OAAO,YAAY,CAAC,IAAI,CAAC,EAAE;QAC/K,UAAU,CAAC,MAAM,GAAG,CAAC;YACnB,CAAC,CAAC,+CAA+C,UAAU,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,IAAI,KAAK,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;YAClI,CAAC,CAAC,EAAE;QACN,sBAAsB,WAAW,CAAC,IAAI,EAAE,EAAE;QAC1C;YACE,qEAAqE;YACrE,qHAAqH;YACrH,mGAAmG;YACnG,6GAA6G;YAC7G,6EAA6E;YAC7E,wFAAwF;SACzF,CAAC,IAAI,CAAC,IAAI,CAAC;QACZ,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,0DAA0D,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE;KACvI;SACE,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,MAAM,CAAC,CAAC;IAEhB,MAAM,QAAQ,GAAG,CACf,MAAe,EACmI,EAAE;QACpJ,MAAM,GAAG,GAAG,CAAC,MAAM,IAAI,EAAE,CAAwH,CAAC;QAClJ,MAAM,SAAS,GAAG,CAAC,OAAO,GAAG,CAAC,MAAM,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAA4B,CAAC;QACvH,wFAAwF;QACxF,MAAM,UAAU,GAAG,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,IAAK,MAAM,CAAC,IAAI,CAAY,CAAC,CAAC,CAAC,CAAC;QAChI,MAAM,aAAa,GAAa,EAAE,CAAC;QACnC,MAAM,OAAO,GAAgB,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;YAC7F,MAAM,KAAK,GAAG,CAAC,IAAI,IAAI,EAAE,CAA+F,CAAC;YACzH,MAAM,KAAK,GAAc,EAAE,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;YAC9J,MAAM,UAAU,GAAG,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAClD,IAAI,UAAU,EAAE,MAAM,EAAE,CAAC;gBACvB,0FAA0F;gBAC1F,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;gBACxE,MAAM,KAAK,GAAG,SAAS,CAAC,UAAU,EAAE,KAAK,CAAC,KAAK,IAAI,CAAC,MAAM,EAAE,OAAO,KAAK,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;gBACnH,IAAI,KAAK,CAAC,OAAO;oBAAE,aAAa,CAAC,IAAI,CAAC,SAAS,KAAK,GAAG,CAAC,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;gBAC9E,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS;oBAAE,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;YAC3D,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC,CAAC,CAAC;QACH,MAAM,IAAI,GAAG;YACX,OAAO,EAAE,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC;YAC/B,QAAQ,EAAE,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,eAAe;YACpD,KAAK,EAAE,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC;YAC3B,QAAQ,EAAE,CAAC,OAAO,GAAG,CAAC,SAAS,KAAK,QAAQ,IAAI,GAAG,CAAC,SAAS,IAAI,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAa;YACtH,MAAM,EAAE,EAAE,GAAG,MAAM,EAAE,GAAG,UAAU,EAAE;YACpC,OAAO;SACR,CAAC;QACF,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,gCAAgC,EAAE,CAAC;QACxF,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACpF,KAAK,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;YAC/C,MAAM,KAAK,GAAG,SAAS,KAAK,GAAG,CAAC,EAAE,CAAC;YACnC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,IAAI,GAAG,CAAC,IAAI,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;gBACvF,OAAO,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,KAAK,+DAA+D,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,EAAE,CAAC;YAC5H,CAAC;YACD,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC;gBAAE,OAAO,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,KAAK,sBAAsB,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC;YACjH,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YACxE,IAAI,MAAM,EAAE,OAAO,KAAK,KAAK,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;gBACrE,OAAO,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,KAAK,cAAc,KAAK,CAAC,OAAO,sDAAsD,EAAE,CAAC;YACzH,CAAC;YACD,IAAI,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM;gBAAE,OAAO,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,KAAK,mDAAmD,EAAE,CAAC;QACzH,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IAEF,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,SAAS,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAe,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,IAAI,KAAK,CAAC,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACxK,MAAM,UAAU,GAAG,cAAc,CAAC,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;IACzF,IAAI,IAAI,GAAG,QAAQ,CAAC,MAAM,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC,CAAC;IAC9H,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,MAAM,KAAK,GAAG,GAAG,WAAW,+CAA+C,IAAI,CAAC,OAAO,iBAAiB,CAAC;QACzG,IAAI,GAAG,QAAQ,CAAC,MAAM,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC;QACpH,IAAI,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,SAAS,CAAC,iDAAiD,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;IACzG,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;IAC/B,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,CAAC,QAAQ,KAAK,eAAe,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,IAAI,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC1I,oEAAoE;IACpE,IAAI,QAAQ,KAAK,eAAe,EAAE,CAAC;QACjC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,OAAO;YAAE,IAAI,CAAC,KAAK,CAAC,MAAM;gBAAE,KAAK,CAAC,MAAM,GAAG,uCAAuC,CAAC;IAC9G,CAAC;IAED,wFAAwF;IACxF,MAAM,SAAS,GAAG,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC5C,MAAM,OAAO,GAAG,SAAS,KAAK,OAAO,CAAC,SAAS,CAAC;IAChD,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC;IAC9B,MAAM,SAAS,GAAG,CAAC,KAAgB,EAAE,EAAE,CACrC,YAAY,CAAC,QAAQ,EAAE,EAAE,GAAG,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,uBAAuB,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;IAE3I,kGAAkG;IAClG,MAAM,IAAI,GAA8D,EAAE,CAAC;IAC3E,MAAM,IAAI,GAAG,IAAI,GAAG,EAAqB,CAAC;IAC1C,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;QACpC,MAAM,MAAM,GAAG,KAAK,GAAG,CAAC,CAAC;QACzB,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACxE,MAAM,UAAU,GAAG,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAe,CAAC;QAEhE,IAAI,MAAM,IAAI,MAAM,CAAC,OAAO,KAAK,KAAK,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YAChE,uGAAuG;YACvG,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,UAAU,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;gBACrF,KAAK,CAAC,MAAM,GAAG,OAAO,KAAK,CAAC,KAAK,IAAI,UAAU,CAAC,MAAM,EAAE,IAAI,IAAI,MAAM,IAAI,CAAC;YAC7E,CAAC;iBAAM,IAAI,OAAO,IAAI,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;gBACxC,KAAK,CAAC,MAAM,GAAG,8DAA8D,CAAC;YAChF,CAAC;QACH,CAAC;QAED,IAAI,MAAM,IAAI,MAAM,CAAC,OAAO,KAAK,KAAK,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YAChE,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC;YAC1C,OAAO;QACT,CAAC;QAED,MAAM,OAAO,GAA8B,EAAE,CAAC;QAC9C,IAAI,MAAM,IAAI,MAAM,CAAC,OAAO,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC;YAC/C,2GAA2G;YAC3G,KAAK,MAAM,IAAI,IAAI,cAAc,CAAC,UAAU,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC3D,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACtC,IAAI,KAAK,KAAK,SAAS;oBAAE,SAAS;gBAClC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,IAAI,OAAO,CAAC;gBACrC,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,MAAM,KAAK,MAAM,IAAI,MAAM,KAAK,MAAM;oBAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;YACrH,CAAC;QACH,CAAC;aAAM,IAAI,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YACnC,qGAAqG;YACrG,MAAM,aAAa,GAAG,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACtD,MAAM,MAAM,GAAG,CAAC,aAAa,EAAE,KAAK,IAAI,EAAE,CAAC;iBACxC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,OAAO,IAAI,IAAI,CAAC,SAAS,KAAK,OAAO,CAAC;iBACrE,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;iBACtC,MAAM,CAAC,UAAU,CAAC,CAAC;YACtB,KAAK,MAAM,IAAI,IAAI,cAAc,CAAC,UAAU,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC3D,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,IAAI,IAAI,CAAC,SAAS,KAAK,OAAO;oBAAE,SAAS;gBAClE,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,EAAE,CAAC;gBAC7B,IAAI,KAAK;oBAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;YACxC,CAAC;QACH,CAAC;QAED,gHAAgH;QAChH,MAAM,GAAG,GAAmB,MAAM,IAAI,MAAM,CAAC,OAAO,KAAK,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;QACvI,IAAI,OAAO,GAAG,WAAW,CAAC,UAAU,EAAE,GAAG,EAAE,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;QACvF,IAAI,QAAQ,IAAI,OAAO,IAAI,MAAM,IAAI,MAAM,CAAC,OAAO,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC;YACtE,mGAAmG;YACnG,KAAK,MAAM,IAAI,IAAI,cAAc,CAAC,UAAU,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC3D,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACtC,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,IAAI,KAAK,KAAK,SAAS;oBAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;YAC/E,CAAC;YACD,OAAO,GAAG,WAAW,CAAC,UAAU,EAAE,GAAG,EAAE,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;QACrF,CAAC;QACD,IAAI,QAAQ,IAAI,OAAO;YAAE,MAAM,IAAI,SAAS,CAAC,SAAS,MAAM,cAAc,KAAK,CAAC,OAAO,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QAE9G,MAAM,GAAG,GAAuD;YAC9D,MAAM;YACN,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,OAAO,EAAE,KAAK,CAAC,MAAM;YACrB,OAAO;YACP,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,MAAM,CAAC,OAAO,KAAK,KAAK,CAAC,OAAO;SACrD,CAAC;QACF,IAAI,MAAM;YAAE,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC;QAChC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACjB,CAAC,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAG,CAAC,OAA+B,EAAY,EAAE;QAC7D,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;QAC1I,oGAAoG;QACpG,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1E,MAAM,IAAI,GAAa,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QACnF,IAAI,SAAS,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC,SAAS,CAAC;;YACtC,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAChC,IAAI,IAAI,CAAC,KAAK;YAAE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACxC,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC;YAAE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QACnE,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IAEF,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,2CAA2C;QAC3C,OAAO,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,GAAG,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAC3F,CAAC;IAED,mCAAmC;IACnC,OAAO,CAAC,UAAU,EAAE,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IAC9D,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO;SAC1B,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;QACpB,MAAM,MAAM,GAAG,KAAK,GAAG,CAAC,CAAC;QACzB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACnC,OAAO,SAAS,CAAC,CAAC,CAAC,GAAG,MAAM,KAAK,KAAK,CAAC,OAAO,eAAe,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,MAAM,KAAK,KAAK,CAAC,OAAO,YAAY,CAAC;IACjI,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAC;IACd,MAAM,KAAK,GAAG,IAAI;SACf,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QACX,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACpF,MAAM,KAAK,GAAG,CAAC,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,KAAK,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QACjH,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;YACf,2GAA2G;YAC3G,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,IAAI,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,KAAK,IAAI,CAAC,CAAC;YACrI,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,CAC9B,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAClJ,CAAC;YACF,KAAK,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,kCAAkC,CAAC,CAAC,CAAC,iBAAiB,KAAK,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACjH,CAAC;QACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC,CAAC;SACD,IAAI,CAAC,MAAM,CAAC,CAAC;IAChB,MAAM,OAAO,GAAG;QACd,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,0CAA0C,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE;QACxE,sBAAsB,WAAW,CAAC,IAAI,EAAE,EAAE;QAC1C,+BAA+B,QAAQ,EAAE;QACzC,kJAAkJ;QAClJ,KAAK;QACL,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC;QAC9B,mGAAmG;KACpG;SACE,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,MAAM,CAAC,CAAC;IAEhB,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC;QAC9B,GAAG,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC;QACvE,OAAO;QACP,IAAI;QACJ,OAAO;QACP,QAAQ;QACR,QAAQ;QACR,MAAM;QACN,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,CAAC;QACnC,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;KAC1F,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC;IAC1E,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,IAAI,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAC7D,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAChD,MAAM,QAAQ,GAAG,mBAAmB,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAe,CAAC,CAAC,CAAC;IACxH,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,GAAG,QAAQ,CAAC,EAAE,CAAC;AAC1G,CAAC"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import type { Issue, LayoutMode } from '../deck/validate.ts';
|
|
2
|
+
import type { DeckSpec } from '../deck/spec.ts';
|
|
3
|
+
import type { JsonSchema, LlmProvider } from '../llm/provider.ts';
|
|
4
|
+
import type { Template } from '../render/render.ts';
|
|
5
|
+
import type { Direction, TextSize } from '../template/manifest.ts';
|
|
6
|
+
import type { AssetDef, IconDef, ImageDensity } from './catalog.ts';
|
|
7
|
+
/** What the person asked for. */
|
|
8
|
+
export interface Brief {
|
|
9
|
+
/** What the deck is about, in the person's own words. */
|
|
10
|
+
prompt: string;
|
|
11
|
+
/** A fixed number of slides, or a range. Defaults to 6 to 10. */
|
|
12
|
+
slideCount?: number | {
|
|
13
|
+
min: number;
|
|
14
|
+
max: number;
|
|
15
|
+
};
|
|
16
|
+
/** BCP 47 tag of the language to write in. Defaults to the template's language. */
|
|
17
|
+
language?: string;
|
|
18
|
+
/** Reading direction. Defaults to the language's. */
|
|
19
|
+
direction?: Direction;
|
|
20
|
+
/** How many slides should carry a photo. Defaults to `medium`. */
|
|
21
|
+
imageDensity?: ImageDensity;
|
|
22
|
+
/** Anything else to respect: audience, tone, points that must be covered. */
|
|
23
|
+
instructions?: string;
|
|
24
|
+
/** Deck-level values the template needs, e.g. the unit shown in the header. */
|
|
25
|
+
fields?: Record<string, string>;
|
|
26
|
+
/** Size of body text. Larger text means less of it fits on a slide. Defaults to `normal`. */
|
|
27
|
+
textSize?: TextSize;
|
|
28
|
+
}
|
|
29
|
+
export type PlanProgress = {
|
|
30
|
+
stage: 'outline';
|
|
31
|
+
} | {
|
|
32
|
+
stage: 'write';
|
|
33
|
+
slides: number;
|
|
34
|
+
} | {
|
|
35
|
+
stage: 'repair';
|
|
36
|
+
attempt: number;
|
|
37
|
+
issues: number;
|
|
38
|
+
};
|
|
39
|
+
export interface PlanOptions {
|
|
40
|
+
llm: LlmProvider;
|
|
41
|
+
/** Defaults to `strict`. */
|
|
42
|
+
layout?: LayoutMode;
|
|
43
|
+
/** The app's icon set. Patterns with icon slots are only offered when this is given. */
|
|
44
|
+
icons?: IconDef[];
|
|
45
|
+
/** Ready-made pictures the deck may use, e.g. rendered diagrams. */
|
|
46
|
+
assets?: AssetDef[];
|
|
47
|
+
/** Restrict the deck to these pattern ids. */
|
|
48
|
+
patterns?: string[];
|
|
49
|
+
/**
|
|
50
|
+
* When patterns built around numbers may be used. `from-brief` (default) offers them only if
|
|
51
|
+
* the brief contains figures; a model given such a pattern and no data tends to invent some.
|
|
52
|
+
*/
|
|
53
|
+
numberPatterns?: 'from-brief' | 'always' | 'never';
|
|
54
|
+
/** How many times the model may be asked to fix a draft that breaks the template's limits. Defaults to 2. */
|
|
55
|
+
maxRepairs?: number;
|
|
56
|
+
onProgress?: (event: PlanProgress) => void;
|
|
57
|
+
signal?: AbortSignal;
|
|
58
|
+
}
|
|
59
|
+
export interface OutlineEntry {
|
|
60
|
+
pattern: string;
|
|
61
|
+
purpose: string;
|
|
62
|
+
/** For a pattern with a row of items: how many items the slide has. */
|
|
63
|
+
items?: number;
|
|
64
|
+
}
|
|
65
|
+
export interface PlanResult {
|
|
66
|
+
deck: DeckSpec;
|
|
67
|
+
/** Limits the final draft still exceeds, e.g. text a little over a slot's budget. */
|
|
68
|
+
warnings: Issue[];
|
|
69
|
+
outline: OutlineEntry[];
|
|
70
|
+
}
|
|
71
|
+
export declare class PlanError extends Error {
|
|
72
|
+
constructor(message: string);
|
|
73
|
+
}
|
|
74
|
+
export declare function directionOf(language: string): Direction;
|
|
75
|
+
/** Whether a text contains any digit, in any script. */
|
|
76
|
+
export declare function hasFigures(text: string): boolean;
|
|
77
|
+
/** Binds a provider to a system prompt and an optional abort signal. */
|
|
78
|
+
export declare function asker(llm: LlmProvider, system: string, signal: AbortSignal | undefined): (prompt: string, schema: JsonSchema) => Promise<unknown>;
|
|
79
|
+
/** A deck before its content is written: the slides in order, each with a pattern and the point it makes. */
|
|
80
|
+
export interface DeckPlan {
|
|
81
|
+
version: 1;
|
|
82
|
+
title: string;
|
|
83
|
+
/** The request, with everything needed to write the deck later. */
|
|
84
|
+
brief: Brief;
|
|
85
|
+
slides: OutlineEntry[];
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* First stage: decides which pattern each slide uses and the point it makes. One model call.
|
|
89
|
+
* The result is small and quick to produce, so it is the thing to show a person and let them change.
|
|
90
|
+
*/
|
|
91
|
+
export declare function planOutline(template: Template, brief: Brief, options: PlanOptions): Promise<DeckPlan>;
|
|
92
|
+
/**
|
|
93
|
+
* Changes a plan by instruction ("add a slide about pricing", "make it shorter", "in English").
|
|
94
|
+
* One model call. The instruction is kept with the brief, so facts it adds reach the writing stage.
|
|
95
|
+
*/
|
|
96
|
+
export declare function editPlan(template: Template, plan: DeckPlan, instruction: string, options: PlanOptions): Promise<{
|
|
97
|
+
plan: DeckPlan;
|
|
98
|
+
summary: string;
|
|
99
|
+
}>;
|
|
100
|
+
/**
|
|
101
|
+
* Second stage: writes the content of every slot of a plan's slides, against a schema built for
|
|
102
|
+
* exactly that sequence. Drafts that break the template's limits go back to the model.
|
|
103
|
+
*/
|
|
104
|
+
export declare function writeDeck(template: Template, plan: DeckPlan, options: PlanOptions): Promise<PlanResult>;
|
|
105
|
+
/** Brief to deck spec in one go: {@link planOutline}, then {@link writeDeck}. */
|
|
106
|
+
export declare function planDeck(template: Template, brief: Brief, options: PlanOptions): Promise<PlanResult>;
|