@agent-native/core 0.186.0-nightly-20260923174435 → 0.186.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/CHANGELOG.md +6 -0
  3. package/corpus/templates/analytics/app/components/Markdown.tsx +3 -3
  4. package/corpus/templates/analytics/app/i18n/en-US.ts +1513 -3
  5. package/corpus/templates/analytics/app/routes/$.tsx +2 -2
  6. package/corpus/templates/analytics/app/routes/agents.tsx +2 -2
  7. package/corpus/templates/analytics/app/routes/analyses.$id.tsx +2 -2
  8. package/corpus/templates/analytics/app/routes/analyses._index.tsx +2 -2
  9. package/corpus/templates/analytics/app/routes/ask.tsx +2 -2
  10. package/corpus/templates/analytics/app/routes/dashboards.$id.tsx +2 -2
  11. package/corpus/templates/analytics/app/routes/data-dictionary.tsx +2 -2
  12. package/corpus/templates/analytics/app/routes/data-sources.tsx +2 -2
  13. package/corpus/templates/analytics/app/routes/extensions.$id.tsx +2 -2
  14. package/corpus/templates/analytics/app/routes/extensions._index.tsx +2 -2
  15. package/corpus/templates/analytics/app/routes/monitoring._index.tsx +2 -2
  16. package/corpus/templates/analytics/app/routes/sessions.$recordingId.tsx +2 -2
  17. package/corpus/templates/analytics/app/routes/sessions._index.tsx +2 -2
  18. package/corpus/templates/analytics/app/routes/settings.tsx +2 -2
  19. package/corpus/templates/analytics/app/routes/team.tsx +2 -2
  20. package/corpus/templates/analytics/changelog/2026-09-23-analytics-opens-faster-by-loading-translation-catalogs-and-r.md +6 -0
  21. package/corpus/templates/calendar/CHANGELOG.md +12 -0
  22. package/corpus/templates/calendar/app/i18n/en-US.ts +985 -3
  23. package/corpus/templates/calendar/app/i18n/index.ts +16 -11
  24. package/corpus/templates/calendar/app/routes/_app.$.tsx +2 -2
  25. package/corpus/templates/calendar/app/routes/_app.agent.tsx +2 -2
  26. package/corpus/templates/calendar/app/routes/_app.booking-links.tsx +2 -2
  27. package/corpus/templates/calendar/app/routes/_app.settings.tsx +2 -2
  28. package/corpus/templates/calendar/app/routes/_app.shared-availability.add.tsx +2 -4
  29. package/corpus/templates/calendar/app/routes/_app.team.tsx +2 -2
  30. package/corpus/templates/calendar/app/routes/booking-og-meta.ts +2 -2
  31. package/corpus/templates/calendar/app/routes/booking.manage.$token.tsx +2 -2
  32. package/corpus/templates/calendar/app/routes/event.tsx +2 -2
  33. package/corpus/templates/calendar/changelog/2026-09-23-calendar-opens-faster-by-loading-translated-catalogs-only-wh.md +6 -0
  34. package/corpus/templates/clips/CHANGELOG.md +10 -0
  35. package/corpus/templates/clips/app/components/library/recording-card.tsx +1 -1
  36. package/corpus/templates/clips/app/components/player/agent-view-count.tsx +61 -0
  37. package/corpus/templates/clips/app/components/player/recording-views-badge.tsx +57 -72
  38. package/corpus/templates/clips/changelog/2026-09-23-insights-charts-load-only-when-opened-keeping-the-recording-.md +6 -0
  39. package/corpus/templates/content/app/components/editor/DocumentToolbar.tsx +1 -1
  40. package/corpus/templates/content/app/components/layout/Header.tsx +1 -1
  41. package/corpus/templates/content/app/components/layout/Layout.tsx +5 -5
  42. package/corpus/templates/content/app/root.tsx +2 -1
  43. package/corpus/templates/design/.agents/skills/design-editor-architecture/SKILL.md +2 -2
  44. package/corpus/templates/design/CHANGELOG.md +7 -0
  45. package/corpus/templates/design/app/components/editor/PromptDialog.tsx +55 -20
  46. package/corpus/templates/design/app/i18n/en-US.ts +1964 -21
  47. package/corpus/templates/design/app/pages/Index.tsx +5 -1
  48. package/corpus/templates/design/app/pages/Templates.tsx +5 -1
  49. package/corpus/templates/design/app/routes/$.tsx +2 -2
  50. package/corpus/templates/design/app/routes/design-systems.tsx +2 -2
  51. package/corpus/templates/design/app/routes/design-systems_.setup.tsx +2 -2
  52. package/corpus/templates/design/app/routes/design.$id.tsx +2 -2
  53. package/corpus/templates/design/app/routes/extensions.$id.tsx +2 -2
  54. package/corpus/templates/design/app/routes/extensions._index.tsx +2 -2
  55. package/corpus/templates/design/app/routes/extensions.tsx +2 -2
  56. package/corpus/templates/design/app/routes/observability.tsx +2 -2
  57. package/corpus/templates/design/app/routes/present.$id.tsx +2 -2
  58. package/corpus/templates/design/app/routes/settings.tsx +2 -2
  59. package/corpus/templates/design/app/routes/team.tsx +2 -2
  60. package/corpus/templates/design/app/routes/templates.tsx +2 -2
  61. package/corpus/templates/design/app/routes/visual-edit.tsx +2 -2
  62. package/corpus/templates/design/app/routes/visual-edit_.$id.tsx +2 -2
  63. package/corpus/templates/design/changelog/2026-09-23-design-loads-translated-catalogs-and-ai-prompt-tools-only-wh.md +6 -0
  64. package/corpus/templates/plan/app/components/layout/Sidebar.tsx +56 -13
  65. package/corpus/templates/plan/app/lib/plan-local-bridge.ts +2 -9
  66. package/corpus/templates/plan/app/lib/plan-return-path.ts +8 -0
  67. package/corpus/templates/slides/CHANGELOG.md +6 -0
  68. package/corpus/templates/slides/app/components/editor/AddSlidePopover.tsx +6 -17
  69. package/corpus/templates/slides/app/components/editor/DeferredPopoverFallback.tsx +148 -0
  70. package/corpus/templates/slides/app/components/editor/EditorActionCluster.tsx +7 -1
  71. package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +66 -42
  72. package/corpus/templates/slides/app/components/editor/PromptDialog.tsx +7 -284
  73. package/corpus/templates/slides/app/lib/deferred-editor-surfaces.ts +25 -0
  74. package/corpus/templates/slides/app/lib/portaled-layer.ts +7 -0
  75. package/corpus/templates/slides/app/lib/prompt-file-uploads.ts +269 -0
  76. package/corpus/templates/slides/app/pages/DeckEditor.tsx +3 -0
  77. package/corpus/templates/slides/app/pages/Index.tsx +139 -52
  78. package/corpus/templates/slides/changelog/2026-09-23-slides-loads-ai-prompt-tools-and-extra-slide-controls-only-w.md +6 -0
  79. package/dist/client/agent-chat/index.d.ts +2 -1
  80. package/dist/client/agent-chat/index.js +1 -1
  81. package/dist/client/chat/assistant-chat-history-version.d.ts +13 -0
  82. package/dist/client/chat/assistant-chat-history-version.js +18 -0
  83. package/dist/client/chat/message-components.d.ts +3 -8
  84. package/dist/client/chat/message-components.js +2 -18
  85. package/dist/client/chat/run-recovery.js +2 -1
  86. package/dist/client/lazy-chunk-retry-fallback.d.ts +3 -0
  87. package/dist/client/lazy-chunk-retry-fallback.js +9 -0
  88. package/dist/client/settings/deferred-builder-connect-popover.d.ts +1 -3
  89. package/dist/client/settings/deferred-builder-connect-popover.js +3 -9
  90. package/dist/collab/awareness.d.ts +2 -2
  91. package/dist/collab/routes.d.ts +1 -1
  92. package/dist/file-upload/actions/upload-image.d.ts +2 -2
  93. package/dist/notifications/routes.d.ts +3 -3
  94. package/dist/observability/routes.d.ts +8 -8
  95. package/dist/org/index.d.ts +1 -1
  96. package/dist/progress/routes.d.ts +1 -1
  97. package/dist/provider-api/actions/custom-provider-registration.d.ts +8 -8
  98. package/dist/provider-api/actions/provider-api.d.ts +12 -12
  99. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  100. package/dist/secrets/routes.d.ts +3 -3
  101. package/dist/server/agent-engine-ollama-models-route.d.ts +1 -1
  102. package/package.json +8 -4
  103. package/corpus/templates/analytics/app/i18n-data.ts +0 -13975
  104. package/corpus/templates/calendar/app/i18n-data.ts +0 -10572
  105. package/corpus/templates/design/app/i18n-data.ts +0 -17719
