@agent-native/core 0.124.3 → 0.124.4

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 (254) hide show
  1. package/README.md +1 -1
  2. package/corpus/README.md +2 -2
  3. package/corpus/core/CHANGELOG.md +10 -0
  4. package/corpus/core/docs/content/cloneable-saas.mdx +9 -9
  5. package/corpus/core/docs/content/creating-templates.mdx +2 -2
  6. package/corpus/core/docs/content/deployment.mdx +23 -0
  7. package/corpus/core/docs/content/faq.mdx +4 -4
  8. package/corpus/core/docs/content/key-concepts.mdx +1 -1
  9. package/corpus/core/docs/content/multi-app-workspace.mdx +1 -1
  10. package/corpus/core/docs/content/syncing-template-changes.mdx +1 -1
  11. package/corpus/core/docs/content/template-analytics-developers.mdx +2 -2
  12. package/corpus/core/docs/content/template-analytics.mdx +2 -2
  13. package/corpus/core/docs/content/template-assets-developers.mdx +3 -3
  14. package/corpus/core/docs/content/template-assets.mdx +2 -2
  15. package/corpus/core/docs/content/template-brain-developers.mdx +2 -2
  16. package/corpus/core/docs/content/template-brain.mdx +1 -1
  17. package/corpus/core/docs/content/template-calendar-developers.mdx +1 -1
  18. package/corpus/core/docs/content/template-calendar.mdx +1 -1
  19. package/corpus/core/docs/content/template-chat.mdx +1 -1
  20. package/corpus/core/docs/content/template-clips-developers.mdx +4 -4
  21. package/corpus/core/docs/content/template-clips.mdx +2 -2
  22. package/corpus/core/docs/content/template-content-developers.mdx +2 -2
  23. package/corpus/core/docs/content/template-content.mdx +1 -1
  24. package/corpus/core/docs/content/template-design-brand-and-figma.mdx +1 -1
  25. package/corpus/core/docs/content/template-design-developers.mdx +2 -2
  26. package/corpus/core/docs/content/template-design.mdx +2 -2
  27. package/corpus/core/docs/content/template-dispatch-developers.mdx +5 -5
  28. package/corpus/core/docs/content/template-forms-developers.mdx +1 -1
  29. package/corpus/core/docs/content/template-forms.mdx +1 -1
  30. package/corpus/core/docs/content/template-mail-developers.mdx +2 -2
  31. package/corpus/core/docs/content/template-mail.mdx +2 -2
  32. package/corpus/core/docs/content/template-plan-developers.mdx +3 -3
  33. package/corpus/core/docs/content/template-plan.mdx +3 -3
  34. package/corpus/core/docs/content/template-slides-developers.mdx +4 -4
  35. package/corpus/core/docs/content/template-slides.mdx +1 -1
  36. package/corpus/core/docs/content/what-is-agent-native.mdx +5 -5
  37. package/corpus/core/package.json +1 -1
  38. package/corpus/core/src/a2a/auth-policy.ts +1 -1
  39. package/corpus/core/src/agent/production-agent.ts +14 -1
  40. package/corpus/core/src/agent/run-manager.ts +6 -13
  41. package/corpus/core/src/cli/index.ts +11 -1
  42. package/corpus/core/src/client/route-chunk-recovery.ts +18 -7
  43. package/corpus/core/src/db/client.ts +7 -6
  44. package/corpus/core/src/db/migrations.ts +2 -1
  45. package/corpus/core/src/deploy/build.ts +290 -4
  46. package/corpus/core/src/deploy/nitro-preset.ts +50 -0
  47. package/corpus/core/src/integrations/pending-tasks-retry-job.ts +2 -1
  48. package/corpus/core/src/scripts/call-agent.ts +4 -2
  49. package/corpus/core/src/server/agent-discovery.ts +1 -0
  50. package/corpus/core/src/server/agent-run-context.ts +13 -3
  51. package/corpus/core/src/server/request-context.ts +2 -0
  52. package/corpus/core/src/shared/cloudflare-globals.d.ts +2 -1
  53. package/corpus/core/src/shared/runtime.ts +2 -0
  54. package/corpus/core/src/templates/default/.agents/skills/secrets/SKILL.md +29 -0
  55. package/corpus/core/src/templates/default/app/i18n/ar-SA.ts +6 -6
  56. package/corpus/core/src/templates/default/app/i18n/de-DE.ts +6 -6
  57. package/corpus/core/src/templates/default/app/i18n/en-US.ts +6 -6
  58. package/corpus/core/src/templates/default/app/i18n/es-ES.ts +6 -6
  59. package/corpus/core/src/templates/default/app/i18n/fr-FR.ts +6 -6
  60. package/corpus/core/src/templates/default/app/i18n/hi-IN.ts +6 -6
  61. package/corpus/core/src/templates/default/app/i18n/ja-JP.ts +6 -6
  62. package/corpus/core/src/templates/default/app/i18n/ko-KR.ts +6 -6
  63. package/corpus/core/src/templates/default/app/i18n/pt-BR.ts +6 -6
  64. package/corpus/core/src/templates/default/app/i18n/zh-CN.ts +6 -6
  65. package/corpus/core/src/templates/default/app/i18n/zh-TW.ts +6 -6
  66. package/corpus/core/src/templates/headless/.agents/skills/secrets/SKILL.md +29 -0
  67. package/corpus/core/src/templates/workspace-core/.agents/skills/secrets/SKILL.md +29 -0
  68. package/corpus/core/src/vite/client.ts +20 -1
  69. package/corpus/templates/analytics/actions/restore-dashboard-revision.ts +9 -2
  70. package/corpus/templates/analytics/app/components/dashboard/DashboardHistoryPanel.tsx +3 -0
  71. package/corpus/templates/analytics/app/components/dashboard/DashboardPanelSkeleton.tsx +1 -1
  72. package/corpus/templates/analytics/app/global.css +10 -9
  73. package/corpus/templates/analytics/app/hooks/use-chart-tooltip-portal.ts +59 -18
  74. package/corpus/templates/analytics/app/hooks/use-dashboard-revisions.ts +14 -2
  75. package/corpus/templates/analytics/app/i18n-data.ts +102 -0
  76. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +232 -2
  77. package/corpus/templates/analytics/changelog/2026-07-27-chart-tooltips-stay-beside-the-cursor-when-they-extend-beyon.md +6 -0
  78. package/corpus/templates/analytics/changelog/2026-07-27-chat-no-longer-claims-a-data-source-is-disconnected-when-it-.md +6 -0
  79. package/corpus/templates/analytics/changelog/2026-07-27-dashboard-changes-can-be-undone-with-cmd-z-and-actions-menu.md +6 -0
  80. package/corpus/templates/analytics/changelog/2026-07-27-dashboard-redo-with-cmd-shift-z-and-actions-menu.md +6 -0
  81. package/corpus/templates/analytics/changelog/2026-07-27-dashboard-skeletons-are-subtler-and-smoother.md +6 -0
  82. package/corpus/templates/analytics/server/lib/dashboards-store.ts +61 -20
  83. package/corpus/templates/analytics/server/lib/real-data-actions.ts +1 -0
  84. package/corpus/templates/analytics/server/plugins/agent-chat.ts +7 -3
  85. package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +7 -32
  86. package/corpus/templates/calendar/changelog/2026-07-27-calendar-s-sidebar-now-uses-a-cleaner-layout-with-fewer-util.md +6 -0
  87. package/corpus/templates/content/app/components/editor/database/sidebar.tsx +14 -6
  88. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +32 -37
  89. package/corpus/templates/content/changelog/2026-07-27-content-sidebar-page-lists-now-load-with-quiet-skeletons-and.md +6 -0
  90. package/corpus/templates/design/app/components/layout/Sidebar.tsx +16 -18
  91. package/corpus/templates/design/changelog/2026-07-27-collapsed-sidebar-keeps-the-agent-native-logo.md +6 -0
  92. package/corpus/templates/dispatch/AGENTS.md +7 -2
  93. package/corpus/templates/dispatch/actions/view-screen.ts +3 -2
  94. package/corpus/templates/dispatch/changelog/2026-07-17-curated-template-remixes.md +1 -1
  95. package/corpus/templates/dispatch/changelog/2026-07-27-creating-an-app-from-a-curated-template-now-uses-clearer-mor.md +6 -0
  96. package/corpus/templates/dispatch/changelog/2026-07-27-thread-debug-accepts-request-run-ids.md +6 -0
  97. package/corpus/templates/slides/actions/create-design-system.ts +10 -2
  98. package/corpus/templates/slides/actions/import-file.ts +173 -1
  99. package/corpus/templates/slides/actions/list-slide-comments.ts +16 -1
  100. package/corpus/templates/slides/actions/update-design-system.ts +13 -2
  101. package/corpus/templates/slides/app/components/editor/AssetLibraryPanel.tsx +35 -12
  102. package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +36 -0
  103. package/corpus/templates/slides/app/i18n/en-US.ts +3 -0
  104. package/corpus/templates/slides/app/lib/dynamic-import.ts +63 -0
  105. package/corpus/templates/slides/app/lib/export-pdf-client.ts +3 -2
  106. package/corpus/templates/slides/app/lib/export-pptx-client.ts +5 -2
  107. package/corpus/templates/slides/app/pages/DesignSystems.tsx +9 -1
  108. package/corpus/templates/slides/server/db/schema.ts +11 -0
  109. package/corpus/templates/slides/server/handlers/assets.ts +64 -19
  110. package/corpus/templates/slides/server/handlers/import/html-converter.ts +38 -0
  111. package/corpus/templates/slides/server/plugins/db.ts +20 -0
  112. package/corpus/templates/slides/shared/design-system-validation.ts +62 -0
  113. package/dist/a2a/auth-policy.js +1 -1
  114. package/dist/a2a/auth-policy.js.map +1 -1
  115. package/dist/agent/production-agent.d.ts +1 -0
  116. package/dist/agent/production-agent.d.ts.map +1 -1
  117. package/dist/agent/production-agent.js +12 -1
  118. package/dist/agent/production-agent.js.map +1 -1
  119. package/dist/agent/run-manager.d.ts +2 -0
  120. package/dist/agent/run-manager.d.ts.map +1 -1
  121. package/dist/agent/run-manager.js +4 -10
  122. package/dist/agent/run-manager.js.map +1 -1
  123. package/dist/cli/index.js +8 -1
  124. package/dist/cli/index.js.map +1 -1
  125. package/dist/client/route-chunk-recovery.d.ts.map +1 -1
  126. package/dist/client/route-chunk-recovery.js +16 -7
  127. package/dist/client/route-chunk-recovery.js.map +1 -1
  128. package/dist/collab/awareness.d.ts +2 -2
  129. package/dist/collab/awareness.d.ts.map +1 -1
  130. package/dist/collab/routes.d.ts +1 -1
  131. package/dist/collab/struct-routes.d.ts +1 -1
  132. package/dist/db/client.d.ts.map +1 -1
  133. package/dist/db/client.js +4 -2
  134. package/dist/db/client.js.map +1 -1
  135. package/dist/db/migrations.d.ts.map +1 -1
  136. package/dist/db/migrations.js +2 -1
  137. package/dist/db/migrations.js.map +1 -1
  138. package/dist/deploy/build.d.ts +25 -0
  139. package/dist/deploy/build.d.ts.map +1 -1
  140. package/dist/deploy/build.js +227 -4
  141. package/dist/deploy/build.js.map +1 -1
  142. package/dist/deploy/nitro-preset.d.ts +8 -0
  143. package/dist/deploy/nitro-preset.d.ts.map +1 -0
  144. package/dist/deploy/nitro-preset.js +36 -0
  145. package/dist/deploy/nitro-preset.js.map +1 -0
  146. package/dist/integrations/pending-tasks-retry-job.d.ts.map +1 -1
  147. package/dist/integrations/pending-tasks-retry-job.js +2 -1
  148. package/dist/integrations/pending-tasks-retry-job.js.map +1 -1
  149. package/dist/notifications/routes.d.ts +3 -3
  150. package/dist/observability/routes.d.ts +3 -3
  151. package/dist/progress/routes.d.ts +1 -1
  152. package/dist/provider-api/actions/custom-provider-registration.d.ts +11 -11
  153. package/dist/provider-api/actions/provider-api.d.ts +11 -11
  154. package/dist/scripts/call-agent.d.ts.map +1 -1
  155. package/dist/scripts/call-agent.js +4 -2
  156. package/dist/scripts/call-agent.js.map +1 -1
  157. package/dist/secrets/routes.d.ts +3 -3
  158. package/dist/server/agent-discovery.d.ts.map +1 -1
  159. package/dist/server/agent-discovery.js +1 -0
  160. package/dist/server/agent-discovery.js.map +1 -1
  161. package/dist/server/agent-run-context.d.ts.map +1 -1
  162. package/dist/server/agent-run-context.js +10 -3
  163. package/dist/server/agent-run-context.js.map +1 -1
  164. package/dist/server/request-context.d.ts +2 -0
  165. package/dist/server/request-context.d.ts.map +1 -1
  166. package/dist/server/request-context.js.map +1 -1
  167. package/dist/server/transcribe-voice.d.ts +1 -1
  168. package/dist/shared/runtime.d.ts.map +1 -1
  169. package/dist/shared/runtime.js +2 -0
  170. package/dist/shared/runtime.js.map +1 -1
  171. package/dist/templates/default/.agents/skills/secrets/SKILL.md +29 -0
  172. package/dist/templates/default/app/i18n/ar-SA.ts +6 -6
  173. package/dist/templates/default/app/i18n/de-DE.ts +6 -6
  174. package/dist/templates/default/app/i18n/en-US.ts +6 -6
  175. package/dist/templates/default/app/i18n/es-ES.ts +6 -6
  176. package/dist/templates/default/app/i18n/fr-FR.ts +6 -6
  177. package/dist/templates/default/app/i18n/hi-IN.ts +6 -6
  178. package/dist/templates/default/app/i18n/ja-JP.ts +6 -6
  179. package/dist/templates/default/app/i18n/ko-KR.ts +6 -6
  180. package/dist/templates/default/app/i18n/pt-BR.ts +6 -6
  181. package/dist/templates/default/app/i18n/zh-CN.ts +6 -6
  182. package/dist/templates/default/app/i18n/zh-TW.ts +6 -6
  183. package/dist/templates/headless/.agents/skills/secrets/SKILL.md +29 -0
  184. package/dist/templates/workspace-core/.agents/skills/secrets/SKILL.md +29 -0
  185. package/dist/vite/client.d.ts +1 -1
  186. package/dist/vite/client.d.ts.map +1 -1
  187. package/dist/vite/client.js +16 -0
  188. package/dist/vite/client.js.map +1 -1
  189. package/docs/content/cloneable-saas.mdx +9 -9
  190. package/docs/content/creating-templates.mdx +2 -2
  191. package/docs/content/deployment.mdx +23 -0
  192. package/docs/content/faq.mdx +4 -4
  193. package/docs/content/key-concepts.mdx +1 -1
  194. package/docs/content/multi-app-workspace.mdx +1 -1
  195. package/docs/content/syncing-template-changes.mdx +1 -1
  196. package/docs/content/template-analytics-developers.mdx +2 -2
  197. package/docs/content/template-analytics.mdx +2 -2
  198. package/docs/content/template-assets-developers.mdx +3 -3
  199. package/docs/content/template-assets.mdx +2 -2
  200. package/docs/content/template-brain-developers.mdx +2 -2
  201. package/docs/content/template-brain.mdx +1 -1
  202. package/docs/content/template-calendar-developers.mdx +1 -1
  203. package/docs/content/template-calendar.mdx +1 -1
  204. package/docs/content/template-chat.mdx +1 -1
  205. package/docs/content/template-clips-developers.mdx +4 -4
  206. package/docs/content/template-clips.mdx +2 -2
  207. package/docs/content/template-content-developers.mdx +2 -2
  208. package/docs/content/template-content.mdx +1 -1
  209. package/docs/content/template-design-brand-and-figma.mdx +1 -1
  210. package/docs/content/template-design-developers.mdx +2 -2
  211. package/docs/content/template-design.mdx +2 -2
  212. package/docs/content/template-dispatch-developers.mdx +5 -5
  213. package/docs/content/template-forms-developers.mdx +1 -1
  214. package/docs/content/template-forms.mdx +1 -1
  215. package/docs/content/template-mail-developers.mdx +2 -2
  216. package/docs/content/template-mail.mdx +2 -2
  217. package/docs/content/template-plan-developers.mdx +3 -3
  218. package/docs/content/template-plan.mdx +3 -3
  219. package/docs/content/template-slides-developers.mdx +4 -4
  220. package/docs/content/template-slides.mdx +1 -1
  221. package/docs/content/what-is-agent-native.mdx +5 -5
  222. package/package.json +1 -1
  223. package/src/a2a/auth-policy.ts +1 -1
  224. package/src/agent/production-agent.ts +14 -1
  225. package/src/agent/run-manager.ts +6 -13
  226. package/src/cli/index.ts +11 -1
  227. package/src/client/route-chunk-recovery.ts +18 -7
  228. package/src/db/client.ts +7 -6
  229. package/src/db/migrations.ts +2 -1
  230. package/src/deploy/build.ts +290 -4
  231. package/src/deploy/nitro-preset.ts +50 -0
  232. package/src/integrations/pending-tasks-retry-job.ts +2 -1
  233. package/src/scripts/call-agent.ts +4 -2
  234. package/src/server/agent-discovery.ts +1 -0
  235. package/src/server/agent-run-context.ts +13 -3
  236. package/src/server/request-context.ts +2 -0
  237. package/src/shared/cloudflare-globals.d.ts +2 -1
  238. package/src/shared/runtime.ts +2 -0
  239. package/src/templates/default/.agents/skills/secrets/SKILL.md +29 -0
  240. package/src/templates/default/app/i18n/ar-SA.ts +6 -6
  241. package/src/templates/default/app/i18n/de-DE.ts +6 -6
  242. package/src/templates/default/app/i18n/en-US.ts +6 -6
  243. package/src/templates/default/app/i18n/es-ES.ts +6 -6
  244. package/src/templates/default/app/i18n/fr-FR.ts +6 -6
  245. package/src/templates/default/app/i18n/hi-IN.ts +6 -6
  246. package/src/templates/default/app/i18n/ja-JP.ts +6 -6
  247. package/src/templates/default/app/i18n/ko-KR.ts +6 -6
  248. package/src/templates/default/app/i18n/pt-BR.ts +6 -6
  249. package/src/templates/default/app/i18n/zh-CN.ts +6 -6
  250. package/src/templates/default/app/i18n/zh-TW.ts +6 -6
  251. package/src/templates/headless/.agents/skills/secrets/SKILL.md +29 -0
  252. package/src/templates/workspace-core/.agents/skills/secrets/SKILL.md +29 -0
  253. package/src/vite/client.ts +20 -1
  254. /package/corpus/templates/slides/server/routes/api/assets/{[filename].delete.ts → [id].delete.ts} +0 -0
