@gui-chat-plugin/sequence 0.4.1 → 0.5.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/CHANGELOG.md +21 -0
- package/README.md +45 -11
- package/dist/core/chartSlide.d.ts +14 -0
- package/dist/core/definitions.d.ts +24 -9
- package/dist/core/host.d.ts +5 -2
- package/dist/core/index.d.ts +2 -0
- package/dist/core/markdownSlide.d.ts +9 -0
- package/dist/core/slideHtml.d.ts +3 -1
- package/dist/core-DNUfOXPo.cjs +232 -0
- package/dist/{core-Dsp7rj6a.js → core-g9C3DDiR.js} +342 -157
- package/dist/index.cjs +1 -1
- package/dist/index.js +2 -2
- package/dist/style.css +1 -1
- package/dist/vue.cjs +1 -1
- package/dist/vue.js +48 -48
- package/package.json +5 -1
- package/dist/core-Bl4BX0HI.cjs +0 -145
|
@@ -4,9 +4,9 @@ var t = 1280, n = 720, r = 6e4, i = "https://cdn.jsdelivr.net/npm/@tailwindcss/b
|
|
|
4
4
|
"animate",
|
|
5
5
|
"counter",
|
|
6
6
|
"typewriter"
|
|
7
|
-
], s = 8, c = "\n(() => {\n const EASE = {\n linear: (t) => t,\n easeIn: (t) => t * t,\n easeOut: (t) => 1 - (1 - t) * (1 - t),\n easeInOut: (t) => (t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2),\n };\n const AUTO_END = 8;\n const TRANSFORMS = [\n [\"data-translate-x\", \"translateX\", \"px\"],\n [\"data-translate-y\", \"translateY\", \"px\"],\n [\"data-scale\", \"scale\", \"\"],\n [\"data-rotate\", \"rotate\", \"deg\"],\n [\"data-rotate-x\", \"rotateX\", \"deg\"],\n [\"data-rotate-y\", \"rotateY\", \"deg\"],\n [\"data-rotate-z\", \"rotateZ\", \"deg\"],\n ];\n const STYLES = [\n [\"data-opacity\", \"opacity\", \"\"],\n [\"data-width\", \"width\", \"px\"],\n [\"data-height\", \"height\", \"px\"],\n ];\n const number = (value, fallback) => {\n const n = Number(value);\n return value !== null && value.trim() !== \"\" && Number.isFinite(n) ? n : fallback;\n };\n const range = (value, unit) => {\n if (value === null) return null;\n const parts = value.split(\",\").map((part) => part.trim());\n const from = Number(parts[0]);\n const to = Number(parts[1]);\n if (!Number.isFinite(from) || !Number.isFinite(to)) return null;\n return { from, to, unit: parts[2] || unit };\n };\n const ranges = (el, table) =>\n table\n .map(([attr, name, unit]) => [name, range(el.getAttribute(attr), unit)])\n .filter(([, r]) => r);\n let entries = [];\n const collect = () => {\n entries = [...document.querySelectorAll(\"[data-animation]\")].map((el) => {\n const kind = el.getAttribute(\"data-animation\");\n const end = el.getAttribute(\"data-end\");\n const entry = {\n el,\n kind,\n start: number(el.getAttribute(\"data-start\"), 0),\n end: end === null || end.trim() === \"auto\" ? null : number(end, null),\n ease: EASE[el.getAttribute(\"data-easing\")] || EASE.linear,\n };\n if (kind === \"animate\") {\n entry.transforms = ranges(el, TRANSFORMS);\n entry.styles = ranges(el, STYLES);\n } else if (kind === \"counter\") {\n entry.from = number(el.getAttribute(\"data-from\"), 0);\n entry.to = number(el.getAttribute(\"data-to\"), 0);\n entry.decimals = Math.max(0, Math.round(number(el.getAttribute(\"data-decimals\"), 0)));\n entry.prefix = el.getAttribute(\"data-prefix\") || \"\";\n entry.suffix = el.getAttribute(\"data-suffix\") || \"\";\n } else if (kind === \"typewriter\") {\n entry.text = el.getAttribute(\"data-text\") ?? el.textContent;\n } else {\n return null;\n }\n return entry;\n }).filter(Boolean);\n };\n const seek = (t) => {\n for (const e of entries) {\n const end = e.end ?? AUTO_END;\n const span = end - e.start;\n const p = span > 0 ? Math.min(1, Math.max(0, (t - e.start) / span)) : t >= e.start ? 1 : 0;\n const k = e.ease(p);\n const at = (r) => r.from + (r.to - r.from) * k;\n if (e.kind === \"animate\") {\n if (e.transforms.length) {\n e.el.style.transform = e.transforms.map(([name, r]) => name + \"(\" + at(r) + r.unit + \")\").join(\" \");\n }\n for (const [name, r] of e.styles) e.el.style[name] = at(r) + r.unit;\n } else if (e.kind === \"counter\") {\n e.el.textContent = e.prefix + (e.from + (e.to - e.from) * k).toFixed(e.decimals) + e.suffix;\n } else {\n e.el.textContent = e.text.slice(0, Math.floor(e.text.length * k));\n }\n }\n };\n window.__slideSeek = seek;\n const play = () => {\n const last = Math.max(0, ...entries.map((e) => e.end ?? AUTO_END));\n const begun = performance.now();\n const tick = (now) => {\n const t = (now - begun) / 1000;\n seek(t);\n if (t <= last) requestAnimationFrame(tick);\n };\n requestAnimationFrame(tick);\n };\n // Collected once the body is parsed: at DOMContentLoaded, or earlier when\n // the fallback shows the slide while a slow Tailwind still holds\n // DOMContentLoaded back (the body is parsed by then: readyState is\n // \"interactive\" before deferred scripts run). Played once both are done.\n let collected = false;\n let shown = false;\n const init = () => {\n if (collected || document.readyState === \"loading\") return;\n collected = true;\n collect();\n seek(0);\n if (shown) play();\n };\n const show = () => {\n if (shown) return;\n init();\n shown = true;\n document.documentElement.classList.add(\"ready\");\n if (collected) play();\n };\n const ready = () => requestAnimationFrame(() => requestAnimationFrame(show));\n const check = () =>\n document.querySelector(\"style:not([type]):not(#slide-base)\") ? ready() : setTimeout(check, 30);\n addEventListener(\"DOMContentLoaded\", () => {\n init();\n check();\n });\n setTimeout(show, 1000);\n addEventListener(\"click\", (event) => {\n if (event.target instanceof Element && event.target.closest(\"a, area\")) event.preventDefault();\n }, true);\n})();", l = [
|
|
7
|
+
], s = 8, c = "\n(() => {\n const EASE = {\n linear: (t) => t,\n easeIn: (t) => t * t,\n easeOut: (t) => 1 - (1 - t) * (1 - t),\n easeInOut: (t) => (t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2),\n };\n const AUTO_END = 8;\n const TRANSFORMS = [\n [\"data-translate-x\", \"translateX\", \"px\"],\n [\"data-translate-y\", \"translateY\", \"px\"],\n [\"data-scale\", \"scale\", \"\"],\n [\"data-rotate\", \"rotate\", \"deg\"],\n [\"data-rotate-x\", \"rotateX\", \"deg\"],\n [\"data-rotate-y\", \"rotateY\", \"deg\"],\n [\"data-rotate-z\", \"rotateZ\", \"deg\"],\n ];\n const STYLES = [\n [\"data-opacity\", \"opacity\", \"\"],\n [\"data-width\", \"width\", \"px\"],\n [\"data-height\", \"height\", \"px\"],\n ];\n const number = (value, fallback) => {\n const n = Number(value);\n return value !== null && value.trim() !== \"\" && Number.isFinite(n) ? n : fallback;\n };\n const range = (value, unit) => {\n if (value === null) return null;\n const parts = value.split(\",\").map((part) => part.trim());\n const from = Number(parts[0]);\n const to = Number(parts[1]);\n if (!Number.isFinite(from) || !Number.isFinite(to)) return null;\n return { from, to, unit: parts[2] || unit };\n };\n const ranges = (el, table) =>\n table\n .map(([attr, name, unit]) => [name, range(el.getAttribute(attr), unit)])\n .filter(([, r]) => r);\n let entries = [];\n const collect = () => {\n entries = [...document.querySelectorAll(\"[data-animation]\")].map((el) => {\n const kind = el.getAttribute(\"data-animation\");\n const end = el.getAttribute(\"data-end\");\n const entry = {\n el,\n kind,\n start: number(el.getAttribute(\"data-start\"), 0),\n end: end === null || end.trim() === \"auto\" ? null : number(end, null),\n ease: EASE[el.getAttribute(\"data-easing\")] || EASE.linear,\n };\n if (kind === \"animate\") {\n entry.transforms = ranges(el, TRANSFORMS);\n entry.styles = ranges(el, STYLES);\n } else if (kind === \"counter\") {\n entry.from = number(el.getAttribute(\"data-from\"), 0);\n entry.to = number(el.getAttribute(\"data-to\"), 0);\n entry.decimals = Math.max(0, Math.round(number(el.getAttribute(\"data-decimals\"), 0)));\n entry.prefix = el.getAttribute(\"data-prefix\") || \"\";\n entry.suffix = el.getAttribute(\"data-suffix\") || \"\";\n } else if (kind === \"typewriter\") {\n entry.text = el.getAttribute(\"data-text\") ?? el.textContent;\n } else {\n return null;\n }\n return entry;\n }).filter(Boolean);\n };\n const seek = (t) => {\n for (const e of entries) {\n const end = e.end ?? AUTO_END;\n const span = end - e.start;\n const p = span > 0 ? Math.min(1, Math.max(0, (t - e.start) / span)) : t >= e.start ? 1 : 0;\n const k = e.ease(p);\n const at = (r) => r.from + (r.to - r.from) * k;\n if (e.kind === \"animate\") {\n if (e.transforms.length) {\n e.el.style.transform = e.transforms.map(([name, r]) => name + \"(\" + at(r) + r.unit + \")\").join(\" \");\n }\n for (const [name, r] of e.styles) e.el.style[name] = at(r) + r.unit;\n } else if (e.kind === \"counter\") {\n e.el.textContent = e.prefix + (e.from + (e.to - e.from) * k).toFixed(e.decimals) + e.suffix;\n } else {\n e.el.textContent = e.text.slice(0, Math.floor(e.text.length * k));\n }\n }\n };\n window.__slideSeek = seek;\n const fit = () => {\n for (const el of document.querySelectorAll(\"[data-fit]\")) {\n let size = parseFloat(getComputedStyle(el).fontSize);\n while (size > 12 && (el.scrollHeight > el.clientHeight + 1 || el.scrollWidth > el.clientWidth + 1)) {\n size -= 1;\n el.style.fontSize = size + \"px\";\n }\n }\n };\n const play = () => {\n const last = Math.max(0, ...entries.map((e) => e.end ?? AUTO_END));\n const begun = performance.now();\n const tick = (now) => {\n const t = (now - begun) / 1000;\n seek(t);\n if (t <= last) requestAnimationFrame(tick);\n };\n requestAnimationFrame(tick);\n };\n // Collected once the body is parsed: at DOMContentLoaded, or earlier when\n // the fallback shows the slide while a slow Tailwind still holds\n // DOMContentLoaded back (the body is parsed by then: readyState is\n // \"interactive\" before deferred scripts run). Played once both are done.\n let collected = false;\n let shown = false;\n const init = () => {\n if (collected || document.readyState === \"loading\") return;\n collected = true;\n collect();\n seek(0);\n if (shown) play();\n };\n const show = () => {\n if (shown) return;\n init();\n fit();\n shown = true;\n document.documentElement.classList.add(\"ready\");\n if (collected) play();\n };\n const ready = () => requestAnimationFrame(() => requestAnimationFrame(show));\n const check = () =>\n document.querySelector(\"style:not([type]):not(#slide-base)\") ? ready() : setTimeout(check, 30);\n addEventListener(\"DOMContentLoaded\", () => {\n init();\n check();\n });\n setTimeout(show, 1000);\n addEventListener(\"click\", (event) => {\n if (event.target instanceof Element && event.target.closest(\"a, area\")) event.preventDefault();\n }, true);\n})();", l = [
|
|
8
8
|
"default-src 'none'",
|
|
9
|
-
`script-src 'sha256-
|
|
9
|
+
`script-src 'sha256-bNBxv6ehYc2PHOgmTReFSYsrxiGvq6aqqg9m5RwS7Lc=' ${i}`,
|
|
10
10
|
"style-src 'unsafe-inline' https://fonts.googleapis.com",
|
|
11
11
|
"font-src https://fonts.gstatic.com data:",
|
|
12
12
|
"img-src data: blob:",
|
|
@@ -14,56 +14,121 @@ var t = 1280, n = 720, r = 6e4, i = "https://cdn.jsdelivr.net/npm/@tailwindcss/b
|
|
|
14
14
|
"connect-src 'none'",
|
|
15
15
|
"form-action 'none'",
|
|
16
16
|
"base-uri 'none'"
|
|
17
|
-
].join("; "), u =
|
|
17
|
+
].join("; "), u = {
|
|
18
|
+
"&": "&",
|
|
19
|
+
"<": "<",
|
|
20
|
+
">": ">",
|
|
21
|
+
"\"": """
|
|
22
|
+
}, d = (e) => e.replace(/[&<>"]/g, (e) => u[e] ?? e), f = (e) => e.replace(/<(?=(meta|base|link)\b)/gi, "<").replace(/shadowroot/gi, "data-no-shadow-root"), p = "*, *::before, *::after { animation-play-state: paused !important; animation-duration: 0s !important; animation-delay: 0s !important; animation-iteration-count: 1 !important; animation-fill-mode: both !important; transition: none !important; }", ee = `
|
|
18
23
|
html, body { margin: 0; width: ${t}px; height: 720px; overflow: hidden; }
|
|
19
24
|
html:not(.ready) body { visibility: hidden; }
|
|
20
|
-
${
|
|
21
|
-
function
|
|
25
|
+
${p}`;
|
|
26
|
+
function te(e) {
|
|
22
27
|
return `<!doctype html>
|
|
23
28
|
<html lang="en">
|
|
24
29
|
<head>
|
|
25
30
|
<meta charset="utf-8">
|
|
26
31
|
<meta http-equiv="Content-Security-Policy" content="${l}">
|
|
27
|
-
<style id="slide-base">${
|
|
32
|
+
<style id="slide-base">${ee}</style>
|
|
28
33
|
<script>${c}<\/script>
|
|
29
34
|
<script defer src="${i}" integrity="${a}" crossorigin="anonymous"><\/script>
|
|
30
35
|
</head>
|
|
31
36
|
<body class="bg-white text-slate-900 font-sans antialiased">
|
|
32
|
-
${
|
|
37
|
+
${f(e)}
|
|
38
|
+
</body>
|
|
39
|
+
</html>`;
|
|
40
|
+
}
|
|
41
|
+
//#endregion
|
|
42
|
+
//#region src/core/chartSlide.ts
|
|
43
|
+
var m = [
|
|
44
|
+
"bar",
|
|
45
|
+
"line",
|
|
46
|
+
"pie",
|
|
47
|
+
"doughnut",
|
|
48
|
+
"radar",
|
|
49
|
+
"polarArea",
|
|
50
|
+
"scatter",
|
|
51
|
+
"bubble"
|
|
52
|
+
], h = "https://cdn.jsdelivr.net/npm/chart.js@4.5.1/dist/chart.umd.min.js", ne = "sha384-jb8JQMbMoBUzgWatfe6COACi2ljcDdZQ2OxczGA3bGNeWe+6DChMTBJemed7ZnvJ", re = "\n(() => {\n const fail = (why) => {\n document.getElementById(\"chart-error\").textContent = why;\n document.documentElement.classList.add(\"failed\");\n };\n addEventListener(\"DOMContentLoaded\", () => {\n if (!window.Chart) return fail(\"The chart couldn't be drawn: Chart.js didn't load.\");\n let config;\n try {\n config = JSON.parse(document.getElementById(\"chart-config\").textContent);\n } catch {\n return fail(\"The chart couldn't be drawn: its configuration isn't valid.\");\n }\n Chart.defaults.font.size = 22;\n Chart.defaults.color = \"#334155\";\n Chart.defaults.animation.duration = 1200;\n config.options = { ...config.options, responsive: true, maintainAspectRatio: false };\n try {\n new Chart(document.getElementById(\"chart\"), config);\n } catch (error) {\n fail(\"The chart couldn't be drawn: \" + (error && error.message ? error.message : error));\n }\n });\n})();", ie = [
|
|
53
|
+
"default-src 'none'",
|
|
54
|
+
`script-src 'sha256-TfZZxJX+yWgzYLy7zqsMa85OJEaC+zNLIpKLDZVnUqA=' ${h}`,
|
|
55
|
+
"style-src 'unsafe-inline'",
|
|
56
|
+
"img-src data: blob:",
|
|
57
|
+
"connect-src 'none'",
|
|
58
|
+
"form-action 'none'",
|
|
59
|
+
"base-uri 'none'"
|
|
60
|
+
].join("; "), ae = `
|
|
61
|
+
html, body { margin: 0; width: ${t}px; height: 720px; overflow: hidden; background: #ffffff; color: #0f172a; font-family: ui-sans-serif, system-ui, sans-serif; }
|
|
62
|
+
body { box-sizing: border-box; padding: 40px 64px 48px; display: flex; flex-direction: column; gap: 24px; }
|
|
63
|
+
h1 { margin: 0; font-size: 52px; font-weight: 800; color: #1e3a8a; line-height: 1.15; text-align: center; }
|
|
64
|
+
.chart { position: relative; flex: 1; min-height: 0; }
|
|
65
|
+
#chart-error { display: none; margin: auto; font-size: 28px; color: #b91c1c; }
|
|
66
|
+
.failed .chart { display: none; }
|
|
67
|
+
.failed #chart-error { display: block; }`, oe = (e) => JSON.stringify(e).replace(/</g, "\\u003c");
|
|
68
|
+
function se(e, t) {
|
|
69
|
+
return `<!doctype html>
|
|
70
|
+
<html lang="en">
|
|
71
|
+
<head>
|
|
72
|
+
<meta charset="utf-8">
|
|
73
|
+
<meta http-equiv="Content-Security-Policy" content="${ie}">
|
|
74
|
+
<style>${ae}</style>
|
|
75
|
+
<script>${re}<\/script>
|
|
76
|
+
<script defer src="${h}" integrity="${ne}" crossorigin="anonymous"><\/script>
|
|
77
|
+
<script type="application/json" id="chart-config">${oe(t)}<\/script>
|
|
78
|
+
</head>
|
|
79
|
+
<body>
|
|
80
|
+
${e ? `<h1>${d(e)}</h1>` : ""}
|
|
81
|
+
<div class="chart"><canvas id="chart"></canvas></div>
|
|
82
|
+
<p id="chart-error"></p>
|
|
33
83
|
</body>
|
|
34
84
|
</html>`;
|
|
35
85
|
}
|
|
36
86
|
//#endregion
|
|
37
87
|
//#region src/core/definitions.ts
|
|
38
|
-
var
|
|
39
|
-
function
|
|
40
|
-
let
|
|
41
|
-
|
|
88
|
+
var g = "presentSlide", _ = "defineStoryboard", v = "presentPanel", ce = 4, le = 12, ue = 3, de = /^[0-9a-f]{12}$/, y = (e) => typeof e == "object" && !!e && !Array.isArray(e), b = (e) => typeof e == "string" ? e.trim() : "", x = (e, t) => e.toLowerCase() === t.toLowerCase(), S = (e) => typeof e == "number" && Number.isInteger(e), fe = "presentSlide needs slide and totalSlides (whole numbers, slide from 1 to totalSlides), and one of imagePrompt, html, markdown or chart", C = `presentSlide's slide is too long: keep its html, markdown or chart under ${r} characters`, w = `presentSlide's chart must be a Chart.js configuration: an object with type (${m.join(", ")}), data ({ labels, datasets }) and optionally options`;
|
|
89
|
+
function pe(e) {
|
|
90
|
+
let t = e;
|
|
91
|
+
if (typeof t == "string") try {
|
|
92
|
+
t = JSON.parse(t);
|
|
93
|
+
} catch {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
if (!y(t) || !y(t.data)) return null;
|
|
97
|
+
let n = t.type;
|
|
98
|
+
return !m.some((e) => e === n) || t.options !== void 0 && !y(t.options) ? null : t;
|
|
99
|
+
}
|
|
100
|
+
function me(e) {
|
|
101
|
+
let { slide: t, totalSlides: n, title: r, imagePrompt: i } = e, a = b(e.html), o = a ? "" : b(e.markdown), s = !a && !o && e.chart !== void 0 && e.chart !== null;
|
|
102
|
+
if (!S(t) || !S(n) || t < 1 || n < t || !a && !o && !s && !b(i)) return fe;
|
|
103
|
+
let c = s ? pe(e.chart) : null;
|
|
104
|
+
return s && !c ? w : Math.max(a.length, o.length, c ? JSON.stringify(c).length : 0) > 6e4 ? C : {
|
|
42
105
|
slide: t,
|
|
43
106
|
totalSlides: n,
|
|
44
107
|
title: typeof r == "string" ? r : "",
|
|
45
|
-
imagePrompt: a
|
|
108
|
+
imagePrompt: !a && !o && !c ? String(i) : "",
|
|
46
109
|
...a && { html: a },
|
|
110
|
+
...o && { markdown: o },
|
|
111
|
+
...c && { chart: c },
|
|
47
112
|
mode: e.mode === "steps" ? "steps" : "presentation"
|
|
48
113
|
};
|
|
49
114
|
}
|
|
50
|
-
var
|
|
115
|
+
var he = "teach its subject in at least two sentences, as a presenter speaking to the audience. Begin with the content itself, never with the slide or your plan: no \"This slide is about…\", \"The first slide shows…\", \"Let's unpack this one\", \"Next, I'll…\". A line about the slide is not an explanation.", T = ({ slide: e, totalSlides: t, title: n, mode: r }) => {
|
|
51
116
|
let i = n ? ` ("${n}")` : "";
|
|
52
117
|
if (r === "steps") {
|
|
53
118
|
let n = `Step ${e} of ${t}${i}`;
|
|
54
119
|
return e < t ? `${n} is now on the screen. Say what to do in this step, directly ("Crack two eggs into a bowl…", not "This step is about eggs"), then stop and wait while the user does it. When they say they're ready (next, done, go on), call presentSlide for step ${e + 1} with mode "steps". If they ask to go back or to see a step again, call presentSlide for that step.` : `${n}, the last one, is now on the screen. Say what to do, directly, then wrap up the guide once the user is done.`;
|
|
55
120
|
}
|
|
56
121
|
let a = `Slide ${e} of ${t}${i}`;
|
|
57
|
-
return e < t ? `${a} is now on the screen. Explain it: ${
|
|
58
|
-
},
|
|
122
|
+
return e < t ? `${a} is now on the screen. Explain it: ${he} Then, in this same reply and without waiting for the user, call presentSlide for slide ${e + 1}. If the user has asked you to stop, or asked something else, since the slideshow began, answer them instead of going on.` : `${a}, the last one, is now on the screen. Explain it: ${he} Then wrap up the slideshow.`;
|
|
123
|
+
}, ge = [
|
|
59
124
|
`For an HTML slide, instead of imagePrompt: the slide's content, the inside of <body> only (no <html>, <head> or <body> tags), for a ${t}x720 px canvas, which it should fill (start with a <div class="w-full h-full ...">). Style it with Tailwind CSS v4 classes, which are loaded for you: a clear layout, a large title (text-6xl or so), few words in large type, a color scheme, and inline SVG or emoji for icons and diagrams. There is no network: no <img> from URLs, no links to follow.`,
|
|
60
125
|
"Animate it so it builds up as you explain it, with MulmoCast's data-animation attributes (the same ones make it move in a movie of the slideshow): data-animation=\"animate\" with data-opacity=\"0,1\", data-translate-x, data-translate-y (px), data-scale, data-rotate (deg), data-width or data-height (\"0,80,%\"), each \"from,to\"; data-animation=\"counter\" with data-from, data-to, data-decimals, data-prefix, data-suffix; data-animation=\"typewriter\" (its text, or data-text). Give every one data-start and data-end in seconds, and optionally data-easing (linear, easeIn, easeOut, easeInOut); stagger the parts with later data-start values so they appear one after another over a few seconds (for example 0, 0.6, 1.2). Set the first frame inline too (style=\"opacity:0\" on an element that fades in).",
|
|
61
126
|
"CSS animations, transitions and scripts don't play: animate only with data-animation. A <style> for layout is allowed (and Google Fonts by @import)."
|
|
62
|
-
].join(" "),
|
|
127
|
+
].join(" "), _e = "For a Markdown slide, instead of imagePrompt: the slide in Markdown (GitHub's: headings, lists, bold, tables, code), with math in TeX between $...$ inline or $$...$$ for a displayed equation (on lines of its own). Start with a # heading, and keep it to what fits on one slide: a heading and a few lines, a list or an equation or two. Write a dollar sign that isn't math as \\$.", ve = `For a chart slide, instead of imagePrompt: a Chart.js configuration as JSON text, {"type": ..., "data": ...}: { type, data: { labels, datasets: [{ label, data, backgroundColor }] }, options }. type is one of ${m.join(", ")}. It is drawn under the slide's title, so leave out options.plugins.title; give the datasets colors, and the axes titles (options.scales.x.title) when their units aren't obvious. JSON values only: no functions.`, ye = "When the user asks for a slideshow (or to explain something with slides), plan four to six slides, then show them one at a time with presentSlide: slide 1 first, and each next slide only after you have explained the one on the screen. Explain the subject, not the slides: say what the slide teaches, not that a slide is about it. Go on to the last slide without asking whether to continue. A slide is a generated picture (imagePrompt), a chart (chart), a text slide in Markdown (markdown) or a designed slide in HTML (html): use a picture for a scene, an object or a place; a chart for numbers to compare, a trend or proportions; Markdown for equations and formulas (TeX math), definitions, short lists and small tables; and HTML for designed layouts, comparisons, timelines and diagrams. A picture model draws words, numbers and math badly, so they go on the other kinds; a slideshow can mix them. When the user asks for HTML slides (slides in HTML, an HTML presentation), this is the tool: make them HTML slides with presentSlide, one call per slide, not one HTML page. When the user wants to be shown how to do something they will do along with you (cooking, folding, fixing, an exercise), make it a step-by-step guide instead: mode \"steps\", one slide per step, and after each step wait for the user to say they are ready. Use generateImage for a single picture, not for slides.", E = {
|
|
63
128
|
type: "function",
|
|
64
|
-
name:
|
|
65
|
-
prompt:
|
|
66
|
-
description: "Show one slide of a slideshow, full screen: a picture generated from imagePrompt, or a slide written in HTML (html). Call it once per slide, in order, starting with slide 1. With mode \"steps\" it is a step-by-step guide: one slide per step, and the next step waits for the user.",
|
|
129
|
+
name: g,
|
|
130
|
+
prompt: ye,
|
|
131
|
+
description: "Show one slide of a slideshow, full screen: a picture generated from imagePrompt, a chart (chart), a slide written in Markdown with TeX math (markdown), or a slide written in HTML (html). Give one of the four. Call it once per slide, in order, starting with slide 1. With mode \"steps\" it is a step-by-step guide: one slide per step, and the next step waits for the user.",
|
|
67
132
|
parameters: {
|
|
68
133
|
type: "object",
|
|
69
134
|
properties: {
|
|
@@ -81,11 +146,19 @@ var w = "teach its subject in at least two sentences, as a presenter speaking to
|
|
|
81
146
|
},
|
|
82
147
|
imagePrompt: {
|
|
83
148
|
type: "string",
|
|
84
|
-
description: "For a picture slide: the picture, a clear illustration of its point, with the title as its only large text. Be concrete. For a step, show the action: hands, tools and the object. Leave it out for
|
|
149
|
+
description: "For a picture slide: the picture, a clear illustration of its point, with the title as its only large text. Be concrete. For a step, show the action: hands, tools and the object. Leave it out for a chart, Markdown or HTML slide."
|
|
85
150
|
},
|
|
86
151
|
html: {
|
|
87
152
|
type: "string",
|
|
88
|
-
description:
|
|
153
|
+
description: ge
|
|
154
|
+
},
|
|
155
|
+
markdown: {
|
|
156
|
+
type: "string",
|
|
157
|
+
description: _e
|
|
158
|
+
},
|
|
159
|
+
chart: {
|
|
160
|
+
type: "string",
|
|
161
|
+
description: ve
|
|
89
162
|
},
|
|
90
163
|
mode: {
|
|
91
164
|
type: "string",
|
|
@@ -100,49 +173,49 @@ var w = "teach its subject in at least two sentences, as a presenter speaking to
|
|
|
100
173
|
]
|
|
101
174
|
}
|
|
102
175
|
};
|
|
103
|
-
function
|
|
176
|
+
function D(e) {
|
|
104
177
|
let { totalPanels: t } = e;
|
|
105
|
-
if (!
|
|
178
|
+
if (!S(t) || t < 1 || t > 12) return "totalPanels must be a whole number from 1 to 12";
|
|
106
179
|
let n = [];
|
|
107
180
|
for (let t of Array.isArray(e.characters) ? e.characters : []) {
|
|
108
|
-
let e =
|
|
181
|
+
let e = y(t) ? b(t.name) : "", r = y(t) ? b(t.description) : "";
|
|
109
182
|
if (!e || !r) return "every character needs a name and a description";
|
|
110
|
-
if (n.some((t) =>
|
|
183
|
+
if (n.some((t) => x(t.name, e))) return `two characters are named ${e}`;
|
|
111
184
|
n.push({
|
|
112
185
|
name: e,
|
|
113
186
|
description: r
|
|
114
187
|
});
|
|
115
188
|
}
|
|
116
189
|
return n.length < 1 || n.length > 4 ? "a storyboard has 1 to 4 characters" : {
|
|
117
|
-
title:
|
|
118
|
-
style:
|
|
190
|
+
title: b(e.title),
|
|
191
|
+
style: b(e.style),
|
|
119
192
|
totalPanels: t,
|
|
120
193
|
characters: n,
|
|
121
194
|
interactive: e.interactive === !0
|
|
122
195
|
};
|
|
123
196
|
}
|
|
124
|
-
var
|
|
125
|
-
function
|
|
126
|
-
let { panel: t } = e, n =
|
|
127
|
-
if (!n || !r || !
|
|
128
|
-
let i = (e) => (Array.isArray(e) ? e : []).map(
|
|
197
|
+
var O = ({ title: e, id: t }) => `The cast of "${e}" is now on the screen. Introduce the characters briefly, then, in this same reply and without waiting for the user, call presentPanel for panel 1 with storyboardId "${t}". If the user has asked you to stop, or asked something else, answer them instead of going on.`, k = "presentPanel needs a storyboardId, a panel number (from 1) and an imagePrompt";
|
|
198
|
+
function A(e) {
|
|
199
|
+
let { panel: t } = e, n = b(e.storyboardId), r = b(e.imagePrompt);
|
|
200
|
+
if (!n || !r || !S(t) || t < 1) return null;
|
|
201
|
+
let i = (e) => (Array.isArray(e) ? e : []).map(b).filter(Boolean);
|
|
129
202
|
return {
|
|
130
203
|
storyboardId: n,
|
|
131
204
|
panel: t,
|
|
132
205
|
characters: i(e.characters),
|
|
133
206
|
imagePrompt: r,
|
|
134
|
-
caption:
|
|
207
|
+
caption: b(e.caption),
|
|
135
208
|
choices: i(e.choices).slice(0, 3)
|
|
136
209
|
};
|
|
137
210
|
}
|
|
138
|
-
function
|
|
211
|
+
function j(e, t, n) {
|
|
139
212
|
let { id: r, totalPanels: i } = e;
|
|
140
213
|
return n.length ? `Panel ${t} of ${i} is now on the screen, with the user's choices: ${n.map((e, t) => `${t + 1}. ${e}`).join(" ")} Tell this part of the story, then read the choices out and ask the user which one they pick, and wait for their answer. Then call presentPanel for panel ${t + 1} with storyboardId "${r}", going on the way they chose.` : t < i ? `Panel ${t} of ${i} is now on the screen. Tell this part of the story, then, in this same reply and without waiting for the user, call presentPanel for panel ${t + 1} with storyboardId "${r}". If the user has asked you to stop, or asked something else, since the story began, answer them instead of going on.` : `Panel ${t} of ${i}, the last one, is now on the screen. Tell this part of the story, then bring it to an end.`;
|
|
141
214
|
}
|
|
142
|
-
var
|
|
215
|
+
var M = "When the user asks for a story, a picture book, a comic or a storyboard, tell it in pictures: first call defineStoryboard with the art style and the characters who appear more than once (it draws a reference sheet for each, so they look the same in every panel), then show the panels one at a time with presentPanel, naming the characters in each, and tell each part of the story when its panel appears. Go on to the last panel without asking whether to continue, unless the story is interactive. When the user wants to decide what happens (an adventure, a story for a child who wants to choose), set interactive, and give two or three choices on two or three of the panels: the story waits there for the user's pick and goes on their way; it still ends at the last panel whichever way it goes. Use presentSlide to explain a topic, not to tell a story.", N = {
|
|
143
216
|
type: "function",
|
|
144
|
-
name:
|
|
145
|
-
prompt:
|
|
217
|
+
name: _,
|
|
218
|
+
prompt: M,
|
|
146
219
|
description: "Start a story told in pictures: set its art style and draw a reference sheet for each recurring character, shown as the cast. Then call presentPanel for each panel, in order.",
|
|
147
220
|
parameters: {
|
|
148
221
|
type: "object",
|
|
@@ -189,9 +262,9 @@ var N = "When the user asks for a story, a picture book, a comic or a storyboard
|
|
|
189
262
|
"characters"
|
|
190
263
|
]
|
|
191
264
|
}
|
|
192
|
-
},
|
|
265
|
+
}, P = {
|
|
193
266
|
type: "function",
|
|
194
|
-
name:
|
|
267
|
+
name: v,
|
|
195
268
|
description: "Show one panel of a storyboard made with defineStoryboard: a picture of the scene with its characters drawn as in their reference sheets, and a caption. Call it once per panel, in order, starting with panel 1.",
|
|
196
269
|
parameters: {
|
|
197
270
|
type: "object",
|
|
@@ -230,54 +303,60 @@ var N = "When the user asks for a story, a picture book, a comic or a storyboard
|
|
|
230
303
|
"imagePrompt"
|
|
231
304
|
]
|
|
232
305
|
}
|
|
233
|
-
},
|
|
234
|
-
function
|
|
235
|
-
let t =
|
|
306
|
+
}, F = (e) => typeof e == "object" && !!e && !Array.isArray(e), be = (e) => F(e) && typeof e.message == "string";
|
|
307
|
+
function I(e) {
|
|
308
|
+
let t = F(e?.data) ? e.data : {};
|
|
236
309
|
return {
|
|
237
310
|
...typeof t.imageData == "string" && { imageData: t.imageData },
|
|
238
311
|
...typeof t.imagePath == "string" && { imagePath: t.imagePath }
|
|
239
312
|
};
|
|
240
313
|
}
|
|
241
|
-
function
|
|
242
|
-
let t =
|
|
314
|
+
function L(e) {
|
|
315
|
+
let t = F(e?.data) ? e.data : {};
|
|
243
316
|
return typeof t.html == "string" ? t.html : "";
|
|
244
317
|
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
318
|
+
function R(e) {
|
|
319
|
+
let t = F(e?.data) ? e.data : {};
|
|
320
|
+
return F(t.chart) ? JSON.stringify(t.chart) : "";
|
|
321
|
+
}
|
|
322
|
+
var xe = (e) => !!I(e).imageData || !!L(e) || !!R(e);
|
|
323
|
+
function Se(e, t) {
|
|
324
|
+
let n = I(e), r = I(t);
|
|
248
325
|
if (n.imagePath && r.imagePath) return n.imagePath === r.imagePath;
|
|
249
326
|
if (n.imageData) return n.imageData === r.imageData;
|
|
250
|
-
let i =
|
|
251
|
-
|
|
327
|
+
let i = L(e);
|
|
328
|
+
if (i) return i === L(t);
|
|
329
|
+
let a = R(e);
|
|
330
|
+
return !!a && a === R(t);
|
|
252
331
|
}
|
|
253
|
-
var
|
|
254
|
-
async function
|
|
332
|
+
var z = (e, t) => e.userSpokeAt === void 0 || e.userSpokeAt > t, B = () => crypto.randomUUID().replace(/-/g, "").slice(0, 12), Ce = "artifacts/";
|
|
333
|
+
async function V(e, t) {
|
|
255
334
|
let n = e.files?.artifacts;
|
|
256
335
|
if (!e.app?.editImages || !n) return [];
|
|
257
336
|
let r = [];
|
|
258
|
-
for (let e of t) if (e.startsWith(
|
|
337
|
+
for (let e of t) if (e.startsWith(Ce)) try {
|
|
259
338
|
await n.exists(e.slice(10)) && r.push(e);
|
|
260
339
|
} catch {}
|
|
261
340
|
return r;
|
|
262
341
|
}
|
|
263
|
-
async function
|
|
342
|
+
async function H(e, t, n = []) {
|
|
264
343
|
let r = e.app, i = r?.editImages, a = r?.generateImage;
|
|
265
344
|
try {
|
|
266
345
|
let e;
|
|
267
346
|
if (n.length && i) e = await i(t, [...n]);
|
|
268
347
|
else if (a) e = await a(t);
|
|
269
348
|
else return { message: "image generation isn't available" };
|
|
270
|
-
return
|
|
349
|
+
return be(e) ? e : { message: "image generation returned an unrecognized result" };
|
|
271
350
|
} catch (e) {
|
|
272
351
|
return { message: `image generation failed: ${e instanceof Error ? e.message : String(e)}` };
|
|
273
352
|
}
|
|
274
353
|
}
|
|
275
|
-
var
|
|
276
|
-
function
|
|
354
|
+
var we = 50;
|
|
355
|
+
function U(e) {
|
|
277
356
|
let t = /* @__PURE__ */ new Map();
|
|
278
357
|
return (n) => {
|
|
279
358
|
let r = n.conversationId ?? "", i = t.get(r);
|
|
280
|
-
if (i === void 0 ? i = e() : t.delete(r), t.set(r, i), t.size >
|
|
359
|
+
if (i === void 0 ? i = e() : t.delete(r), t.set(r, i), t.size > we) {
|
|
281
360
|
let e = t.keys().next().value;
|
|
282
361
|
e !== void 0 && t.delete(e);
|
|
283
362
|
}
|
|
@@ -285,21 +364,112 @@ function H(e) {
|
|
|
285
364
|
};
|
|
286
365
|
}
|
|
287
366
|
//#endregion
|
|
367
|
+
//#region src/core/markdownSlide.ts
|
|
368
|
+
var W = "slide-md", Te = `
|
|
369
|
+
.${W} { box-sizing: border-box; width: ${t}px; height: 720px; padding: 56px 80px; overflow: hidden; display: flex; flex-direction: column; justify-content: center; gap: 0.5em; background: #ffffff; color: #0f172a; font-family: ui-sans-serif, system-ui, sans-serif; line-height: 1.35; }
|
|
370
|
+
.${W} > * { margin: 0; }
|
|
371
|
+
.${W} h1 { font-size: 1.9em; font-weight: 800; color: #1e3a8a; line-height: 1.15; }
|
|
372
|
+
.${W} h2 { font-size: 1.5em; font-weight: 700; color: #1e40af; line-height: 1.2; }
|
|
373
|
+
.${W} h3 { font-size: 1.2em; font-weight: 700; color: #334155; }
|
|
374
|
+
.${W} ul, .${W} ol { padding-left: 1.3em; display: flex; flex-direction: column; gap: 0.3em; }
|
|
375
|
+
.${W} ul { list-style: disc; }
|
|
376
|
+
.${W} ol { list-style: decimal; }
|
|
377
|
+
.${W} li > ul, .${W} li > ol { margin-top: 0.3em; font-size: 0.9em; }
|
|
378
|
+
.${W} li::marker { color: #2563eb; }
|
|
379
|
+
.${W} strong { font-weight: 700; color: #1e3a8a; }
|
|
380
|
+
.${W} em { font-style: italic; }
|
|
381
|
+
.${W} a { color: #2563eb; text-decoration: underline; }
|
|
382
|
+
.${W} code { font-family: ui-monospace, monospace; font-size: 0.85em; background: #f1f5f9; border-radius: 0.2em; padding: 0.05em 0.3em; }
|
|
383
|
+
.${W} pre { background: #0f172a; color: #e2e8f0; border-radius: 0.4em; padding: 0.6em 0.8em; font-size: 0.75em; overflow: hidden; }
|
|
384
|
+
.${W} pre code { background: none; padding: 0; color: inherit; }
|
|
385
|
+
.${W} blockquote { border-left: 0.2em solid #93c5fd; padding-left: 0.8em; color: #475569; font-style: italic; }
|
|
386
|
+
.${W} table { border-collapse: collapse; font-size: 0.85em; align-self: flex-start; }
|
|
387
|
+
.${W} th, .${W} td { border: 1px solid #cbd5e1; padding: 0.25em 0.7em; text-align: left; }
|
|
388
|
+
.${W} th { background: #eff6ff; font-weight: 700; }
|
|
389
|
+
.${W} hr { border: 0; border-top: 2px solid #e2e8f0; }
|
|
390
|
+
.${W} img { max-width: 100%; max-height: 60%; }
|
|
391
|
+
.${W} .math-display { display: block; text-align: center; font-size: 1.15em; }
|
|
392
|
+
.${W} math { font-family: "Latin Modern Math", "STIX Two Math", "Cambria Math", math; }
|
|
393
|
+
.${W} mtd { padding: 0.1em 0.4em; }
|
|
394
|
+
.${W} mtd:first-child { padding-left: 0; }
|
|
395
|
+
.${W} mtd:last-child { padding-right: 0; }
|
|
396
|
+
.${W} .math-error { color: #b91c1c; font-family: ui-monospace, monospace; }`;
|
|
397
|
+
function Ee(e) {
|
|
398
|
+
let t = e.split("\n").filter((e) => e.trim()).length, n = e.length;
|
|
399
|
+
return t <= 5 && n <= 250 ? 40 : t <= 8 && n <= 450 ? 34 : t <= 12 && n <= 700 ? 28 : 24;
|
|
400
|
+
}
|
|
401
|
+
var De = /^[ \t]*(?:\$\$([\s\S]+?)\$\$|\\\[([\s\S]+?)\\\])[ \t]*(?:\n|$)/, Oe = /^(?:\$\$(.+?)\$\$|\$(?!\s)((?:\\.|[^\\$\n])+?)(?<!\s)\$(?!\d)|\\\((.+?)\\\))/;
|
|
402
|
+
function ke(e) {
|
|
403
|
+
return [{
|
|
404
|
+
name: "blockMath",
|
|
405
|
+
level: "block",
|
|
406
|
+
start: (e) => {
|
|
407
|
+
let t = /(^|\n)(?=[ \t]*(?:\$\$|\\\[))/.exec(e);
|
|
408
|
+
return t ? t.index + (t[1] ?? "").length : void 0;
|
|
409
|
+
},
|
|
410
|
+
tokenizer(e) {
|
|
411
|
+
let t = De.exec(e);
|
|
412
|
+
if (t) return {
|
|
413
|
+
type: "blockMath",
|
|
414
|
+
raw: t[0],
|
|
415
|
+
text: (t[1] ?? t[2] ?? "").trim()
|
|
416
|
+
};
|
|
417
|
+
},
|
|
418
|
+
renderer: (t) => `<div class="math-display">${e(String(t.text), !0)}</div>\n`
|
|
419
|
+
}, {
|
|
420
|
+
name: "inlineMath",
|
|
421
|
+
level: "inline",
|
|
422
|
+
start: (e) => e.match(/(?<!\\)\$|\\\(/)?.index,
|
|
423
|
+
tokenizer(e) {
|
|
424
|
+
let t = Oe.exec(e);
|
|
425
|
+
if (t) return {
|
|
426
|
+
type: "inlineMath",
|
|
427
|
+
raw: t[0],
|
|
428
|
+
text: (t[1] ?? t[2] ?? t[3] ?? "").trim(),
|
|
429
|
+
display: t[1] !== void 0
|
|
430
|
+
};
|
|
431
|
+
},
|
|
432
|
+
renderer: (t) => e(String(t.text), t.display === !0)
|
|
433
|
+
}];
|
|
434
|
+
}
|
|
435
|
+
var Ae = /(<\/mi>|<\/mn>|<\/mrow>|<mo[^>]*>[)\]]<\/mo>)?(<mi(?: mathvariant="normal")?>[A-Za-z]{2,}<\/mi>)<mo>\u2061<\/mo>/g, je = "<mspace width=\"0.1667em\"></mspace>", Me = (e) => e.replace(Ae, (e, t, n) => `${t ? t + je : ""}${n}<mo lspace="0" rspace="0.1667em">\u2061</mo>`);
|
|
436
|
+
async function G(e) {
|
|
437
|
+
let [{ Marked: t }, { default: n }] = await Promise.all([import("marked"), import("katex")]), r = (e, t) => {
|
|
438
|
+
try {
|
|
439
|
+
return Me(n.renderToString(e, {
|
|
440
|
+
output: "mathml",
|
|
441
|
+
displayMode: t,
|
|
442
|
+
throwOnError: !0
|
|
443
|
+
}));
|
|
444
|
+
} catch {
|
|
445
|
+
return `<code class="math-error">${d(e)}</code>`;
|
|
446
|
+
}
|
|
447
|
+
}, i = new t({
|
|
448
|
+
gfm: !0,
|
|
449
|
+
breaks: !1
|
|
450
|
+
});
|
|
451
|
+
i.use({ extensions: ke(r) });
|
|
452
|
+
let a = await i.parse(e);
|
|
453
|
+
return `<style>${Te}</style>
|
|
454
|
+
<div class="${W}" data-fit style="font-size: ${Ee(e)}px">
|
|
455
|
+
${a}</div>`;
|
|
456
|
+
}
|
|
457
|
+
//#endregion
|
|
288
458
|
//#region src/core/records.ts
|
|
289
|
-
var
|
|
290
|
-
function
|
|
291
|
-
let t =
|
|
292
|
-
return t ||
|
|
293
|
-
}
|
|
294
|
-
function
|
|
295
|
-
let r =
|
|
296
|
-
r ||
|
|
459
|
+
var K = "slideshows", q = "storyboards", J = {}, Y = /* @__PURE__ */ new WeakMap(), X = /* @__PURE__ */ new WeakMap();
|
|
460
|
+
function Ne(e) {
|
|
461
|
+
let t = Y.get(e);
|
|
462
|
+
return t || Y.set(e, t = /* @__PURE__ */ new Map()), t;
|
|
463
|
+
}
|
|
464
|
+
function Pe(t, n) {
|
|
465
|
+
let r = X.get(t);
|
|
466
|
+
r || X.set(t, r = /* @__PURE__ */ new Map());
|
|
297
467
|
let i = r.get(n);
|
|
298
468
|
return i || r.set(n, i = e()), i;
|
|
299
469
|
}
|
|
300
|
-
var
|
|
301
|
-
async function
|
|
302
|
-
let n =
|
|
470
|
+
var Fe = (e, t) => `${e}/${t}.json`;
|
|
471
|
+
async function Ie(e, t) {
|
|
472
|
+
let n = Ne(e ?? J), r = n.get(t);
|
|
303
473
|
if (r) return r;
|
|
304
474
|
if (!e) return null;
|
|
305
475
|
try {
|
|
@@ -309,14 +479,14 @@ async function X(e, t) {
|
|
|
309
479
|
return null;
|
|
310
480
|
}
|
|
311
481
|
}
|
|
312
|
-
async function
|
|
313
|
-
return
|
|
482
|
+
async function Le(e, t, n) {
|
|
483
|
+
return de.test(n) ? Ie(e, Fe(t, n)) : null;
|
|
314
484
|
}
|
|
315
|
-
async function
|
|
316
|
-
let i =
|
|
317
|
-
return
|
|
318
|
-
let t = r(await
|
|
319
|
-
if (
|
|
485
|
+
async function Z(e, t, n, r) {
|
|
486
|
+
let i = Fe(t, n), a = e ?? J;
|
|
487
|
+
return Pe(a, i)(async () => {
|
|
488
|
+
let t = r(await Ie(e, i));
|
|
489
|
+
if (Ne(a).set(i, t), !e) return !1;
|
|
320
490
|
try {
|
|
321
491
|
return await e.write(i, JSON.stringify(t, null, 2)), !0;
|
|
322
492
|
} catch (e) {
|
|
@@ -324,12 +494,12 @@ async function Q(e, t, n, r) {
|
|
|
324
494
|
}
|
|
325
495
|
});
|
|
326
496
|
}
|
|
327
|
-
var
|
|
328
|
-
function
|
|
497
|
+
var Q = (e) => `the ${e} could not be saved, so it lasts only until the app or server restarts`, Re = 6e4;
|
|
498
|
+
function ze() {
|
|
329
499
|
let e = /* @__PURE__ */ new Map();
|
|
330
500
|
return { claim: (t) => {
|
|
331
501
|
let n = Date.now();
|
|
332
|
-
for (let [t, r] of e) n - r.at >
|
|
502
|
+
for (let [t, r] of e) n - r.at > Re && e.delete(t);
|
|
333
503
|
let r = e.get(t);
|
|
334
504
|
if (r) return { earlier: r.shown };
|
|
335
505
|
let i = () => void 0, a = new Promise((e) => i = e);
|
|
@@ -343,7 +513,7 @@ function pe() {
|
|
|
343
513
|
}
|
|
344
514
|
//#endregion
|
|
345
515
|
//#region src/core/presentSlide.ts
|
|
346
|
-
function
|
|
516
|
+
function Be({ slide: e, totalSlides: t, mode: n }) {
|
|
347
517
|
return n === "steps" ? {
|
|
348
518
|
step: e,
|
|
349
519
|
total: t,
|
|
@@ -361,26 +531,28 @@ function me({ slide: e, totalSlides: t, mode: n }) {
|
|
|
361
531
|
nextCall: `call presentSlide for slide ${e + 1} of ${t}`
|
|
362
532
|
};
|
|
363
533
|
}
|
|
364
|
-
var
|
|
534
|
+
var Ve = (e, { slide: t, totalSlides: n, title: r, imagePrompt: i, html: a, markdown: o, chart: s }) => JSON.stringify([
|
|
365
535
|
e,
|
|
366
536
|
t,
|
|
367
537
|
n,
|
|
368
538
|
r,
|
|
369
539
|
i,
|
|
370
|
-
a
|
|
371
|
-
|
|
540
|
+
a,
|
|
541
|
+
o,
|
|
542
|
+
s
|
|
543
|
+
]), He = U(() => ({
|
|
372
544
|
latest: {
|
|
373
545
|
presentation: null,
|
|
374
546
|
steps: null
|
|
375
547
|
},
|
|
376
548
|
lastShown: null,
|
|
377
|
-
repeats:
|
|
549
|
+
repeats: ze()
|
|
378
550
|
}));
|
|
379
|
-
function
|
|
551
|
+
function Ue(e, t) {
|
|
380
552
|
let n = e.latest[t.mode], r = n?.totalSlides === t.totalSlides && (t.slide !== 1 || n.firstTitle === t.title);
|
|
381
553
|
if (n && r) return n;
|
|
382
554
|
let i = {
|
|
383
|
-
id:
|
|
555
|
+
id: B(),
|
|
384
556
|
mode: t.mode,
|
|
385
557
|
totalSlides: t.totalSlides,
|
|
386
558
|
firstTitle: t.slide === 1 ? t.title : "",
|
|
@@ -390,7 +562,7 @@ function _e(e, t) {
|
|
|
390
562
|
};
|
|
391
563
|
return e.latest[t.mode] = i, i;
|
|
392
564
|
}
|
|
393
|
-
function
|
|
565
|
+
function $(e, t, n, r) {
|
|
394
566
|
t.current = n.slide, t.shownAt = Date.now(), e.lastShown = t;
|
|
395
567
|
let i = n.mode === "steps" ? "step" : "slide", { uuid: a, ...o } = r;
|
|
396
568
|
return {
|
|
@@ -398,10 +570,10 @@ function ve(e, t, n, r) {
|
|
|
398
570
|
message: `${i} ${n.slide} of ${n.totalSlides} is on the screen again, as it was`,
|
|
399
571
|
instructions: T(n),
|
|
400
572
|
instructionsRequired: !0,
|
|
401
|
-
sequence:
|
|
573
|
+
sequence: Be(n)
|
|
402
574
|
};
|
|
403
575
|
}
|
|
404
|
-
function
|
|
576
|
+
function We(e, t) {
|
|
405
577
|
if (e.mode !== "steps") return e.title ? `A presentation slide titled "${e.title}". ${e.imagePrompt}` : e.imagePrompt;
|
|
406
578
|
let n = e.title ? `, "${e.title}"` : "";
|
|
407
579
|
return [
|
|
@@ -410,12 +582,21 @@ function ye(e, t) {
|
|
|
410
582
|
"Show the action clearly, with little or no text."
|
|
411
583
|
].filter(Boolean).join(" ");
|
|
412
584
|
}
|
|
413
|
-
async function
|
|
585
|
+
async function Ge(e, t, n) {
|
|
414
586
|
if (n.html) return {
|
|
415
587
|
html: n.html,
|
|
416
588
|
prompt: ""
|
|
417
589
|
};
|
|
418
|
-
|
|
590
|
+
if (n.chart) return {
|
|
591
|
+
chart: n.chart,
|
|
592
|
+
prompt: ""
|
|
593
|
+
};
|
|
594
|
+
if (n.markdown) return {
|
|
595
|
+
html: await G(n.markdown),
|
|
596
|
+
markdown: n.markdown,
|
|
597
|
+
prompt: ""
|
|
598
|
+
};
|
|
599
|
+
let r = t.slides.get(n.slide - 1), i = n.mode === "steps" ? I(r).imagePath : void 0, a = i ? await V(e, [i]) : [], o = We(n, a.length > 0), s = await H(e, o, a), { imageData: c, imagePath: l } = I(s);
|
|
419
600
|
return c ? {
|
|
420
601
|
imageData: c,
|
|
421
602
|
...l && { imagePath: l },
|
|
@@ -425,12 +606,12 @@ async function be(e, t, n) {
|
|
|
425
606
|
sequence: null
|
|
426
607
|
} };
|
|
427
608
|
}
|
|
428
|
-
async function
|
|
429
|
-
let r = await
|
|
609
|
+
async function Ke(e, t, n) {
|
|
610
|
+
let r = await Ge(e, t, n);
|
|
430
611
|
if ("failed" in r) return r.failed;
|
|
431
|
-
let { imageData: i, imagePath: a, html: o,
|
|
612
|
+
let { imageData: i, imagePath: a, html: o, markdown: s, chart: c, prompt: l } = r, u = t.id, d = await Z(e.files?.artifacts, K, u, (e) => {
|
|
432
613
|
let t = e ?? {
|
|
433
|
-
id:
|
|
614
|
+
id: u,
|
|
434
615
|
title: "",
|
|
435
616
|
mode: n.mode,
|
|
436
617
|
totalSlides: n.totalSlides,
|
|
@@ -440,40 +621,44 @@ async function xe(e, t, n) {
|
|
|
440
621
|
title: n.title,
|
|
441
622
|
imagePrompt: n.imagePrompt,
|
|
442
623
|
...a && { imagePath: a },
|
|
443
|
-
...o && { html: o }
|
|
624
|
+
...o && { html: o },
|
|
625
|
+
...s && { markdown: s },
|
|
626
|
+
...c && { chart: c }
|
|
444
627
|
}, t;
|
|
445
|
-
}),
|
|
628
|
+
}), f = {
|
|
446
629
|
...i && { imageData: i },
|
|
447
630
|
...a && { imagePath: a },
|
|
448
631
|
...o && { html: o },
|
|
449
|
-
|
|
450
|
-
|
|
632
|
+
...s && { markdown: s },
|
|
633
|
+
...c && { chart: c },
|
|
634
|
+
prompt: l,
|
|
635
|
+
slideshowId: u,
|
|
451
636
|
slide: n.slide,
|
|
452
637
|
totalSlides: n.totalSlides,
|
|
453
638
|
title: n.title,
|
|
454
639
|
mode: n.mode
|
|
455
|
-
},
|
|
640
|
+
}, p = n.mode === "steps" ? "step" : "slide";
|
|
456
641
|
return {
|
|
457
|
-
data:
|
|
642
|
+
data: f,
|
|
458
643
|
title: n.title || `Slide ${n.slide}`,
|
|
459
644
|
message: [
|
|
460
|
-
`${
|
|
645
|
+
`${p} ${n.slide} of ${n.totalSlides} of slideshow "${u}" is on the screen`,
|
|
461
646
|
a ? `saved to ${a}` : "",
|
|
462
|
-
|
|
647
|
+
d ? "" : Q("slideshow")
|
|
463
648
|
].filter(Boolean).join("; "),
|
|
464
649
|
instructions: T(n),
|
|
465
650
|
instructionsRequired: !0,
|
|
466
|
-
sequence:
|
|
651
|
+
sequence: Be(n)
|
|
467
652
|
};
|
|
468
653
|
}
|
|
469
|
-
async function
|
|
470
|
-
let n =
|
|
654
|
+
async function qe(e, t) {
|
|
655
|
+
let n = me(t);
|
|
471
656
|
if (typeof n == "string") return {
|
|
472
657
|
message: n,
|
|
473
658
|
sequence: null
|
|
474
659
|
};
|
|
475
|
-
let r =
|
|
476
|
-
if (a && n.slide > i.current && i.current > 0 && !
|
|
660
|
+
let r = He(e), i = Ue(r, n), a = n.mode === "steps";
|
|
661
|
+
if (a && n.slide > i.current && i.current > 0 && !z(e, i.shownAt)) {
|
|
477
662
|
console.info(`[sequence] holding step ${n.slide} for the user`);
|
|
478
663
|
let e = i.shownAt === Infinity ? "is still being drawn" : "is still on the screen";
|
|
479
664
|
return {
|
|
@@ -482,15 +667,15 @@ async function Se(e, t) {
|
|
|
482
667
|
};
|
|
483
668
|
}
|
|
484
669
|
let o = a ? i.slides.get(n.slide) : void 0;
|
|
485
|
-
if (o) return
|
|
670
|
+
if (o) return Se(e.currentResult, o) ? {
|
|
486
671
|
message: `step ${n.slide} of ${n.totalSlides} is already on the screen`,
|
|
487
672
|
cancelled: !0
|
|
488
|
-
} :
|
|
489
|
-
let s = r.repeats.claim(
|
|
673
|
+
} : $(r, i, n, o);
|
|
674
|
+
let s = r.repeats.claim(Ve(i.id, n));
|
|
490
675
|
if ("earlier" in s) {
|
|
491
|
-
if (!await s.earlier) return
|
|
676
|
+
if (!await s.earlier) return qe(e, t);
|
|
492
677
|
let a = i.slides.get(n.slide);
|
|
493
|
-
return a && r.lastShown !== i ?
|
|
678
|
+
return a && r.lastShown !== i ? $(r, i, n, a) : {
|
|
494
679
|
message: `slide ${n.slide} of ${n.totalSlides} is already on the screen`,
|
|
495
680
|
cancelled: !0
|
|
496
681
|
};
|
|
@@ -502,22 +687,22 @@ async function Se(e, t) {
|
|
|
502
687
|
i.current = n.slide, i.shownAt = Infinity;
|
|
503
688
|
let u = !1;
|
|
504
689
|
try {
|
|
505
|
-
let t = await
|
|
506
|
-
return u =
|
|
690
|
+
let t = await Ke(e, i, n);
|
|
691
|
+
return u = xe(t), u && (i.slides.set(n.slide, t), i.current = n.slide, i.shownAt = Date.now(), r.lastShown = i), t;
|
|
507
692
|
} finally {
|
|
508
693
|
c(u), !u && i.current === n.slide && (i.current = l.current, i.shownAt = l.shownAt);
|
|
509
694
|
}
|
|
510
695
|
}
|
|
511
696
|
//#endregion
|
|
512
697
|
//#region src/core/storyboard.ts
|
|
513
|
-
var
|
|
698
|
+
var Je = ({ id: e, title: t, totalPanels: n }) => ({
|
|
514
699
|
step: 0,
|
|
515
700
|
total: n,
|
|
516
701
|
kind: "story",
|
|
517
702
|
label: `The cast of "${t}"`,
|
|
518
703
|
onShown: "introduce the characters",
|
|
519
704
|
nextCall: `call presentPanel for panel 1 of ${n} with storyboardId "${e}"`
|
|
520
|
-
}),
|
|
705
|
+
}), Ye = ({ id: e, totalPanels: t }, n, r) => ({
|
|
521
706
|
step: n,
|
|
522
707
|
total: t,
|
|
523
708
|
kind: "story",
|
|
@@ -525,21 +710,21 @@ var Ce = ({ id: e, title: t, totalPanels: n }) => ({
|
|
|
525
710
|
onShown: "tell that part of the story",
|
|
526
711
|
nextCall: `call presentPanel for panel ${n + 1} of ${t} with storyboardId "${e}"`,
|
|
527
712
|
...r.length > 0 && { waitsForUser: !0 }
|
|
528
|
-
}),
|
|
529
|
-
async function
|
|
530
|
-
let n =
|
|
713
|
+
}), Xe = (e, t) => e ? `${e}. ${t}` : t, Ze = (e, { name: t, description: n }) => Xe(e, `Character reference sheet of ${t}: ${n}. Full body, front, side and back views, on a plain white background. No text or labels.`);
|
|
714
|
+
async function Qe(e, t) {
|
|
715
|
+
let n = D(t);
|
|
531
716
|
if (typeof n == "string") return {
|
|
532
717
|
message: n,
|
|
533
718
|
sequence: null
|
|
534
719
|
};
|
|
535
|
-
let r = await Promise.all(n.characters.map((t) =>
|
|
720
|
+
let r = await Promise.all(n.characters.map((t) => H(e, Ze(n.style, t)))), i = r.map(I), a = r.find((e, t) => !i[t]?.imageData);
|
|
536
721
|
if (i.every(({ imageData: e }) => !e) && a) return {
|
|
537
722
|
...a,
|
|
538
723
|
message: `the character sheets couldn't be made: ${a.message}`,
|
|
539
724
|
sequence: null
|
|
540
725
|
};
|
|
541
726
|
let o = {
|
|
542
|
-
id:
|
|
727
|
+
id: B(),
|
|
543
728
|
...n,
|
|
544
729
|
characters: n.characters.map((e, t) => {
|
|
545
730
|
let n = i[t]?.imagePath;
|
|
@@ -549,7 +734,7 @@ async function De(e, t) {
|
|
|
549
734
|
};
|
|
550
735
|
}),
|
|
551
736
|
panels: {}
|
|
552
|
-
}, s = await
|
|
737
|
+
}, s = await Z(e.files?.artifacts, q, o.id, () => o), c = o.characters.filter((e) => e.imagePath).map((e) => `${e.name}: ${e.imagePath}`), l = n.characters.map(({ name: e }, t) => i[t]?.imageData ? null : `${e} (${r[t]?.message ?? ""})`).filter((e) => !!e), u = i.find((e) => e.imageData)?.imageData;
|
|
553
738
|
return {
|
|
554
739
|
data: {
|
|
555
740
|
storyboardId: o.id,
|
|
@@ -570,39 +755,39 @@ async function De(e, t) {
|
|
|
570
755
|
`storyboard "${o.id}" is ready with ${o.totalPanels} panels; the cast is on the screen`,
|
|
571
756
|
c.length ? `character sheets saved to ${c.join(", ")}` : "",
|
|
572
757
|
l.length ? `no sheet for ${l.join("; ")}: they will be drawn from their description` : "",
|
|
573
|
-
s ? "" :
|
|
758
|
+
s ? "" : Q("storyboard")
|
|
574
759
|
].filter(Boolean).join("; "),
|
|
575
|
-
instructions:
|
|
760
|
+
instructions: O(o),
|
|
576
761
|
instructionsRequired: !0,
|
|
577
|
-
sequence:
|
|
762
|
+
sequence: Je(o)
|
|
578
763
|
};
|
|
579
764
|
}
|
|
580
|
-
function
|
|
581
|
-
let r = [
|
|
765
|
+
function $e(e, t, n) {
|
|
766
|
+
let r = [Xe(e.style, `Panel ${t.panel} of ${e.totalPanels} of the illustrated story "${e.title}". ${t.imagePrompt}`)], i = 0, a = n.map(({ character: e, hasSheet: t }) => t ? `${e.name} is the character in reference image ${++i}` : `${e.name}: ${e.description}`);
|
|
582
767
|
return a.length && r.push(`${a.join(". ")}.`), i && r.push("Draw each character exactly as in their reference image: the same face, hair, clothes and colors. Use the reference images only for how the characters look, not for their pose or the background."), r.push("No captions, speech bubbles or other text in the picture."), r.join(" ");
|
|
583
768
|
}
|
|
584
|
-
async function
|
|
769
|
+
async function et(e, t, n) {
|
|
585
770
|
let r = [], i = [];
|
|
586
771
|
for (let a of n.characters) {
|
|
587
|
-
let n = t.characters.find((e) =>
|
|
772
|
+
let n = t.characters.find((e) => x(e.name, a));
|
|
588
773
|
if (!n) r.push(a);
|
|
589
774
|
else if (!i.some((e) => e.character === n)) {
|
|
590
|
-
let [t] = n.imagePath ? await
|
|
775
|
+
let [t] = n.imagePath ? await V(e, [n.imagePath]) : [];
|
|
591
776
|
i.push({
|
|
592
777
|
character: n,
|
|
593
778
|
sheet: t ?? null
|
|
594
779
|
});
|
|
595
780
|
}
|
|
596
781
|
}
|
|
597
|
-
let a = i.map(({ sheet: e }) => e).filter((e) => !!e), o =
|
|
782
|
+
let a = i.map(({ sheet: e }) => e).filter((e) => !!e), o = $e(t, n, i.map(({ character: e, sheet: t }) => ({
|
|
598
783
|
character: e,
|
|
599
784
|
hasSheet: !!t
|
|
600
|
-
}))), s = await
|
|
785
|
+
}))), s = await H(e, o, a), { imageData: c, imagePath: l } = I(s);
|
|
601
786
|
if (!c) return {
|
|
602
787
|
...s,
|
|
603
788
|
sequence: null
|
|
604
789
|
};
|
|
605
|
-
let u = n.panel < t.totalPanels && n.choices.length >= 2 ? n.choices : [], d = await
|
|
790
|
+
let u = n.panel < t.totalPanels && n.choices.length >= 2 ? n.choices : [], d = await Z(e.files?.artifacts, q, t.id, (e) => {
|
|
606
791
|
let r = e ?? t;
|
|
607
792
|
return u.length && (r.interactive = !0), r.panels[String(n.panel)] = {
|
|
608
793
|
caption: n.caption,
|
|
@@ -628,25 +813,25 @@ async function ke(e, t, n) {
|
|
|
628
813
|
`panel ${n.panel} of ${t.totalPanels} is on the screen`,
|
|
629
814
|
l ? `saved to ${l}` : "",
|
|
630
815
|
r.length ? `not in the cast, so drawn from the prompt alone: ${r.join(", ")}` : "",
|
|
631
|
-
d ? "" :
|
|
816
|
+
d ? "" : Q("storyboard")
|
|
632
817
|
].filter(Boolean).join("; "),
|
|
633
|
-
instructions:
|
|
818
|
+
instructions: j(t, n.panel, u),
|
|
634
819
|
instructionsRequired: !0,
|
|
635
|
-
sequence:
|
|
820
|
+
sequence: Ye(t, n.panel, u)
|
|
636
821
|
};
|
|
637
822
|
}
|
|
638
|
-
var
|
|
639
|
-
repeats:
|
|
823
|
+
var tt = U(() => ({
|
|
824
|
+
repeats: ze(),
|
|
640
825
|
awaitingChoice: /* @__PURE__ */ new Map()
|
|
641
826
|
}));
|
|
642
|
-
async function
|
|
643
|
-
let n =
|
|
827
|
+
async function nt(e, t) {
|
|
828
|
+
let n = A(t);
|
|
644
829
|
if (!n) return {
|
|
645
|
-
message:
|
|
830
|
+
message: k,
|
|
646
831
|
sequence: null
|
|
647
832
|
};
|
|
648
|
-
let { storyboardId: r, panel: i } = n, { repeats: a, awaitingChoice: o } =
|
|
649
|
-
if (s && i > s.panel && !
|
|
833
|
+
let { storyboardId: r, panel: i } = n, { repeats: a, awaitingChoice: o } = tt(e), s = o.get(r);
|
|
834
|
+
if (s && i > s.panel && !z(e, s.shownAt)) return console.info(`[sequence] holding panel ${i} for the user`), {
|
|
650
835
|
message: s.shownAt === Infinity ? `panel ${i} was not shown: panel ${s.panel} is still being drawn. Wait for it before going on.` : `panel ${i} was not shown: the user hasn't picked a choice yet, and panel ${s.panel} is still on the screen. Wait for their answer.`,
|
|
651
836
|
cancelled: !0
|
|
652
837
|
};
|
|
@@ -654,7 +839,7 @@ async function je(e, t) {
|
|
|
654
839
|
if ("earlier" in c) return await c.earlier ? {
|
|
655
840
|
message: `panel ${i} is already on the screen`,
|
|
656
841
|
cancelled: !0
|
|
657
|
-
} :
|
|
842
|
+
} : nt(e, t);
|
|
658
843
|
let { settle: l } = c, u = {
|
|
659
844
|
panel: i,
|
|
660
845
|
shownAt: Infinity
|
|
@@ -662,7 +847,7 @@ async function je(e, t) {
|
|
|
662
847
|
o.set(r, u);
|
|
663
848
|
let f = () => o.get(r) === u, p = !1;
|
|
664
849
|
try {
|
|
665
|
-
let t = await
|
|
850
|
+
let t = await Le(e.files?.artifacts, q, r);
|
|
666
851
|
if (!t) return {
|
|
667
852
|
message: `there is no storyboard "${r}"; call defineStoryboard first`,
|
|
668
853
|
sequence: null
|
|
@@ -671,8 +856,8 @@ async function je(e, t) {
|
|
|
671
856
|
message: `storyboard "${t.id}" has ${t.totalPanels} panels`,
|
|
672
857
|
sequence: null
|
|
673
858
|
};
|
|
674
|
-
let a = await
|
|
675
|
-
p = !!
|
|
859
|
+
let a = await et(e, t, n);
|
|
860
|
+
p = !!I(a).imageData;
|
|
676
861
|
let s = a.data;
|
|
677
862
|
return p && f() && (s?.choices?.length ? o.set(r, {
|
|
678
863
|
panel: i,
|
|
@@ -684,21 +869,21 @@ async function je(e, t) {
|
|
|
684
869
|
}
|
|
685
870
|
//#endregion
|
|
686
871
|
//#region src/core/index.ts
|
|
687
|
-
var
|
|
688
|
-
toolDefinition:
|
|
872
|
+
var rt = {
|
|
873
|
+
toolDefinition: E,
|
|
689
874
|
generatingMessage: "Making the slide...",
|
|
690
875
|
isEnabled: () => !0,
|
|
691
|
-
execute: (e, t) =>
|
|
692
|
-
},
|
|
693
|
-
toolDefinition:
|
|
876
|
+
execute: (e, t) => qe(e, t)
|
|
877
|
+
}, it = {
|
|
878
|
+
toolDefinition: N,
|
|
694
879
|
generatingMessage: "Drawing the characters...",
|
|
695
880
|
isEnabled: () => !0,
|
|
696
|
-
execute: (e, t) =>
|
|
697
|
-
},
|
|
698
|
-
toolDefinition:
|
|
881
|
+
execute: (e, t) => Qe(e, t)
|
|
882
|
+
}, at = {
|
|
883
|
+
toolDefinition: P,
|
|
699
884
|
generatingMessage: "Drawing the panel...",
|
|
700
885
|
isEnabled: () => !0,
|
|
701
|
-
execute: (e, t) =>
|
|
886
|
+
execute: (e, t) => nt(e, t)
|
|
702
887
|
};
|
|
703
888
|
//#endregion
|
|
704
|
-
export {
|
|
889
|
+
export { T as A, M as C, me as D, A as E, s as F, p as I, n as L, se as M, r as N, D as O, o as P, t as R, C as S, j as T, E as _, q as a, fe as b, _ as c, ue as d, le as f, g, P as h, K as i, m as j, x as k, N as l, v as m, at as n, Le as o, k as p, rt as r, G as s, it as t, ce as u, ye as v, O as w, w as x, de as y, te as z };
|