@kywk/open-slide-core 2.3.1 → 2.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/dist/{build-CZ6Qtrng.js → build-46dO14h1.js} +1 -1
  2. package/dist/cli/bin.js +4 -4
  3. package/dist/{config-CpmGqpQi.d.ts → config-DJ8ZOe7C.d.ts} +6 -2
  4. package/dist/{config-B5LArqpp.js → config-KyYvWqq-.js} +2061 -355
  5. package/dist/{dev-CCgdakbZ.js → dev-C0n-o0-c.js} +2 -2
  6. package/dist/index.d.ts +3 -3
  7. package/dist/index.js +73 -32
  8. package/dist/locale/index.d.ts +1 -1
  9. package/dist/locale/index.js +1 -1
  10. package/dist/{preview-AwAqvG17.js → preview-CDWAGSfB.js} +1 -1
  11. package/dist/{types-CvAqFqsY.d.ts → types-tdaXSyah.d.ts} +111 -0
  12. package/dist/{update-C_RlnKu4.js → update-CqZqQRQk.js} +128 -7
  13. package/dist/vite/index.d.ts +1 -1
  14. package/dist/vite/index.js +1 -1
  15. package/dist/{zh-tw-B7_Oqv2q.js → zh-tw-DXcqQTrA.js} +540 -0
  16. package/package.json +10 -3
  17. package/src/agent/prompt.ts +141 -0
  18. package/src/agent/provider.ts +123 -0
  19. package/src/agent/types.ts +151 -0
  20. package/src/app/components/agent/agent-dock.tsx +35 -0
  21. package/src/app/components/agent/agent-markdown.tsx +45 -0
  22. package/src/app/components/agent/agent-panel.tsx +692 -0
  23. package/src/app/components/agent/agent-presence.tsx +74 -0
  24. package/src/app/components/agent/composer.tsx +120 -0
  25. package/src/app/components/agent/connect-view.tsx +184 -0
  26. package/src/app/components/agent/history-view.tsx +135 -0
  27. package/src/app/components/agent/provider-logo.tsx +34 -0
  28. package/src/app/components/agent/transcript.tsx +609 -0
  29. package/src/app/components/command/slide-command-menu.tsx +10 -0
  30. package/src/app/components/inline-svg.tsx +52 -21
  31. package/src/app/components/inspector/comment-layer.tsx +20 -1
  32. package/src/app/components/inspector/image-crop-dialog.tsx +1 -5
  33. package/src/app/components/inspector/inspector-panel.tsx +1 -1
  34. package/src/app/components/mermaid.tsx +42 -11
  35. package/src/app/components/panel/editor-sidebar.tsx +85 -16
  36. package/src/app/components/panel/panel-shell.tsx +2 -2
  37. package/src/app/components/panel/resize-handle.tsx +129 -0
  38. package/src/app/components/player.tsx +105 -23
  39. package/src/app/components/present/curtain.tsx +52 -0
  40. package/src/app/components/present/last-slide-hint.tsx +36 -0
  41. package/src/app/components/slide-canvas.tsx +1 -1
  42. package/src/app/components/thumbnail-rail.tsx +1 -1
  43. package/src/app/lib/agent/use-agent.ts +543 -0
  44. package/src/app/lib/use-auto-grow.ts +15 -0
  45. package/src/app/lib/utils.ts +4 -0
  46. package/src/app/routes/home.tsx +51 -7
  47. package/src/app/routes/slide.tsx +172 -116
  48. package/src/app/styles.css +170 -0
  49. package/src/editing/placeholder-id.ts +1 -0
  50. package/src/locale/en.ts +107 -0
  51. package/src/locale/es.ts +109 -0
  52. package/src/locale/ja.ts +100 -0
  53. package/src/locale/types.ts +110 -0
  54. package/src/locale/zh-cn.ts +97 -0
  55. package/src/locale/zh-tw.ts +97 -0