@@ -12,7 +12,6 @@ import {
12
12
  IconDatabase,
13
13
  IconDots,
14
14
  IconFileText,
15
- IconLoader2,
16
15
  IconPlus,
17
16
  IconStar,
18
17
  IconTrash,
@@ -44,6 +43,7 @@ import {
44
43
  DropdownMenuTrigger,
45
44
  } from "@/components/ui/dropdown-menu";
46
45
  import { ScrollArea } from "@/components/ui/scroll-area";
46
+ import { Skeleton } from "@/components/ui/skeleton";
47
47
  import {
48
48
  Tooltip,
49
49
  TooltipContent,
@@ -261,7 +261,6 @@ export function DatabaseSidebarView({
261
261
  hierarchyItems,
262
262
  hierarchyUniverseItems,
263
263
  scroll = true,
264
- loadingLabel,
265
264
  noMatchesLabel,
266
265
  clearLabel,
267
266
  navigationLabel,
@@ -286,7 +285,6 @@ export function DatabaseSidebarView({
286
285
  hierarchyItems?: ContentDatabaseItem[];
287
286
  hierarchyUniverseItems?: ContentDatabaseItem[];
288
287
  scroll?: boolean;
289
- loadingLabel: string;
290
288
  noMatchesLabel: string;
291
289
  clearLabel: string;
292
290
  navigationLabel: string;
@@ -367,9 +365,19 @@ export function DatabaseSidebarView({
367
365
 
368
366
  if (isLoading) {
369
367
  return (
370
- <div className="flex h-16 items-center gap-2 px-2 text-sm text-muted-foreground">
371
- <IconLoader2 className="size-4 animate-spin" />
372
- {loadingLabel}
368
+ <div aria-hidden="true" className="grid gap-1 p-1">
369
+ {[70, 55, 85, 60, 45].map((width, index) => (
370
+ <div
371
+ key={`sidebar-skeleton-${index}`}
372
+ className="flex h-7 items-center gap-1.5 rounded px-1.5"
373
+ >
374
+ <Skeleton className="size-3.5 shrink-0 rounded-sm bg-sidebar-foreground/12 dark:bg-sidebar-foreground/10" />
375
+ <Skeleton
376
+ className="h-3 rounded bg-sidebar-foreground/12 dark:bg-sidebar-foreground/10"
377
+ style={{ width: `${width}%` }}
378
+ />
379
+ </div>
380
+ ))}
373
381
  </div>
374
382
  );
375
383
  }
@@ -63,7 +63,6 @@ import { toast } from "sonner";
63
63
 
64
64
  import { ContentFilesSidebarView } from "@/components/editor/database/sidebar";
65
65
  import { QueryErrorState } from "@/components/QueryErrorState";
66
- import { ThemeToggle } from "@/components/ThemeToggle";
67
66
  import {
68
67
  AlertDialog,
69
68
  AlertDialogAction,
@@ -83,6 +82,7 @@ import {
83
82
  DropdownMenuTrigger,
84
83
  } from "@/components/ui/dropdown-menu";
85
84
  import { ScrollArea } from "@/components/ui/scroll-area";
85
+ import { Skeleton } from "@/components/ui/skeleton";
86
86
  import {
87
87
  Tooltip,
88
88
  TooltipContent,
@@ -133,7 +133,6 @@ import {
133
133
  DocumentTreeItem,
134
134
  FavoriteDocumentItem,
135
135
  } from "./DocumentTreeItem";
136
- import { NotionButton } from "./NotionButton";
137
136
  import {
138
137
  contentSpaceAvailability,
139
138
  contentSpaceForStoredSelection,
@@ -288,7 +287,7 @@ function WorkspaceFilesSection({
288
287
  const failed = filesDatabase.isError || filesPersonalView.isError;
289
288
 
290
289
  return (
291
- <div className="ms-3 border-s border-border/70 pb-1 ps-1">
290
+ <div className="ms-3 pb-1 ps-1">
292
291
  {failed ? (
293
292
  <QueryErrorState
294
293
  compact
@@ -329,7 +328,6 @@ function WorkspaceFilesSection({
329
328
  onDeleteItem={onDeleteItem}
330
329
  onToggleFavorite={onToggleFavorite}
331
330
  labels={{
332
- loadingLabel: t("sidebar.loadingFiles"),
333
331
  noMatchesLabel: t("database.noRowsMatchThisView"),
334
332
  clearLabel: t("database.clearSearchAndFilters"),
335
333
  navigationLabel: `${space.name} ${t("sidebar.files")}`,
@@ -1407,12 +1405,12 @@ export function DocumentSidebar({
1407
1405
  };
1408
1406
 
1409
1407
  const renderTreeSkeleton = () => (
1410
- <div className="space-y-1 px-3 py-1">
1408
+ <div aria-hidden="true" className="grid gap-1 px-3 py-1">
1411
1409
  {[70, 55, 85, 60, 45].map((w, i) => (
1412
1410
  <div key={i} className="flex items-center gap-2 px-1 py-1.5">
1413
- <div className="h-3.5 w-3.5 shrink-0 animate-pulse rounded bg-muted" />
1414
- <div
1415
- className="h-3.5 animate-pulse rounded bg-muted"
1411
+ <Skeleton className="size-3.5 shrink-0 rounded-sm bg-sidebar-foreground/12 dark:bg-sidebar-foreground/10" />
1412
+ <Skeleton
1413
+ className="h-3 rounded bg-sidebar-foreground/12 dark:bg-sidebar-foreground/10"
1416
1414
  style={{ width: `${w}%` }}
1417
1415
  />
1418
1416
  </div>
@@ -1611,7 +1609,6 @@ export function DocumentSidebar({
1611
1609
  }}
1612
1610
  scroll={false}
1613
1611
  labels={{
1614
- loadingLabel: t("sidebar.loadingFiles"),
1615
1612
  noMatchesLabel: t("database.noRowsMatchThisView"),
1616
1613
  clearLabel: t("database.clearSearchAndFilters"),
1617
1614
  navigationLabel: "Content navigation",
@@ -1637,9 +1634,7 @@ export function DocumentSidebar({
1637
1634
  </div>
1638
1635
  </div>
1639
1636
  ) : contentSpaceState === "loading" ? (
1640
- <div className="px-3 py-4 text-center text-sm text-muted-foreground">
1641
- {t("sidebar.loadingFiles")}
1642
- </div>
1637
+ renderTreeSkeleton()
1643
1638
  ) : (
1644
1639
  <QueryErrorState
1645
1640
  compact
@@ -1656,7 +1651,7 @@ export function DocumentSidebar({
1656
1651
  const collapsed = collapsedSections.trash;
1657
1652
 
1658
1653
  return (
1659
- <div className="mt-3 border-t border-border/60 pt-2">
1654
+ <div className="mt-3 pt-2">
1660
1655
  <div className="px-2">
1661
1656
  <button
1662
1657
  type="button"
@@ -2025,26 +2020,30 @@ export function DocumentSidebar({
2025
2020
  </Link>
2026
2021
  </div>
2027
2022
  {!collapsedSections.favorites &&
2028
- favorites.map((doc) => (
2029
- <FavoriteDocumentItem
2030
- key={doc.id}
2031
- document={doc}
2032
- active={doc.id === activeDocumentId}
2033
- sidebarWidth={favoriteRowWidth}
2034
- onSelect={() => {
2035
- handleOpenFavorite(doc);
2036
- onNavigate?.();
2037
- }}
2038
- onCreateChildPage={() => void handleCreatePage(doc.id)}
2039
- onCreateChildDatabase={() =>
2040
- void handleCreateDatabase(doc.id)
2041
- }
2042
- onRemoveFavorite={() =>
2043
- handleToggleFavorite(doc.id, false)
2044
- }
2045
- onDelete={() => void handleDelete(doc.id)}
2046
- />
2047
- ))}
2023
+ (isLoading
2024
+ ? renderTreeSkeleton()
2025
+ : favorites.map((doc) => (
2026
+ <FavoriteDocumentItem
2027
+ key={doc.id}
2028
+ document={doc}
2029
+ active={doc.id === activeDocumentId}
2030
+ sidebarWidth={favoriteRowWidth}
2031
+ onSelect={() => {
2032
+ handleOpenFavorite(doc);
2033
+ onNavigate?.();
2034
+ }}
2035
+ onCreateChildPage={() =>
2036
+ void handleCreatePage(doc.id)
2037
+ }
2038
+ onCreateChildDatabase={() =>
2039
+ void handleCreateDatabase(doc.id)
2040
+ }
2041
+ onRemoveFavorite={() =>
2042
+ handleToggleFavorite(doc.id, false)
2043
+ }
2044
+ onDelete={() => void handleDelete(doc.id)}
2045
+ />
2046
+ )))}
2048
2047
  </div>
2049
2048
  )}
2050
2049
 
@@ -2080,10 +2079,6 @@ export function DocumentSidebar({
2080
2079
  {/* Footer */}
2081
2080
  <div className="shrink-0 space-y-2 px-3 py-2">
2082
2081
  {isCodeMode ? <DevDatabaseLink /> : null}
2083
- <div className="flex justify-end gap-0.5">
2084
- <NotionButton />
2085
- <ThemeToggle />
2086
- </div>
2087
2082
  <SidebarFooterActions
2088
2083
  feedback={feedbackButton}
2089
2084
  translate={translateButton}
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-07-27
4
+ ---
5
+
6
+ Content sidebar page lists now load with quiet skeletons and less visual chrome.
@@ -17,7 +17,6 @@ import {
17
17
  import { useEffect, useState } from "react";
18
18
  import { Link, useLocation } from "react-router";
19
19
 
20
- import { ThemeToggle } from "@/components/ThemeToggle";
21
20
  import {
22
21
  Tooltip,
23
22
  TooltipContent,
@@ -128,25 +127,25 @@ export function Sidebar() {
128
127
  collapsed ? "justify-center px-2" : "justify-between px-4",
129
128
  )}
130
129
  >
131
- {!collapsed && (
132
- <div className="flex items-center gap-2">
133
- <img
134
- src={appPath("/agent-native-icon-light.svg")}
135
- alt=""
136
- aria-hidden="true"
137
- className="block h-4 w-auto dark:hidden"
138
- />
139
- <img
140
- src={appPath("/agent-native-icon-dark.svg")}
141
- alt=""
142
- aria-hidden="true"
143
- className="hidden h-4 w-auto dark:block"
144
- />
130
+ <div className="flex items-center gap-2">
131
+ <img
132
+ src={appPath("/agent-native-icon-light.svg")}
133
+ alt=""
134
+ aria-hidden="true"
135
+ className="block h-4 w-auto dark:hidden"
136
+ />
137
+ <img
138
+ src={appPath("/agent-native-icon-dark.svg")}
139
+ alt=""
140
+ aria-hidden="true"
141
+ className="hidden h-4 w-auto dark:block"
142
+ />
143
+ {!collapsed && (
145
144
  <span className="text-sm font-semibold tracking-tight">
146
145
  {t("navigation.brand")}
147
146
  </span>
148
- </div>
149
- )}
147
+ )}
148
+ </div>
150
149
  </div>
151
150
 
152
151
  <div className="flex min-h-0 flex-1 flex-col overflow-y-auto">
@@ -234,7 +233,6 @@ export function Sidebar() {
234
233
  </div>
235
234
  <div className="px-3 py-2">
236
235
  <DevDatabaseLink />
237
- <ThemeToggle className="h-8 w-8 shrink-0" />
238
236
  </div>
239
237
  </div>
240
238
  )}
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-07-27
4
+ ---
5
+
6
+ The collapsed sidebar keeps the Agent Native logo visible and removes the theme toggle from the sidebar.
@@ -36,9 +36,9 @@ ladder.
36
36
  setup item is unclear.
37
37
  - Keep approval and routing behavior explicit. Never silently widen access to
38
38
  secrets, apps, integrations, or workspace resources.
39
- - Curated workspace templates are private remix sources. Use
39
+ - Curated workspace templates are private app sources. Use
40
40
  `list-curated-workspace-templates` to inspect the reviewed catalog and
41
- `remix-workspace-template` to create an independent app. A remix may use
41
+ `remix-workspace-template` to create an independent app. A new app may use
42
42
  empty or synthetic data only; never copy source-app records, credentials,
43
43
  secrets, or private configuration.
44
44
  - `/operations` is the focused operator console. Its Monitoring tab reuses the
@@ -49,6 +49,11 @@ ladder.
49
49
  Destinations for concrete thread, change-history, and delivery investigations;
50
50
  Dispatch does not invent a separate issue tracker when those framework
51
51
  surfaces contain the operational evidence.
52
+ - Thread Debug accepts the copied request/run ID from an Agent Native chat
53
+ response as well as a chat thread ID; use the exact source that owns the run.
54
+ Hosted production sources appear only when Dispatch has their
55
+ <APP>_DATABASE_URL connection variables (or an equivalent
56
+ AGENT_NATIVE_THREAD_DEBUG_DATABASES configuration).
52
57
 
53
58
  ## Application State
54
59
 
@@ -197,10 +197,11 @@ export default defineAction({
197
197
  },
198
198
  );
199
199
  }
200
- if (nav.threadId) {
200
+ if (nav.threadId || nav.runId) {
201
201
  const detail = (await runDispatchAction("get-agent-thread-debug", {
202
202
  sourceId: nav.sourceId,
203
- threadId: nav.threadId,
203
+ threadId: nav.runId ? undefined : nav.threadId,
204
+ runId: nav.runId,
204
205
  ownerEmail: nav.ownerEmail,
205
206
  maxRuns: 5,
206
207
  maxEvents: 80,
@@ -3,4 +3,4 @@ type: added
3
3
  date: 2026-07-17
4
4
  ---
5
5
 
6
- Dispatch now offers curated workspace templates that can be remixed into private apps.
6
+ Dispatch now offers curated workspace templates that can be used to create private apps.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-07-27
4
+ ---
5
+
6
+ Creating an app from a curated template now uses clearer, more direct language.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-07-27
4
+ ---
5
+
6
+ Thread Debug can open a run directly from the copied request ID in an Agent Native chat.
@@ -8,6 +8,7 @@ import { nanoid } from "nanoid";
8
8
  import { z } from "zod";
9
9
 
10
10
  import { getDb, schema } from "../server/db/index.js";
11
+ import { missingDesignSystemDataFields } from "../shared/design-system-validation.js";
11
12
 
12
13
  export default defineAction({
13
14
  description:
@@ -36,12 +37,19 @@ export default defineAction({
36
37
  ),
37
38
  }),
38
39
  run: async ({ title, description, data, assets, customInstructions }) => {
39
- // Validate that data is valid JSON
40
+ let parsedData: unknown;
40
41
  try {
41
- JSON.parse(data);
42
+ parsedData = JSON.parse(data);
42
43
  } catch {
43
44
  throw new Error("data must be a valid JSON string");
44
45
  }
46
+ const missingFields = missingDesignSystemDataFields(parsedData);
47
+ if (missingFields.length > 0) {
48
+ throw new Error(
49
+ "data is missing required design system field(s): " +
50
+ missingFields.join(", "),
51
+ );
52
+ }
45
53
  if (assets) {
46
54
  try {
47
55
  JSON.parse(assets);
@@ -2,6 +2,7 @@ import path from "path";
2
2
 
3
3
  import { defineAction } from "@agent-native/core";
4
4
  import { writeAppState } from "@agent-native/core/application-state";
5
+ import { uploadFile } from "@agent-native/core/file-upload";
5
6
  import { startBuilderDesignSystemIndex } from "@agent-native/core/server";
6
7
  import {
7
8
  getRequestOrgId,
@@ -15,6 +16,11 @@ import { getDb, schema } from "../server/db/index.js";
15
16
  import { notifyClients } from "../server/handlers/decks.js";
16
17
  import { upsertBuilderProxyDesignSystem } from "../server/lib/builder-design-system-proxy.js";
17
18
  import { setupPdfParse } from "../server/lib/pdf-parse-setup.js";
19
+ import {
20
+ ASPECT_RATIOS,
21
+ DEFAULT_ASPECT_RATIO,
22
+ type AspectRatio,
23
+ } from "../shared/aspect-ratios.js";
18
24
  import { readUserUploadedFile } from "./_uploaded-files.js";
19
25
 
20
26
  const DEFAULT_MAX_SOURCE_CHARS = 60_000;
@@ -213,6 +219,25 @@ export default defineAction({
213
219
 
214
220
  if (detectedFormat === "pdf") {
215
221
  const { PDFParse, canvasFactory } = await setupPdfParse();
222
+ const title = titleFromPath(filename);
223
+
224
+ // Designed slide PDFs (photo backgrounds, gradients, custom
225
+ // typography) bake their visuals into vector/image page content with
226
+ // no reliable text/shape structure to reconstruct, so importing into a
227
+ // deck rasterizes each page instead of flattening it to generic bullet
228
+ // text. Falls through to the text-only path below when the optional
229
+ // canvas renderer isn't available in this runtime.
230
+ if (importIntoDeck && canvasFactory) {
231
+ if (!deckId) throw new Error("deckId is required to import into deck");
232
+ return importPdfPagesAsFullBleedSlides({
233
+ fileBuffer,
234
+ title,
235
+ deckId,
236
+ PDFParse,
237
+ canvasFactory,
238
+ });
239
+ }
240
+
216
241
  const { convertSectionsToSlides } =
217
242
  await import("../server/handlers/import/html-converter.js");
218
243
  const pdf = new PDFParse({
@@ -222,7 +247,6 @@ export default defineAction({
222
247
  const result = await pdf.getText().finally(() => pdf.destroy());
223
248
  const pages = normalizePdfPages(result);
224
249
  const textPages = pages.filter((p) => p.text.trim());
225
- const title = titleFromPath(filename);
226
250
 
227
251
  if (textPages.length === 0) {
228
252
  throw new Error(
@@ -278,6 +302,152 @@ export default defineAction({
278
302
  },
279
303
  });
280
304
 
305
+ /** Closest configured deck aspect ratio to a source image's own dimensions. */
306
+ function nearestAspectRatio(width: number, height: number): AspectRatio {
307
+ const target = width / height;
308
+ let best: AspectRatio = DEFAULT_ASPECT_RATIO;
309
+ let bestDiff = Infinity;
310
+ for (const key of Object.keys(ASPECT_RATIOS) as AspectRatio[]) {
311
+ const preset = ASPECT_RATIOS[key];
312
+ const diff = Math.abs(preset.width / preset.height - target);
313
+ if (diff < bestDiff) {
314
+ bestDiff = diff;
315
+ best = key;
316
+ }
317
+ }
318
+ return best;
319
+ }
320
+
321
+ async function importPdfPagesAsFullBleedSlides(args: {
322
+ fileBuffer: Buffer;
323
+ title: string;
324
+ deckId: string;
325
+ PDFParse: Awaited<ReturnType<typeof setupPdfParse>>["PDFParse"];
326
+ canvasFactory: object;
327
+ }) {
328
+ const { fileBuffer, title, deckId, PDFParse, canvasFactory } = args;
329
+ const { buildFullBleedImageSlideHtml, convertSectionsToSlides } =
330
+ await import("../server/handlers/import/html-converter.js");
331
+
332
+ const pdf = new PDFParse({
333
+ data: new Uint8Array(fileBuffer),
334
+ CanvasFactory: canvasFactory,
335
+ });
336
+ let pages: { num: number; text: string }[];
337
+ let imagesByPage: Map<
338
+ number,
339
+ { data: Uint8Array; width: number; height: number }
340
+ >;
341
+ try {
342
+ pages = normalizePdfPages(await pdf.getText());
343
+ // Reuse the page's own embedded photo rather than rasterizing the whole
344
+ // page: headless canvas text rendering depends on the PDF's embedded
345
+ // fonts resolving in this runtime, which is unreliable, so real
346
+ // extracted text is drawn as HTML below instead of trusting the render.
347
+ const imageResult = await pdf.getImage({
348
+ imageBuffer: true,
349
+ imageDataUrl: false,
350
+ });
351
+ imagesByPage = new Map();
352
+ for (const page of imageResult.pages) {
353
+ const largest = page.images.reduce<
354
+ { data: Uint8Array; width: number; height: number } | undefined
355
+ >((best, image) => {
356
+ if (!best || image.width * image.height > best.width * best.height) {
357
+ return { data: image.data, width: image.width, height: image.height };
358
+ }
359
+ return best;
360
+ }, undefined);
361
+ if (largest) imagesByPage.set(page.pageNumber, largest);
362
+ }
363
+ } finally {
364
+ await pdf.destroy();
365
+ }
366
+
367
+ // Source decks (e.g. Instagram carousel exports) are commonly portrait or
368
+ // square, not the deck editor's 16:9 default — match the canvas to the
369
+ // first embedded photo's own proportions instead of stretching/cropping it.
370
+ const firstImage = pages
371
+ .map((page) => imagesByPage.get(page.num))
372
+ .find((image): image is NonNullable<typeof image> => Boolean(image));
373
+ const aspectRatio = firstImage
374
+ ? nearestAspectRatio(firstImage.width, firstImage.height)
375
+ : undefined;
376
+
377
+ const ownerEmail = getRequestUserEmail();
378
+ const slides = await Promise.all(
379
+ pages.map(async (page) => {
380
+ const lines = page.text
381
+ .split(/\r?\n/)
382
+ .map((line) => line.trim())
383
+ .filter(Boolean);
384
+ const backgroundImage = imagesByPage.get(page.num);
385
+
386
+ if (!backgroundImage) {
387
+ const [content] = convertSectionsToSlides([
388
+ { heading: lines[0] ?? `Page ${page.num}`, content: page.text },
389
+ ]);
390
+ return {
391
+ id: newSlideId(),
392
+ content: content ?? '<div class="fmd-slide"></div>',
393
+ layout: "content",
394
+ notes: "",
395
+ };
396
+ }
397
+
398
+ const uploadResult = await uploadFile({
399
+ data: Buffer.from(backgroundImage.data),
400
+ filename: `slide-import-${Date.now()}-p${page.num}.png`,
401
+ mimeType: "image/png",
402
+ ownerEmail: ownerEmail ?? undefined,
403
+ recordAsset: false,
404
+ });
405
+ if (!uploadResult?.url) {
406
+ throw new Error(
407
+ "File storage is not configured. Connect Builder.io or another upload provider before importing PDF slides.",
408
+ );
409
+ }
410
+ // pdf-parse breaks wrapped text across lines with no way to tell a
411
+ // wrapped title from a heading followed by a body paragraph. Treat a
412
+ // couple of short lines as one wrapped title (join them so the
413
+ // sentence isn't cut off); three or more lines as a heading plus body
414
+ // text, rendered with distinct sizes so they don't collapse into one
415
+ // flat paragraph.
416
+ const heading =
417
+ lines.length > 2 ? lines[0] : lines.join(" ") || undefined;
418
+ const subtitle = lines.length > 2 ? lines.slice(1).join(" ") : undefined;
419
+ return {
420
+ id: newSlideId(),
421
+ content: buildFullBleedImageSlideHtml(
422
+ uploadResult.url,
423
+ heading,
424
+ subtitle,
425
+ ),
426
+ layout: "full-image",
427
+ notes: page.text,
428
+ };
429
+ }),
430
+ );
431
+
432
+ await replaceDeckSlides(
433
+ deckId,
434
+ title,
435
+ slides,
436
+ "import-file:pdf",
437
+ aspectRatio,
438
+ );
439
+
440
+ return {
441
+ format: "pdf",
442
+ title,
443
+ pageCount: slides.length,
444
+ slideCount: slides.length,
445
+ aspectRatio,
446
+ deckId,
447
+ imported: true,
448
+ };
449
+ }
450
+
281
451
  function newSlideId(): string {
282
452
  return `slide-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;
283
453
  }
@@ -367,6 +537,7 @@ async function replaceDeckSlides(
367
537
  notes?: string;
368
538
  }>,
369
539
  source: string,
540
+ aspectRatio?: AspectRatio,
370
541
  ) {
371
542
  await assertAccess("deck", deckId, "editor");
372
543
 
@@ -387,6 +558,7 @@ async function replaceDeckSlides(
387
558
  ...previousData,
388
559
  title,
389
560
  slides,
561
+ ...(aspectRatio ? { aspectRatio } : {}),
390
562
  updatedAt: now,
391
563
  };
392
564
 
@@ -27,6 +27,21 @@ export default defineAction({
27
27
  ),
28
28
  )
29
29
  .orderBy(asc(schema.slideComments.createdAt));
30
- return { comments: rows };
30
+ return {
31
+ comments: rows.map((row) => ({
32
+ id: row.id,
33
+ deck_id: row.deckId,
34
+ slide_id: row.slideId,
35
+ thread_id: row.threadId,
36
+ parent_id: row.parentId,
37
+ content: row.content,
38
+ quoted_text: row.quotedText,
39
+ author_email: row.authorEmail,
40
+ author_name: row.authorName,
41
+ resolved: row.resolved,
42
+ created_at: row.createdAt,
43
+ updated_at: row.updatedAt,
44
+ })),
45
+ };
31
46
  },
32
47
  });
@@ -4,6 +4,7 @@ import { eq } from "drizzle-orm";
4
4
  import { z } from "zod";
5
5
 
6
6
  import { getDb, schema } from "../server/db/index.js";
7
+ import { missingDesignSystemDataFields } from "../shared/design-system-validation.js";
7
8
 
8
9
  export default defineAction({
9
10
  description:
@@ -29,13 +30,23 @@ export default defineAction({
29
30
  ),
30
31
  }),
31
32
  run: async ({ id, title, description, data, assets, customInstructions }) => {
32
- // Validate that data/assets are valid JSON when provided
33
+ // Validate that data/assets are valid JSON, and that data has the shape
34
+ // the Design Systems page and slide renderers read unconditionally
35
+ // (data.colors.*, data.typography.*) — see create-design-system.ts.
33
36
  if (data !== undefined) {
37
+ let parsedData: unknown;
34
38
  try {
35
- JSON.parse(data);
39
+ parsedData = JSON.parse(data);
36
40
  } catch {
37
41
  throw new Error("data must be a valid JSON string");
38
42
  }
43
+ const missingFields = missingDesignSystemDataFields(parsedData);
44
+ if (missingFields.length > 0) {
45
+ throw new Error(
46
+ "data is missing required design system field(s): " +
47
+ missingFields.join(", "),
48
+ );
49
+ }
39
50
  }
40
51
  if (assets !== undefined) {
41
52
  try {