@agent-native/core 0.132.1 → 0.133.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 (456) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +198 -0
  3. package/corpus/core/package.json +1 -1
  4. package/corpus/core/src/a2a/correlation.ts +11 -1
  5. package/corpus/core/src/a2a/types.ts +11 -3
  6. package/corpus/core/src/agent/engine/ai-sdk-engine.ts +33 -46
  7. package/corpus/core/src/agent/engine/builder-engine.ts +22 -10
  8. package/corpus/core/src/agent/engine/error-detail.ts +184 -3
  9. package/corpus/core/src/agent/engine/failure-taxonomy.ts +123 -0
  10. package/corpus/core/src/agent/engine/index.ts +8 -0
  11. package/corpus/core/src/agent/engine/registry.ts +92 -8
  12. package/corpus/core/src/agent/engine/translate-ai-sdk.ts +17 -2
  13. package/corpus/core/src/agent/production-agent.ts +13 -33
  14. package/corpus/core/src/agent/run-loop-with-resume.ts +1 -1
  15. package/corpus/core/src/agent/run-manager.ts +43 -14
  16. package/corpus/core/src/agent/run-store.ts +30 -3
  17. package/corpus/core/src/agent/thread-data-builder.ts +36 -4
  18. package/corpus/core/src/chat-threads/store.ts +42 -0
  19. package/corpus/core/src/cli/templates-meta.ts +13 -0
  20. package/corpus/core/src/cli/workspace-dev.ts +1 -0
  21. package/corpus/core/src/client/error-format.ts +12 -0
  22. package/corpus/core/src/client/use-chat-threads.ts +76 -16
  23. package/corpus/core/src/credentials/index.ts +51 -12
  24. package/corpus/core/src/extensions/url-safety.ts +46 -12
  25. package/corpus/core/src/integrations/adapters/slack.ts +32 -10
  26. package/corpus/core/src/integrations/google-docs-poller.ts +12 -1
  27. package/corpus/core/src/integrations/installations-store.ts +30 -0
  28. package/corpus/core/src/integrations/plugin.ts +5 -5
  29. package/corpus/core/src/integrations/types.ts +7 -0
  30. package/corpus/core/src/integrations/webhook-handler.ts +24 -1
  31. package/corpus/core/src/jobs/background-automation-runner.ts +38 -1
  32. package/corpus/core/src/provider-api/index.ts +8 -2
  33. package/corpus/core/src/scripts/call-agent.ts +6 -0
  34. package/corpus/core/src/server/agent-chat-plugin.ts +46 -10
  35. package/corpus/core/src/server/agent-discovery.ts +2 -0
  36. package/corpus/core/src/server/builder-design-systems.ts +21 -0
  37. package/corpus/core/src/server/credential-provider.ts +51 -12
  38. package/corpus/core/src/server/index.ts +1 -0
  39. package/corpus/core/src/server/onboarding-html.ts +37 -2
  40. package/corpus/core/src/shared/reasoning-effort.ts +1 -1
  41. package/corpus/core/src/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +11 -0
  42. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +6 -2
  43. package/corpus/templates/assets/app/components/layout/Sidebar.tsx +39 -19
  44. package/corpus/templates/assets/changelog/2026-07-31-the-agent-native-logo-stays-visible-when-the-sidebar-is-coll.md +6 -0
  45. package/corpus/templates/brain/app/components/layout/Sidebar.tsx +30 -3
  46. package/corpus/templates/brain/changelog/2026-07-31-clicking-the-agent-native-logo-now-toggles-the-app-sidebar.md +6 -0
  47. package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +1 -1
  48. package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +54 -25
  49. package/corpus/templates/calendar/changelog/2026-07-31-the-agent-native-logo-stays-visible-when-the-sidebar-is-coll.md +6 -0
  50. package/corpus/templates/chat/app/components/layout/Sidebar.tsx +30 -3
  51. package/corpus/templates/chat/changelog/2026-07-31-clicking-the-agent-native-logo-now-toggles-the-app-sidebar.md +6 -0
  52. package/corpus/templates/clips/app/components/library/library-layout.tsx +37 -21
  53. package/corpus/templates/clips/changelog/2026-07-30-meeting-microphone-transcription-works-reliably-from-the-fir.md +6 -0
  54. package/corpus/templates/clips/changelog/2026-07-31-the-agent-native-logo-stays-visible-when-the-sidebar-is-coll.md +6 -0
  55. package/corpus/templates/clips/desktop/src/hooks/useMediaDevices.ts +1 -1
  56. package/corpus/templates/clips/desktop/src/lib/media-capture-constraints.ts +1 -1
  57. package/corpus/templates/clips/desktop/src-tauri/src/native_screen/custom_capture.rs +13 -0
  58. package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +2 -0
  59. package/corpus/templates/clips/desktop/src-tauri/src/system_audio.rs +25 -132
  60. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +34 -17
  61. package/corpus/templates/content/changelog/2026-07-31-the-agent-native-logo-stays-visible-when-the-sidebar-is-coll.md +6 -0
  62. package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +6 -2
  63. package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +5 -0
  64. package/corpus/templates/design/actions/create-design-system.ts +1 -0
  65. package/corpus/templates/design/actions/set-default-design-system.ts +34 -26
  66. package/corpus/templates/design/app/components/design/KeyboardShortcutsPanel.tsx +5 -3
  67. package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +23 -0
  68. package/corpus/templates/design/app/components/design/keyboard-shortcuts.ts +3 -0
  69. package/corpus/templates/design/app/components/layout/Sidebar.tsx +21 -4
  70. package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +11 -7
  71. package/corpus/templates/design/app/i18n-data.ts +39 -0
  72. package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +229 -12
  73. package/corpus/templates/design/app/pages/DesignSystems.tsx +10 -4
  74. package/corpus/templates/design/changelog/2026-07-30-fixed-the-keyboard-shortcuts-panel-not-opening-with-ctrl-shi.md +6 -0
  75. package/corpus/templates/design/changelog/2026-07-31-clicking-the-agent-native-logo-now-toggles-the-app-sidebar.md +6 -0
  76. package/corpus/templates/design/changelog/2026-07-31-design-system-indexing-keeps-your-chosen-name-when-you-uploa.md +6 -0
  77. package/corpus/templates/design/server/lib/builder-design-system-proxy.ts +19 -4
  78. package/corpus/templates/dispatch/AGENTS.md +4 -0
  79. package/corpus/templates/factory/.agents/skills/actions/SKILL.md +562 -0
  80. package/corpus/templates/factory/.agents/skills/adding-a-feature/SKILL.md +198 -0
  81. package/corpus/templates/factory/.agents/skills/agent-native-docs/SKILL.md +115 -0
  82. package/corpus/templates/factory/.agents/skills/agent-native-toolkit/SKILL.md +182 -0
  83. package/corpus/templates/factory/.agents/skills/capture-learnings/SKILL.md +89 -0
  84. package/corpus/templates/factory/.agents/skills/create-skill/SKILL.md +221 -0
  85. package/corpus/templates/factory/.agents/skills/customizing-agent-native/SKILL.md +220 -0
  86. package/corpus/templates/factory/.agents/skills/delegate-to-agent/SKILL.md +263 -0
  87. package/corpus/templates/factory/.agents/skills/factory-graphs/SKILL.md +52 -0
  88. package/corpus/templates/factory/.agents/skills/feature-flags/SKILL.md +169 -0
  89. package/corpus/templates/factory/.agents/skills/frontend-design/SKILL.md +174 -0
  90. package/corpus/templates/factory/.agents/skills/real-time-sync/SKILL.md +232 -0
  91. package/corpus/templates/factory/.agents/skills/security/SKILL.md +324 -0
  92. package/corpus/templates/factory/.agents/skills/self-modifying-code/SKILL.md +119 -0
  93. package/corpus/templates/factory/.agents/skills/shadcn-ui/SKILL.md +123 -0
  94. package/corpus/templates/factory/.agents/skills/sharing/SKILL.md +232 -0
  95. package/corpus/templates/factory/.agents/skills/storing-data/SKILL.md +178 -0
  96. package/corpus/templates/factory/.agents/skills/upgrade-agent-native/SKILL.md +122 -0
  97. package/corpus/templates/factory/.env.example +24 -0
  98. package/corpus/templates/factory/.ignore +0 -0
  99. package/corpus/templates/factory/.oxfmtrc.json +8 -0
  100. package/corpus/templates/factory/AGENTS.md +90 -0
  101. package/corpus/templates/factory/CHANGELOG.md +10 -0
  102. package/corpus/templates/factory/DEVELOPING.md +185 -0
  103. package/corpus/templates/factory/README.md +64 -0
  104. package/corpus/templates/factory/_gitignore +42 -0
  105. package/corpus/templates/factory/actions/add-factory-comment.ts +55 -0
  106. package/corpus/templates/factory/actions/approve-factory-item.ts +214 -0
  107. package/corpus/templates/factory/actions/babysit-pull-request.ts +126 -0
  108. package/corpus/templates/factory/actions/evaluate-triage-item.ts +172 -0
  109. package/corpus/templates/factory/actions/get-factory-graph.ts +62 -0
  110. package/corpus/templates/factory/actions/get-triage-config.ts +42 -0
  111. package/corpus/templates/factory/actions/get-triage-item.ts +74 -0
  112. package/corpus/templates/factory/actions/hello.ts +13 -0
  113. package/corpus/templates/factory/actions/ingest-github-observation.ts +100 -0
  114. package/corpus/templates/factory/actions/list-factories.ts +40 -0
  115. package/corpus/templates/factory/actions/list-factory-comments.ts +40 -0
  116. package/corpus/templates/factory/actions/list-triage-items.ts +85 -0
  117. package/corpus/templates/factory/actions/list-triage-rules.ts +44 -0
  118. package/corpus/templates/factory/actions/navigate.ts +41 -0
  119. package/corpus/templates/factory/actions/poll-slack-channel.ts +118 -0
  120. package/corpus/templates/factory/actions/reconcile-triage-run.ts +179 -0
  121. package/corpus/templates/factory/actions/record-triage-feedback.ts +58 -0
  122. package/corpus/templates/factory/actions/run.ts +2 -0
  123. package/corpus/templates/factory/actions/save-factory-graph.ts +129 -0
  124. package/corpus/templates/factory/actions/save-triage-config.ts +67 -0
  125. package/corpus/templates/factory/actions/save-triage-rule.ts +89 -0
  126. package/corpus/templates/factory/actions/suggest-factory-rules.ts +70 -0
  127. package/corpus/templates/factory/actions/view-screen.ts +73 -0
  128. package/corpus/templates/factory/app/components/factory/FactoryCanvas.tsx +441 -0
  129. package/corpus/templates/factory/app/components/factory/FactoryInspector.tsx +388 -0
  130. package/corpus/templates/factory/app/components/layout/Header.tsx +60 -0
  131. package/corpus/templates/factory/app/components/layout/Layout.tsx +190 -0
  132. package/corpus/templates/factory/app/components/layout/Sidebar.tsx +538 -0
  133. package/corpus/templates/factory/app/components/triage/triage-status-pill.tsx +28 -0
  134. package/corpus/templates/factory/app/components/ui/button.tsx +1 -0
  135. package/corpus/templates/factory/app/components/ui/card.tsx +1 -0
  136. package/corpus/templates/factory/app/components/ui/dropdown-menu.tsx +1 -0
  137. package/corpus/templates/factory/app/components/ui/input.tsx +1 -0
  138. package/corpus/templates/factory/app/components/ui/label.tsx +1 -0
  139. package/corpus/templates/factory/app/components/ui/sheet.tsx +1 -0
  140. package/corpus/templates/factory/app/components/ui/textarea.tsx +1 -0
  141. package/corpus/templates/factory/app/components/ui/toolkit-provider.tsx +17 -0
  142. package/corpus/templates/factory/app/components/ui/tooltip.tsx +1 -0
  143. package/corpus/templates/factory/app/design-system.ts +3 -0
  144. package/corpus/templates/factory/app/entry.client.tsx +22 -0
  145. package/corpus/templates/factory/app/entry.server.tsx +10 -0
  146. package/corpus/templates/factory/app/global.css +93 -0
  147. package/corpus/templates/factory/app/hooks/use-navigation-state.ts +113 -0
  148. package/corpus/templates/factory/app/i18n/en-US.ts +211 -0
  149. package/corpus/templates/factory/app/i18n/index.ts +34 -0
  150. package/corpus/templates/factory/app/i18n-data.ts +556 -0
  151. package/corpus/templates/factory/app/lib/agent-page.tsx +49 -0
  152. package/corpus/templates/factory/app/lib/app-config.ts +11 -0
  153. package/corpus/templates/factory/app/lib/tab-id.ts +1 -0
  154. package/corpus/templates/factory/app/lib/utils.ts +1 -0
  155. package/corpus/templates/factory/app/root.tsx +175 -0
  156. package/corpus/templates/factory/app/routes/_index.tsx +94 -0
  157. package/corpus/templates/factory/app/routes/agent.tsx +24 -0
  158. package/corpus/templates/factory/app/routes/chat.$threadId.tsx +1 -0
  159. package/corpus/templates/factory/app/routes/database.tsx +17 -0
  160. package/corpus/templates/factory/app/routes/extensions.$id.$slug.tsx +2 -0
  161. package/corpus/templates/factory/app/routes/extensions.$id.tsx +11 -0
  162. package/corpus/templates/factory/app/routes/extensions._index.tsx +11 -0
  163. package/corpus/templates/factory/app/routes/extensions.tsx +5 -0
  164. package/corpus/templates/factory/app/routes/factory.tsx +1003 -0
  165. package/corpus/templates/factory/app/routes/observability.tsx +19 -0
  166. package/corpus/templates/factory/app/routes/settings.tsx +89 -0
  167. package/corpus/templates/factory/app/routes/team.tsx +11 -0
  168. package/corpus/templates/factory/app/routes.ts +4 -0
  169. package/corpus/templates/factory/app/vite-env.d.ts +6 -0
  170. package/corpus/templates/factory/changelog/2026-06-24-a-new-settings-page-gives-quick-access-to-language-workspace.md +6 -0
  171. package/corpus/templates/factory/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
  172. package/corpus/templates/factory/changelog/2026-06-27-traditional-chinese-copy-uses-taiwan-terminology.md +6 -0
  173. package/corpus/templates/factory/changelog/2026-06-28-left-sidebar-collapse-motion-and-footer-chrome-are-quieter.md +6 -0
  174. package/corpus/templates/factory/changelog/2026-06-29-chat-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
  175. package/corpus/templates/factory/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  176. package/corpus/templates/factory/changelog/2026-07-10-chat-now-makes-ai-connection-setup-clear-without-shifting-th.md +6 -0
  177. package/corpus/templates/factory/changelog/2026-07-13-a-full-agent-page-now-brings-context-files-connections-jobs-.md +6 -0
  178. package/corpus/templates/factory/changelog/2026-07-14-chat-opens-reliably-on-hosted-deployments-instead-of-failing.md +6 -0
  179. package/corpus/templates/factory/changelog/2026-07-14-fixed-chat-template-startup-with-older-core-versions.md +6 -0
  180. package/corpus/templates/factory/changelog/2026-07-15-chat-navigation-focuses-on-chat-and-agent.md +6 -0
  181. package/corpus/templates/factory/changelog/2026-07-17-the-agent-chat-sidebar-stays-closed-until-you-open-it-or-sta.md +6 -0
  182. package/corpus/templates/factory/changelog/2026-07-22-compact-sidebar-footer.md +6 -0
  183. package/corpus/templates/factory/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +6 -0
  184. package/corpus/templates/factory/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
  185. package/corpus/templates/factory/changelog/2026-07-22-recent-chats-are-easier-to-scan-and-expand.md +6 -0
  186. package/corpus/templates/factory/changelog/2026-07-23-full-page-chat-is-better-centered-with-quieter-chat-history-.md +6 -0
  187. package/corpus/templates/factory/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
  188. package/corpus/templates/factory/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
  189. package/corpus/templates/factory/changelog/2026-07-25-settings-navigation-now-keeps-manage-agent-as-a-dedicated-li.md +6 -0
  190. package/corpus/templates/factory/changelog/2026-07-29-sidebar-footers-now-keep-feedback-search-and-collapse-togeth.md +6 -0
  191. package/corpus/templates/factory/changelog/2026-07-31-added-an-inspectable-observe-only-factory-queue-for-slack-.md +6 -0
  192. package/corpus/templates/factory/changelog/2026-07-31-clicking-the-agent-native-logo-now-toggles-the-app-sidebar.md +6 -0
  193. package/corpus/templates/factory/components.json +20 -0
  194. package/corpus/templates/factory/data/sync-config.json +1 -0
  195. package/corpus/templates/factory/learnings.defaults.md +5 -0
  196. package/corpus/templates/factory/netlify.toml +10 -0
  197. package/corpus/templates/factory/package.json +105 -0
  198. package/corpus/templates/factory/public/agent-native-icon-dark.svg +10 -0
  199. package/corpus/templates/factory/public/agent-native-icon-light.svg +10 -0
  200. package/corpus/templates/factory/public/agent-native-logo-dark.svg +21 -0
  201. package/corpus/templates/factory/public/agent-native-logo-light.svg +21 -0
  202. package/corpus/templates/factory/public/favicon.svg +1 -0
  203. package/corpus/templates/factory/public/icon-180.svg +1 -0
  204. package/corpus/templates/factory/public/icon-192.svg +1 -0
  205. package/corpus/templates/factory/public/icon-512.svg +1 -0
  206. package/corpus/templates/factory/public/manifest.json +21 -0
  207. package/corpus/templates/factory/react-router.config.ts +7 -0
  208. package/corpus/templates/factory/server/connectors/credentials.ts +129 -0
  209. package/corpus/templates/factory/server/connectors/slack.ts +129 -0
  210. package/corpus/templates/factory/server/db/index.ts +6 -0
  211. package/corpus/templates/factory/server/db/schema.ts +193 -0
  212. package/corpus/templates/factory/server/factory-graph/contracts.ts +212 -0
  213. package/corpus/templates/factory/server/factory-graph/store.ts +121 -0
  214. package/corpus/templates/factory/server/lib/require-workspace-member.ts +55 -0
  215. package/corpus/templates/factory/server/middleware/auth.ts +15 -0
  216. package/corpus/templates/factory/server/plugins/agent-chat.ts +58 -0
  217. package/corpus/templates/factory/server/plugins/auth.ts +14 -0
  218. package/corpus/templates/factory/server/plugins/factory-migrations.ts +247 -0
  219. package/corpus/templates/factory/server/plugins/factory-scheduler-job.ts +116 -0
  220. package/corpus/templates/factory/server/plugins/integrations.ts +46 -0
  221. package/corpus/templates/factory/server/routes/[...page].get.ts +5 -0
  222. package/corpus/templates/factory/server/routes/_agent-native/factory/builder-callback.post.ts +116 -0
  223. package/corpus/templates/factory/server/triage/ai-services-git.ts +197 -0
  224. package/corpus/templates/factory/server/triage/builder-executor.ts +118 -0
  225. package/corpus/templates/factory/server/triage/contracts.ts +164 -0
  226. package/corpus/templates/factory/server/triage/github-ingestion.ts +35 -0
  227. package/corpus/templates/factory/server/triage/guards.ts +121 -0
  228. package/corpus/templates/factory/server/triage/ids.ts +27 -0
  229. package/corpus/templates/factory/server/triage/pr-babysit.ts +100 -0
  230. package/corpus/templates/factory/server/triage/pr-monitor.ts +220 -0
  231. package/corpus/templates/factory/server/triage/slack-client.ts +55 -0
  232. package/corpus/templates/factory/server/triage/slack-poller.ts +152 -0
  233. package/corpus/templates/factory/ssr-entry.ts +15 -0
  234. package/corpus/templates/factory/tsconfig.json +21 -0
  235. package/corpus/templates/factory/vite.config.ts +19 -0
  236. package/corpus/templates/forms/app/components/layout/Sidebar.tsx +55 -5
  237. package/corpus/templates/forms/changelog/2026-07-31-the-agent-native-logo-stays-visible-when-the-sidebar-is-coll.md +6 -0
  238. package/corpus/templates/macros/app/components/layout/AppLayout.tsx +6 -2
  239. package/corpus/templates/plan/app/components/layout/Sidebar.tsx +21 -6
  240. package/corpus/templates/plan/changelog/2026-07-31-clicking-the-agent-native-logo-now-toggles-the-app-sidebar.md +6 -0
  241. package/corpus/templates/slides/.agents/skills/create-deck/SKILL.md +12 -0
  242. package/corpus/templates/slides/.agents/skills/design-systems/SKILL.md +9 -0
  243. package/corpus/templates/slides/.agents/skills/slide-editing/SKILL.md +11 -0
  244. package/corpus/templates/slides/AGENTS.md +5 -6
  245. package/corpus/templates/slides/actions/_await-fit-check.ts +20 -10
  246. package/corpus/templates/slides/actions/add-slide.ts +17 -4
  247. package/corpus/templates/slides/actions/create-design-system.ts +16 -4
  248. package/corpus/templates/slides/actions/delete-design-system.ts +18 -2
  249. package/corpus/templates/slides/actions/get-layout-overflows.ts +88 -0
  250. package/corpus/templates/slides/actions/import-file.ts +1 -0
  251. package/corpus/templates/slides/actions/index-design-system-with-builder.ts +8 -0
  252. package/corpus/templates/slides/actions/patch-deck.ts +48 -16
  253. package/corpus/templates/slides/actions/set-default-design-system.ts +49 -19
  254. package/corpus/templates/slides/actions/update-slide.ts +13 -3
  255. package/corpus/templates/slides/actions/view-screen.ts +87 -10
  256. package/corpus/templates/slides/app/components/deck/SlideRenderer.tsx +155 -28
  257. package/corpus/templates/slides/app/components/design-system/DesignSystemCard.tsx +21 -17
  258. package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +849 -341
  259. package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +102 -2
  260. package/corpus/templates/slides/app/components/editor/PromptDialog.tsx +13 -16
  261. package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +60 -12
  262. package/corpus/templates/slides/app/components/editor/SlideOverflowWarning.tsx +11 -1
  263. package/corpus/templates/slides/app/components/layout/Sidebar.tsx +66 -19
  264. package/corpus/templates/slides/app/i18n/en-US.ts +23 -0
  265. package/corpus/templates/slides/app/lib/normalize-slide-padding.ts +8 -15
  266. package/corpus/templates/slides/app/pages/DeckEditor.tsx +4 -3
  267. package/corpus/templates/slides/app/pages/DesignSystems.tsx +4 -3
  268. package/corpus/templates/slides/app/pages/Index.tsx +1 -1
  269. package/corpus/templates/slides/changelog/2026-07-31-design-system-details-now-show-their-source-and-indexing-sta.md +6 -0
  270. package/corpus/templates/slides/changelog/2026-07-31-design-system-indexing-keeps-your-chosen-name-when-you-uploa.md +6 -0
  271. package/corpus/templates/slides/changelog/2026-07-31-design-system-setup-keeps-focus-rings-visible-and-uses-a-sim.md +6 -0
  272. package/corpus/templates/slides/changelog/2026-07-31-skip-prompt-is-now-available-in-the-new-deck-prompt-header.md +6 -0
  273. package/corpus/templates/slides/changelog/2026-07-31-slides-now-detect-real-text-and-box-overflow-across-the-deck.md +6 -0
  274. package/corpus/templates/slides/changelog/2026-07-31-the-agent-native-logo-stays-visible-when-the-sidebar-is-coll.md +6 -0
  275. package/corpus/templates/slides/server/handlers/design-systems.ts +1 -0
  276. package/corpus/templates/slides/server/handlers/index-design-system-sources.ts +1 -0
  277. package/corpus/templates/slides/server/lib/builder-design-system-proxy.ts +23 -4
  278. package/corpus/templates/slides/server/plugins/agent-chat.ts +5 -0
  279. package/corpus/templates/slides/server/plugins/creative-context.ts +16 -3
  280. package/corpus/templates/slides/server/workspace-defaults.ts +5 -1
  281. package/corpus/templates/slides/shared/slide-fit.ts +26 -0
  282. package/corpus/templates/tasks/app/components/layout/Sidebar.tsx +30 -3
  283. package/corpus/templates/tasks/changelog/2026-07-31-clicking-the-agent-native-logo-now-toggles-the-app-sidebar.md +6 -0
  284. package/dist/a2a/correlation.d.ts +4 -1
  285. package/dist/a2a/correlation.d.ts.map +1 -1
  286. package/dist/a2a/correlation.js +8 -1
  287. package/dist/a2a/correlation.js.map +1 -1
  288. package/dist/a2a/types.d.ts +11 -3
  289. package/dist/a2a/types.d.ts.map +1 -1
  290. package/dist/a2a/types.js.map +1 -1
  291. package/dist/agent/engine/ai-sdk-engine.d.ts.map +1 -1
  292. package/dist/agent/engine/ai-sdk-engine.js +27 -41
  293. package/dist/agent/engine/ai-sdk-engine.js.map +1 -1
  294. package/dist/agent/engine/builder-engine.d.ts.map +1 -1
  295. package/dist/agent/engine/builder-engine.js +18 -8
  296. package/dist/agent/engine/builder-engine.js.map +1 -1
  297. package/dist/agent/engine/error-detail.d.ts +61 -0
  298. package/dist/agent/engine/error-detail.d.ts.map +1 -1
  299. package/dist/agent/engine/error-detail.js +145 -3
  300. package/dist/agent/engine/error-detail.js.map +1 -1
  301. package/dist/agent/engine/failure-taxonomy.d.ts +24 -0
  302. package/dist/agent/engine/failure-taxonomy.d.ts.map +1 -0
  303. package/dist/agent/engine/failure-taxonomy.js +88 -0
  304. package/dist/agent/engine/failure-taxonomy.js.map +1 -0
  305. package/dist/agent/engine/index.d.ts +2 -1
  306. package/dist/agent/engine/index.d.ts.map +1 -1
  307. package/dist/agent/engine/index.js +2 -1
  308. package/dist/agent/engine/index.js.map +1 -1
  309. package/dist/agent/engine/registry.d.ts +16 -0
  310. package/dist/agent/engine/registry.d.ts.map +1 -1
  311. package/dist/agent/engine/registry.js +71 -6
  312. package/dist/agent/engine/registry.js.map +1 -1
  313. package/dist/agent/engine/translate-ai-sdk.d.ts.map +1 -1
  314. package/dist/agent/engine/translate-ai-sdk.js +14 -2
  315. package/dist/agent/engine/translate-ai-sdk.js.map +1 -1
  316. package/dist/agent/production-agent.d.ts.map +1 -1
  317. package/dist/agent/production-agent.js +13 -24
  318. package/dist/agent/production-agent.js.map +1 -1
  319. package/dist/agent/run-loop-with-resume.js +1 -1
  320. package/dist/agent/run-loop-with-resume.js.map +1 -1
  321. package/dist/agent/run-manager.d.ts.map +1 -1
  322. package/dist/agent/run-manager.js +39 -10
  323. package/dist/agent/run-manager.js.map +1 -1
  324. package/dist/agent/run-store.d.ts +10 -0
  325. package/dist/agent/run-store.d.ts.map +1 -1
  326. package/dist/agent/run-store.js +20 -3
  327. package/dist/agent/run-store.js.map +1 -1
  328. package/dist/agent/thread-data-builder.d.ts.map +1 -1
  329. package/dist/agent/thread-data-builder.js +28 -4
  330. package/dist/agent/thread-data-builder.js.map +1 -1
  331. package/dist/chat-threads/store.d.ts +13 -0
  332. package/dist/chat-threads/store.d.ts.map +1 -1
  333. package/dist/chat-threads/store.js +35 -0
  334. package/dist/chat-threads/store.js.map +1 -1
  335. package/dist/cli/templates-meta.d.ts.map +1 -1
  336. package/dist/cli/templates-meta.js +13 -0
  337. package/dist/cli/templates-meta.js.map +1 -1
  338. package/dist/cli/workspace-dev.d.ts.map +1 -1
  339. package/dist/cli/workspace-dev.js +1 -0
  340. package/dist/cli/workspace-dev.js.map +1 -1
  341. package/dist/client/error-format.d.ts.map +1 -1
  342. package/dist/client/error-format.js +10 -0
  343. package/dist/client/error-format.js.map +1 -1
  344. package/dist/client/use-chat-threads.d.ts.map +1 -1
  345. package/dist/client/use-chat-threads.js +66 -16
  346. package/dist/client/use-chat-threads.js.map +1 -1
  347. package/dist/collab/awareness.d.ts +2 -2
  348. package/dist/collab/awareness.d.ts.map +1 -1
  349. package/dist/collab/struct-routes.d.ts +1 -1
  350. package/dist/credentials/index.d.ts +9 -2
  351. package/dist/credentials/index.d.ts.map +1 -1
  352. package/dist/credentials/index.js +50 -8
  353. package/dist/credentials/index.js.map +1 -1
  354. package/dist/extensions/url-safety.d.ts.map +1 -1
  355. package/dist/extensions/url-safety.js +38 -12
  356. package/dist/extensions/url-safety.js.map +1 -1
  357. package/dist/integrations/adapters/slack.d.ts.map +1 -1
  358. package/dist/integrations/adapters/slack.js +25 -8
  359. package/dist/integrations/adapters/slack.js.map +1 -1
  360. package/dist/integrations/google-docs-poller.d.ts.map +1 -1
  361. package/dist/integrations/google-docs-poller.js +13 -1
  362. package/dist/integrations/google-docs-poller.js.map +1 -1
  363. package/dist/integrations/installations-store.d.ts +10 -0
  364. package/dist/integrations/installations-store.d.ts.map +1 -1
  365. package/dist/integrations/installations-store.js +24 -0
  366. package/dist/integrations/installations-store.js.map +1 -1
  367. package/dist/integrations/plugin.d.ts.map +1 -1
  368. package/dist/integrations/plugin.js +6 -5
  369. package/dist/integrations/plugin.js.map +1 -1
  370. package/dist/integrations/types.d.ts +7 -0
  371. package/dist/integrations/types.d.ts.map +1 -1
  372. package/dist/integrations/types.js.map +1 -1
  373. package/dist/integrations/webhook-handler.d.ts.map +1 -1
  374. package/dist/integrations/webhook-handler.js +16 -1
  375. package/dist/integrations/webhook-handler.js.map +1 -1
  376. package/dist/jobs/background-automation-runner.d.ts.map +1 -1
  377. package/dist/jobs/background-automation-runner.js +35 -2
  378. package/dist/jobs/background-automation-runner.js.map +1 -1
  379. package/dist/notifications/routes.d.ts +6 -6
  380. package/dist/observability/routes.d.ts +3 -3
  381. package/dist/provider-api/actions/custom-provider-registration.d.ts +14 -14
  382. package/dist/provider-api/actions/provider-api.d.ts +8 -8
  383. package/dist/provider-api/index.js +7 -3
  384. package/dist/provider-api/index.js.map +1 -1
  385. package/dist/scripts/call-agent.d.ts.map +1 -1
  386. package/dist/scripts/call-agent.js +6 -1
  387. package/dist/scripts/call-agent.js.map +1 -1
  388. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  389. package/dist/server/agent-chat-plugin.js +38 -9
  390. package/dist/server/agent-chat-plugin.js.map +1 -1
  391. package/dist/server/agent-discovery.d.ts +2 -0
  392. package/dist/server/agent-discovery.d.ts.map +1 -1
  393. package/dist/server/agent-discovery.js.map +1 -1
  394. package/dist/server/builder-design-systems.d.ts +4 -1
  395. package/dist/server/builder-design-systems.d.ts.map +1 -1
  396. package/dist/server/builder-design-systems.js +11 -1
  397. package/dist/server/builder-design-systems.js.map +1 -1
  398. package/dist/server/credential-provider.d.ts.map +1 -1
  399. package/dist/server/credential-provider.js +49 -12
  400. package/dist/server/credential-provider.js.map +1 -1
  401. package/dist/server/index.d.ts +1 -1
  402. package/dist/server/index.d.ts.map +1 -1
  403. package/dist/server/index.js.map +1 -1
  404. package/dist/server/onboarding-html.d.ts.map +1 -1
  405. package/dist/server/onboarding-html.js +37 -2
  406. package/dist/server/onboarding-html.js.map +1 -1
  407. package/dist/server/transcribe-voice.d.ts +1 -1
  408. package/dist/shared/reasoning-effort.d.ts +1 -0
  409. package/dist/shared/reasoning-effort.d.ts.map +1 -1
  410. package/dist/shared/reasoning-effort.js +1 -1
  411. package/dist/shared/reasoning-effort.js.map +1 -1
  412. package/dist/templates/chat/app/components/layout/Sidebar.tsx +30 -3
  413. package/dist/templates/chat/changelog/2026-07-31-clicking-the-agent-native-logo-now-toggles-the-app-sidebar.md +6 -0
  414. package/dist/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +11 -0
  415. package/package.json +1 -1
  416. package/src/a2a/correlation.ts +11 -1
  417. package/src/a2a/types.ts +11 -3
  418. package/src/agent/engine/ai-sdk-engine.ts +33 -46
  419. package/src/agent/engine/builder-engine.ts +22 -10
  420. package/src/agent/engine/error-detail.ts +184 -3
  421. package/src/agent/engine/failure-taxonomy.ts +123 -0
  422. package/src/agent/engine/index.ts +8 -0
  423. package/src/agent/engine/registry.ts +92 -8
  424. package/src/agent/engine/translate-ai-sdk.ts +17 -2
  425. package/src/agent/production-agent.ts +13 -33
  426. package/src/agent/run-loop-with-resume.ts +1 -1
  427. package/src/agent/run-manager.ts +43 -14
  428. package/src/agent/run-store.ts +30 -3
  429. package/src/agent/thread-data-builder.ts +36 -4
  430. package/src/chat-threads/store.ts +42 -0
  431. package/src/cli/templates-meta.ts +13 -0
  432. package/src/cli/workspace-dev.ts +1 -0
  433. package/src/client/error-format.ts +12 -0
  434. package/src/client/use-chat-threads.ts +76 -16
  435. package/src/credentials/index.ts +51 -12
  436. package/src/extensions/url-safety.ts +46 -12
  437. package/src/integrations/adapters/slack.ts +32 -10
  438. package/src/integrations/google-docs-poller.ts +12 -1
  439. package/src/integrations/installations-store.ts +30 -0
  440. package/src/integrations/plugin.ts +5 -5
  441. package/src/integrations/types.ts +7 -0
  442. package/src/integrations/webhook-handler.ts +24 -1
  443. package/src/jobs/background-automation-runner.ts +38 -1
  444. package/src/provider-api/index.ts +8 -2
  445. package/src/scripts/call-agent.ts +6 -0
  446. package/src/server/agent-chat-plugin.ts +46 -10
  447. package/src/server/agent-discovery.ts +2 -0
  448. package/src/server/builder-design-systems.ts +21 -0
  449. package/src/server/credential-provider.ts +51 -12
  450. package/src/server/index.ts +1 -0
  451. package/src/server/onboarding-html.ts +37 -2
  452. package/src/shared/reasoning-effort.ts +1 -1
  453. package/src/templates/chat/app/components/layout/Sidebar.tsx +30 -3
  454. package/src/templates/chat/changelog/2026-07-31-clicking-the-agent-native-logo-now-toggles-the-app-sidebar.md +6 -0
  455. package/src/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +11 -0
  456. package/corpus/templates/clips/desktop/src/lib/media-device-selection.ts +0 -157