@@ -1,6 +1,6 @@
1
- import { j as ownPackageName } from "./update-C_RlnKu4.js";
1
+ import { z as ownPackageName } from "./update-CqZqQRQk.js";
2
2
  import { a as printUrls, i as printShortcutsHint, n as formatError, o as shortcutsEnabled, r as printHeader, s as startupDuration, t as createCliLogger } from "./cli/bin.js";
3
- import { n as DEV_SUPERVISED_ENV, t as createViteConfig } from "./config-B5LArqpp.js";
3
+ import { n as DEV_SUPERVISED_ENV, t as createViteConfig } from "./config-KyYvWqq-.js";
4
4
  import path from "node:path";
5
5
  import { existsSync } from "node:fs";
6
6
  import { fork } from "node:child_process";
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { n as Plural, t as Locale } from "./types-CvAqFqsY.js";
2
- import { t as OpenSlideConfig } from "./config-CpmGqpQi.js";
1
+ import { n as Plural, t as Locale } from "./types-tdaXSyah.js";
2
+ import { n as OpenSlideConfig, t as OpenSlideAgentConfig } from "./config-DJ8ZOe7C.js";
3
3
  import { CSSProperties, ComponentType, HTMLAttributes, PropsWithChildren, ReactNode } from "react";
4
4
  //#region src/app/components/image-placeholder.d.ts
