@gui-chat-plugin/sequence 0.6.3 → 0.7.1

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.
@@ -154,33 +154,33 @@ var t = 1280, n = 720, r = 6e4, i = "https://cdn.jsdelivr.net/npm/@tailwindcss/b
154
154
  "<": "&lt;",
155
155
  ">": "&gt;",
156
156
  "\"": "&quot;"
157
- }, p = (e) => e.replace(/[&<>"]/g, (e) => f[e] ?? e), m = (e) => e.replace(/<(?=(meta|base|link)\b)/gi, "&lt;").replace(/shadowroot/gi, "data-no-shadow-root"), h = "*, *::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 = `
157
+ }, p = (e) => e.replace(/[&<>"]/g, (e) => f[e] ?? e), m = (e) => e.replace(/<(?=(meta|base|link)\b)/gi, "&lt;").replace(/shadowroot/gi, "data-no-shadow-root"), h = "*, *::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; }", g = `
158
158
  html, body { margin: 0; width: ${t}px; height: 720px; overflow: hidden; }
159
159
  html:not(.ready) body { visibility: hidden; }
160
- ${h}`, g = "{{image}}", _ = /(\bsrc\s*=\s*["']?|\burl\(\s*["']?)(?:\{\{image\}\}|%7B%7Bimage%7D%7D)/gi, te = /^data:image\/[a-z0-9.+-]+;base64,[a-z0-9+/=]+$/i, ne = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7", v = /(<pre\b[\s\S]*?<\/pre>|<code\b[\s\S]*?<\/code>)/gi, y = (e) => e.split(v).some((e, t) => t % 2 == 0 && new RegExp(_.source, "i").test(e)), re = {
160
+ ${h}`, _ = "{{image}}", v = /(\bsrc\s*=\s*["']?|\burl\(\s*["']?)(?:\{\{image\}\}|%7B%7Bimage%7D%7D)/gi, ee = /^data:image\/[a-z0-9.+-]+;base64,[a-z0-9+/=]+$/i, te = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7", y = /(<pre\b[\s\S]*?<\/pre>|<code\b[\s\S]*?<\/code>)/gi, b = (e) => e.split(y).some((e, t) => t % 2 == 0 && new RegExp(v.source, "i").test(e)), ne = {
161
161
  "&amp;": "&",
162
162
  "&lt;": "<",
163
163
  "&gt;": ">",
164
164
  "&quot;": "\"",
165
165
  "&#39;": "'"
166
- }, ie = (e) => {
167
- for (let t of e.split(v).filter((e, t) => t % 2 == 0)) for (let e of t.match(/<img\b[^>]*>/gi) ?? []) {
168
- if (!new RegExp(_.source, "i").test(e)) continue;
166
+ }, re = (e) => {
167
+ for (let t of e.split(y).filter((e, t) => t % 2 == 0)) for (let e of t.match(/<img\b[^>]*>/gi) ?? []) {
168
+ if (!new RegExp(v.source, "i").test(e)) continue;
169
169
  let t = /\balt\s*=\s*(?:"([^"]*)"|'([^']*)')/i.exec(e);
170
- return (t?.[1] ?? t?.[2] ?? "").replace(/&(?:amp|lt|gt|quot|#39);/g, (e) => re[e] ?? e).trim();
170
+ return (t?.[1] ?? t?.[2] ?? "").replace(/&(?:amp|lt|gt|quot|#39);/g, (e) => ne[e] ?? e).trim();
171
171
  }
172
172
  return "";
173
- }, ae = (e, t) => {
174
- let n = t && te.test(t) ? t : ne;
175
- return e.split(v).map((e, t) => t % 2 == 1 ? e : e.replace(_, (e, t) => t + n)).join("");
173
+ }, ie = (e, t) => {
174
+ let n = t && ee.test(t) ? t : te;
175
+ return e.split(y).map((e, t) => t % 2 == 1 ? e : e.replace(v, (e, t) => t + n)).join("");
176
176
  };
177
- function oe(e) {
177
+ function ae(e) {
178
178
  return `<!doctype html>
179
179
  <html lang="en">
180
180
  <head>
181
181
  <meta charset="utf-8">
182
182
  <meta http-equiv="Content-Security-Policy" content="${d}">
183
- <style id="slide-base">${ee}</style>
183
+ <style id="slide-base">${g}</style>
184
184
  <script>${u}<\/script>
185
185
  <script defer src="${i}" integrity="${a}" crossorigin="anonymous"><\/script>
186
186
  </head>
@@ -191,7 +191,7 @@ ${m(e)}
191
191
  }
192
192
  //#endregion
193
193
  //#region src/core/chartSlide.ts
194
- var b = [
194
+ var x = [
195
195
  "bar",
196
196
  "line",
197
197
  "pie",
@@ -200,32 +200,32 @@ var b = [
200
200
  "polarArea",
201
201
  "scatter",
202
202
  "bubble"
203
- ], x = "https://cdn.jsdelivr.net/npm/chart.js@4.5.1/dist/chart.umd.min.js", se = "sha384-jb8JQMbMoBUzgWatfe6COACi2ljcDdZQ2OxczGA3bGNeWe+6DChMTBJemed7ZnvJ", ce = "\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})();", le = [
203
+ ], S = "https://cdn.jsdelivr.net/npm/chart.js@4.5.1/dist/chart.umd.min.js", oe = "sha384-jb8JQMbMoBUzgWatfe6COACi2ljcDdZQ2OxczGA3bGNeWe+6DChMTBJemed7ZnvJ", se = "\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})();", ce = [
204
204
  "default-src 'none'",
205
- `script-src 'sha256-TfZZxJX+yWgzYLy7zqsMa85OJEaC+zNLIpKLDZVnUqA=' ${x}`,
205
+ `script-src 'sha256-TfZZxJX+yWgzYLy7zqsMa85OJEaC+zNLIpKLDZVnUqA=' ${S}`,
206
206
  "style-src 'unsafe-inline'",
207
207
  "img-src data: blob:",
208
208
  "connect-src 'none'",
209
209
  "form-action 'none'",
210
210
  "base-uri 'none'"
211
- ].join("; "), ue = `
211
+ ].join("; "), le = `
212
212
  html, body { margin: 0; width: ${t}px; height: 720px; overflow: hidden; background: #ffffff; color: #0f172a; font-family: ui-sans-serif, system-ui, sans-serif; }
213
213
  body { box-sizing: border-box; padding: 40px 64px 48px; display: flex; flex-direction: column; gap: 24px; }
214
214
  h1 { margin: 0; font-size: 52px; font-weight: 800; color: #1e3a8a; line-height: 1.15; text-align: center; }
215
215
  .chart { position: relative; flex: 1; min-height: 0; }
216
216
  #chart-error { display: none; margin: auto; font-size: 28px; color: #b91c1c; }
217
217
  .failed .chart { display: none; }
218
- .failed #chart-error { display: block; }`, de = (e) => JSON.stringify(e).replace(/</g, "\\u003c");
219
- function fe(e, t) {
218
+ .failed #chart-error { display: block; }`, ue = (e) => JSON.stringify(e).replace(/</g, "\\u003c");
219
+ function de(e, t) {
220
220
  return `<!doctype html>
221
221
  <html lang="en">
222
222
  <head>
223
223
  <meta charset="utf-8">
224
- <meta http-equiv="Content-Security-Policy" content="${le}">
225
- <style>${ue}</style>
226
- <script>${ce}<\/script>
227
- <script defer src="${x}" integrity="${se}" crossorigin="anonymous"><\/script>
228
- <script type="application/json" id="chart-config">${de(t)}<\/script>
224
+ <meta http-equiv="Content-Security-Policy" content="${ce}">
225
+ <style>${le}</style>
226
+ <script>${se}<\/script>
227
+ <script defer src="${S}" integrity="${oe}" crossorigin="anonymous"><\/script>
228
+ <script type="application/json" id="chart-config">${ue(t)}<\/script>
229
229
  </head>
230
230
  <body>
231
231
  ${e ? `<h1>${p(e)}</h1>` : ""}
@@ -236,33 +236,35 @@ ${e ? `<h1>${p(e)}</h1>` : ""}
236
236
  }
237
237
  //#endregion
238
238
  //#region src/core/definitions.ts
239
- var S = "presentSlide", pe = "defineStoryboard", me = "presentPanel", he = 4, ge = 12, _e = 3, ve = /^[0-9a-f]{12}$/, C = (e) => typeof e == "object" && !!e && !Array.isArray(e), w = (e) => typeof e == "string" ? e.trim() : "", T = (e, t) => e.toLowerCase() === t.toLowerCase(), E = (e) => typeof e == "number" && Number.isInteger(e), ye = "presentSlide needs slide and totalSlides (whole numbers, slide from 1 to totalSlides), and one of imagePrompt, html, markdown or chart", D = `presentSlide's slide is too long: keep its html, markdown or chart under ${r} characters`, O = `presentSlide's chart must be a Chart.js configuration: an object with type (${b.join(", ")}), data ({ labels, datasets }) and optionally options`;
240
- function be(e) {
239
+ var C = "presentSlide", w = "defineStoryboard", fe = "presentPanel", pe = 4, me = 12, he = 3, T = /^[0-9a-f]{12}$/, E = (e) => typeof e == "object" && !!e && !Array.isArray(e), D = (e) => typeof e == "string" ? e.trim() : "", O = (e, t) => e.toLowerCase() === t.toLowerCase(), k = (e) => typeof e == "number" && Number.isInteger(e), ge = "presentSlide needs slide and totalSlides (whole numbers, slide from 1 to totalSlides), and one of imagePrompt, imageUrl, html, markdown or chart", _e = `presentSlide's slide is too long: keep its html, markdown or chart under ${r} characters`, ve = `presentSlide's chart must be a Chart.js configuration: an object with type (${x.join(", ")}), data ({ labels, datasets }) and optionally options`;
240
+ function ye(e) {
241
241
  let t = e;
242
242
  if (typeof t == "string") try {
243
243
  t = JSON.parse(t);
244
244
  } catch {
245
245
  return null;
246
246
  }
247
- if (!C(t) || !C(t.data)) return null;
247
+ if (!E(t) || !E(t.data)) return null;
248
248
  let n = t.type;
249
- return !b.some((e) => e === n) || t.options !== void 0 && !C(t.options) ? null : t;
249
+ return !x.some((e) => e === n) || t.options !== void 0 && !E(t.options) ? null : t;
250
250
  }
251
- function k(e) {
252
- let { slide: t, totalSlides: n, title: r, imagePrompt: i } = e, a = w(e.html), o = a ? "" : w(e.markdown), s = !a && !o && e.chart !== void 0 && e.chart !== null;
253
- if (!E(t) || !E(n) || t < 1 || n < t || !a && !o && !s && !w(i)) return ye;
254
- let c = s ? be(e.chart) : null;
255
- if (s && !c) return O;
256
- if (Math.max(a.length, o.length, c ? JSON.stringify(c).length : 0) > 6e4) return D;
257
- let l = !a && !o && !c, u = !!a && y(a);
251
+ function be(e) {
252
+ let { slide: t, totalSlides: n, title: r, imagePrompt: i } = e, a = D(e.imageUrl), o = D(e.html), s = o ? "" : D(e.markdown), c = !o && !s && e.chart !== void 0 && e.chart !== null;
253
+ if (!k(t) || !k(n) || t < 1 || n < t || !o && !s && !c && !D(i) && !a) return ge;
254
+ let l = c ? ye(e.chart) : null;
255
+ if (c && !l) return ve;
256
+ if (Math.max(o.length, s.length, l ? JSON.stringify(l).length : 0) > 6e4) return _e;
257
+ let u = !o && !s && !l, d = !!o && b(o), f = u || d || !!s;
258
258
  return {
259
259
  slide: t,
260
260
  totalSlides: n,
261
261
  title: typeof r == "string" ? r : "",
262
- imagePrompt: l ? String(i) : u || o ? w(i) : "",
263
- ...a && { html: a },
264
- ...o && { markdown: o },
265
- ...c && { chart: c },
262
+ imagePrompt: u ? typeof i == "string" ? i : "" : f ? D(i) : "",
263
+ ...f && a && { imageUrl: a },
264
+ ...!f && a && { unplacedImageUrl: a },
265
+ ...o && { html: o },
266
+ ...s && { markdown: s },
267
+ ...l && { chart: l },
266
268
  mode: e.mode === "steps" ? "steps" : "presentation"
267
269
  };
268
270
  }
@@ -275,14 +277,14 @@ var xe = "teach its subject as a presenter speaking to the audience, and cover e
275
277
  let a = `Slide ${e} of ${t}${i}`;
276
278
  return e < t ? `${a} is now on the screen. Explain it: ${xe} This reply is only the explanation: don't call presentSlide in it. When you have finished, you will be asked 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: ${xe} Then wrap up the slideshow.`;
277
279
  }, Se = [
278
- `For an HTML slide: 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. For one generated picture on the slide (a photo, a scene, an object beside the text), give imagePrompt too and put <img src="${g}" alt="..." class="..."> where it goes, sized by its classes (for example class="w-1/2 h-full object-cover rounded-2xl").`,
280
+ `For an HTML slide: 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. For one picture on the slide (a photo, a scene, an object beside the text), give imagePrompt (a generated picture) or imageUrl (a picture from the web) too and put <img src="${_}" alt="..." class="..."> where it goes, sized by its classes (for example class="w-1/2 h-full object-cover rounded-2xl").`,
279
281
  "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).",
280
282
  "CSS animations, transitions and scripts don't play: animate only with data-animation. A <style> for layout is allowed (and Google Fonts by @import)."
281
- ].join(" "), Ce = `For a Markdown slide: 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 \\$, and & % # inside \\text{} as \\& \\% \\#. For one generated picture on the slide, give imagePrompt too and put ![what it shows](${g}) on a line of its own: the slide is then two columns, the text on the left and the picture on the right. Without imagePrompt, the alt text is what is drawn.`, we = `For a chart slide, instead of imagePrompt (for numbers: real figures you have, never a picture of a chart): a Chart.js configuration as JSON text, {"type": ..., "data": ...}: { type, data: { labels, datasets: [{ label, data, backgroundColor }] }, options }. type is one of ${b.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.`, Te = "When the user asks for a slideshow (or to explain something with slides), plan four to six slides (more when the subject or your instructions need them), 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, and explain everything on a slide before showing the next; put on a slide only what you will explain. 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 a picture helps the text (the thing being explained, beside its key points), make an HTML or Markdown slide with one generated picture on it: imagePrompt for the picture, and {{image}} where it goes. Numbers go on a chart slide: when you have figures (from a search, a document or the user: revenue, market share, growth, prices, counts over time), show them in a chart with those exact values, labelled with their units and the year or period, and say where they come from. Figures over time, shares of a whole or values side by side are a chart, not a list or table on a Markdown or HTML slide. Never make a chart, graph or table a picture (imagePrompt): a picture of a chart has made-up bars and no real numbers. A slideshow about a business, a market or a comparison of companies has its figures on chart slides, not only in text. Never invent figures; with none to show, leave the chart out. A slide holds only its subject, never notes about your work (what you searched for, that a search succeeded). 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.", j = {
283
+ ].join(" "), Ce = `For a Markdown slide: 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 \\$, and & % # inside \\text{} as \\& \\% \\#. For one picture on the slide, give imagePrompt (a generated picture) or imageUrl (a picture from the web) too and put ![what it shows](${_}) on a line of its own: the slide is then two columns, the text on the left and the picture on the right. Without imagePrompt, the alt text is what is drawn.`, we = `For a chart slide, instead of imagePrompt (for numbers: real figures you have, never a picture of a chart): a Chart.js configuration as JSON text, {"type": ..., "data": ...}: { type, data: { labels, datasets: [{ label, data, backgroundColor }] }, options }. type is one of ${x.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.`, Te = "When the user asks for a slideshow (or to explain something with slides), plan four to six slides (more when the subject or your instructions need them), 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, and explain everything on a slide before showing the next; put on a slide only what you will explain. 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 a picture helps the text (the thing being explained, beside its key points), make an HTML or Markdown slide with one picture on it: imagePrompt for the picture, and {{image}} where it goes. When the slide is about a real, particular thing (a person, a building, a product, an artwork) and you have the address of a picture of it or of a page about it (an image file, or an article from a search), give that as imageUrl instead of imagePrompt: the picture, or the preview picture of the page, is shown as it is. Numbers go on a chart slide: when you have figures (from a search, a document or the user: revenue, market share, growth, prices, counts over time), show them in a chart with those exact values, labelled with their units and the year or period, and say where they come from. Figures over time, shares of a whole or values side by side are a chart, not a list or table on a Markdown or HTML slide. Never make a chart, graph or table a picture (imagePrompt): a picture of a chart has made-up bars and no real numbers. A slideshow about a business, a market or a comparison of companies has its figures on chart slides, not only in text. Never invent figures; with none to show, leave the chart out. A slide holds only its subject, never notes about your work (what you searched for, that a search succeeded). 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.", Ee = {
282
284
  type: "function",
283
- name: S,
285
+ name: C,
284
286
  prompt: Te,
285
- 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; an HTML or Markdown slide can also hold one generated picture (imagePrompt, placed at {{image}}). 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.",
287
+ description: "Show one slide of a slideshow, full screen: a picture generated from imagePrompt or from the web (imageUrl), a chart (chart), a slide written in Markdown with TeX math (markdown), or a slide written in HTML (html). Give one of them; an HTML or Markdown slide can also hold one picture (imagePrompt or imageUrl, placed at {{image}}). 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.",
286
288
  parameters: {
287
289
  type: "object",
288
290
  properties: {
@@ -302,6 +304,10 @@ var xe = "teach its subject as a presenter speaking to the audience, and cover e
302
304
  type: "string",
303
305
  description: "For a picture slide: the picture, a clear illustration of its point, with the title as its only large text. Be concrete. Never a chart, graph, table, dashboard, infographic, key figures or anything with numbers: those are chart, Markdown or HTML slides. For a step, show the action: hands, tools and the object. With html or markdown, it is the one picture placed where the slide has {{image}}; leave it out for a chart, and for an HTML or Markdown slide without {{image}}."
304
306
  },
307
+ imageUrl: {
308
+ type: "string",
309
+ description: "A picture from the web, shown instead of a generated one, of a real, particular thing: the https address of an image file (PNG, JPEG, GIF or WebP), or of a web page about it (an article from a search), whose preview picture is shown. Never an address you made up. With imagePrompt too, the picture is drawn from imagePrompt if the address can't be fetched. With html or markdown, it is the one picture placed where the slide has {{image}}, which the slide must have: without it, the picture isn't shown."
310
+ },
305
311
  html: {
306
312
  type: "string",
307
313
  description: Se
@@ -327,49 +333,49 @@ var xe = "teach its subject as a presenter speaking to the audience, and cover e
327
333
  ]
328
334
  }
329
335
  };
330
- function M(e) {
336
+ function De(e) {
331
337
  let { totalPanels: t } = e;
332
- if (!E(t) || t < 1 || t > 12) return "totalPanels must be a whole number from 1 to 12";
338
+ if (!k(t) || t < 1 || t > 12) return "totalPanels must be a whole number from 1 to 12";
333
339
  let n = [];
334
340
  for (let t of Array.isArray(e.characters) ? e.characters : []) {
335
- let e = C(t) ? w(t.name) : "", r = C(t) ? w(t.description) : "";
341
+ let e = E(t) ? D(t.name) : "", r = E(t) ? D(t.description) : "";
336
342
  if (!e || !r) return "every character needs a name and a description";
337
- if (n.some((t) => T(t.name, e))) return `two characters are named ${e}`;
343
+ if (n.some((t) => O(t.name, e))) return `two characters are named ${e}`;
338
344
  n.push({
339
345
  name: e,
340
346
  description: r
341
347
  });
342
348
  }
343
349
  return n.length < 1 || n.length > 4 ? "a storyboard has 1 to 4 characters" : {
344
- title: w(e.title),
345
- style: w(e.style),
350
+ title: D(e.title),
351
+ style: D(e.style),
346
352
  totalPanels: t,
347
353
  characters: n,
348
354
  interactive: e.interactive === !0
349
355
  };
350
356
  }
351
- var N = ({ title: e }) => `The cast of "${e}" is now on the screen. Introduce the characters briefly. This reply is only the introduction: don't call presentPanel in it. When you have finished, you will be asked for panel 1. If the user has asked you to stop, or asked something else, answer them instead of going on.`, P = "presentPanel needs a storyboardId, a panel number (from 1) and an imagePrompt";
352
- function F(e) {
353
- let { panel: t } = e, n = w(e.storyboardId), r = w(e.imagePrompt);
354
- if (!n || !r || !E(t) || t < 1) return null;
355
- let i = (e) => (Array.isArray(e) ? e : []).map(w).filter(Boolean);
357
+ var Oe = ({ title: e }) => `The cast of "${e}" is now on the screen. Introduce the characters briefly. This reply is only the introduction: don't call presentPanel in it. When you have finished, you will be asked for panel 1. If the user has asked you to stop, or asked something else, answer them instead of going on.`, j = "presentPanel needs a storyboardId, a panel number (from 1) and an imagePrompt";
358
+ function M(e) {
359
+ let { panel: t } = e, n = D(e.storyboardId), r = D(e.imagePrompt);
360
+ if (!n || !r || !k(t) || t < 1) return null;
361
+ let i = (e) => (Array.isArray(e) ? e : []).map(D).filter(Boolean);
356
362
  return {
357
363
  storyboardId: n,
358
364
  panel: t,
359
365
  characters: i(e.characters),
360
366
  imagePrompt: r,
361
- caption: w(e.caption),
367
+ caption: D(e.caption),
362
368
  choices: i(e.choices).slice(0, 3)
363
369
  };
364
370
  }
365
- function I(e, t, n) {
371
+ function N(e, t, n) {
366
372
  let { id: r, totalPanels: i } = e;
367
373
  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, aloud, as a storyteller. This reply is only the telling: don't call presentPanel in it. When you have finished, you will be asked for panel ${t + 1}. 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.`;
368
374
  }
369
- var L = "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.", R = {
375
+ var P = "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.", F = {
370
376
  type: "function",
371
- name: pe,
372
- prompt: L,
377
+ name: w,
378
+ prompt: P,
373
379
  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.",
374
380
  parameters: {
375
381
  type: "object",
@@ -416,9 +422,9 @@ var L = "When the user asks for a story, a picture book, a comic or a storyboard
416
422
  "characters"
417
423
  ]
418
424
  }
419
- }, z = {
425
+ }, I = {
420
426
  type: "function",
421
- name: me,
427
+ name: fe,
422
428
  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.",
423
429
  parameters: {
424
430
  type: "object",
@@ -457,60 +463,60 @@ var L = "When the user asks for a story, a picture book, a comic or a storyboard
457
463
  "imagePrompt"
458
464
  ]
459
465
  }
460
- }, B = (e) => typeof e == "object" && !!e && !Array.isArray(e), Ee = (e) => B(e) && typeof e.message == "string";
461
- function V(e) {
462
- let t = B(e?.data) ? e.data : {};
466
+ }, L = (e) => typeof e == "object" && !!e && !Array.isArray(e), ke = (e) => L(e) && typeof e.message == "string";
467
+ function R(e) {
468
+ let t = L(e?.data) ? e.data : {};
463
469
  return {
464
470
  ...typeof t.imageData == "string" && { imageData: t.imageData },
465
471
  ...typeof t.imagePath == "string" && { imagePath: t.imagePath }
466
472
  };
467
473
  }
468
- function H(e) {
469
- let t = B(e?.data) ? e.data : {};
474
+ function z(e) {
475
+ let t = L(e?.data) ? e.data : {};
470
476
  return typeof t.html == "string" ? t.html : "";
471
477
  }
472
- function U(e) {
473
- let t = B(e?.data) ? e.data : {};
474
- return B(t.chart) ? JSON.stringify(t.chart) : "";
478
+ function B(e) {
479
+ let t = L(e?.data) ? e.data : {};
480
+ return L(t.chart) ? JSON.stringify(t.chart) : "";
475
481
  }
476
- var De = (e) => !!V(e).imageData || !!H(e) || !!U(e);
477
- function Oe(e, t) {
478
- let n = V(e), r = V(t);
482
+ var Ae = (e) => !!R(e).imageData || !!z(e) || !!B(e);
483
+ function je(e, t) {
484
+ let n = R(e), r = R(t);
479
485
  if (n.imagePath && r.imagePath) return n.imagePath === r.imagePath;
480
486
  if (n.imageData) return n.imageData === r.imageData;
481
- let i = H(e);
482
- if (i) return i === H(t);
483
- let a = U(e);
484
- return !!a && a === U(t);
487
+ let i = z(e);
488
+ if (i) return i === z(t);
489
+ let a = B(e);
490
+ return !!a && a === B(t);
485
491
  }
486
- var W = (e, t) => e.userSpokeAt === void 0 || e.userSpokeAt > t, G = () => crypto.randomUUID().replace(/-/g, "").slice(0, 12), ke = "artifacts/";
487
- async function K(e, t) {
492
+ var V = (e, t) => e.userSpokeAt === void 0 || e.userSpokeAt > t, H = () => crypto.randomUUID().replace(/-/g, "").slice(0, 12), Me = "artifacts/";
493
+ async function U(e, t) {
488
494
  let n = e.files?.artifacts;
489
495
  if (!e.app?.editImages || !n) return [];
490
496
  let r = [];
491
- for (let e of t) if (e.startsWith(ke)) try {
497
+ for (let e of t) if (e.startsWith(Me)) try {
492
498
  await n.exists(e.slice(10)) && r.push(e);
493
499
  } catch {}
494
500
  return r;
495
501
  }
496
- async function q(e, t, n = []) {
502
+ async function W(e, t, n = []) {
497
503
  let r = e.app, i = r?.editImages, a = r?.generateImage;
498
504
  try {
499
505
  let e;
500
506
  if (n.length && i) e = await i(t, [...n]);
501
507
  else if (a) e = await a(t);
502
508
  else return { message: "image generation isn't available" };
503
- return Ee(e) ? e : { message: "image generation returned an unrecognized result" };
509
+ return ke(e) ? e : { message: "image generation returned an unrecognized result" };
504
510
  } catch (e) {
505
511
  return { message: `image generation failed: ${e instanceof Error ? e.message : String(e)}` };
506
512
  }
507
513
  }
508
- var Ae = 50;
509
- function J(e) {
514
+ var Ne = 50;
515
+ function G(e) {
510
516
  let t = /* @__PURE__ */ new Map();
511
517
  return (n) => {
512
518
  let r = n.conversationId ?? "", i = t.get(r);
513
- if (i === void 0 ? i = e() : t.delete(r), t.set(r, i), t.size > Ae) {
519
+ if (i === void 0 ? i = e() : t.delete(r), t.set(r, i), t.size > Ne) {
514
520
  let e = t.keys().next().value;
515
521
  e !== void 0 && t.delete(e);
516
522
  }
@@ -519,45 +525,45 @@ function J(e) {
519
525
  }
520
526
  //#endregion
521
527
  //#region src/core/markdownSlide.ts
522
- var Y = "slide-md", je = "slide-md-split", X = "slide-md-text", Me = "slide-md-picture", Ne = .8, Pe = `
523
- .${Y} { box-sizing: border-box; flex-shrink: 0; 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; }
524
- .${Y} > * { margin: 0; }
525
- .${Y} h1 { font-size: 1.9em; font-weight: 800; color: #1e3a8a; line-height: 1.15; }
526
- .${Y} h2 { font-size: 1.5em; font-weight: 700; color: #1e40af; line-height: 1.2; }
527
- .${Y} h3 { font-size: 1.2em; font-weight: 700; color: #334155; }
528
- .${Y} ul, .${Y} ol { padding-left: 1.3em; display: flex; flex-direction: column; gap: 0.3em; }
529
- .${Y} ul { list-style: disc; }
530
- .${Y} ol { list-style: decimal; }
531
- .${Y} li > ul, .${Y} li > ol { margin-top: 0.3em; font-size: 0.9em; }
532
- .${Y} li::marker { color: #2563eb; }
533
- .${Y} strong { font-weight: 700; color: #1e3a8a; }
534
- .${Y} em { font-style: italic; }
535
- .${Y} a { color: #2563eb; text-decoration: underline; }
536
- .${Y} code { font-family: ui-monospace, monospace; font-size: 0.85em; background: #f1f5f9; border-radius: 0.2em; padding: 0.05em 0.3em; }
537
- .${Y} pre { background: #0f172a; color: #e2e8f0; border-radius: 0.4em; padding: 0.6em 0.8em; font-size: 0.75em; overflow: hidden; }
538
- .${Y} pre code { background: none; padding: 0; color: inherit; }
539
- .${Y} blockquote { border-left: 0.2em solid #93c5fd; padding-left: 0.8em; color: #475569; font-style: italic; }
540
- .${Y} table { border-collapse: collapse; font-size: 0.85em; align-self: flex-start; }
541
- .${Y} th, .${Y} td { border: 1px solid #cbd5e1; padding: 0.25em 0.7em; text-align: left; }
542
- .${Y} th { background: #eff6ff; font-weight: 700; }
543
- .${Y} hr { border: 0; border-top: 2px solid #e2e8f0; }
544
- .${Y} img { max-width: 100%; max-height: 60%; }
545
- .${Y}.${je} { flex-direction: row; align-items: center; gap: 48px; }
546
- .${Y} .${X} { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; justify-content: center; gap: 0.5em; }
547
- .${Y} .${X} > * { margin: 0; }
548
- .${Y} .${Me} { flex: 0 0 44%; width: 44%; height: 100%; max-width: none; max-height: 100%; object-fit: cover; border-radius: 0.6em; box-shadow: 0 10px 30px rgba(15, 23, 42, 0.18); }
549
- .${Y} .math-display { display: block; text-align: center; font-size: 1.15em; }
550
- .${Y} math { font-family: "Latin Modern Math", "STIX Two Math", "Cambria Math", math; }
551
- .${Y} mtd { padding: 0.1em 0.4em; }
552
- .${Y} mtd:first-child { padding-left: 0; }
553
- .${Y} mtd:last-child { padding-right: 0; }
554
- .${Y} .math-error { color: #b91c1c; font-family: ui-monospace, monospace; }`;
555
- function Fe(e) {
528
+ var K = "slide-md", Pe = "slide-md-split", q = "slide-md-text", Fe = "slide-md-picture", Ie = .8, Le = `
529
+ .${K} { box-sizing: border-box; flex-shrink: 0; 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; }
530
+ .${K} > * { margin: 0; }
531
+ .${K} h1 { font-size: 1.9em; font-weight: 800; color: #1e3a8a; line-height: 1.15; }
532
+ .${K} h2 { font-size: 1.5em; font-weight: 700; color: #1e40af; line-height: 1.2; }
533
+ .${K} h3 { font-size: 1.2em; font-weight: 700; color: #334155; }
534
+ .${K} ul, .${K} ol { padding-left: 1.3em; display: flex; flex-direction: column; gap: 0.3em; }
535
+ .${K} ul { list-style: disc; }
536
+ .${K} ol { list-style: decimal; }
537
+ .${K} li > ul, .${K} li > ol { margin-top: 0.3em; font-size: 0.9em; }
538
+ .${K} li::marker { color: #2563eb; }
539
+ .${K} strong { font-weight: 700; color: #1e3a8a; }
540
+ .${K} em { font-style: italic; }
541
+ .${K} a { color: #2563eb; text-decoration: underline; }
542
+ .${K} code { font-family: ui-monospace, monospace; font-size: 0.85em; background: #f1f5f9; border-radius: 0.2em; padding: 0.05em 0.3em; }
543
+ .${K} pre { background: #0f172a; color: #e2e8f0; border-radius: 0.4em; padding: 0.6em 0.8em; font-size: 0.75em; overflow: hidden; }
544
+ .${K} pre code { background: none; padding: 0; color: inherit; }
545
+ .${K} blockquote { border-left: 0.2em solid #93c5fd; padding-left: 0.8em; color: #475569; font-style: italic; }
546
+ .${K} table { border-collapse: collapse; font-size: 0.85em; align-self: flex-start; }
547
+ .${K} th, .${K} td { border: 1px solid #cbd5e1; padding: 0.25em 0.7em; text-align: left; }
548
+ .${K} th { background: #eff6ff; font-weight: 700; }
549
+ .${K} hr { border: 0; border-top: 2px solid #e2e8f0; }
550
+ .${K} img { max-width: 100%; max-height: 60%; }
551
+ .${K}.${Pe} { flex-direction: row; align-items: center; gap: 48px; }
552
+ .${K} .${q} { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; justify-content: center; gap: 0.5em; }
553
+ .${K} .${q} > * { margin: 0; }
554
+ .${K} .${Fe} { flex: 0 0 44%; width: 44%; height: 100%; max-width: none; max-height: 100%; object-fit: cover; border-radius: 0.6em; box-shadow: 0 10px 30px rgba(15, 23, 42, 0.18); }
555
+ .${K} .math-display { display: block; text-align: center; font-size: 1.15em; }
556
+ .${K} math { font-family: "Latin Modern Math", "STIX Two Math", "Cambria Math", math; }
557
+ .${K} mtd { padding: 0.1em 0.4em; }
558
+ .${K} mtd:first-child { padding-left: 0; }
559
+ .${K} mtd:last-child { padding-right: 0; }
560
+ .${K} .math-error { color: #b91c1c; font-family: ui-monospace, monospace; }`;
561
+ function Re(e) {
556
562
  let t = e.split("\n").filter((e) => e.trim()).length, n = e.length;
557
563
  return t <= 5 && n <= 250 ? 40 : t <= 8 && n <= 450 ? 34 : t <= 12 && n <= 700 ? 28 : 24;
558
564
  }
559
- var Ie = /^[ \t]*(?:\$\$([\s\S]+?)\$\$|\\\[([\s\S]+?)\\\])[ \t]*(?:\n|$)/, Le = /^(?:\$\$(.+?)\$\$|\$(?!\s)((?:\\.|[^\\$\n])+?)(?<!\s)\$(?!\d)|\\\((.+?)\\\))/;
560
- function Re(e) {
565
+ var ze = /^[ \t]*(?:\$\$([\s\S]+?)\$\$|\\\[([\s\S]+?)\\\])[ \t]*(?:\n|$)/, Be = /^(?:\$\$(.+?)\$\$|\$(?!\s)((?:\\.|[^\\$\n])+?)(?<!\s)\$(?!\d)|\\\((.+?)\\\))/;
566
+ function Ve(e) {
561
567
  return [{
562
568
  name: "blockMath",
563
569
  level: "block",
@@ -566,7 +572,7 @@ function Re(e) {
566
572
  return t ? t.index + (t[1] ?? "").length : void 0;
567
573
  },
568
574
  tokenizer(e) {
569
- let t = Ie.exec(e);
575
+ let t = ze.exec(e);
570
576
  if (t) return {
571
577
  type: "blockMath",
572
578
  raw: t[0],
@@ -579,7 +585,7 @@ function Re(e) {
579
585
  level: "inline",
580
586
  start: (e) => e.match(/(?<!\\)\$|\\\(/)?.index,
581
587
  tokenizer(e) {
582
- let t = Le.exec(e);
588
+ let t = Be.exec(e);
583
589
  if (t) return {
584
590
  type: "inlineMath",
585
591
  raw: t[0],
@@ -590,9 +596,9 @@ function Re(e) {
590
596
  renderer: (t) => e(String(t.text), t.display === !0)
591
597
  }];
592
598
  }
593
- var ze = /(<\/mi>|<\/mn>|<\/mrow>|<mo[^>]*>[)\]]<\/mo>)?(<mi(?: mathvariant="normal")?>[A-Za-z]{2,}<\/mi>)<mo>\u2061<\/mo>/g, Be = "<mspace width=\"0.1667em\"></mspace>", Ve = (e) => e.replace(ze, (e, t, n) => `${t ? t + Be : ""}${n}<mo lspace="0" rspace="0.1667em">\u2061</mo>`), He = /\\(?:text(?:bf|it|rm|sf|tt|normal)?|mbox)\s*\{/g, Ue = (e) => {
599
+ var He = /(<\/mi>|<\/mn>|<\/mrow>|<mo[^>]*>[)\]]<\/mo>)?(<mi(?: mathvariant="normal")?>[A-Za-z]{2,}<\/mi>)<mo>\u2061<\/mo>/g, Ue = "<mspace width=\"0.1667em\"></mspace>", We = (e) => e.replace(He, (e, t, n) => `${t ? t + Ue : ""}${n}<mo lspace="0" rspace="0.1667em">\u2061</mo>`), Ge = /\\(?:text(?:bf|it|rm|sf|tt|normal)?|mbox)\s*\{/g, Ke = (e) => {
594
600
  let t = "", n = 0;
595
- for (let r of e.matchAll(He)) {
601
+ for (let r of e.matchAll(Ge)) {
596
602
  let i = r.index + r[0].length;
597
603
  if (i <= n) continue;
598
604
  let a = 1, o = i;
@@ -601,10 +607,10 @@ var ze = /(<\/mi>|<\/mn>|<\/mrow>|<mo[^>]*>[)\]]<\/mo>)?(<mi(?: mathvariant="nor
601
607
  }
602
608
  return t + e.slice(n);
603
609
  };
604
- async function We(e) {
610
+ async function qe(e) {
605
611
  let [{ Marked: t }, { default: n }] = await Promise.all([import("marked"), import("katex")]), r = (e, t) => {
606
612
  try {
607
- return Ve(n.renderToString(Ue(e), {
613
+ return We(n.renderToString(Ke(e), {
608
614
  output: "mathml",
609
615
  displayMode: t,
610
616
  throwOnError: !0
@@ -616,42 +622,42 @@ async function We(e) {
616
622
  gfm: !0,
617
623
  breaks: !1
618
624
  });
619
- i.use({ extensions: Re(r) });
625
+ i.use({ extensions: Ve(r) });
620
626
  let a = i.lexer(e), o = a.findIndex((e) => {
621
627
  if (e.type !== "paragraph" || e.tokens?.length !== 1) return !1;
622
628
  let t = e.tokens[0];
623
- return t?.type === "image" ? t.href.trim() === g : t?.type === "text" && t.text.trim() === "{{image}}";
629
+ return t?.type === "image" ? t.href.trim() === _ : t?.type === "text" && t.text.trim() === "{{image}}";
624
630
  });
625
631
  if (o >= 0) {
626
632
  let [t] = a.splice(o, 1), n = t?.type === "paragraph" ? t.tokens?.[0] : void 0, r = n?.type === "image" ? n.text : "", s = i.parser(a), c = e.replace(t?.raw ?? "", "");
627
- return `<style>${Pe}</style>
628
- <div class="${Y} ${je}" data-fit style="font-size: ${Math.round(Fe(c) * Ne)}px">
629
- <div class="${X}">
633
+ return `<style>${Le}</style>
634
+ <div class="${K} ${Pe}" data-fit style="font-size: ${Math.round(Re(c) * Ie)}px">
635
+ <div class="${q}">
630
636
  ${s}</div>
631
- <img class="${Me}" src="${g}" alt="${p(r)}">
637
+ <img class="${Fe}" src="${_}" alt="${p(r)}">
632
638
  </div>`;
633
639
  }
634
640
  let s = await i.parse(e);
635
- return `<style>${Pe}</style>
636
- <div class="${Y}" data-fit style="font-size: ${Fe(e)}px">
641
+ return `<style>${Le}</style>
642
+ <div class="${K}" data-fit style="font-size: ${Re(e)}px">
637
643
  ${s}</div>`;
638
644
  }
639
645
  //#endregion
640
646
  //#region src/core/records.ts
641
- var Ge = "slideshows", Z = "storyboards", Ke = {}, qe = /* @__PURE__ */ new WeakMap(), Je = /* @__PURE__ */ new WeakMap();
642
- function Ye(e) {
643
- let t = qe.get(e);
644
- return t || qe.set(e, t = /* @__PURE__ */ new Map()), t;
647
+ var Je = "slideshows", J = "storyboards", Ye = {}, Xe = /* @__PURE__ */ new WeakMap(), Ze = /* @__PURE__ */ new WeakMap();
648
+ function Qe(e) {
649
+ let t = Xe.get(e);
650
+ return t || Xe.set(e, t = /* @__PURE__ */ new Map()), t;
645
651
  }
646
- function Xe(t, n) {
647
- let r = Je.get(t);
648
- r || Je.set(t, r = /* @__PURE__ */ new Map());
652
+ function $e(t, n) {
653
+ let r = Ze.get(t);
654
+ r || Ze.set(t, r = /* @__PURE__ */ new Map());
649
655
  let i = r.get(n);
650
656
  return i || r.set(n, i = e()), i;
651
657
  }
652
- var Ze = (e, t) => `${e}/${t}.json`;
653
- async function Qe(e, t) {
654
- let n = Ye(e ?? Ke), r = n.get(t);
658
+ var et = (e, t) => `${e}/${t}.json`;
659
+ async function tt(e, t) {
660
+ let n = Qe(e ?? Ye), r = n.get(t);
655
661
  if (r) return r;
656
662
  if (!e) return null;
657
663
  try {
@@ -661,14 +667,14 @@ async function Qe(e, t) {
661
667
  return null;
662
668
  }
663
669
  }
664
- async function $e(e, t, n) {
665
- return ve.test(n) ? Qe(e, Ze(t, n)) : null;
670
+ async function nt(e, t, n) {
671
+ return T.test(n) ? tt(e, et(t, n)) : null;
666
672
  }
667
- async function Q(e, t, n, r) {
668
- let i = Ze(t, n), a = e ?? Ke;
669
- return Xe(a, i)(async () => {
670
- let t = r(await Qe(e, i));
671
- if (Ye(a).set(i, t), !e) return !1;
673
+ async function Y(e, t, n, r) {
674
+ let i = et(t, n), a = e ?? Ye;
675
+ return $e(a, i)(async () => {
676
+ let t = r(await tt(e, i));
677
+ if (Qe(a).set(i, t), !e) return !1;
672
678
  try {
673
679
  return await e.write(i, JSON.stringify(t, null, 2)), !0;
674
680
  } catch (e) {
@@ -676,12 +682,12 @@ async function Q(e, t, n, r) {
676
682
  }
677
683
  });
678
684
  }
679
- var $ = (e) => `the ${e} could not be saved, so it lasts only until the app or server restarts`, et = 6e4;
680
- function tt() {
685
+ var X = (e) => `the ${e} could not be saved, so it lasts only until the app or server restarts`, rt = 6e4;
686
+ function it() {
681
687
  let e = /* @__PURE__ */ new Map();
682
688
  return { claim: (t) => {
683
689
  let n = Date.now();
684
- for (let [t, r] of e) n - r.at > et && e.delete(t);
690
+ for (let [t, r] of e) n - r.at > rt && e.delete(t);
685
691
  let r = e.get(t);
686
692
  if (r) return { earlier: r.shown };
687
693
  let i = () => void 0, a = new Promise((e) => i = e);
@@ -694,8 +700,178 @@ function tt() {
694
700
  } };
695
701
  }
696
702
  //#endregion
703
+ //#region src/core/webImage.ts
704
+ var at = 1e4, ot = 5242880, st = 3, ct = "images", lt = "artifacts/";
705
+ function ut(e) {
706
+ if (e.protocol !== "https:") return "only https URLs are fetched";
707
+ if (e.username || e.password) return "a URL with a password isn't fetched";
708
+ let t = e.hostname.toLowerCase().replace(/\.$/, "");
709
+ return t.startsWith("[") || /^\d+\.\d+\.\d+\.\d+$/.test(t) ? "a URL with an IP address isn't fetched" : !t.includes(".") || /\.(localhost|local|internal|lan|home\.arpa)$/.test(t) ? "a URL on a local network isn't fetched" : null;
710
+ }
711
+ var Z = (e, t, n = 0) => t.every((t, r) => e[n + r] === t);
712
+ function dt(e) {
713
+ return Z(e, [
714
+ 137,
715
+ 80,
716
+ 78,
717
+ 71,
718
+ 13,
719
+ 10,
720
+ 26,
721
+ 10
722
+ ]) ? {
723
+ mime: "image/png",
724
+ extension: "png"
725
+ } : Z(e, [
726
+ 255,
727
+ 216,
728
+ 255
729
+ ]) ? {
730
+ mime: "image/jpeg",
731
+ extension: "jpg"
732
+ } : Z(e, [
733
+ 71,
734
+ 73,
735
+ 70,
736
+ 56
737
+ ]) ? {
738
+ mime: "image/gif",
739
+ extension: "gif"
740
+ } : Z(e, [
741
+ 82,
742
+ 73,
743
+ 70,
744
+ 70
745
+ ]) && Z(e, [
746
+ 87,
747
+ 69,
748
+ 66,
749
+ 80
750
+ ], 8) ? {
751
+ mime: "image/webp",
752
+ extension: "webp"
753
+ } : null;
754
+ }
755
+ function ft(e) {
756
+ let t = "", n = 32768;
757
+ for (let r = 0; r < e.length; r += n) t += String.fromCharCode(...e.subarray(r, r + n));
758
+ return btoa(t);
759
+ }
760
+ var Q = (e) => e.body?.cancel().catch(() => void 0) ?? Promise.resolve();
761
+ async function pt(e) {
762
+ if (Number(e.headers.get("content-length")) > 5242880) return await Q(e), null;
763
+ if (!e.body) {
764
+ let t = new Uint8Array(await e.arrayBuffer());
765
+ return t.length > 5242880 ? null : t;
766
+ }
767
+ let t = e.body.getReader(), n = [], r = 0;
768
+ for (;;) {
769
+ let { done: e, value: i } = await t.read();
770
+ if (e) break;
771
+ if (r += i.length, r > 5242880) return await t.cancel(), null;
772
+ n.push(i);
773
+ }
774
+ let i = new Uint8Array(r), a = 0;
775
+ for (let e of n) i.set(e, a), a += e.length;
776
+ return i;
777
+ }
778
+ var mt = [
779
+ "og:image:secure_url",
780
+ "og:image:url",
781
+ "og:image",
782
+ "twitter:image",
783
+ "twitter:image:src"
784
+ ], ht = /([a-z:-]+)\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'>]+))/gi, gt = (e, t) => t <= 1114111 ? String.fromCodePoint(t) : e, _t = (e) => e.replace(/&#x([0-9a-f]+);/gi, (e, t) => gt(e, parseInt(t, 16))).replace(/&#(\d+);/g, (e, t) => gt(e, Number(t))).replace(/&quot;/g, "\"").replace(/&apos;/g, "'").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&amp;/g, "&");
785
+ function vt(e, t) {
786
+ let n = /* @__PURE__ */ new Map();
787
+ for (let [t] of e.matchAll(/<meta\b[^>]*>/gi)) {
788
+ let e = /* @__PURE__ */ new Map();
789
+ for (let [, n, r, i, a] of t.matchAll(ht)) n && e.set(n.toLowerCase(), r ?? i ?? a ?? "");
790
+ let r = (e.get("property") ?? e.get("name") ?? "").toLowerCase(), i = _t(e.get("content") ?? "").trim();
791
+ i && !n.has(r) && n.set(r, i);
792
+ }
793
+ for (let e of mt) {
794
+ let r = n.get(e);
795
+ if (r) try {
796
+ return new URL(r, t).href;
797
+ } catch {}
798
+ }
799
+ return null;
800
+ }
801
+ async function yt(e, t) {
802
+ let n;
803
+ try {
804
+ n = new URL(e);
805
+ } catch {
806
+ return "it isn't a URL";
807
+ }
808
+ for (let e = 0;; e++) {
809
+ let r = ut(n);
810
+ if (r) return r;
811
+ let i = await fetch(n, {
812
+ redirect: "manual",
813
+ signal: t,
814
+ credentials: "omit",
815
+ referrerPolicy: "no-referrer"
816
+ });
817
+ if (i.type === "opaqueredirect") {
818
+ let e = await fetch(n, {
819
+ signal: t,
820
+ credentials: "omit",
821
+ referrerPolicy: "no-referrer"
822
+ });
823
+ return {
824
+ response: e,
825
+ url: e.url || n.href
826
+ };
827
+ }
828
+ let a = i.headers.get("location");
829
+ if (i.status < 300 || i.status >= 400 || !a) return {
830
+ response: i,
831
+ url: n.href
832
+ };
833
+ if (await Q(i), e >= st) return "it redirects too many times";
834
+ n = new URL(a, n);
835
+ }
836
+ }
837
+ async function $(e, t, n = !1) {
838
+ let r, i;
839
+ try {
840
+ let t = await yt(e, AbortSignal.timeout(at));
841
+ if (typeof t == "string") return { error: t };
842
+ let { response: n } = t;
843
+ if (i = t.url, !n.ok) return await Q(n), { error: `the site answered ${n.status}` };
844
+ r = await pt(n);
845
+ } catch (e) {
846
+ return { error: `it couldn't be fetched (${e instanceof Error ? e.message : String(e)})` };
847
+ }
848
+ if (!r) return { error: `it is larger than ${ot / 1024 / 1024} MB` };
849
+ let a = dt(r);
850
+ if (!a) {
851
+ if (n) return { error: "it isn't a PNG, JPEG, GIF or WebP picture" };
852
+ let e = vt(new TextDecoder().decode(r), i);
853
+ if (!e) return { error: "it isn't a PNG, JPEG, GIF or WebP picture, or a web page with a preview picture (og:image)" };
854
+ let a = await $(e, t, !0);
855
+ return "error" in a ? { error: `its page's preview picture, ${e}: ${a.error}` } : {
856
+ ...a,
857
+ source: e
858
+ };
859
+ }
860
+ let o = `data:${a.mime};base64,${ft(r)}`;
861
+ if (!t) return { imageData: o };
862
+ let s = /* @__PURE__ */ new Date(), c = String(s.getUTCMonth() + 1).padStart(2, "0"), l = crypto.randomUUID().replace(/-/g, "").slice(0, 16), u = `${ct}/${s.getUTCFullYear()}/${c}/${l}.${a.extension}`;
863
+ try {
864
+ return await t.write(u, r), {
865
+ imageData: o,
866
+ imagePath: `${lt}${u}`
867
+ };
868
+ } catch {
869
+ return { imageData: o };
870
+ }
871
+ }
872
+ //#endregion
697
873
  //#region src/core/presentSlide.ts
698
- function nt({ slide: e, totalSlides: t, mode: n }) {
874
+ function bt({ slide: e, totalSlides: t, mode: n }) {
699
875
  return n === "steps" ? {
700
876
  step: e,
701
877
  total: t,
@@ -713,7 +889,7 @@ function nt({ slide: e, totalSlides: t, mode: n }) {
713
889
  nextCall: `call presentSlide for slide ${e + 1} of ${t}`
714
890
  };
715
891
  }
716
- var rt = (e, { slide: t, totalSlides: n, title: r, imagePrompt: i, html: a, markdown: o, chart: s }) => JSON.stringify([
892
+ var xt = (e, { slide: t, totalSlides: n, title: r, imagePrompt: i, imageUrl: a, html: o, markdown: s, chart: c }) => JSON.stringify([
717
893
  e,
718
894
  t,
719
895
  n,
@@ -721,20 +897,21 @@ var rt = (e, { slide: t, totalSlides: n, title: r, imagePrompt: i, html: a, mark
721
897
  i,
722
898
  a,
723
899
  o,
724
- s
725
- ]), it = J(() => ({
900
+ s,
901
+ c
902
+ ]), St = G(() => ({
726
903
  latest: {
727
904
  presentation: null,
728
905
  steps: null
729
906
  },
730
907
  lastShown: null,
731
- repeats: tt()
908
+ repeats: it()
732
909
  }));
733
- function at(e, t) {
910
+ function Ct(e, t) {
734
911
  let n = e.latest[t.mode], r = n?.totalSlides === t.totalSlides && (t.slide !== 1 || n.firstTitle === t.title);
735
912
  if (n && r) return n;
736
913
  let i = {
737
- id: G(),
914
+ id: H(),
738
915
  mode: t.mode,
739
916
  totalSlides: t.totalSlides,
740
917
  firstTitle: t.slide === 1 ? t.title : "",
@@ -744,7 +921,7 @@ function at(e, t) {
744
921
  };
745
922
  return e.latest[t.mode] = i, i;
746
923
  }
747
- function ot(e, t, n, r) {
924
+ function wt(e, t, n, r) {
748
925
  t.current = n.slide, t.shownAt = Date.now(), e.lastShown = t;
749
926
  let i = n.mode === "steps" ? "step" : "slide", { uuid: a, ...o } = r;
750
927
  return {
@@ -752,77 +929,110 @@ function ot(e, t, n, r) {
752
929
  message: `${i} ${n.slide} of ${n.totalSlides} is on the screen again, as it was`,
753
930
  instructions: A(n),
754
931
  instructionsRequired: !0,
755
- sequence: nt(n)
932
+ sequence: bt(n)
756
933
  };
757
934
  }
758
- function st(e, t) {
935
+ function Tt(e, t) {
759
936
  if (e.mode !== "steps") return e.title ? `A presentation slide titled "${e.title}". ${e.imagePrompt}` : e.imagePrompt;
760
937
  let n = e.title ? `, "${e.title}"` : "";
761
938
  return [
762
939
  `An instructional illustration of step ${e.slide} of ${e.totalSlides}${n}. ${e.imagePrompt}`,
763
- t ? ct : "",
940
+ t ? Et : "",
764
941
  "Show the action clearly, with little or no text."
765
942
  ].filter(Boolean).join(" ");
766
943
  }
767
- var ct = "The reference image is the previous step: keep the same objects, hands, tools and setting, and show what this step changes.";
768
- async function lt(e, t, n) {
944
+ var Et = "The reference image is the previous step: keep the same objects, hands, tools and setting, and show what this step changes.";
945
+ async function Dt(e, t, n) {
769
946
  if (n.mode !== "steps") return [];
770
- let r = V(t.slides.get(n.slide - 1)).imagePath;
771
- return r ? await K(e, [r]) : [];
947
+ let r = R(t.slides.get(n.slide - 1)).imagePath;
948
+ return r ? await U(e, [r]) : [];
772
949
  }
773
- var ut = (e, t) => [
950
+ var Ot = (e, t) => [
774
951
  e.mode === "steps" ? `An instructional illustration for step ${e.slide} of ${e.totalSlides}${e.title ? `, "${e.title}"` : ""}. ${e.imagePrompt}` : `A picture for a presentation slide${e.title ? ` titled "${e.title}"` : ""}. ${e.imagePrompt}`,
775
- t ? ct : "",
952
+ t ? Et : "",
776
953
  e.markdown ? "Keep the subject in the middle: the picture is cropped to a tall frame." : "",
777
954
  "No text, letters or numbers in the picture."
778
955
  ].filter(Boolean).join(" ");
779
- async function dt(e, t, n) {
956
+ async function kt(e, t) {
957
+ let n = await $(t, e.files?.artifacts);
958
+ return "error" in n && console.info(`[sequence] picture at ${t} not shown: ${n.error}`), n;
959
+ }
960
+ async function At(e, t, n) {
780
961
  if (n.chart) return {
781
962
  chart: n.chart,
782
963
  prompt: ""
783
964
  };
784
965
  if (n.html || n.markdown) {
785
966
  let r = n.html ? { html: n.html } : {
786
- html: await We(n.markdown ?? ""),
967
+ html: await qe(n.markdown ?? ""),
787
968
  markdown: n.markdown ?? ""
788
969
  };
789
- if (!y(r.html)) return {
970
+ if (!b(r.html)) return {
790
971
  ...r,
791
972
  prompt: ""
792
973
  };
793
- let i = n.imagePrompt || ie(r.html) || n.title, a = {
974
+ let i = n.imagePrompt || re(r.html) || n.title, a;
975
+ if (n.imageUrl) {
976
+ let t = await kt(e, n.imageUrl);
977
+ if (!("error" in t)) return {
978
+ ...r,
979
+ ...t,
980
+ imageUrl: n.imageUrl,
981
+ prompt: i,
982
+ imagePrompt: i
983
+ };
984
+ a = t.error;
985
+ }
986
+ let o = {
794
987
  ...n,
795
988
  imagePrompt: i
796
- }, o = await lt(e, t, a), s = ut(a, o.length > 0), c = await q(e, s, o), { imageData: l, imagePath: u } = V(c);
797
- return l ? {
989
+ }, s = await Dt(e, t, o), c = Ot(o, s.length > 0), l = await W(e, c, s), { imageData: u, imagePath: d } = R(l), f = a !== void 0 && { urlFailed: a };
990
+ return u ? {
798
991
  ...r,
799
- imageData: l,
800
- ...u && { imagePath: u },
801
- prompt: s,
802
- imagePrompt: i
992
+ imageData: u,
993
+ ...d && { imagePath: d },
994
+ prompt: c,
995
+ imagePrompt: i,
996
+ ...f
803
997
  } : {
804
998
  ...r,
805
- prompt: s,
999
+ prompt: c,
806
1000
  imagePrompt: i,
807
- pictureFailed: c.message
1001
+ pictureFailed: l.message,
1002
+ ...f
808
1003
  };
809
1004
  }
810
- let r = await lt(e, t, n), i = st(n, r.length > 0), a = await q(e, i, r), { imageData: o, imagePath: s } = V(a);
811
- return o ? {
812
- imageData: o,
813
- ...s && { imagePath: s },
814
- prompt: i
1005
+ let r;
1006
+ if (n.imageUrl) {
1007
+ let t = await kt(e, n.imageUrl);
1008
+ if (!("error" in t)) return {
1009
+ ...t,
1010
+ imageUrl: n.imageUrl,
1011
+ prompt: n.imagePrompt || n.title
1012
+ };
1013
+ if (!n.imagePrompt) return { failed: {
1014
+ message: `the picture at ${n.imageUrl} couldn't be shown: ${t.error}. Call presentSlide again with another imageUrl (an image file's address), or with imagePrompt to draw it.`,
1015
+ sequence: null
1016
+ } };
1017
+ r = t.error;
1018
+ }
1019
+ let i = await Dt(e, t, n), a = Tt(n, i.length > 0), o = await W(e, a, i), { imageData: s, imagePath: c } = R(o);
1020
+ return s ? {
1021
+ imageData: s,
1022
+ ...c && { imagePath: c },
1023
+ prompt: a,
1024
+ ...r !== void 0 && { urlFailed: r }
815
1025
  } : { failed: {
816
- ...a,
1026
+ ...o,
817
1027
  sequence: null
818
1028
  } };
819
1029
  }
820
- async function ft(e, t, n) {
821
- let r = await dt(e, t, n);
1030
+ async function jt(e, t, n) {
1031
+ let r = await At(e, t, n);
822
1032
  if ("failed" in r) return r.failed;
823
- let { imageData: i, imagePath: a, html: o, markdown: s, chart: c, prompt: l, pictureFailed: u } = r, d = t.id, f = await Q(e.files?.artifacts, Ge, d, (e) => {
1033
+ let { imageData: i, imagePath: a, imageUrl: o, html: s, markdown: c, chart: l, prompt: u, pictureFailed: d, urlFailed: f, source: p } = r, m = t.id, h = await Y(e.files?.artifacts, Je, m, (e) => {
824
1034
  let t = e ?? {
825
- id: d,
1035
+ id: m,
826
1036
  title: "",
827
1037
  mode: n.mode,
828
1038
  totalSlides: n.totalSlides,
@@ -830,47 +1040,52 @@ async function ft(e, t, n) {
830
1040
  };
831
1041
  return n.slide === 1 && (t.title = n.title), t.slides[String(n.slide)] = {
832
1042
  title: n.title,
833
- imagePrompt: o ? r.imagePrompt ?? "" : n.imagePrompt,
1043
+ imagePrompt: s ? r.imagePrompt ?? "" : n.imagePrompt,
834
1044
  ...a && { imagePath: a },
835
- ...o && { html: o },
836
- ...s && { markdown: s },
837
- ...c && { chart: c }
1045
+ ...o && { imageUrl: o },
1046
+ ...s && { html: s },
1047
+ ...c && { markdown: c },
1048
+ ...l && { chart: l }
838
1049
  }, t;
839
- }), p = {
1050
+ }), g = {
840
1051
  ...i && { imageData: i },
841
1052
  ...a && { imagePath: a },
842
- ...o && { html: o },
843
- ...s && { markdown: s },
844
- ...c && { chart: c },
845
- prompt: l,
846
- slideshowId: d,
1053
+ ...o && { imageUrl: o },
1054
+ ...s && { html: s },
1055
+ ...c && { markdown: c },
1056
+ ...l && { chart: l },
1057
+ prompt: u,
1058
+ slideshowId: m,
847
1059
  slide: n.slide,
848
1060
  totalSlides: n.totalSlides,
849
1061
  title: n.title,
850
1062
  mode: n.mode
851
- }, m = n.mode === "steps" ? "step" : "slide";
1063
+ }, v = n.mode === "steps" ? "step" : "slide";
852
1064
  return {
853
- data: p,
1065
+ data: g,
854
1066
  title: n.title || `Slide ${n.slide}`,
855
1067
  message: [
856
- `${m} ${n.slide} of ${n.totalSlides} of slideshow "${d}" is on the screen`,
1068
+ `${v} ${n.slide} of ${n.totalSlides} of slideshow "${m}" is on the screen`,
1069
+ o ? p ? `its picture is the preview picture of ${o} (${p})` : `its picture is from ${o}` : "",
857
1070
  a ? `saved to ${a}` : "",
858
- u ? `its picture couldn't be drawn (${u}), so the slide is shown without it` : "",
859
- f ? "" : $("slideshow")
1071
+ n.unplacedImageUrl ? `the picture at ${n.unplacedImageUrl} isn't shown: ${n.chart ? "a chart slide has no picture" : `the slide has no ${_} for it (<img src="${_}" alt="..." class="..."> where it goes)`}` : "",
1072
+ f === void 0 ? "" : `the picture at ${n.imageUrl} couldn't be shown (${f}), so it was drawn instead`,
1073
+ d ? `its picture couldn't be drawn (${d}), so the slide is shown without it` : "",
1074
+ h ? "" : X("slideshow")
860
1075
  ].filter(Boolean).join("; "),
861
1076
  instructions: A(n),
862
1077
  instructionsRequired: !0,
863
- sequence: nt(n)
1078
+ sequence: bt(n)
864
1079
  };
865
1080
  }
866
- async function pt(e, t) {
867
- let n = k(t);
1081
+ async function Mt(e, t) {
1082
+ let n = be(t);
868
1083
  if (typeof n == "string") return {
869
1084
  message: n,
870
1085
  sequence: null
871
1086
  };
872
- let r = it(e), i = at(r, n), a = n.mode === "steps";
873
- if (a && n.slide > i.current && i.current > 0 && !W(e, i.shownAt)) {
1087
+ let r = St(e), i = Ct(r, n), a = n.mode === "steps";
1088
+ if (a && n.slide > i.current && i.current > 0 && !V(e, i.shownAt)) {
874
1089
  console.info(`[sequence] holding step ${n.slide} for the user`);
875
1090
  let e = i.shownAt === Infinity ? "is still being drawn" : "is still on the screen";
876
1091
  return {
@@ -879,15 +1094,15 @@ async function pt(e, t) {
879
1094
  };
880
1095
  }
881
1096
  let o = a ? i.slides.get(n.slide) : void 0;
882
- if (o) return Oe(e.currentResult, o) ? {
1097
+ if (o) return je(e.currentResult, o) ? {
883
1098
  message: `step ${n.slide} of ${n.totalSlides} is already on the screen`,
884
1099
  cancelled: !0
885
- } : ot(r, i, n, o);
886
- let s = r.repeats.claim(rt(i.id, n));
1100
+ } : wt(r, i, n, o);
1101
+ let s = r.repeats.claim(xt(i.id, n));
887
1102
  if ("earlier" in s) {
888
- if (!await s.earlier) return pt(e, t);
1103
+ if (!await s.earlier) return Mt(e, t);
889
1104
  let a = i.slides.get(n.slide);
890
- return a && r.lastShown !== i ? ot(r, i, n, a) : {
1105
+ return a && r.lastShown !== i ? wt(r, i, n, a) : {
891
1106
  message: `slide ${n.slide} of ${n.totalSlides} is already on the screen`,
892
1107
  cancelled: !0
893
1108
  };
@@ -899,22 +1114,22 @@ async function pt(e, t) {
899
1114
  i.current = n.slide, i.shownAt = Infinity;
900
1115
  let u = !1;
901
1116
  try {
902
- let t = await ft(e, i, n);
903
- return u = De(t), u && (i.slides.set(n.slide, t), i.current = n.slide, i.shownAt = Date.now(), r.lastShown = i), t;
1117
+ let t = await jt(e, i, n);
1118
+ return u = Ae(t), u && (i.slides.set(n.slide, t), i.current = n.slide, i.shownAt = Date.now(), r.lastShown = i), t;
904
1119
  } finally {
905
1120
  c(u), !u && i.current === n.slide && (i.current = l.current, i.shownAt = l.shownAt);
906
1121
  }
907
1122
  }
908
1123
  //#endregion
909
1124
  //#region src/core/storyboard.ts
910
- var mt = ({ id: e, title: t, totalPanels: n }) => ({
1125
+ var Nt = ({ id: e, title: t, totalPanels: n }) => ({
911
1126
  step: 0,
912
1127
  total: n,
913
1128
  kind: "story",
914
1129
  label: `The cast of "${t}"`,
915
1130
  onShown: "introduce the characters",
916
1131
  nextCall: `call presentPanel for panel 1 of ${n} with storyboardId "${e}"`
917
- }), ht = ({ id: e, totalPanels: t }, n, r) => ({
1132
+ }), Pt = ({ id: e, totalPanels: t }, n, r) => ({
918
1133
  step: n,
919
1134
  total: t,
920
1135
  kind: "story",
@@ -922,21 +1137,21 @@ var mt = ({ id: e, title: t, totalPanels: n }) => ({
922
1137
  onShown: "tell that part of the story",
923
1138
  nextCall: `call presentPanel for panel ${n + 1} of ${t} with storyboardId "${e}"`,
924
1139
  ...r.length > 0 && { waitsForUser: !0 }
925
- }), gt = (e, t) => e ? `${e}. ${t}` : t, _t = (e, { name: t, description: n }) => gt(e, `Character reference sheet of ${t}: ${n}. Full body, front, side and back views, on a plain white background. No text or labels.`);
926
- async function vt(e, t) {
927
- let n = M(t);
1140
+ }), Ft = (e, t) => e ? `${e}. ${t}` : t, It = (e, { name: t, description: n }) => Ft(e, `Character reference sheet of ${t}: ${n}. Full body, front, side and back views, on a plain white background. No text or labels.`);
1141
+ async function Lt(e, t) {
1142
+ let n = De(t);
928
1143
  if (typeof n == "string") return {
929
1144
  message: n,
930
1145
  sequence: null
931
1146
  };
932
- let r = await Promise.all(n.characters.map((t) => q(e, _t(n.style, t)))), i = r.map(V), a = r.find((e, t) => !i[t]?.imageData);
1147
+ let r = await Promise.all(n.characters.map((t) => W(e, It(n.style, t)))), i = r.map(R), a = r.find((e, t) => !i[t]?.imageData);
933
1148
  if (i.every(({ imageData: e }) => !e) && a) return {
934
1149
  ...a,
935
1150
  message: `the character sheets couldn't be made: ${a.message}`,
936
1151
  sequence: null
937
1152
  };
938
1153
  let o = {
939
- id: G(),
1154
+ id: H(),
940
1155
  ...n,
941
1156
  characters: n.characters.map((e, t) => {
942
1157
  let n = i[t]?.imagePath;
@@ -946,7 +1161,7 @@ async function vt(e, t) {
946
1161
  };
947
1162
  }),
948
1163
  panels: {}
949
- }, s = await Q(e.files?.artifacts, Z, 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;
1164
+ }, s = await Y(e.files?.artifacts, J, 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;
950
1165
  return {
951
1166
  data: {
952
1167
  storyboardId: o.id,
@@ -967,39 +1182,39 @@ async function vt(e, t) {
967
1182
  `storyboard "${o.id}" is ready with ${o.totalPanels} panels; the cast is on the screen`,
968
1183
  c.length ? `character sheets saved to ${c.join(", ")}` : "",
969
1184
  l.length ? `no sheet for ${l.join("; ")}: they will be drawn from their description` : "",
970
- s ? "" : $("storyboard")
1185
+ s ? "" : X("storyboard")
971
1186
  ].filter(Boolean).join("; "),
972
- instructions: N(o),
1187
+ instructions: Oe(o),
973
1188
  instructionsRequired: !0,
974
- sequence: mt(o)
1189
+ sequence: Nt(o)
975
1190
  };
976
1191
  }
977
- function yt(e, t, n) {
978
- let r = [gt(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}`);
1192
+ function Rt(e, t, n) {
1193
+ let r = [Ft(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}`);
979
1194
  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(" ");
980
1195
  }
981
- async function bt(e, t, n) {
1196
+ async function zt(e, t, n) {
982
1197
  let r = [], i = [];
983
1198
  for (let a of n.characters) {
984
- let n = t.characters.find((e) => T(e.name, a));
1199
+ let n = t.characters.find((e) => O(e.name, a));
985
1200
  if (!n) r.push(a);
986
1201
  else if (!i.some((e) => e.character === n)) {
987
- let [t] = n.imagePath ? await K(e, [n.imagePath]) : [];
1202
+ let [t] = n.imagePath ? await U(e, [n.imagePath]) : [];
988
1203
  i.push({
989
1204
  character: n,
990
1205
  sheet: t ?? null
991
1206
  });
992
1207
  }
993
1208
  }
994
- let a = i.map(({ sheet: e }) => e).filter((e) => !!e), o = yt(t, n, i.map(({ character: e, sheet: t }) => ({
1209
+ let a = i.map(({ sheet: e }) => e).filter((e) => !!e), o = Rt(t, n, i.map(({ character: e, sheet: t }) => ({
995
1210
  character: e,
996
1211
  hasSheet: !!t
997
- }))), s = await q(e, o, a), { imageData: c, imagePath: l } = V(s);
1212
+ }))), s = await W(e, o, a), { imageData: c, imagePath: l } = R(s);
998
1213
  if (!c) return {
999
1214
  ...s,
1000
1215
  sequence: null
1001
1216
  };
1002
- let u = n.panel < t.totalPanels && n.choices.length >= 2 ? n.choices : [], d = await Q(e.files?.artifacts, Z, t.id, (e) => {
1217
+ let u = n.panel < t.totalPanels && n.choices.length >= 2 ? n.choices : [], d = await Y(e.files?.artifacts, J, t.id, (e) => {
1003
1218
  let r = e ?? t;
1004
1219
  return u.length && (r.interactive = !0), r.panels[String(n.panel)] = {
1005
1220
  caption: n.caption,
@@ -1025,25 +1240,25 @@ async function bt(e, t, n) {
1025
1240
  `panel ${n.panel} of ${t.totalPanels} is on the screen`,
1026
1241
  l ? `saved to ${l}` : "",
1027
1242
  r.length ? `not in the cast, so drawn from the prompt alone: ${r.join(", ")}` : "",
1028
- d ? "" : $("storyboard")
1243
+ d ? "" : X("storyboard")
1029
1244
  ].filter(Boolean).join("; "),
1030
- instructions: I(t, n.panel, u),
1245
+ instructions: N(t, n.panel, u),
1031
1246
  instructionsRequired: !0,
1032
- sequence: ht(t, n.panel, u)
1247
+ sequence: Pt(t, n.panel, u)
1033
1248
  };
1034
1249
  }
1035
- var xt = J(() => ({
1036
- repeats: tt(),
1250
+ var Bt = G(() => ({
1251
+ repeats: it(),
1037
1252
  awaitingChoice: /* @__PURE__ */ new Map()
1038
1253
  }));
1039
- async function St(e, t) {
1040
- let n = F(t);
1254
+ async function Vt(e, t) {
1255
+ let n = M(t);
1041
1256
  if (!n) return {
1042
- message: P,
1257
+ message: j,
1043
1258
  sequence: null
1044
1259
  };
1045
- let { storyboardId: r, panel: i } = n, { repeats: a, awaitingChoice: o } = xt(e), s = o.get(r);
1046
- if (s && i > s.panel && !W(e, s.shownAt)) return console.info(`[sequence] holding panel ${i} for the user`), {
1260
+ let { storyboardId: r, panel: i } = n, { repeats: a, awaitingChoice: o } = Bt(e), s = o.get(r);
1261
+ if (s && i > s.panel && !V(e, s.shownAt)) return console.info(`[sequence] holding panel ${i} for the user`), {
1047
1262
  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.`,
1048
1263
  cancelled: !0
1049
1264
  };
@@ -1051,7 +1266,7 @@ async function St(e, t) {
1051
1266
  if ("earlier" in c) return await c.earlier ? {
1052
1267
  message: `panel ${i} is already on the screen`,
1053
1268
  cancelled: !0
1054
- } : St(e, t);
1269
+ } : Vt(e, t);
1055
1270
  let { settle: l } = c, u = {
1056
1271
  panel: i,
1057
1272
  shownAt: Infinity
@@ -1059,7 +1274,7 @@ async function St(e, t) {
1059
1274
  o.set(r, u);
1060
1275
  let f = () => o.get(r) === u, p = !1;
1061
1276
  try {
1062
- let t = await $e(e.files?.artifacts, Z, r);
1277
+ let t = await nt(e.files?.artifacts, J, r);
1063
1278
  if (!t) return {
1064
1279
  message: `there is no storyboard "${r}"; call defineStoryboard first`,
1065
1280
  sequence: null
@@ -1068,8 +1283,8 @@ async function St(e, t) {
1068
1283
  message: `storyboard "${t.id}" has ${t.totalPanels} panels`,
1069
1284
  sequence: null
1070
1285
  };
1071
- let a = await bt(e, t, n);
1072
- p = !!V(a).imageData;
1286
+ let a = await zt(e, t, n);
1287
+ p = !!R(a).imageData;
1073
1288
  let s = a.data;
1074
1289
  return p && f() && (s?.choices?.length ? o.set(r, {
1075
1290
  panel: i,
@@ -1081,21 +1296,21 @@ async function St(e, t) {
1081
1296
  }
1082
1297
  //#endregion
1083
1298
  //#region src/core/index.ts
1084
- var Ct = {
1085
- toolDefinition: j,
1299
+ var Ht = {
1300
+ toolDefinition: Ee,
1086
1301
  generatingMessage: "Making the slide...",
1087
1302
  isEnabled: () => !0,
1088
- execute: (e, t) => pt(e, t)
1089
- }, wt = {
1090
- toolDefinition: R,
1303
+ execute: (e, t) => Mt(e, t)
1304
+ }, Ut = {
1305
+ toolDefinition: F,
1091
1306
  generatingMessage: "Drawing the characters...",
1092
1307
  isEnabled: () => !0,
1093
- execute: (e, t) => vt(e, t)
1094
- }, Tt = {
1095
- toolDefinition: z,
1308
+ execute: (e, t) => Lt(e, t)
1309
+ }, Wt = {
1310
+ toolDefinition: I,
1096
1311
  generatingMessage: "Drawing the panel...",
1097
1312
  isEnabled: () => !0,
1098
- execute: (e, t) => St(e, t)
1313
+ execute: (e, t) => Vt(e, t)
1099
1314
  };
1100
1315
  //#endregion
1101
- export { A, t as B, L as C, k as D, F as E, s as F, oe as H, h as I, l as L, fe as M, r as N, M as O, o as P, n as R, D as S, I as T, ae as U, y as V, j as _, Z as a, ye as b, pe as c, _e as d, ge as f, S as g, z as h, Ge as i, b as j, T as k, R as l, me as m, Tt as n, $e as o, P as p, Ct as r, We as s, wt as t, he as u, Te as v, N as w, O as x, ve as y, g as z };
1316
+ export { A, t as B, P as C, be as D, M as E, s as F, ae as H, h as I, l as L, de as M, r as N, De as O, o as P, n as R, _e as S, N as T, ie as U, b as V, Ee as _, J as a, ge as b, w as c, he as d, me as f, C as g, I as h, Je as i, x as j, O as k, F as l, fe as m, Wt as n, nt as o, j as p, Ht as r, qe as s, Ut as t, pe as u, Te as v, Oe as w, ve as x, T as y, _ as z };