@@ -1,24 +1,50 @@
1
1
  import { defineAction } from "@agent-native/core";
2
- import { getRequestUserEmail } from "@agent-native/core/server/request-context";
2
+ import {
3
+ getRequestOrgId,
4
+ getRequestUserEmail,
5
+ } from "@agent-native/core/server/request-context";
3
6
  import { assertAccess } from "@agent-native/core/sharing";
4
- import { and, eq } from "drizzle-orm";
7
+ import { and, eq, isNull } from "drizzle-orm";
5
8
  import { z } from "zod";
6
9
 
7
10
  import { getDb, schema } from "../server/db/index.js";
8
11
 
9
12
  export default defineAction({
10
13
  description:
11
- "Set a design system as the default. Unsets any previously-default design system for this user.",
14
+ "Set or unset a design system as the default for the current user and organization.",
12
15
  schema: z.object({
13
16
  id: z.string().describe("Design system ID to set as default"),
17
+ isDefault: z
18
+ .boolean()
19
+ .optional()
20
+ .default(true)
21
+ .describe("Whether this design system should be the default"),
14
22
  }),
15
- run: async ({ id }) => {
23
+ run: async ({ id, isDefault = true }) => {
16
24
  await assertAccess("design-system", id, "editor");
17
25
 
18
26
  const db = getDb();
19
27
  const now = new Date().toISOString();
20
28
 
21
29
  const userEmail = getRequestUserEmail();
30
+ if (!userEmail) throw new Error("no authenticated user");
31
+ const orgId = getRequestOrgId();
32
+
33
+ const [target] = await db
34
+ .select({
35
+ ownerEmail: schema.designSystems.ownerEmail,
36
+ orgId: schema.designSystems.orgId,
37
+ })
38
+ .from(schema.designSystems)
39
+ .where(eq(schema.designSystems.id, id))
40
+ .limit(1);
41
+
42
+ if (
43
+ target?.ownerEmail !== userEmail ||
44
+ (target.orgId ?? null) !== (orgId ?? null)
45
+ ) {
46
+ throw new Error("Only the owner can set a design system as default");
47
+ }
22
48
 
23
49
  // Use a transaction to atomically unset all defaults then set the new one.
24
50
  // Without a transaction, concurrent set-default requests can interleave and
@@ -26,25 +52,29 @@ export default defineAction({
26
52
  // Only unset/set design systems owned by this user — isDefault is a per-owner
27
53
  // flag and must not bleed across users when operating on shared resources.
28
54
  await db.transaction(async (tx) => {
29
- await tx
30
- .update(schema.designSystems)
31
- .set({ isDefault: false, updatedAt: now })
32
- .where(eq(schema.designSystems.ownerEmail, userEmail ?? ""));
55
+ const targetScope = orgId
56
+ ? and(
57
+ eq(schema.designSystems.ownerEmail, userEmail),
58
+ eq(schema.designSystems.orgId, orgId),
59
+ )
60
+ : and(
61
+ eq(schema.designSystems.ownerEmail, userEmail),
62
+ isNull(schema.designSystems.orgId),
63
+ );
64
+
65
+ if (isDefault) {
66
+ await tx
67
+ .update(schema.designSystems)
68
+ .set({ isDefault: false, updatedAt: now })
69
+ .where(targetScope);
70
+ }
33
71
 
34
- // Only set isDefault on the target if the caller owns it; shared design
35
- // systems should not have their global isDefault flag flipped by someone
36
- // who merely has editor access — that would pollute other owners' defaults.
37
72
  await tx
38
73
  .update(schema.designSystems)
39
- .set({ isDefault: true, updatedAt: now })
40
- .where(
41
- and(
42
- eq(schema.designSystems.id, id),
43
- eq(schema.designSystems.ownerEmail, userEmail ?? ""),
44
- ),
45
- );
74
+ .set({ isDefault, updatedAt: now })
75
+ .where(and(eq(schema.designSystems.id, id), targetScope));
46
76
  });
47
77
 
48
- return { id, isDefault: true };
78
+ return { id, isDefault };
49
79
  },
50
80
  });
@@ -16,6 +16,7 @@ import { normalizeSlidePadding } from "../app/lib/normalize-slide-padding.js";
16
16
  import { getDb, schema } from "../server/db/index.js"; // ensure registerShareableResource runs
17
17
  import { notifyClients } from "../server/handlers/decks.js";
18
18
  import { createDeckVersionSnapshot } from "../server/lib/deck-versions.js";
19
+ import { hashSlideContent } from "../shared/slide-fit.js";
19
20
  import { slideLabelFor, touchAgentSlidePresence } from "./_agent-presence.js";
20
21
  import {
21
22
  awaitLayoutFitCheck,
@@ -137,8 +138,6 @@ export default defineAction({
137
138
  if (!find && !fullContent) {
138
139
  throw new Error("Either --find or --fullContent is required");
139
140
  }
140
- const fitSince = Date.now();
141
-
142
141
  await assertAccess("deck", deckId, "editor");
143
142
 
144
143
  // ─── Read-modify-write under the shared per-deck lock ───────────────────
@@ -344,6 +343,9 @@ export default defineAction({
344
343
  }
345
344
 
346
345
  const { applied } = rmw;
346
+ // Start the freshness window after the SQL write and before notifying the
347
+ // editor. This keeps a fast render from being rejected as stale.
348
+ const fitSince = Date.now();
347
349
 
348
350
  // Best-effort presence: light the agent up on this slide in open editors
349
351
  // and drop a lingering "AI edited" highlight. Never blocks or fails the
@@ -368,7 +370,12 @@ export default defineAction({
368
370
  // Wait briefly for the editor to re-render and measure. If the patched
369
371
  // slide still overflows, surface the new measurement so the agent can
370
372
  // tighten further. Timeout = no editor open / nothing to measure.
371
- const fit = await awaitLayoutFitCheck(slideId, fitSince, 4000);
373
+ const fit = await awaitLayoutFitCheck(
374
+ slideId,
375
+ fitSince,
376
+ 4000,
377
+ hashSlideContent(rmw.slide?.content ?? ""),
378
+ );
372
379
 
373
380
  const base = {
374
381
  ok: true,
@@ -390,7 +397,10 @@ export default defineAction({
390
397
  ...base,
391
398
  layoutOverflow: {
392
399
  verticalOverflow: fit.measurement.verticalOverflow,
400
+ horizontalOverflow: fit.measurement.horizontalOverflow ?? 0,
401
+ contentWidth: fit.measurement.contentWidth,
393
402
  contentHeight: fit.measurement.contentHeight,
403
+ viewportWidth: fit.measurement.viewportWidth,
394
404
  viewportHeight: fit.measurement.viewportHeight,
395
405
  },
396
406
  message: formatOverflowForTool(deckId, fit.measurement),
@@ -8,6 +8,7 @@ import { and, desc, eq } from "drizzle-orm";
8
8
  import { z } from "zod";
9
9
 
10
10
  import { getDb, schema } from "../server/db/index.js";
11
+ import { hashSlideContent, type DeckFitState } from "../shared/slide-fit.js";
11
12
  import { readAppStateForCurrentTab } from "./_tab-state.js";
12
13
 
13
14
  export default defineAction({
@@ -191,29 +192,42 @@ export default defineAction({
191
192
 
192
193
  // ─── Layout-fit measurement ──────────────────────────────────────────
193
194
  // The editor measures the rendered slide and reports vertical overflow
194
- // here whenever the natural content height exceeds the canvas content
195
- // area. If this block is present, the current slide's HTML is too tall
196
- // and needs to be rewritten to fit the canvas.
195
+ // here whenever the natural content bounds exceed the canvas content
196
+ // area. If this block is present, the current slide's HTML needs to be
197
+ // rewritten to fit the canvas.
197
198
  const overflow = (await readAppStateForCurrentTab("slide-fit-check")) as {
198
199
  slideId?: string;
200
+ contentHash?: string;
199
201
  verticalOverflow?: number;
202
+ horizontalOverflow?: number;
200
203
  contentHeight?: number;
204
+ contentWidth?: number;
201
205
  viewportHeight?: number;
206
+ viewportWidth?: number;
202
207
  } | null;
208
+ const verticalOverflow = overflow?.verticalOverflow ?? 0;
209
+ const horizontalOverflow = overflow?.horizontalOverflow ?? 0;
203
210
  if (
204
211
  overflow &&
205
- typeof overflow.verticalOverflow === "number" &&
206
- overflow.verticalOverflow > 0 &&
212
+ typeof overflow.contentHash === "string" &&
213
+ currentSlide?.content &&
214
+ overflow.contentHash === hashSlideContent(currentSlide.content) &&
215
+ Number.isFinite(overflow.verticalOverflow) &&
216
+ (overflow.horizontalOverflow === undefined ||
217
+ Number.isFinite(overflow.horizontalOverflow)) &&
218
+ Number.isFinite(overflow.contentHeight) &&
219
+ Number.isFinite(overflow.viewportHeight) &&
220
+ (verticalOverflow > 0 || horizontalOverflow > 0) &&
207
221
  overflow.slideId === currentSlide?.id
208
222
  ) {
209
223
  lines.push(``);
210
- lines.push(`### ⚠ Layout overflows the canvas vertically`);
224
+ lines.push(`### ⚠ Layout overflows the canvas`);
211
225
  lines.push(
212
- `This slide's natural rendered height is ${overflow.contentHeight}px, ` +
213
- `but the canvas content area is only ${overflow.viewportHeight}px tall ` +
214
- `(overflow: ${overflow.verticalOverflow}px). The renderer no longer ` +
226
+ `This slide's natural rendered content is ${overflow.contentWidth ?? "unknown"}x${overflow.contentHeight}px, ` +
227
+ `but the canvas content area is ${overflow.viewportWidth ?? "unknown"}x${overflow.viewportHeight}px ` +
228
+ `(overflow: ${verticalOverflow}px vertical, ${horizontalOverflow}px horizontal). The renderer no longer ` +
215
229
  `auto-shrinks overflowing slides — you must rewrite the slide HTML so ` +
216
- `the rendered height is at most ${overflow.viewportHeight}px. Options, ` +
230
+ `the rendered content fits the measured content area. Options, ` +
217
231
  `in order of preference: (1) tighten copy — shorter headings/bullets, ` +
218
232
  `drop low-value lines; (2) reduce vertical density — fewer stacked ` +
219
233
  `cards, smaller gaps, slightly smaller body font (not below 16px); ` +
@@ -224,6 +238,69 @@ export default defineAction({
224
238
  );
225
239
  }
226
240
 
241
+ const deckFit = (await readAppStateForCurrentTab(
242
+ "deck-fit-checks",
243
+ )) as DeckFitState | null;
244
+ if (
245
+ deckFit?.deckId === rows[0].id &&
246
+ deckFit.aspectRatio === (deck.aspectRatio ?? "16:9") &&
247
+ deckFit.slides
248
+ ) {
249
+ type DeckFitSummary =
250
+ | { kind: "unknown"; index: number }
251
+ | {
252
+ kind: "overflow";
253
+ index: number;
254
+ measurement: (typeof deckFit.slides)[string];
255
+ };
256
+ const measured: DeckFitSummary[] = slides.flatMap(
257
+ (slide, index): DeckFitSummary[] => {
258
+ const measurement = deckFit.slides[slide.id];
259
+ if (
260
+ !measurement ||
261
+ measurement.contentHash !==
262
+ hashSlideContent(slide.content ?? "") ||
263
+ !Number.isFinite(measurement.verticalOverflow) ||
264
+ !Number.isFinite(measurement.horizontalOverflow) ||
265
+ !Number.isFinite(measurement.contentHeight) ||
266
+ !Number.isFinite(measurement.contentWidth) ||
267
+ !Number.isFinite(measurement.viewportHeight) ||
268
+ !Number.isFinite(measurement.viewportWidth) ||
269
+ !Number.isFinite(measurement.measuredAt)
270
+ ) {
271
+ return [{ kind: "unknown" as const, index }];
272
+ }
273
+ return measurement.verticalOverflow > 0 ||
274
+ measurement.horizontalOverflow > 0
275
+ ? [{ kind: "overflow" as const, index, measurement }]
276
+ : [];
277
+ },
278
+ );
279
+ const unknown = measured.filter((item) => item.kind === "unknown");
280
+ const overflows = measured.filter((item) => item.kind === "overflow");
281
+ lines.push(``);
282
+ lines.push(`### Deck-wide layout fit`);
283
+ if (unknown.length > 0) {
284
+ lines.push(
285
+ `Measured ${slides.length - unknown.length} of ${slides.length} slides; ` +
286
+ `the remaining slides need a fresh browser measurement before claiming the deck fits.`,
287
+ );
288
+ } else if (overflows.length > 0) {
289
+ lines.push(
290
+ `Overflow detected on ${overflows.length} slide(s): ${overflows
291
+ .map((item) => {
292
+ if (item.kind !== "overflow") return "";
293
+ return `slide ${item.index + 1} (${item.measurement.verticalOverflow}px vertical, ${item.measurement.horizontalOverflow}px horizontal)`;
294
+ })
295
+ .join(", ")}.`,
296
+ );
297
+ } else {
298
+ lines.push(
299
+ `All ${slides.length} slides fit their measured content area.`,
300
+ );
301
+ }
302
+ }
303
+
227
304
  return lines.join("\n");
228
305
  }
229
306
 
@@ -129,6 +129,8 @@ const markdownComponents = {
129
129
  };
130
130
 
131
131
  const MIN_AUTOFIT_SCALE = 0.65;
132
+ const VERTICAL_OVERFLOW_TOLERANCE_PX = 8;
133
+ const HORIZONTAL_OVERFLOW_TOLERANCE_PX = 8;
132
134
 
133
135
  const useIsomorphicLayoutEffect =
134
136
  typeof window === "undefined" ? useEffect : useLayoutEffect;
@@ -142,6 +144,8 @@ export interface SlideFitTransform {
142
144
  * rewrite the slide HTML to fit, instead of being papered over with a uniform
143
145
  * shrink that leaves ugly right/bottom margins. */
144
146
  verticalOverflow: number;
147
+ /** Horizontal overflow in CSS px (0 if content fits). */
148
+ horizontalOverflow: number;
145
149
  }
146
150
 
147
151
  export function computeSlideFitTransform({
@@ -149,6 +153,7 @@ export function computeSlideFitTransform({
149
153
  contentHeight,
150
154
  viewportWidth,
151
155
  viewportHeight,
156
+ measuredHorizontalOverflow = 0,
152
157
  minX = 0,
153
158
  minY = 0,
154
159
  minScale = MIN_AUTOFIT_SCALE,
@@ -160,6 +165,7 @@ export function computeSlideFitTransform({
160
165
  minX?: number;
161
166
  minY?: number;
162
167
  minScale?: number;
168
+ measuredHorizontalOverflow?: number;
163
169
  }): SlideFitTransform {
164
170
  // Only scale for horizontal overflow. For vertical overflow we surface a
165
171
  // `verticalOverflow` measurement so the agent can rewrite the slide HTML —
@@ -167,13 +173,33 @@ export function computeSlideFitTransform({
167
173
  // unbalanced right/bottom margins (with origin top-left), which looks worse
168
174
  // than asking the LLM to redo the layout to fit the canvas properly.
169
175
  const safeContentWidth = Math.max(1, contentWidth);
170
- const rawScale = Math.min(1, Math.max(1, viewportWidth) / safeContentWidth);
171
- const scale = Math.max(minScale, rawScale);
172
-
173
- const verticalOverflow = Math.max(
176
+ const rawHorizontalOverflow = Math.max(
177
+ measuredHorizontalOverflow,
178
+ contentWidth - viewportWidth,
174
179
  0,
175
- Math.round(contentHeight - viewportHeight),
176
180
  );
181
+ // Do not visually zoom for the same small wrapper spill that the warning
182
+ // intentionally ignores. Positioned objects also report independently, so
183
+ // their overflow never becomes an accidental scale-to-fit transform.
184
+ const widthToFit =
185
+ rawHorizontalOverflow > HORIZONTAL_OVERFLOW_TOLERANCE_PX
186
+ ? safeContentWidth
187
+ : Math.max(1, viewportWidth);
188
+ const rawScale = Math.min(1, Math.max(1, viewportWidth) / widthToFit);
189
+ const scale = Math.max(minScale, rawScale);
190
+
191
+ const rawVerticalOverflow = Math.max(0, contentHeight - viewportHeight);
192
+ // Small differences are commonly caused by line-box rounding and layout
193
+ // wrappers. Do not turn that harmless spill into an agent repair request;
194
+ // significant overflow is still reported at its measured size.
195
+ const verticalOverflow =
196
+ rawVerticalOverflow > VERTICAL_OVERFLOW_TOLERANCE_PX
197
+ ? Math.round(rawVerticalOverflow)
198
+ : 0;
199
+ const horizontalOverflow =
200
+ rawHorizontalOverflow > HORIZONTAL_OVERFLOW_TOLERANCE_PX
201
+ ? Math.round(rawHorizontalOverflow)
202
+ : 0;
177
203
 
178
204
  return {
179
205
  scale,
@@ -181,6 +207,7 @@ export function computeSlideFitTransform({
181
207
  y: minY < 0 ? -minY * scale : 0,
182
208
  fitted: rawScale < 0.999,
183
209
  verticalOverflow,
210
+ horizontalOverflow,
184
211
  };
185
212
  }
186
213
 
@@ -220,6 +247,7 @@ function ensureRawHtmlFitLayers(root: HTMLElement): HTMLElement[] {
220
247
  function measureContentBounds(target: HTMLElement): {
221
248
  contentWidth: number;
222
249
  contentHeight: number;
250
+ horizontalOverflow: number;
223
251
  minX: number;
224
252
  minY: number;
225
253
  } {
@@ -244,18 +272,14 @@ function measureContentBounds(target: HTMLElement): {
244
272
  }
245
273
  return false;
246
274
  };
247
- const hasFreeformContent = descendants.some(isFreeformElement);
248
-
249
275
  const targetRect = target.getBoundingClientRect();
250
276
  // `scrollWidth` / `clientWidth` return CSS pixels; `getBoundingClientRect`
251
277
  // returns layout pixels after every ancestor transform. In presentation
252
278
  // mode the outer canvas is scaled UP (--slide-scale > 1, e.g. 1.74), so
253
- // child rects come back inflated relative to scrollWidth. Without
254
- // normalization, `Math.max(scrollWidth, maxX - minX)` reads the inflated
255
- // value as content overflow, computeSlideFitTransform clamps to
256
- // MIN_AUTOFIT_SCALE (0.65), and every slide visibly shrinks. The editor
257
- // didn't hit this because thumbnail mode scales DOWN, so scrollWidth
258
- // always wins. Normalize child rects back to CSS-px space.
279
+ // child rects come back inflated relative to their CSS dimensions. Without
280
+ // normalization, the bounds read as content overflow, so every slide can
281
+ // visibly shrink in presentation mode. Normalize child rects back to
282
+ // CSS-px space.
259
283
  const cssWidth = target.clientWidth || target.scrollWidth || 0;
260
284
  const cssHeight = target.clientHeight || target.scrollHeight || 0;
261
285
  const invScaleX =
@@ -266,15 +290,18 @@ function measureContentBounds(target: HTMLElement): {
266
290
  let minX = 0;
267
291
  let minY = 0;
268
292
  // Absolutely positioned objects intentionally move independently of the
269
- // flow layout. They still expand scrollWidth/scrollHeight, but fitting the
270
- // entire layer around them creates a feedback loop where dragging one object
271
- // scales and shifts every sibling. When a layer contains freeform content,
272
- // derive overflow from normal-flow element bounds instead.
273
- let maxX = hasFreeformContent ? target.clientWidth : target.scrollWidth;
274
- let maxY = hasFreeformContent ? target.clientHeight : target.scrollHeight;
293
+ // flow layout. Include them in vertical diagnostics so text boxes cannot
294
+ // silently run off the canvas, but keep them out of the horizontal fit
295
+ // transform. Using scrollHeight as the baseline makes full-size wrappers
296
+ // look like overflowing content even when their visible children fit.
297
+ let flowMaxX = target.clientWidth;
298
+ let flowMaxY = target.clientHeight;
299
+ let contentMaxY = target.clientHeight;
300
+ let contentMinX = 0;
301
+ let contentMaxX = target.clientWidth;
302
+ let hasFlowContent = false;
275
303
 
276
304
  for (const el of descendants) {
277
- if (isFreeformElement(el)) continue;
278
305
  const rect = el.getBoundingClientRect();
279
306
  if (rect.width === 0 && rect.height === 0) continue;
280
307
 
@@ -283,15 +310,39 @@ function measureContentBounds(target: HTMLElement): {
283
310
  const right = (rect.right - targetRect.left) * invScaleX;
284
311
  const bottom = (rect.bottom - targetRect.top) * invScaleY;
285
312
 
313
+ contentMinX = Math.min(contentMinX, left);
314
+ contentMaxX = Math.max(contentMaxX, right);
315
+
316
+ if (isFreeformElement(el)) {
317
+ contentMaxY = Math.max(contentMaxY, bottom);
318
+ continue;
319
+ }
320
+
321
+ hasFlowContent = true;
286
322
  minX = Math.min(minX, left);
287
323
  minY = Math.min(minY, top);
288
- maxX = Math.max(maxX, right);
289
- maxY = Math.max(maxY, bottom);
324
+ flowMaxX = Math.max(flowMaxX, right);
325
+ flowMaxY = Math.max(flowMaxY, bottom);
326
+ contentMaxY = Math.max(contentMaxY, bottom);
327
+ }
328
+
329
+ // Raw text can be a direct child with no measurable element descendant.
330
+ // Only use scroll dimensions in that case; using them alongside normal
331
+ // descendants would count full-size wrappers as content and recreate the
332
+ // false positive.
333
+ if (!hasFlowContent && descendants.length === 0) {
334
+ contentMaxY = Math.max(contentMaxY, target.scrollHeight);
335
+ contentMaxX = Math.max(contentMaxX, target.scrollWidth);
290
336
  }
291
337
 
292
338
  return {
293
- contentWidth: Math.max(target.clientWidth, maxX - minX),
294
- contentHeight: Math.max(target.clientHeight, maxY - minY),
339
+ contentWidth: Math.max(target.clientWidth, flowMaxX - minX),
340
+ contentHeight: Math.max(target.clientHeight, flowMaxY - minY, contentMaxY),
341
+ horizontalOverflow: Math.max(
342
+ 0,
343
+ -contentMinX,
344
+ contentMaxX - target.clientWidth,
345
+ ),
295
346
  minX,
296
347
  minY,
297
348
  };
@@ -303,10 +354,16 @@ function measureContentBounds(target: HTMLElement): {
303
354
  export interface SlideOverflowInfo {
304
355
  /** Vertical overflow in CSS px at native resolution (0 = fits). */
305
356
  verticalOverflow: number;
357
+ /** Horizontal overflow in CSS px at native resolution (0 = fits). */
358
+ horizontalOverflow: number;
306
359
  /** Total natural content height in CSS px. */
307
360
  contentHeight: number;
361
+ /** Total natural content width in CSS px. */
362
+ contentWidth: number;
308
363
  /** Available canvas height inside the slide padding. */
309
364
  viewportHeight: number;
365
+ /** Available canvas width inside the slide padding. */
366
+ viewportWidth: number;
310
367
  }
311
368
 
312
369
  function useSlideAutofit(
@@ -347,6 +404,7 @@ function useSlideAutofit(
347
404
  : [root].filter((target) => target.scrollHeight > 0);
348
405
 
349
406
  let worstOverflow = 0;
407
+ let worstHorizontalOverflow = 0;
350
408
  let worstInfo: SlideOverflowInfo | null = null;
351
409
 
352
410
  for (const target of targets) {
@@ -365,6 +423,7 @@ function useSlideAutofit(
365
423
  const viewportHeight = target.clientHeight || canvasHeight;
366
424
  const transform = computeSlideFitTransform({
367
425
  ...bounds,
426
+ measuredHorizontalOverflow: bounds.horizontalOverflow,
368
427
  viewportWidth,
369
428
  viewportHeight,
370
429
  });
@@ -378,10 +437,22 @@ function useSlideAutofit(
378
437
 
379
438
  if (transform.verticalOverflow > worstOverflow) {
380
439
  worstOverflow = transform.verticalOverflow;
440
+ }
441
+ worstHorizontalOverflow = Math.max(
442
+ worstHorizontalOverflow,
443
+ transform.horizontalOverflow,
444
+ );
445
+ if (
446
+ transform.verticalOverflow > 0 ||
447
+ transform.horizontalOverflow > 0
448
+ ) {
381
449
  worstInfo = {
382
- verticalOverflow: transform.verticalOverflow,
450
+ verticalOverflow: worstOverflow,
451
+ horizontalOverflow: worstHorizontalOverflow,
383
452
  contentHeight: Math.round(bounds.contentHeight),
453
+ contentWidth: Math.round(bounds.contentWidth),
384
454
  viewportHeight: Math.round(viewportHeight),
455
+ viewportWidth: Math.round(viewportWidth),
385
456
  };
386
457
  }
387
458
  }
@@ -398,8 +469,11 @@ function useSlideAutofit(
398
469
  overflowCallbackRef.current?.(
399
470
  worstInfo ?? {
400
471
  verticalOverflow: 0,
472
+ horizontalOverflow: 0,
401
473
  contentHeight: 0,
474
+ contentWidth: 0,
402
475
  viewportHeight: 0,
476
+ viewportWidth: 0,
403
477
  },
404
478
  );
405
479
  autofitSettledRef.current?.();
@@ -615,6 +689,58 @@ export function SlideInner({
615
689
  } as React.CSSProperties)
616
690
  : {};
617
691
 
692
+ const overflowByTargetRef = useRef(new Map<string, SlideOverflowInfo>());
693
+ const reportTargetOverflow = useCallback(
694
+ (targetKey: string, info: SlideOverflowInfo) => {
695
+ overflowByTargetRef.current.set(targetKey, info);
696
+ if (!onOverflowChange) return;
697
+ const measurements = [...overflowByTargetRef.current.values()];
698
+ onOverflowChange(
699
+ measurements.reduce(
700
+ (result, measurement) => ({
701
+ verticalOverflow: Math.max(
702
+ result.verticalOverflow,
703
+ measurement.verticalOverflow,
704
+ ),
705
+ horizontalOverflow: Math.max(
706
+ result.horizontalOverflow,
707
+ measurement.horizontalOverflow,
708
+ ),
709
+ contentHeight: Math.max(
710
+ result.contentHeight,
711
+ measurement.contentHeight,
712
+ ),
713
+ contentWidth: Math.max(
714
+ result.contentWidth,
715
+ measurement.contentWidth,
716
+ ),
717
+ viewportHeight: Math.max(
718
+ result.viewportHeight,
719
+ measurement.viewportHeight,
720
+ ),
721
+ viewportWidth: Math.max(
722
+ result.viewportWidth,
723
+ measurement.viewportWidth,
724
+ ),
725
+ }),
726
+ {
727
+ verticalOverflow: 0,
728
+ horizontalOverflow: 0,
729
+ contentHeight: 0,
730
+ contentWidth: 0,
731
+ viewportHeight: 0,
732
+ viewportWidth: 0,
733
+ },
734
+ ),
735
+ );
736
+ },
737
+ [onOverflowChange],
738
+ );
739
+
740
+ useEffect(() => {
741
+ overflowByTargetRef.current.clear();
742
+ }, [slide.id, slide.content, aspectRatio]);
743
+
618
744
  // If slide has excalidraw data, render it as a static SVG thumbnail
619
745
  if (
620
746
  slide.excalidrawData &&
@@ -668,7 +794,7 @@ export function SlideInner({
668
794
  canvasHeight={dims.height}
669
795
  fitKey={left}
670
796
  className="slide-content text-white/90"
671
- onOverflowChange={onOverflowChange}
797
+ onOverflowChange={(info) => reportTargetOverflow("left", info)}
672
798
  onAutofitSettled={onAutofitSettled}
673
799
  >
674
800
  <ReactMarkdown
@@ -683,6 +809,7 @@ export function SlideInner({
683
809
  canvasHeight={dims.height}
684
810
  fitKey={right}
685
811
  className="slide-content text-white/90"
812
+ onOverflowChange={(info) => reportTargetOverflow("right", info)}
686
813
  onAutofitSettled={onAutofitSettled}
687
814
  >
688
815
  <ReactMarkdown
@@ -708,7 +835,7 @@ export function SlideInner({
708
835
  canvasHeight={dims.height}
709
836
  fitKey={content}
710
837
  className="h-full w-full"
711
- onOverflowChange={onOverflowChange}
838
+ onOverflowChange={(info) => reportTargetOverflow("raw", info)}
712
839
  onAutofitSettled={onAutofitSettled}
713
840
  >
714
841
  <BlankSlideContent content={content} />
@@ -734,7 +861,7 @@ export function SlideInner({
734
861
  canvasHeight={dims.height}
735
862
  fitKey={content}
736
863
  className="slide-content text-white/90 w-full"
737
- onOverflowChange={onOverflowChange}
864
+ onOverflowChange={(info) => reportTargetOverflow("markdown", info)}
738
865
  onAutofitSettled={onAutofitSettled}
739
866
  >
740
867
  <ReactMarkdown
@@ -31,6 +31,7 @@ interface DesignSystemCardProps {
31
31
  data: DesignSystemData;
32
32
  isDefault: boolean;
33
33
  visibility?: "private" | "org" | "public" | null;
34
+ accessRole?: "owner" | "admin" | "editor" | "viewer";
34
35
  canManage?: boolean;
35
36
  onClick: () => void;
36
37
  onSetDefault: () => void;
@@ -50,6 +51,7 @@ export function DesignSystemCard({
50
51
  data,
51
52
  isDefault,
52
53
  visibility,
54
+ accessRole,
53
55
  canManage,
54
56
  onClick,
55
57
  onSetDefault,
@@ -97,23 +99,25 @@ export function DesignSystemCard({
97
99
  className="absolute top-3 right-3 z-10 flex items-center gap-1.5"
98
100
  onClick={(e) => e.stopPropagation()}
99
101
  >
100
- <Tooltip>
101
- <TooltipTrigger asChild>
102
- <button
103
- onClick={onSetDefault}
104
- className="h-9 w-9 inline-flex items-center justify-center rounded-md bg-background/80 backdrop-blur-sm border border-border/40 hover:bg-background cursor-pointer"
105
- >
106
- {isDefault ? (
107
- <IconStarFilled className="w-4 h-4 text-[#609FF8]" />
108
- ) : (
109
- <IconStar className="w-4 h-4 text-muted-foreground group-hover:text-foreground/70" />
110
- )}
111
- </button>
112
- </TooltipTrigger>
113
- <TooltipContent>
114
- {isDefault ? "Default design system" : "Set as default"}
115
- </TooltipContent>
116
- </Tooltip>
102
+ {accessRole === "owner" && (
103
+ <Tooltip>
104
+ <TooltipTrigger asChild>
105
+ <button
106
+ onClick={onSetDefault}
107
+ className="h-9 w-9 inline-flex items-center justify-center rounded-md bg-background/80 backdrop-blur-sm border border-border/40 hover:bg-background cursor-pointer"
108
+ >
109
+ {isDefault ? (
110
+ <IconStarFilled className="w-4 h-4 text-primary" />
111
+ ) : (
112
+ <IconStar className="w-4 h-4 text-muted-foreground group-hover:text-foreground/70" />
113
+ )}
114
+ </button>
115
+ </TooltipTrigger>
116
+ <TooltipContent>
117
+ {isDefault ? "Default design system" : "Set as default"}
118
+ </TooltipContent>
119
+ </Tooltip>
120
+ )}
117
121
  <ShareButton
118
122
  resourceType="design-system"
119
123
  resourceId={id}