5
5
  type ImagePlaceholderProps = {
@@ -130,4 +130,4 @@ type InternalStepProps = StepProps & {
130
130
  };
131
131
  declare function Step({ children, duration, _revealed }: InternalStepProps): import("react").JSX.Element;
132
132
  //#endregion
133
- export { CANVAS_HEIGHT, CANVAS_WIDTH, type DesignFonts, type DesignPalette, type DesignSystem, type DesignTypeScale, ImagePlaceholder, type ImagePlaceholderProps, InlineSvg, type InlineSvgProps, type Locale, Mermaid, Mermaid as Pele, type MermaidConfigLegacy, type MermaidProps, type MermaidProps as PeleProps, MorphElement, type MorphElementProps, type MorphTransition, type OpenSlideConfig, type Page, type Plural, type SlideMeta, type SlideModule, type SlideTransition, Step, type StepProps, Steps, type StepsProps, type TransitionPhase, cssVarsToString, defaultDesign, designToCssVars, useIsActivePage, useSlidePageNumber };
133
+ export { CANVAS_HEIGHT, CANVAS_WIDTH, type DesignFonts, type DesignPalette, type DesignSystem, type DesignTypeScale, ImagePlaceholder, type ImagePlaceholderProps, InlineSvg, type InlineSvgProps, type Locale, Mermaid, Mermaid as Pele, type MermaidConfigLegacy, type MermaidProps, type MermaidProps as PeleProps, MorphElement, type MorphElementProps, type MorphTransition, type OpenSlideAgentConfig, type OpenSlideConfig, type Page, type Plural, type SlideMeta, type SlideModule, type SlideTransition, Step, type StepProps, Steps, type StepsProps, type TransitionPhase, cssVarsToString, defaultDesign, designToCssVars, useIsActivePage, useSlidePageNumber };
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { a as en, i as es, n as zhCN, r as ja, t as zhTW } from "./zh-tw-B7_Oqv2q.js";
1
+ import { a as en, i as es, n as zhCN, r as ja, t as zhTW } from "./zh-tw-DXcqQTrA.js";
2
2
  import { n as defaultDesign, r as designToCssVars, t as cssVarsToString } from "./design-CoZ0cWDN.js";
3
3
  import { Children, cloneElement, createContext, isValidElement, useCallback, useContext, useEffect, useLayoutEffect, useRef, useState, useSyncExternalStore } from "react";
4
4
  import { toast } from "sonner";
@@ -349,26 +349,47 @@ function isLightColor$1(color) {
349
349
  const b = Number.parseInt(hex.slice(4, 6), 16);
350
350
  return (.299 * r + .587 * g + .114 * b) / 255 > .5;
351
351
  }
352
+ const MAX_SVG_CACHE_ENTRIES = 100;
353
+ const svgCache = /* @__PURE__ */ new Map();
354
+ function getCachedSvg(svg, alt) {
355
+ const cacheKey = alt ? `${alt}:::${svg}` : svg;
356
+ let template = svgCache.get(cacheKey);
357
+ if (template) {
358
+ svgCache.delete(cacheKey);
359
+ svgCache.set(cacheKey, template);
360
+ } else {
361
+ const el = document.createElement("template");
362
+ el.innerHTML = svg.trim();
363
+ const svgEl = el.content.querySelector("svg");
364
+ if (!svgEl) return null;
365
+ svgEl.style.width = "100%";
366
+ svgEl.style.height = "100%";
367
+ svgEl.style.display = "block";
368
+ svgEl.setAttribute("preserveAspectRatio", "xMidYMid meet");
369
+ if (alt && !svgEl.getAttribute("aria-label")) {
370
+ svgEl.setAttribute("aria-label", alt);
371
+ svgEl.setAttribute("role", "img");
372
+ }
373
+ template = svgEl;
374
+ if (svgCache.size >= MAX_SVG_CACHE_ENTRIES) {
375
+ const oldest = svgCache.keys().next().value;
376
+ if (oldest !== void 0) svgCache.delete(oldest);
377
+ }
378
+ svgCache.set(cacheKey, template);
379
+ }
380
+ return template.cloneNode(true);
381
+ }
352
382
  function InlineSvg({ svg, className, style, lightbox = true, alt }) {
353
383
  const containerRef = useRef(null);
354
384
  const wrapperRef = useRef(null);
355
385
  const [lightboxOpen, setLightboxOpen] = useState(false);
356
386
  const [canvasBg, setCanvasBg] = useState("#ffffff");
357
- useEffect(() => {
387
+ useLayoutEffect(() => {
358
388
  const el = containerRef.current;
359
389
  if (!el) return;
360
- el.innerHTML = svg;
361
- const svgEl = el.querySelector("svg");
362
- if (svgEl) {
363
- svgEl.style.width = "100%";
364
- svgEl.style.height = "100%";
365
- svgEl.style.display = "block";
366
- svgEl.setAttribute("preserveAspectRatio", "xMidYMid meet");
367
- if (alt && !svgEl.getAttribute("aria-label")) {
368
- svgEl.setAttribute("aria-label", alt);
369
- svgEl.setAttribute("role", "img");
370
- }
371
- }
390
+ const node = getCachedSvg(svg, alt);
391
+ if (node) el.replaceChildren(node);
392
+ else el.replaceChildren();
372
393
  }, [svg, alt]);
373
394
  const handleClick = useCallback(() => {
374
395
  if (lightbox && wrapperRef.current) {
@@ -420,17 +441,12 @@ function InlineSvg({ svg, className, style, lightbox = true, alt }) {
420
441
  function SvgLightbox({ svg, canvasBg, onClose }) {
421
442
  const containerRef = useRef(null);
422
443
  const light = isLightColor$1(canvasBg);
423
- useEffect(() => {
444
+ useLayoutEffect(() => {
424
445
  const el = containerRef.current;
425
446
  if (!el) return;
426
- el.innerHTML = svg;
427
- const svgEl = el.querySelector("svg");
428
- if (svgEl) {
429
- svgEl.style.width = "100%";
430
- svgEl.style.height = "100%";
431
- svgEl.style.display = "block";
432
- svgEl.setAttribute("preserveAspectRatio", "xMidYMid meet");
433
- }
447
+ const node = getCachedSvg(svg);
448
+ if (node) el.replaceChildren(node);
449
+ else el.replaceChildren();
434
450
  }, [svg]);
435
451
  useEffect(() => {
436
452
  const handleKey = (e) => {
@@ -512,7 +528,7 @@ function normalizeSvg(svg, id) {
512
528
  template.innerHTML = svg.trim();
513
529
  const element = template.content.querySelector("svg");
514
530
  if (!element) throw new Error("Pele did not return an SVG");
515
- if (!element.id) element.id = id;
531
+ if (id && !element.id) element.id = id;
516
532
  const origWidth = element.getAttribute("width") ?? "800";
517
533
  const origHeight = element.getAttribute("height") ?? "600";
518
534
  const w = Number.parseFloat(origWidth);
@@ -528,6 +544,26 @@ function normalizeSvg(svg, id) {
528
544
  element.style.maxHeight = "100%";
529
545
  return element;
530
546
  }
547
+ const MAX_CACHE_ENTRIES = 100;
548
+ const diagramCache = /* @__PURE__ */ new Map();
549
+ function getCachedDiagram(chart) {
550
+ let template = diagramCache.get(chart);
551
+ if (template) {
552
+ diagramCache.delete(chart);
553
+ diagramCache.set(chart, template);
554
+ } else {
555
+ const { svg } = render(chart);
556
+ template = normalizeSvg(svg);
557
+ if (diagramCache.size >= MAX_CACHE_ENTRIES) {
558
+ const oldest = diagramCache.keys().next().value;
559
+ if (oldest !== void 0) diagramCache.delete(oldest);
560
+ }
561
+ diagramCache.set(chart, template);
562
+ }
563
+ const clone = template.cloneNode(true);
564
+ clone.id = nextRenderId();
565
+ return clone;
566
+ }
531
567
  const peleDefaults = {
532
568
  "--pele-bg": "var(--osd-bg, #ffffff)",
533
569
  "--pele-fg": "var(--osd-text, #111827)",
@@ -619,7 +655,13 @@ function Mermaid({ chart, className, style, config, fallback, lightbox = true })
619
655
  const wrapperRef = useRef(null);
620
656
  const diagramRef = useRef(null);
621
657
  const renderVersion = useRef(0);
622
- const [diagram, setDiagram] = useState(null);
658
+ const [diagram, setDiagram] = useState(() => {
659
+ if (typeof document === "undefined") return null;
660
+ try {
661
+ if (diagramCache.has(chart)) return { element: getCachedDiagram(chart) };
662
+ } catch {}
663
+ return null;
664
+ });
623
665
  const [error, setError] = useState(null);
624
666
  const [lightboxOpen, setLightboxOpen] = useState(false);
625
667
  const [canvasBg, setCanvasBg] = useState("#ffffff");
@@ -627,22 +669,22 @@ function Mermaid({ chart, className, style, config, fallback, lightbox = true })
627
669
  useEffect(() => {
628
670
  let active = true;
629
671
  const version = ++renderVersion.current;
630
- setDiagram(null);
631
- setError(null);
632
672
  try {
633
- const { svg } = render(chart);
673
+ const element = getCachedDiagram(chart);
634
674
  if (!active || version !== renderVersion.current) return;
635
- setDiagram({ element: normalizeSvg(svg, nextRenderId()) });
675
+ setError(null);
676
+ setDiagram({ element });
636
677
  } catch (cause) {
637
678
  if (!active || version !== renderVersion.current) return;
638
679
  wrapperRef.current?.replaceChildren();
680
+ setDiagram(null);
639
681
  setError(cause);
640
682
  }
641
683
  return () => {
642
684
  active = false;
643
685
  };
644
686
  }, [chart]);
645
- useEffect(() => {
687
+ useLayoutEffect(() => {
646
688
  if (!diagram || !diagramRef.current) return;
647
689
  diagramRef.current.replaceChildren(diagram.element);
648
690
  return () => diagram.element.remove();
@@ -712,9 +754,8 @@ function MermaidLightbox({ chart, config, canvasBg, themeStyles, onClose }) {
712
754
  const light = isLightColor(canvasBg);
713
755
  useEffect(() => {
714
756
  try {
715
- const { svg } = render(chart);
716
757
  if (!containerRef.current) return;
717
- const el = normalizeSvg(svg, nextRenderId());
758
+ const el = getCachedDiagram(chart);
718
759
  containerRef.current.replaceChildren(el);
719
760
  } catch {}
720
761
  }, [chart]);
@@ -1,4 +1,4 @@
1
- import { n as Plural, t as Locale } from "../types-CvAqFqsY.js";
1
+ import { n as Plural, t as Locale } from "../types-tdaXSyah.js";
2
2
  //#region src/locale/en.d.ts
3
3
  declare const en: Locale;
4
4
  //#endregion
@@ -1,4 +1,4 @@
1
- import { a as en, i as es, n as zhCN, r as ja, t as zhTW } from "../zh-tw-B7_Oqv2q.js";
1
+ import { a as en, i as es, n as zhCN, r as ja, t as zhTW } from "../zh-tw-DXcqQTrA.js";
2
2
  //#region src/locale/format.ts
3
3
  function format(template, vars) {
4
4
  return template.replace(/\{(\w+)\}/g, (m, key) => {
@@ -1,5 +1,5 @@
1
1
  import { a as printUrls, i as printShortcutsHint, o as shortcutsEnabled, r as printHeader, s as startupDuration, t as createCliLogger } from "./cli/bin.js";
2
- import { t as createViteConfig } from "./config-B5LArqpp.js";
2
+ import { t as createViteConfig } from "./config-KyYvWqq-.js";
3
3
  import { mergeConfig, preview as preview$1 } from "vite";
4
4
  //#region src/cli/preview.ts
5
5
  async function preview(opts = {}) {
@@ -1,3 +1,7 @@
1
+ //#region src/agent/types.d.ts
2
+ declare const AGENT_EFFORTS: readonly ['minimal', 'low', 'medium', 'high', 'xhigh', 'max'];
3
+ type AgentEffort = (typeof AGENT_EFFORTS)[number];
4
+ //#endregion
1
5
  //#region src/locale/types.d.ts
2
6
  type Plural = {
3
7
  one: string;
@@ -99,6 +103,7 @@ type Locale = {
99
103
  pickIcon: string;
100
104
  };
101
105
  slide: {
106
+ resizeSidePanel: string;
102
107
  home: string;
103
108
  backToHome: string;
104
109
  agentConnected: string;
@@ -176,6 +181,7 @@ type Locale = {
176
181
  helpAria: string;
177
182
  exitAria: string;
178
183
  elapsedTime: string;
184
+ lastSlideHint: string;
179
185
  helpEyebrow: string;
180
186
  helpTitle: string;
181
187
  shortcutNext: string;
@@ -560,6 +566,111 @@ type Locale = {
560
566
  expandPromptAria: string;
561
567
  collapsePromptAria: string;
562
568
  };
569
+ agent: {
570
+ title: string;
571
+ beta: string;
572
+ betaTitle: string;
573
+ betaHint: string;
574
+ open: string;
575
+ openTitle: string;
576
+ close: string;
577
+ newSession: string;
578
+ sessions: string;
579
+ noSessions: string;
580
+ deleteSession: string;
581
+ historyThisDeck: string;
582
+ historyOtherDecks: string;
583
+ historyEmptyHint: string;
584
+ sessionRunning: string;
585
+ /** template: "Ask {provider} to create or edit slides…" */
586
+ composerPlaceholder: string;
587
+ send: string;
588
+ stop: string;
589
+ working: string;
590
+ /** template: "Page {n}" */
591
+ contextPage: string;
592
+ contextSelection: string;
593
+ /** plural, template: "{count} comments" */
594
+ pendingComments: Plural;
595
+ applyComments: string;
596
+ /** template: "Apply with {provider}" */
597
+ applyCommentsWith: string;
598
+ createDeck: string;
599
+ /** template: "Create a deck with {provider}" */
600
+ createDeckWith: string;
601
+ quickCreate: string;
602
+ quickCreateHint: string;
603
+ quickApply: string;
604
+ quickApplyHint: string;
605
+ quickTheme: string;
606
+ quickThemeHint: string;
607
+ quickEdit: string;
608
+ quickEditHint: string;
609
+ emptyTitle: string;
610
+ emptyHint: string;
611
+ questionSubmit: string;
612
+ questionOther: string;
613
+ questionOtherPlaceholder: string;
614
+ questionCancelled: string;
615
+ permissionTitle: string;
616
+ allow: string;
617
+ deny: string;
618
+ allowed: string;
619
+ denied: string;
620
+ autoApprove: string;
621
+ autoApproveHint: string;
622
+ resultDone: string;
623
+ resultStopped: string;
624
+ /** template: "{seconds}s" */
625
+ resultSeconds: string;
626
+ errorEyebrow: string;
627
+ statusLoading: string;
628
+ disabled: string;
629
+ connectTitle: string;
630
+ connectDescription: string;
631
+ connect: string;
632
+ connecting: string;
633
+ connected: string;
634
+ /** template: "Adds {pkg} to this workspace with {pm}." */
635
+ connectInstallHint: string;
636
+ /** template: "CLI found · v{version}" */
637
+ cliFound: string;
638
+ cliFoundNoVersion: string;
639
+ cliMissing: string;
640
+ /** template: "Install the {name} CLI and sign in once; the panel reuses its login." */
641
+ cliHint: string;
642
+ needCliTitle: string;
643
+ needCliDescription: string;
644
+ checkAgain: string;
645
+ retry: string;
646
+ /** template: "{name} connected" */
647
+ toastConnected: string;
648
+ /** template: "Could not install {pkg}" */
649
+ toastConnectFailed: string;
650
+ manageConnections: string;
651
+ backToChat: string;
652
+ toastSendFailed: string;
653
+ newDeckTitle: string;
654
+ newDeckHint: string;
655
+ newDeckPlaceholder: string;
656
+ toastCreateDeckFailed: string;
657
+ steps: Plural;
658
+ questionSkip: string;
659
+ copyMessage: string;
660
+ copied: string;
661
+ editMessage: string;
662
+ cancelEdit: string;
663
+ sendEdit: string;
664
+ editHint: string;
665
+ modelDefault: string;
666
+ reasoning: string;
667
+ effortAuto: string;
668
+ efforts: Record<AgentEffort, string>;
669
+ /** template: "{provider} is editing" */
670
+ presenceEditing: string;
671
+ presenceThinking: string;
672
+ presenceWaiting: string;
673
+ };
563
674
  };
564
675
  //#endregion
565
676
  export { Plural as n, Locale as t };
@@ -98,6 +98,10 @@ function validateMutationRequest(req, opts = {}) {
98
98
  };
99
99
  return { ok: true };
100
100
  }
101
+ function isLoopbackRequest(req) {
102
+ const address = req.socket.remoteAddress ?? "";
103
+ return address === "::1" || address.startsWith("127.") || address.startsWith("::ffff:127.");
104
+ }
101
105
  //#endregion
102
106
  //#region src/editing/slide-ops.ts
103
107
  const SLIDE_ID_RE = /^[a-z0-9_-]+$/i;
@@ -295,6 +299,106 @@ async function duplicateSlideDir(slidesRoot, slideId, desiredId) {
295
299
  };
296
300
  }
297
301
  }
302
+ const BLANK_SLIDE_TITLE = "Untitled";
303
+ function blankSlideSource(createdAt) {
304
+ return `import type { Page, SlideMeta } from '${ownPackageName()}';
305
+
306
+ export const meta: SlideMeta = { title: ${JSON.stringify(BLANK_SLIDE_TITLE)}, createdAt: ${JSON.stringify(createdAt)} };
307
+
308
+ const Blank: Page = () => <div style={{ width: '100%', height: '100%', background: '#ffffff' }} />;
309
+
310
+ export default [Blank] satisfies Page[];
311
+ `;
312
+ }
313
+ async function createBlankSlideDir(slidesRoot) {
314
+ const root = path.resolve(slidesRoot);
315
+ await fs.mkdir(root, { recursive: true });
316
+ for (let suffix = 1; suffix < 1e3; suffix++) {
317
+ const slideId = suffix === 1 ? "untitled" : `untitled-${suffix}`;
318
+ if (await slideIdTaken(root, slideId)) continue;
319
+ const dir = path.join(root, slideId);
320
+ try {
321
+ await fs.mkdir(dir);
322
+ } catch (err) {
323
+ if (err.code === "EEXIST") continue;
324
+ return {
325
+ ok: false,
326
+ status: 500,
327
+ error: String(err.message ?? err)
328
+ };
329
+ }
330
+ const file = path.join(dir, "index.tsx");
331
+ await fs.writeFile(file, blankSlideSource((/* @__PURE__ */ new Date()).toISOString()), "utf8");
332
+ return {
333
+ ok: true,
334
+ slideId,
335
+ file
336
+ };
337
+ }
338
+ return {
339
+ ok: false,
340
+ status: 409,
341
+ error: "no free slide id"
342
+ };
343
+ }
344
+ function slugifyTitle(title) {
345
+ return title.normalize("NFKD").replace(/[\u0300-\u036f]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+/, "").slice(0, 48).replace(/-+$/, "");
346
+ }
347
+ async function renameSlideDir(slidesRoot, slideId, desiredId) {
348
+ if (!SLIDE_ID_RE.test(slideId) || !SLIDE_ID_RE.test(desiredId)) return {
349
+ ok: false,
350
+ status: 400,
351
+ error: "invalid slideId"
352
+ };
353
+ const root = path.resolve(slidesRoot);
354
+ const from = path.resolve(root, slideId);
355
+ if (!from.startsWith(root + path.sep)) return {
356
+ ok: false,
357
+ status: 400,
358
+ error: "invalid slideId"
359
+ };
360
+ try {
361
+ await fs.access(path.join(from, "index.tsx"));
362
+ } catch {
363
+ return {
364
+ ok: false,
365
+ status: 404,
366
+ error: "slide not found"
367
+ };
368
+ }
369
+ for (let suffix = 1; suffix < 1e3; suffix++) {
370
+ const candidate = suffix === 1 ? desiredId : `${desiredId}-${suffix}`;
371
+ if (candidate === slideId) return {
372
+ ok: false,
373
+ status: 409,
374
+ error: "slide id unchanged"
375
+ };
376
+ if (await slideIdTaken(root, candidate)) continue;
377
+ const to = path.join(root, candidate);
378
+ try {
379
+ await fs.rename(from, to);
380
+ } catch (err) {
381
+ const code = err.code;
382
+ if (code === "EEXIST" || code === "ENOTEMPTY") continue;
383
+ return {
384
+ ok: false,
385
+ status: 500,
386
+ error: String(err.message ?? err)
387
+ };
388
+ }
389
+ return {
390
+ ok: true,
391
+ slideId: candidate,
392
+ from,
393
+ to
394
+ };
395
+ }
396
+ return {
397
+ ok: false,
398
+ status: 409,
399
+ error: "no free slide id"
400
+ };
401
+ }
298
402
  function resolveSlideEntry(slidesRoot, slideId) {
299
403
  if (!SLIDE_ID_RE.test(slideId)) return null;
300
404
  const dir = path.resolve(slidesRoot, slideId);
@@ -718,13 +822,29 @@ function makeContext(opts) {
718
822
  slidesRoot,
719
823
  globalAssetsRoot: path.resolve(userCwd, assetsDir),
720
824
  manifestPath: foldersManifestPath(slidesRoot),
721
- coreVersion: opts.coreVersion
825
+ coreVersion: opts.coreVersion,
826
+ agentEnabled: opts.agentEnabled
722
827
  };
723
828
  }
724
- async function readBody(req) {
829
+ var BodyTooLargeError = class extends Error {
830
+ constructor() {
831
+ super("request body too large");
832
+ this.name = "BodyTooLargeError";
833
+ }
834
+ };
835
+ async function readBody(req, limit = Number.POSITIVE_INFINITY) {
725
836
  return await new Promise((resolve, reject) => {
726
837
  const chunks = [];
727
- req.on("data", (c) => chunks.push(c));
838
+ let size = 0;
839
+ req.on("data", (c) => {
840
+ size += c.length;
841
+ if (size > limit) {
842
+ req.destroy();
843
+ reject(new BodyTooLargeError());
844
+ return;
845
+ }
846
+ chunks.push(c);
847
+ });
728
848
  req.on("end", () => {
729
849
  const raw = Buffer.concat(chunks).toString("utf8");
730
850
  if (!raw) return resolve({});
@@ -857,7 +977,7 @@ function localOpenSlideCommand(cwd) {
857
977
  function formatCommand(spec) {
858
978
  return [spec.cmd, ...spec.args].join(" ");
859
979
  }
860
- async function runCommand(spec, cwd) {
980
+ async function runCommand(spec, cwd, timeoutMs = COMMAND_TIMEOUT_MS) {
861
981
  await new Promise((resolve, reject) => {
862
982
  const child = spawn(spec.cmd, spec.args, {
863
983
  cwd,
@@ -867,13 +987,14 @@ async function runCommand(spec, cwd) {
867
987
  "ignore",
868
988
  "ignore",
869
989
  "pipe"
870
- ]
990
+ ],
991
+ windowsHide: true
871
992
  });
872
993
  let stderr = "";
873
994
  const timer = setTimeout(() => {
874
995
  child.kill();
875
996
  reject(/* @__PURE__ */ new Error(`${formatCommand(spec)} timed out`));
876
- }, COMMAND_TIMEOUT_MS);
997
+ }, timeoutMs);
877
998
  child.stderr.on("data", (chunk) => {
878
999
  stderr += chunk.toString("utf8");
879
1000
  if (stderr.length > 2e3) stderr = stderr.slice(-2e3);
@@ -935,4 +1056,4 @@ function registerUpdateRoutes(server, ctx) {
935
1056
  });
936
1057
  }
937
1058
  //#endregion
938
- export { ownPackage as A, reorderDefaultExportPagesInSource as C, updateMetaTitleInSource as D, rmSlideDir as E, validateSlideName as O, removePageFromDefaultExportInSource as S, resolveSlideEntry as T, SLIDE_ID_RE as _, readBody as a, duplicateSlideDir as b, FOLDER_ID_RE as c, readManifest as d, validateIcon as f, shortId as g, writeManifest as h, makeContext as i, ownPackageName as j, validateMutationRequest as k, foldersManifestPath as l, validateReorder as m, registerUpdateRoutes as n, readSlideSource as o, validateName as p, json as r, resolveSlideEntryPath as s, detectPackageManager as t, newFolderId as u, duplicateNotesElementInSource as v, reorderNotesArrayInSource as w, removeNotesElementInSource as x, duplicatePageInDefaultExportInSource as y };
1059
+ export { reorderNotesArrayInSource as A, duplicatePageInDefaultExportInSource as C, removePageFromDefaultExportInSource as D, removeNotesElementInSource as E, validateSlideName as F, isLoopbackRequest as I, validateMutationRequest as L, rmSlideDir as M, slugifyTitle as N, renameSlideDir as O, updateMetaTitleInSource as P, ownPackage as R, duplicateNotesElementInSource as S, readMetaTitleInSource as T, writeManifest as _, json as a, SLIDE_ID_RE as b, readSlideSource as c, foldersManifestPath as d, newFolderId as f, validateReorder as g, validateName as h, BodyTooLargeError as i, resolveSlideEntry as j, reorderDefaultExportPagesInSource as k, resolveSlideEntryPath as l, validateIcon as m, registerUpdateRoutes as n, makeContext as o, readManifest as p, runCommand as r, readBody as s, detectPackageManager as t, FOLDER_ID_RE as u, shortId as v, duplicateSlideDir as w, createBlankSlideDir as x, BLANK_SLIDE_TITLE as y, ownPackageName as z };
@@ -1,4 +1,4 @@
1
- import { t as OpenSlideConfig } from "../config-CpmGqpQi.js";
1
+ import { n as OpenSlideConfig } from "../config-DJ8ZOe7C.js";
2
2
  import { InlineConfig } from "vite";
3
3
  //#region src/vite/config.d.ts
4
4
  type CreateViteConfigOptions = {
@@ -1,2 +1,2 @@
1
- import { t as createViteConfig } from "../config-B5LArqpp.js";
1
+ import { t as createViteConfig } from "../config-KyYvWqq-.js";
2
2
  export { createViteConfig };