@@ -41,7 +41,9 @@ import { toast } from "sonner";
41
41
  import { trace } from "@/components/design/design-trace";
42
42
  import { DesignThumbnail } from "@/components/design/DesignThumbnail";
43
43
  import { designSystemPickerOptions } from "@/components/editor/design-start-pickers";
44
- import PromptPopover from "@/components/editor/PromptDialog";
44
+ import PromptPopover, {
45
+ preloadPromptComposer,
46
+ } from "@/components/editor/PromptDialog";
45
47
  import type {
46
48
  PromptTemplateOption,
47
49
  UploadedFile,
@@ -310,6 +312,7 @@ export default function Index() {
310
312
 
311
313
  const handleNewPromptOpenChange = useCallback(
312
314
  (open: boolean) => {
315
+ if (open) preloadPromptComposer();
313
316
  setShowNewPrompt(open);
314
317
  if (!open) {
315
318
  newDesignSystemWasChosenRef.current = false;
@@ -779,6 +782,7 @@ export default function Index() {
779
782
 
780
783
  const openNewDesign = useCallback(
781
784
  (e: React.MouseEvent<HTMLElement>) => {
785
+ preloadPromptComposer();
782
786
  anchorElRef.current = e.currentTarget;
783
787
  setNewDesignDraftRevision((revision) => revision + 1);
784
788
  newDesignSystemWasChosenRef.current = false;
@@ -23,7 +23,9 @@ import { useNavigate, useSearchParams } from "react-router";
23
23
  import { toast } from "sonner";
24
24
 
25
25
  import { designSystemPickerOptions } from "@/components/editor/design-start-pickers";
26
- import PromptPopover from "@/components/editor/PromptDialog";
26
+ import PromptPopover, {
27
+ preloadPromptComposer,
28
+ } from "@/components/editor/PromptDialog";
27
29
  import type { UploadedFile } from "@/components/editor/PromptDialog";
28
30
  import { QueryErrorState } from "@/components/QueryErrorState";
29
31
  import { TemplatePreview } from "@/components/templates/TemplatePreview";
@@ -187,6 +189,7 @@ export default function Templates() {
187
189
  ? template.designSystemId
188
190
  : resolveDefaultDesignSystemId(),
189
191
  );
192
+ preloadPromptComposer();
190
193
  setPromptOpen(true);
191
194
  card?.scrollIntoView({ block: "center", behavior: "smooth" });
192
195
  useButton?.focus();
@@ -202,6 +205,7 @@ export default function Templates() {
202
205
  template: DesignTemplateSummary,
203
206
  element: HTMLElement,
204
207
  ) => {
208
+ preloadPromptComposer();
205
209
  anchorElRef.current = element;
206
210
  handledTemplateIdRef.current = template.id;
207
211
  setSelectedTemplateParam(template.id);
@@ -1,8 +1,8 @@
1
- import { messagesByLocale } from "@/i18n-data";
1
+ import enUSMessages from "@/i18n/en-US";
2
2
  import NotFound from "@/pages/NotFound";
3
3
 
4
4
  export function meta() {
5
- return [{ title: messagesByLocale["en-US"].routeTitles.notFound }];
5
+ return [{ title: enUSMessages.routeTitles.notFound }];
6
6
  }
7
7
 
8
8
  export default function CatchAllRoute() {
@@ -1,6 +1,6 @@
1
1
  export { default } from "../pages/DesignSystems";
2
- import { messagesByLocale } from "@/i18n-data";
2
+ import enUSMessages from "@/i18n/en-US";
3
3
 
4
4
  export function meta() {
5
- return [{ title: messagesByLocale["en-US"].routeTitles.designSystems }];
5
+ return [{ title: enUSMessages.routeTitles.designSystems }];
6
6
  }
@@ -1,6 +1,6 @@
1
1
  export { default } from "../pages/DesignSystemSetup";
2
- import { messagesByLocale } from "@/i18n-data";
2
+ import enUSMessages from "@/i18n/en-US";
3
3
 
4
4
  export function meta() {
5
- return [{ title: messagesByLocale["en-US"].routeTitles.designSystemSetup }];
5
+ return [{ title: enUSMessages.routeTitles.designSystemSetup }];
6
6
  }
@@ -1,4 +1,4 @@
1
- import { messagesByLocale } from "@/i18n-data";
1
+ import enUSMessages from "@/i18n/en-US";
2
2
 
3
3
  import DesignEditorRoute from "../pages/DesignEditor";
4
4
 
@@ -12,5 +12,5 @@ export default function DesignRoute() {
12
12
  }
13
13
 
14
14
  export function meta() {
15
- return [{ title: messagesByLocale["en-US"].routeTitles.designEditor }];
15
+ return [{ title: enUSMessages.routeTitles.designEditor }];
16
16
  }
@@ -1,9 +1,9 @@
1
1
  import { ExtensionViewerPage } from "@agent-native/core/client/extensions";
2
2
 
3
- import { messagesByLocale } from "@/i18n-data";
3
+ import enUSMessages from "@/i18n/en-US";
4
4
 
5
5
  export function meta() {
6
- return [{ title: messagesByLocale["en-US"].routeTitles.toolDesign }];
6
+ return [{ title: enUSMessages.routeTitles.toolDesign }];
7
7
  }
8
8
 
9
9
  export default function ExtensionViewerRoute() {
@@ -1,9 +1,9 @@
1
1
  import { Navigate } from "react-router";
2
2
 
3
- import { messagesByLocale } from "@/i18n-data";
3
+ import enUSMessages from "@/i18n/en-US";
4
4
 
5
5
  export function meta() {
6
- return [{ title: messagesByLocale["en-US"].routeTitles.extensionsDesign }];
6
+ return [{ title: enUSMessages.routeTitles.extensionsDesign }];
7
7
  }
8
8
 
9
9
  export default function ExtensionsRoute() {
@@ -1,9 +1,9 @@
1
1
  import { Outlet } from "react-router";
2
2
 
3
- import { messagesByLocale } from "@/i18n-data";
3
+ import enUSMessages from "@/i18n/en-US";
4
4
 
5
5
  export function meta() {
6
- return [{ title: messagesByLocale["en-US"].routeTitles.extensionsDesign }];
6
+ return [{ title: enUSMessages.routeTitles.extensionsDesign }];
7
7
  }
8
8
 
9
9
  export default function ExtensionsLayout() {
@@ -1,9 +1,9 @@
1
1
  import { ObservabilityDashboard } from "@agent-native/core/client/observability";
2
2
 
3
- import { messagesByLocale } from "@/i18n-data";
3
+ import enUSMessages from "@/i18n/en-US";
4
4
 
5
5
  export function meta() {
6
- return [{ title: messagesByLocale["en-US"].routeTitles.agentObservability }];
6
+ return [{ title: enUSMessages.routeTitles.agentObservability }];
7
7
  }
8
8
 
9
9
  export default function ObservabilityPage() {
@@ -1,6 +1,6 @@
1
1
  export { default } from "../pages/Present";
2
- import { messagesByLocale } from "@/i18n-data";
2
+ import enUSMessages from "@/i18n/en-US";
3
3
 
4
4
  export function meta() {
5
- return [{ title: messagesByLocale["en-US"].routeTitles.designPreview }];
5
+ return [{ title: enUSMessages.routeTitles.designPreview }];
6
6
  }
@@ -18,12 +18,12 @@ import {
18
18
  import { DESIGN_LABS } from "@shared/labs";
19
19
  import { useMemo } from "react";
20
20
 
21
- import { messagesByLocale } from "@/i18n-data";
21
+ import enUSMessages from "@/i18n/en-US";
22
22
 
23
23
  import changelog from "../../CHANGELOG.md?raw";
24
24
 
25
25
  export function meta() {
26
- return [{ title: messagesByLocale["en-US"].routeTitles.settingsDesign }];
26
+ return [{ title: enUSMessages.routeTitles.settingsDesign }];
27
27
  }
28
28
 
29
29
  export default function SettingsRoute() {
@@ -1,9 +1,9 @@
1
1
  import { Navigate } from "react-router";
2
2
 
3
- import { messagesByLocale } from "@/i18n-data";
3
+ import enUSMessages from "@/i18n/en-US";
4
4
 
5
5
  export function meta() {
6
- return [{ title: messagesByLocale["en-US"].routeTitles.teamDesign }];
6
+ return [{ title: enUSMessages.routeTitles.teamDesign }];
7
7
  }
8
8
 
9
9
  export default function TeamRoute() {
@@ -1,7 +1,7 @@
1
1
  export { default } from "../pages/Templates";
2
2
 
3
- import { messagesByLocale } from "@/i18n-data";
3
+ import enUSMessages from "@/i18n/en-US";
4
4
 
5
5
  export function meta() {
6
- return [{ title: messagesByLocale["en-US"].routeTitles.designTemplates }];
6
+ return [{ title: enUSMessages.routeTitles.designTemplates }];
7
7
  }
@@ -1,7 +1,7 @@
1
- import { messagesByLocale } from "@/i18n-data";
1
+ import enUSMessages from "@/i18n/en-US";
2
2
 
3
3
  export { default } from "../pages/VisualEdit";
4
4
 
5
5
  export function meta() {
6
- return [{ title: messagesByLocale["en-US"].routeTitles.visualEdit }];
6
+ return [{ title: enUSMessages.routeTitles.visualEdit }];
7
7
  }
@@ -1,4 +1,4 @@
1
- import { messagesByLocale } from "@/i18n-data";
1
+ import enUSMessages from "@/i18n/en-US";
2
2
 
3
3
  import DesignEditorRoute from "../pages/DesignEditor";
4
4
 
@@ -11,5 +11,5 @@ export default function LocalVisualEditRoute() {
11
11
  }
12
12
 
13
13
  export function meta() {
14
- return [{ title: messagesByLocale["en-US"].routeTitles.designEditor }];
14
+ return [{ title: enUSMessages.routeTitles.designEditor }];
15
15
  }
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-09-23
4
+ ---
5
+
6
+ Design loads translated catalogs and AI prompt tools only when you need them.
@@ -6,10 +6,11 @@ import {
6
6
  type ChatThreadSummary,
7
7
  } from "@agent-native/core/client/agent-chat";
8
8
  import { useCodeMode } from "@agent-native/core/client/agent-chat";
9
- import { PromptComposer } from "@agent-native/core/client/composer";
10
9
  import { DevDatabaseLink } from "@agent-native/core/client/db-admin";
11
10
  import { useSession } from "@agent-native/core/client/hooks";
12
11
  import { useT } from "@agent-native/core/client/i18n";
12
+ import { LazyChunkErrorBoundary } from "@agent-native/core/client/lazy-chunk-error-boundary";
13
+ import { LazyChunkRetryFallback } from "@agent-native/core/client/lazy-chunk-retry-fallback";
13
14
  import { openCommandMenu } from "@agent-native/core/client/navigation";
14
15
  import { OrgSwitcher } from "@agent-native/core/client/org";
15
16
  import {
@@ -32,7 +33,14 @@ import {
32
33
  IconRefresh,
33
34
  IconSettings,
34
35
  } from "@tabler/icons-react";
35
- import { useEffect, useMemo, useState, type MouseEvent } from "react";
36
+ import {
37
+ lazy,
38
+ Suspense,
39
+ useEffect,
40
+ useMemo,
41
+ useState,
42
+ type MouseEvent,
43
+ } from "react";
36
44
  import { Link, useLocation, useNavigate } from "react-router";
37
45
  import { toast } from "sonner";
38
46
 
@@ -51,9 +59,19 @@ import {
51
59
  } from "@/components/ui/tooltip";
52
60
  import { usePlans } from "@/hooks/use-plans";
53
61
  import { APP_TITLE } from "@/lib/app-config";
54
- import { planReturnPathFromLocation } from "@/lib/plan-local-bridge";
62
+ import { planReturnPathFromLocation } from "@/lib/plan-return-path";
55
63
  import { cn } from "@/lib/utils";
56
64
 
65
+ const loadPlanBrandingComposer = () =>
66
+ import("@agent-native/core/client/composer").then(({ PromptComposer }) => ({
67
+ default: PromptComposer,
68
+ }));
69
+ const LazyPlanBrandingComposer = lazy(loadPlanBrandingComposer);
70
+
71
+ function preloadPlanBrandingComposer() {
72
+ void loadPlanBrandingComposer().catch(() => {});
73
+ }
74
+
57
75
  const PLAN_CHAT_STORAGE_KEY = "plans";
58
76
 
59
77
  const PLAN_BRANDING_CODE_CONTEXT = [
@@ -489,12 +507,20 @@ function BrandingCustomizePopover() {
489
507
  return (
490
508
  <>
491
509
  {codeRequiredDialog}
492
- <Popover open={open} onOpenChange={setOpen}>
510
+ <Popover
511
+ open={open}
512
+ onOpenChange={(nextOpen) => {
513
+ if (nextOpen) preloadPlanBrandingComposer();
514
+ setOpen(nextOpen);
515
+ }}
516
+ >
493
517
  <PopoverTrigger asChild>
494
518
  <button
495
519
  type="button"
496
520
  aria-label={t("sidebar.customizePlanBranding")}
497
521
  title={t("sidebar.customizeBranding")}
522
+ onPointerEnter={preloadPlanBrandingComposer}
523
+ onFocus={preloadPlanBrandingComposer}
498
524
  className="flex size-7 shrink-0 items-center justify-center rounded-md text-sidebar-foreground/55 opacity-0 transition-colors hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring group-hover/brand:opacity-100 group-focus-within/brand:opacity-100 data-[state=open]:opacity-100"
499
525
  >
500
526
  <IconEdit className="size-3.5" />
@@ -514,15 +540,32 @@ function BrandingCustomizePopover() {
514
540
  {t("sidebar.customizeBrandingDescription")}
515
541
  </p>
516
542
  </div>
517
- <PromptComposer
518
- autoFocus
519
- disabled={isGenerating}
520
- attachmentsEnabled={false}
521
- showModelSelector={false}
522
- placeholder={t("sidebar.customizeBrandingPlaceholder")}
523
- draftScope="plans:customize-branding"
524
- onSubmit={handleSubmit}
525
- />
543
+ <LazyChunkErrorBoundary fallback={<LazyChunkRetryFallback />}>
544
+ <Suspense
545
+ fallback={
546
+ <div
547
+ aria-busy="true"
548
+ className="flex min-h-36 flex-col justify-between gap-3"
549
+ >
550
+ <Skeleton className="h-24 w-full" />
551
+ <div className="flex justify-end gap-2">
552
+ <Skeleton className="h-8 w-16" />
553
+ <Skeleton className="h-8 w-20" />
554
+ </div>
555
+ </div>
556
+ }
557
+ >
558
+ <LazyPlanBrandingComposer
559
+ autoFocus
560
+ disabled={isGenerating}
561
+ attachmentsEnabled={false}
562
+ showModelSelector={false}
563
+ placeholder={t("sidebar.customizeBrandingPlaceholder")}
564
+ draftScope="plans:customize-branding"
565
+ onSubmit={handleSubmit}
566
+ />
567
+ </Suspense>
568
+ </LazyChunkErrorBoundary>
526
569
  </PopoverContent>
527
570
  </Popover>
528
571
  </>
@@ -8,6 +8,8 @@ import type { PlanMdxFolder } from "@/lib/desktop-plan-files";
8
8
 
9
9
  import { parsePlanMdxFolder } from "../../server/plan-mdx";
10
10
 
11
+ export { planReturnPathFromLocation } from "./plan-return-path";
12
+
11
13
  export type LocalPlanBundle = PlanBundle & {
12
14
  localOnly: true;
13
15
  slug: string;
@@ -99,15 +101,6 @@ export function localPlanBridgeUrlFromLocation(
99
101
  }
100
102
  }
101
103
 
102
- export function planReturnPathFromLocation(location: {
103
- pathname: string;
104
- search: string;
105
- hash: string;
106
- }): string {
107
- const safeHash = location.hash.startsWith("#bridge=") ? "" : location.hash;
108
- return `${location.pathname}${location.search}${safeHash}`;
109
- }
110
-
111
104
  export async function localNetworkAccessPermissionState(): Promise<
112
105
  Exclude<LocalNetworkAccessPermissionState, "checking">
113
106
  > {
@@ -0,0 +1,8 @@
1
+ export function planReturnPathFromLocation(location: {
2
+ pathname: string;
3
+ search: string;
4
+ hash: string;
5
+ }): string {
6
+ const safeHash = location.hash.startsWith("#bridge=") ? "" : location.hash;
7
+ return `${location.pathname}${location.search}${safeHash}`;
8
+ }
@@ -3,6 +3,12 @@
3
3
  All notable user-facing changes to Agent-Native Slides are documented here. Open it any
4
4
  time from the command menu (Cmd+K → "What's new").
5
5
 
6
+ ## 2026-09-23
7
+
8
+ ### Improved
9
+
10
+ - Slides loads AI prompt tools and extra slide controls only when you open them.
11
+
6
12
  ## 2026-09-22
7
13
 
8
14
  ### Improved
@@ -1,4 +1,3 @@
1
- import { appBasePath } from "@agent-native/core/client/api-path";
2
1
  import {
3
2
  PromptComposer,
4
3
  useEagerFileUploads,
@@ -16,13 +15,14 @@ import { createPortal } from "react-dom";
16
15
  import { toast } from "sonner";
17
16
 
18
17
  import { GoogleDocImportHint } from "@/components/editor/GoogleDocImportHint";
18
+ import { addSlideAgentMessage } from "@/lib/agent-visible-message";
19
+ import { WEBSITE_STYLE_REFERENCE_DIRECTIVE } from "@/lib/create-deck-generation";
20
+ import { isInsidePortaledLayer } from "@/lib/portaled-layer";
19
21
  import {
20
- isInsidePortaledLayer,
22
+ deleteUploadedPromptFile,
21
23
  uploadPromptFiles,
22
24
  type UploadedFile,
23
- } from "@/components/editor/PromptDialog";
24
- import { addSlideAgentMessage } from "@/lib/agent-visible-message";
25
- import { WEBSITE_STYLE_REFERENCE_DIRECTIVE } from "@/lib/create-deck-generation";
25
+ } from "@/lib/prompt-file-uploads";
26
26
 
27
27
  import { MAX_REFERENCE_FILE_BYTES } from "../../../shared/upload-types";
28
28
 
@@ -107,17 +107,6 @@ export function AddSlidePopover({
107
107
  const [panelHeight, setPanelHeight] = useState(320);
108
108
  const [submitting, setSubmitting] = useState(false);
109
109
  const submittingRef = useRef(false);
110
- const deleteUploadedFile = useCallback(async (file: UploadedFile) => {
111
- const response = await fetch(`${appBasePath()}/api/uploads`, {
112
- method: "DELETE",
113
- headers: { "content-type": "application/json" },
114
- credentials: "include",
115
- body: JSON.stringify({ path: file.path }),
116
- });
117
- if (!response.ok) {
118
- throw new Error(`Upload cleanup failed (${response.status})`);
119
- }
120
- }, []);
121
110
  const handleRetainedFilesAbandoned = useCallback(
122
111
  (_files: readonly File[], discard: () => void) => {
123
112
  if (!submittingRef.current) discard();
@@ -133,7 +122,7 @@ export function AddSlidePopover({
133
122
  uploading,
134
123
  reset: resetEagerUploads,
135
124
  } = useEagerFileUploads(uploadPromptFiles, {
136
- onDiscard: deleteUploadedFile,
125
+ onDiscard: deleteUploadedPromptFile,
137
126
  onRetainedFilesAbandoned: handleRetainedFilesAbandoned,
138
127
  });
139
128
 
@@ -0,0 +1,148 @@
1
+ import { LazyChunkRetryFallback } from "@agent-native/core/client/lazy-chunk-retry-fallback";
2
+ import type { CSSProperties, RefObject } from "react";
3
+ import { useEffect, useLayoutEffect, useRef, useState } from "react";
4
+ import { createPortal } from "react-dom";
5
+
6
+ import { Skeleton } from "@/components/ui/skeleton";
7
+
8
+ export function DeferredPopoverFallback({
9
+ surface,
10
+ anchorRef,
11
+ centered = false,
12
+ failed = false,
13
+ onClose,
14
+ }: {
15
+ surface: "prompt" | "add-slide";
16
+ anchorRef?: RefObject<HTMLElement | null>;
17
+ centered?: boolean;
18
+ failed?: boolean;
19
+ onClose?: () => void;
20
+ }) {
21
+ const [position, setPosition] = useState<CSSProperties>({
22
+ top: "50%",
23
+ left: "50%",
24
+ transform: "translate(-50%, -50%)",
25
+ });
26
+ const contentRef = useRef<HTMLDivElement>(null);
27
+
28
+ useEffect(() => {
29
+ if (!onClose) return;
30
+
31
+ const handlePointerDown = (event: PointerEvent) => {
32
+ const target = event.target;
33
+ if (
34
+ !(target instanceof Node) ||
35
+ contentRef.current?.contains(target) ||
36
+ anchorRef?.current?.contains(target)
37
+ ) {
38
+ return;
39
+ }
40
+ onClose();
41
+ };
42
+ const handleKeyDown = (event: KeyboardEvent) => {
43
+ if (event.key !== "Escape") return;
44
+ event.preventDefault();
45
+ onClose();
46
+ };
47
+
48
+ document.addEventListener("pointerdown", handlePointerDown, true);
49
+ document.addEventListener("keydown", handleKeyDown);
50
+ return () => {
51
+ document.removeEventListener("pointerdown", handlePointerDown, true);
52
+ document.removeEventListener("keydown", handleKeyDown);
53
+ };
54
+ }, [anchorRef, onClose]);
55
+
56
+ useLayoutEffect(() => {
57
+ const anchor = anchorRef?.current;
58
+ if (centered || !anchor) {
59
+ setPosition({
60
+ top: "50%",
61
+ left: "50%",
62
+ transform: "translate(-50%, -50%)",
63
+ });
64
+ return;
65
+ }
66
+
67
+ const rect = anchor.getBoundingClientRect();
68
+ const width = Math.min(
69
+ surface === "prompt" ? 500 : 420,
70
+ window.innerWidth - 24,
71
+ );
72
+ if (surface === "add-slide") {
73
+ setPosition({
74
+ top: Math.max(12, Math.min(rect.top, window.innerHeight - 332)),
75
+ left: Math.min(rect.right + 8, window.innerWidth - width - 12),
76
+ });
77
+ return;
78
+ }
79
+
80
+ const height = 240;
81
+ let top = rect.bottom + 12;
82
+ if (top + height > window.innerHeight - 12) {
83
+ top = Math.max(12, rect.top - height - 12);
84
+ }
85
+ let left = rect.left + rect.width / 2 - width / 2;
86
+ if (left + width > window.innerWidth - 12) {
87
+ left = window.innerWidth - width - 12;
88
+ }
89
+ if (left < 12) left = 12;
90
+ setPosition({ top, left });
91
+ }, [anchorRef, centered, surface]);
92
+
93
+ if (typeof document === "undefined") return null;
94
+
95
+ const prompt = surface === "prompt";
96
+ return createPortal(
97
+ <>
98
+ {centered && prompt ? (
99
+ <div
100
+ // guard:allow-raw-color — modal scrim remains black in either theme.
101
+ className="fixed inset-0 z-[199] bg-black/40"
102
+ />
103
+ ) : null}
104
+ <div
105
+ ref={contentRef}
106
+ role={failed ? "alert" : "dialog"}
107
+ aria-modal={prompt && centered ? true : undefined}
108
+ aria-busy={failed ? undefined : true}
109
+ className={
110
+ prompt
111
+ ? "fixed z-[200] w-[min(500px,calc(100vw-24px))] rounded-xl border border-border/80 bg-popover shadow-xl shadow-black/15"
112
+ : "fixed z-[200] w-[min(420px,calc(100vw-24px))] rounded-xl border border-border bg-popover p-3 shadow-2xl shadow-black/60"
113
+ }
114
+ style={position}
115
+ >
116
+ {failed ? (
117
+ <div className="flex min-h-12 items-center justify-center p-3">
118
+ <LazyChunkRetryFallback />
119
+ </div>
120
+ ) : prompt ? (
121
+ <>
122
+ <div className="flex items-center justify-between gap-3 px-4 pb-2.5 pt-3.5">
123
+ <Skeleton className="h-4 w-32" />
124
+ <Skeleton className="h-3 w-10" />
125
+ </div>
126
+ <div className="px-2.5 pb-2.5">
127
+ <Skeleton className="h-36 w-full rounded-lg" />
128
+ </div>
129
+ <div className="flex items-center gap-2 border-t border-border/60 px-4 py-2.5">
130
+ <Skeleton className="h-6 w-16" />
131
+ <Skeleton className="h-6 w-20" />
132
+ </div>
133
+ </>
134
+ ) : (
135
+ <>
136
+ <div className="flex items-center justify-between px-1 pb-2">
137
+ <Skeleton className="h-4 w-36" />
138
+ <Skeleton className="size-5" />
139
+ </div>
140
+ <Skeleton className="mb-2 h-8 w-full rounded-md" />
141
+ <Skeleton className="h-36 w-full rounded-lg" />
142
+ </>
143
+ )}
144
+ </div>
145
+ </>,
146
+ document.body,
147
+ );
148
+ }
@@ -22,6 +22,7 @@ import {
22
22
  TooltipContent,
23
23
  TooltipTrigger,
24
24
  } from "@/components/ui/tooltip";
25
+ import { preloadAddSlidePopover } from "@/lib/deferred-editor-surfaces";
25
26
  import { cn } from "@/lib/utils";
26
27
 
27
28
  const BUTTON_CLASS =
@@ -112,7 +113,12 @@ export function EditorActionCluster({
112
113
  variant="ghost"
113
114
  size="sm"
114
115
  className="h-7 shrink-0 gap-1.5 px-2 text-xs text-muted-foreground hover:text-foreground"
115
- onClick={onAddEmptySlide}
116
+ onPointerEnter={preloadAddSlidePopover}
117
+ onFocus={preloadAddSlidePopover}
118
+ onClick={() => {
119
+ preloadAddSlidePopover();
120
+ onAddEmptySlide();
121
+ }}
116
122
  disabled={addSlideGenerating}
117
123
  >
118
124
  <IconPlus className="size-3.5" />