@agent-native/core 0.141.6 → 0.144.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 (501) hide show
  1. package/agent-native.eject.json +9 -0
  2. package/corpus/README.md +1 -1
  3. package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +3 -14
  4. package/corpus/templates/analytics/.agents/skills/data-querying/SKILL.md +11 -6
  5. package/corpus/templates/analytics/.agents/skills/prometheus/SKILL.md +5 -5
  6. package/corpus/templates/analytics/.agents/skills/provider-api/SKILL.md +19 -0
  7. package/corpus/templates/analytics/.agents/skills/turn-into-app/SKILL.md +296 -0
  8. package/corpus/templates/analytics/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  9. package/corpus/templates/analytics/.agents/skills/turn-into-skill/SKILL.md +112 -0
  10. package/corpus/templates/analytics/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  11. package/corpus/templates/analytics/AGENTS.md +37 -40
  12. package/corpus/templates/analytics/actions/compose-dashboard.ts +1 -1
  13. package/corpus/templates/analytics/actions/ensure-native-v2-dashboards.ts +1 -1
  14. package/corpus/templates/analytics/actions/list-dashboard-usage-stats.ts +17 -22
  15. package/corpus/templates/analytics/actions/migrate-first-party-analytics-to-bigquery.ts +135 -0
  16. package/corpus/templates/analytics/actions/navigate.ts +5 -6
  17. package/corpus/templates/analytics/actions/provider-api-register.ts +50 -0
  18. package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +46 -13
  19. package/corpus/templates/analytics/actions/test-custom-api-connection.ts +106 -0
  20. package/corpus/templates/analytics/actions/update-dashboard.ts +0 -1
  21. package/corpus/templates/analytics/actions/view-screen.ts +0 -20
  22. package/corpus/templates/analytics/app/components/CustomApiCard.tsx +430 -0
  23. package/corpus/templates/analytics/app/components/layout/Header.tsx +0 -1
  24. package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +5 -5
  25. package/corpus/templates/analytics/app/i18n-data.ts +682 -90
  26. package/corpus/templates/analytics/app/lib/native-mcp-exclusions.ts +6 -0
  27. package/corpus/templates/analytics/app/lib/sql-query.ts +33 -6
  28. package/corpus/templates/analytics/app/pages/Agents.tsx +0 -3
  29. package/corpus/templates/analytics/app/pages/DataSources.tsx +4 -0
  30. package/corpus/templates/analytics/app/pages/Settings.tsx +22 -43
  31. package/corpus/templates/analytics/app/pages/settings/settings-search.ts +23 -20
  32. package/corpus/templates/analytics/app/routes/extensions._index.tsx +1 -1
  33. package/corpus/templates/analytics/app/routes/settings.$.tsx +1 -0
  34. package/corpus/templates/analytics/app/routes/team.tsx +1 -1
  35. package/corpus/templates/analytics/changelog/2026-08-05-settings-no-longer-includes-an-unnecessary-about-section.md +6 -0
  36. package/corpus/templates/analytics/changelog/2026-08-06-analytics-dashboards-load-reliably-during-background-data-sw.md +6 -0
  37. package/corpus/templates/analytics/changelog/2026-08-06-analytics-dashboards-remain-responsive-while-historical-data.md +6 -0
  38. package/corpus/templates/analytics/changelog/2026-08-06-analytics-query-results-now-render-as-a-table-with-csv-downl.md +6 -0
  39. package/corpus/templates/analytics/changelog/2026-08-06-connect-public-https-custom-apis-and-hand-tested-endpoints-t.md +6 -0
  40. package/corpus/templates/analytics/changelog/2026-08-06-durable-agent-worker-memory.md +6 -0
  41. package/corpus/templates/analytics/changelog/2026-08-06-live-dashboard-panels-use-the-shared-query-timeout.md +6 -0
  42. package/corpus/templates/analytics/changelog/2026-08-06-on-demand-billing-is-available-as-a-native-dashboard-with-ta.md +6 -0
  43. package/corpus/templates/analytics/changelog/2026-08-06-visible-dashboard-names-are-unique.md +6 -0
  44. package/corpus/templates/analytics/docs/schemas/first-party-analytics.md +1 -1
  45. package/corpus/templates/analytics/netlify.toml +7 -0
  46. package/corpus/templates/analytics/scripts/emit-netlify-dashboard-report-cron.ts +4 -0
  47. package/corpus/templates/analytics/scripts/first-party-analytics-bigquery.sql +104 -0
  48. package/corpus/templates/analytics/server/db/index.ts +27 -0
  49. package/corpus/templates/analytics/server/db/schema.ts +10 -0
  50. package/corpus/templates/analytics/server/lib/agent-chat-plan-mode.ts +0 -2
  51. package/corpus/templates/analytics/server/lib/dashboards-store.ts +227 -60
  52. package/corpus/templates/analytics/server/lib/first-party-analytics-backend.ts +1147 -0
  53. package/corpus/templates/analytics/server/lib/first-party-analytics-health.ts +34 -15
  54. package/corpus/templates/analytics/server/lib/first-party-analytics.ts +57 -4
  55. package/corpus/templates/analytics/server/lib/native-v2-dashboards.ts +227 -1
  56. package/corpus/templates/analytics/server/lib/real-data-actions.ts +1 -3
  57. package/corpus/templates/analytics/server/plugins/agent-chat.ts +7 -4
  58. package/corpus/templates/analytics/server/plugins/analytics-rollup-backfill-jobs.ts +1 -0
  59. package/corpus/templates/analytics/server/plugins/db.ts +52 -18
  60. package/corpus/templates/assets/.agents/skills/asset-generation/SKILL.md +36 -8
  61. package/corpus/templates/assets/.agents/skills/image-generation/SKILL.md +16 -1
  62. package/corpus/templates/assets/.agents/skills/library-management/SKILL.md +16 -1
  63. package/corpus/templates/assets/.agents/skills/turn-into-app/SKILL.md +296 -0
  64. package/corpus/templates/assets/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  65. package/corpus/templates/assets/.agents/skills/turn-into-skill/SKILL.md +112 -0
  66. package/corpus/templates/assets/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  67. package/corpus/templates/assets/AGENTS.md +1 -0
  68. package/corpus/templates/assets/actions/_helpers.ts +12 -0
  69. package/corpus/templates/assets/actions/generate-image.ts +9 -3
  70. package/corpus/templates/assets/actions/import-style-from-url.ts +115 -0
  71. package/corpus/templates/assets/app/hooks/use-navigation-state.ts +3 -1
  72. package/corpus/templates/assets/app/routes/extensions._index.tsx +1 -1
  73. package/corpus/templates/assets/app/routes/settings.$.tsx +1 -0
  74. package/corpus/templates/assets/app/routes/settings.tsx +5 -0
  75. package/corpus/templates/assets/app/routes/team.tsx +1 -1
  76. package/corpus/templates/assets/changelog/2026-08-05-brand-kits-can-import-a-website-s-hydrated-visual-language-a.md +6 -0
  77. package/corpus/templates/assets/changelog/2026-08-05-generated-images-now-hand-off-embeddable-previews-to-other-w.md +6 -0
  78. package/corpus/templates/assets/server/lib/generation.ts +58 -0
  79. package/corpus/templates/assets/shared/api.ts +12 -0
  80. package/corpus/templates/brain/.agents/skills/turn-into-app/SKILL.md +296 -0
  81. package/corpus/templates/brain/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  82. package/corpus/templates/brain/.agents/skills/turn-into-skill/SKILL.md +112 -0
  83. package/corpus/templates/brain/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  84. package/corpus/templates/brain/actions/list-connection-providers.ts +24 -3
  85. package/corpus/templates/brain/app/lib/dispatch-links.ts +44 -0
  86. package/corpus/templates/brain/app/routes/extensions._index.tsx +1 -1
  87. package/corpus/templates/brain/app/routes/sources.tsx +15 -7
  88. package/corpus/templates/brain/app/routes/team.tsx +1 -1
  89. package/corpus/templates/brain/app/routes.ts +1 -1
  90. package/corpus/templates/brain/changelog/2026-08-06-brain-provider-setup-links-open-dispatch-correctly-in-standa.md +6 -0
  91. package/corpus/templates/brain/server/plugins/agent-chat.ts +1 -0
  92. package/corpus/templates/calendar/.agents/skills/event-management/SKILL.md +26 -0
  93. package/corpus/templates/calendar/.agents/skills/turn-into-app/SKILL.md +296 -0
  94. package/corpus/templates/calendar/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  95. package/corpus/templates/calendar/.agents/skills/turn-into-skill/SKILL.md +112 -0
  96. package/corpus/templates/calendar/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  97. package/corpus/templates/calendar/AGENTS.md +11 -32
  98. package/corpus/templates/calendar/actions/update-event.ts +107 -1
  99. package/corpus/templates/calendar/app/components/calendar/EventCalendarSelect.tsx +83 -0
  100. package/corpus/templates/calendar/app/components/calendar/EventDetailPanel.tsx +57 -0
  101. package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +59 -73
  102. package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +3 -1
  103. package/corpus/templates/calendar/app/hooks/use-events.ts +4 -1
  104. package/corpus/templates/calendar/app/i18n-data.ts +20 -0
  105. package/corpus/templates/calendar/app/routes/_app.extensions._index.tsx +1 -1
  106. package/corpus/templates/calendar/app/routes/_app.settings.$.tsx +1 -0
  107. package/corpus/templates/calendar/app/routes/_app.team.tsx +1 -1
  108. package/corpus/templates/calendar/changelog/2026-08-06-delegated-requests-continue-in-the-background.md +6 -0
  109. package/corpus/templates/calendar/changelog/2026-08-06-existing-events-can-move-between-connected-google-account-ca.md +6 -0
  110. package/corpus/templates/calendar/server/lib/google-calendar.ts +101 -0
  111. package/corpus/templates/calendar/server/plugins/agent-chat.ts +7 -1
  112. package/corpus/templates/chat/.agents/skills/turn-into-app/SKILL.md +296 -0
  113. package/corpus/templates/chat/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  114. package/corpus/templates/chat/.agents/skills/turn-into-skill/SKILL.md +112 -0
  115. package/corpus/templates/chat/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  116. package/corpus/templates/chat/app/components/layout/Layout.tsx +1 -1
  117. package/corpus/templates/chat/app/hooks/use-navigation-state.ts +1 -1
  118. package/corpus/templates/chat/app/root.tsx +1 -1
  119. package/corpus/templates/chat/app/routes/agent.tsx +7 -7
  120. package/corpus/templates/chat/app/routes/extensions._index.tsx +1 -1
  121. package/corpus/templates/chat/app/routes/settings.$.tsx +1 -0
  122. package/corpus/templates/chat/app/routes/team.tsx +1 -1
  123. package/corpus/templates/clips/.agents/skills/turn-into-app/SKILL.md +296 -0
  124. package/corpus/templates/clips/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  125. package/corpus/templates/clips/.agents/skills/turn-into-skill/SKILL.md +112 -0
  126. package/corpus/templates/clips/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  127. package/corpus/templates/clips/app/components/editor/editor-layout.tsx +9 -24
  128. package/corpus/templates/clips/app/components/editor/timeline-geometry.ts +15 -0
  129. package/corpus/templates/clips/app/components/editor/waveform.tsx +4 -17
  130. package/corpus/templates/clips/app/components/library/library-layout.tsx +1 -1
  131. package/corpus/templates/clips/app/components/player/delete-recording-menu.tsx +14 -3
  132. package/corpus/templates/clips/app/components/player/transcript-panel.tsx +1 -1
  133. package/corpus/templates/clips/app/components/recorder/storage-setup-card.tsx +1 -1
  134. package/corpus/templates/clips/app/routes/_app.extensions._index.tsx +1 -1
  135. package/corpus/templates/clips/app/routes/_app.settings.$.tsx +1 -0
  136. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +28 -38
  137. package/corpus/templates/clips/app/routes/share.$shareId.tsx +21 -27
  138. package/corpus/templates/clips/changelog/2026-08-06-clips-recovers-from-stalled-recording-setup-without-requirin.md +6 -0
  139. package/corpus/templates/clips/changelog/2026-08-06-clips-starts-faster-after-a-deploy-or-idle-period-startup-no.md +6 -0
  140. package/corpus/templates/clips/changelog/2026-08-06-deleting-a-recording-returns-cleanly-to-the-library-and-fit-.md +6 -0
  141. package/corpus/templates/clips/changelog/2026-08-06-hide-clip-insights-from-viewers-without-analytics-access.md +6 -0
  142. package/corpus/templates/clips/desktop/src/app.tsx +48 -20
  143. package/corpus/templates/clips/desktop/src/lib/recorder.ts +275 -74
  144. package/corpus/templates/clips/desktop/src/lib/recording-start-guard.ts +84 -0
  145. package/corpus/templates/clips/desktop/src/overlays/toolbar.tsx +14 -4
  146. package/corpus/templates/clips/server/plugins/db.ts +214 -26
  147. package/corpus/templates/content/.agents/skills/turn-into-app/SKILL.md +296 -0
  148. package/corpus/templates/content/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  149. package/corpus/templates/content/.agents/skills/turn-into-skill/SKILL.md +112 -0
  150. package/corpus/templates/content/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  151. package/corpus/templates/content/app/routes/_app.extensions._index.tsx +1 -1
  152. package/corpus/templates/content/app/routes/_app.settings.$.tsx +1 -0
  153. package/corpus/templates/content/app/routes/_app.team.tsx +1 -1
  154. package/corpus/templates/content/e2e/global-setup.ts +1 -1
  155. package/corpus/templates/crm/.agents/skills/turn-into-app/SKILL.md +296 -0
  156. package/corpus/templates/crm/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  157. package/corpus/templates/crm/.agents/skills/turn-into-skill/SKILL.md +112 -0
  158. package/corpus/templates/crm/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  159. package/corpus/templates/crm/changelog/2026-08-06-crm-starts-faster-after-a-deploy-or-idle-period-one-time-dat.md +6 -0
  160. package/corpus/templates/crm/server/plugins/db.ts +11 -8
  161. package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +36 -1
  162. package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +6 -1
  163. package/corpus/templates/design/.agents/skills/turn-into-app/SKILL.md +296 -0
  164. package/corpus/templates/design/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  165. package/corpus/templates/design/.agents/skills/turn-into-skill/SKILL.md +112 -0
  166. package/corpus/templates/design/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  167. package/corpus/templates/design/actions/analyze-brand-assets.ts +7 -7
  168. package/corpus/templates/design/actions/import-from-url.ts +6 -5
  169. package/corpus/templates/design/app/components/design/LayersPanel.tsx +27 -18
  170. package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +2 -2
  171. package/corpus/templates/design/app/pages/Index.tsx +6 -2
  172. package/corpus/templates/design/app/routes/extensions._index.tsx +1 -1
  173. package/corpus/templates/design/app/routes/settings.$.tsx +1 -0
  174. package/corpus/templates/design/app/routes/team.tsx +1 -1
  175. package/corpus/templates/design/changelog/2026-08-05-deleting-a-design-from-the-home-page-no-longer-leaves-the-ap.md +6 -0
  176. package/corpus/templates/design/changelog/2026-08-05-renaming-a-layer-now-focuses-its-name-field-automatically.md +6 -0
  177. package/corpus/templates/design/changelog/2026-08-05-website-url-imports-now-capture-hydrated-browser-computed-de.md +6 -0
  178. package/corpus/templates/design/e2e/global-setup.ts +1 -1
  179. package/corpus/templates/design/server/plugins/agent-chat.ts +2 -0
  180. package/corpus/templates/dispatch/.agents/skills/turn-into-app/SKILL.md +296 -0
  181. package/corpus/templates/dispatch/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  182. package/corpus/templates/dispatch/.agents/skills/turn-into-skill/SKILL.md +112 -0
  183. package/corpus/templates/dispatch/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  184. package/corpus/templates/dispatch/app/hooks/use-navigation-state.ts +1 -1
  185. package/corpus/templates/dispatch/app/routes/settings.$.tsx +1 -0
  186. package/corpus/templates/dispatch/app/routes/team.tsx +1 -1
  187. package/corpus/templates/dispatch/changelog/2026-08-06-ready-workspace-apps-stay-one-click-away-in-a-compact-dispat.md +6 -0
  188. package/corpus/templates/dispatch/changelog/2026-08-06-shared-vault-values-and-management-are-now-restricted-to-wor.md +6 -0
  189. package/corpus/templates/factory/.agents/skills/turn-into-app/SKILL.md +296 -0
  190. package/corpus/templates/factory/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  191. package/corpus/templates/factory/.agents/skills/turn-into-skill/SKILL.md +112 -0
  192. package/corpus/templates/factory/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  193. package/corpus/templates/factory/app/hooks/use-navigation-state.ts +1 -1
  194. package/corpus/templates/factory/app/routes/extensions._index.tsx +1 -1
  195. package/corpus/templates/factory/app/routes/settings.$.tsx +1 -0
  196. package/corpus/templates/factory/app/routes/team.tsx +1 -1
  197. package/corpus/templates/forms/.agents/skills/turn-into-app/SKILL.md +296 -0
  198. package/corpus/templates/forms/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  199. package/corpus/templates/forms/.agents/skills/turn-into-skill/SKILL.md +112 -0
  200. package/corpus/templates/forms/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  201. package/corpus/templates/forms/app/routes/_app.extensions._index.tsx +1 -1
  202. package/corpus/templates/forms/app/routes/_app.settings.$.tsx +1 -0
  203. package/corpus/templates/forms/app/routes/_app.team.tsx +1 -1
  204. package/corpus/templates/forms/changelog/2026-08-06-delegated-requests-continue-in-the-background.md +6 -0
  205. package/corpus/templates/forms/server/plugins/agent-chat.ts +4 -0
  206. package/corpus/templates/forms/shared/navigation.ts +1 -1
  207. package/corpus/templates/macros/.agents/skills/turn-into-app/SKILL.md +296 -0
  208. package/corpus/templates/macros/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  209. package/corpus/templates/macros/.agents/skills/turn-into-skill/SKILL.md +112 -0
  210. package/corpus/templates/macros/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  211. package/corpus/templates/macros/app/routes/extensions._index.tsx +1 -1
  212. package/corpus/templates/macros/app/routes/settings.$.tsx +1 -0
  213. package/corpus/templates/macros/app/routes/team.tsx +1 -1
  214. package/corpus/templates/mail/.agents/skills/turn-into-app/SKILL.md +296 -0
  215. package/corpus/templates/mail/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  216. package/corpus/templates/mail/.agents/skills/turn-into-skill/SKILL.md +112 -0
  217. package/corpus/templates/mail/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  218. package/corpus/templates/mail/app/routes/extensions._index.tsx +1 -1
  219. package/corpus/templates/mail/app/routes/settings.$.tsx +1 -0
  220. package/corpus/templates/mail/changelog/2026-08-06-delegated-requests-continue-in-the-background.md +6 -0
  221. package/corpus/templates/mail/server/plugins/agent-chat.ts +6 -0
  222. package/corpus/templates/plan/.agents/skills/turn-into-app/SKILL.md +296 -0
  223. package/corpus/templates/plan/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  224. package/corpus/templates/plan/.agents/skills/turn-into-skill/SKILL.md +112 -0
  225. package/corpus/templates/plan/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  226. package/corpus/templates/plan/app/hooks/use-navigation-state.ts +1 -1
  227. package/corpus/templates/plan/app/routes/extensions._index.tsx +1 -1
  228. package/corpus/templates/plan/app/routes/settings.$.tsx +1 -0
  229. package/corpus/templates/plan/app/routes/team.tsx +1 -1
  230. package/corpus/templates/slides/.agents/skills/create-deck/SKILL.md +48 -5
  231. package/corpus/templates/slides/.agents/skills/design-systems/SKILL.md +40 -2
  232. package/corpus/templates/slides/.agents/skills/image-generation-via-a2a/SKILL.md +6 -0
  233. package/corpus/templates/slides/.agents/skills/slide-editing/SKILL.md +15 -2
  234. package/corpus/templates/slides/.agents/skills/slide-images/SKILL.md +29 -24
  235. package/corpus/templates/slides/.agents/skills/turn-into-app/SKILL.md +296 -0
  236. package/corpus/templates/slides/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  237. package/corpus/templates/slides/.agents/skills/turn-into-skill/SKILL.md +112 -0
  238. package/corpus/templates/slides/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  239. package/corpus/templates/slides/AGENTS.md +7 -9
  240. package/corpus/templates/slides/_gitignore +1 -0
  241. package/corpus/templates/slides/actions/analyze-brand-assets.ts +7 -7
  242. package/corpus/templates/slides/actions/export-pptx.ts +402 -36
  243. package/corpus/templates/slides/actions/import-file.ts +46 -85
  244. package/corpus/templates/slides/actions/import-from-url.ts +6 -6
  245. package/corpus/templates/slides/actions/import-google-slides-reference.ts +271 -12
  246. package/corpus/templates/slides/actions/import-pptx.ts +85 -60
  247. package/corpus/templates/slides/app/components/deck/DeckCard.tsx +10 -13
  248. package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +1 -1
  249. package/corpus/templates/slides/app/components/editor/AddSlidePopover.tsx +5 -1
  250. package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +25 -12
  251. package/corpus/templates/slides/app/components/editor/ExportMenu.tsx +112 -57
  252. package/corpus/templates/slides/app/components/editor/GoogleDriveConnectionCta.tsx +202 -0
  253. package/corpus/templates/slides/app/components/editor/GoogleSlidesReferenceImport.tsx +26 -14
  254. package/corpus/templates/slides/app/components/editor/PromptDialog.tsx +176 -0
  255. package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +182 -141
  256. package/corpus/templates/slides/app/components/editor/canvas-interactions/index.ts +1 -0
  257. package/corpus/templates/slides/app/components/editor/canvas-interactions/slides-canvas-adapter.ts +18 -0
  258. package/corpus/templates/slides/app/components/editor/slide-text-targets.ts +85 -0
  259. package/corpus/templates/slides/app/components/layout/Layout.tsx +3 -0
  260. package/corpus/templates/slides/app/components/onboarding/FirstDeckOnboardingFlow.tsx +13 -3
  261. package/corpus/templates/slides/app/components/presentation/PresentationView.tsx +27 -1
  262. package/corpus/templates/slides/app/context/DeckContext.tsx +71 -20
  263. package/corpus/templates/slides/app/global.css +6 -0
  264. package/corpus/templates/slides/app/i18n/en-US.ts +1 -0
  265. package/corpus/templates/slides/app/lib/create-deck-generation.ts +10 -6
  266. package/corpus/templates/slides/app/lib/deck-preview-frame.ts +15 -0
  267. package/corpus/templates/slides/app/lib/deck-share-links.ts +9 -0
  268. package/corpus/templates/slides/app/lib/export-pptx-client.ts +89 -0
  269. package/corpus/templates/slides/app/lib/slide-animation-elements.ts +3 -0
  270. package/corpus/templates/slides/app/pages/DeckEditor.tsx +17 -0
  271. package/corpus/templates/slides/app/pages/Index.tsx +107 -6
  272. package/corpus/templates/slides/app/routes/extensions._index.tsx +1 -1
  273. package/corpus/templates/slides/app/routes/settings.$.tsx +1 -0
  274. package/corpus/templates/slides/app/routes/team.tsx +1 -1
  275. package/corpus/templates/slides/changelog/2026-08-05-failed-deck-creation-and-reference-uploads-now-recover-clean.md +6 -0
  276. package/corpus/templates/slides/changelog/2026-08-05-slides-recover-completed-generation-results-after-a-sync-hic.md +6 -0
  277. package/corpus/templates/slides/changelog/2026-08-05-website-url-imports-now-capture-hydrated-browser-computed-st.md +6 -0
  278. package/corpus/templates/slides/changelog/2026-08-06-clicking-the-gray-canvas-around-a-slide-clears-its-selection.md +6 -0
  279. package/corpus/templates/slides/changelog/2026-08-06-deck-thumbnails-keep-a-consistent-listing-frame-across-aspec.md +6 -0
  280. package/corpus/templates/slides/changelog/2026-08-06-deep-linked-decks-open-directly-instead-of-being-interrupted.md +6 -0
  281. package/corpus/templates/slides/changelog/2026-08-06-google-slides-exports-now-show-clear-import-steps-when-direc.md +6 -0
  282. package/corpus/templates/slides/changelog/2026-08-06-import-pdf-google-slides-and-powerpoint-decks-directly-from-.md +6 -0
  283. package/corpus/templates/slides/changelog/2026-08-06-imported-powerpoint-exports-keep-text-and-images-editable-an.md +6 -0
  284. package/corpus/templates/slides/changelog/2026-08-06-presentation-prompts-continue-adding-rendered-slides-until-t.md +6 -0
  285. package/corpus/templates/slides/changelog/2026-08-06-public-decks-now-share-read-only-presentation-links-by-defau.md +6 -0
  286. package/corpus/templates/slides/changelog/2026-08-06-slides-offers-a-direct-connect-google-button-when-a-drive-co.md +6 -0
  287. package/corpus/templates/slides/changelog/2026-08-06-slides-preserve-uploaded-pdf-layouts-accept-larger-reference.md +6 -0
  288. package/corpus/templates/slides/changelog/2026-08-06-styled-words-stay-part-of-their-text-box-instead-of-becoming.md +6 -0
  289. package/corpus/templates/slides/server/handlers/google-docs-auth.ts +7 -20
  290. package/corpus/templates/slides/server/handlers/import/html-converter.ts +236 -13
  291. package/corpus/templates/slides/server/handlers/import/pptx-assets.ts +67 -0
  292. package/corpus/templates/slides/server/handlers/import/pptx-parser.ts +2 -0
  293. package/corpus/templates/slides/server/handlers/uploads.ts +7 -3
  294. package/corpus/templates/slides/server/lib/chat-attachments.ts +6 -3
  295. package/corpus/templates/slides/server/lib/emails.ts +7 -2
  296. package/corpus/templates/slides/server/lib/google-docs-error.ts +50 -0
  297. package/corpus/templates/slides/server/lib/google-docs-oauth.ts +1 -0
  298. package/corpus/templates/slides/server/lib/import-asset-storage.ts +127 -0
  299. package/corpus/templates/slides/server/plugins/agent-chat.ts +4 -3
  300. package/corpus/templates/slides/server/routes/api/import-assets/[token].get.ts +70 -0
  301. package/corpus/templates/slides/shared/upload-types.ts +3 -0
  302. package/corpus/templates/tasks/.agents/skills/turn-into-app/SKILL.md +296 -0
  303. package/corpus/templates/tasks/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  304. package/corpus/templates/tasks/.agents/skills/turn-into-skill/SKILL.md +112 -0
  305. package/corpus/templates/tasks/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  306. package/corpus/templates/tasks/app/components/layout/Header.tsx +3 -1
  307. package/corpus/templates/tasks/app/routes/extensions._index.tsx +1 -1
  308. package/corpus/templates/tasks/app/routes/settings.$.tsx +1 -0
  309. package/dist/agent/engine/ai-sdk-engine.js +49 -3
  310. package/dist/agent/production-agent.d.ts +18 -0
  311. package/dist/agent/production-agent.js +80 -1
  312. package/dist/agent/types.d.ts +7 -0
  313. package/dist/cli/agent-plugin.d.ts +112 -0
  314. package/dist/cli/agent-plugin.js +1081 -0
  315. package/dist/cli/app-skill.js +39 -1
  316. package/dist/cli/code-agent-executor.d.ts +3 -0
  317. package/dist/cli/code-agent-executor.js +51 -13
  318. package/dist/cli/index.js +13 -0
  319. package/dist/cli/templates-meta.js +1 -1
  320. package/dist/client/AgentPanel.d.ts +3 -1
  321. package/dist/client/AgentPanel.js +9 -2
  322. package/dist/client/AssistantChat.d.ts +8 -0
  323. package/dist/client/AssistantChat.js +23 -8
  324. package/dist/client/NewWorkspaceAppFlow.js +1 -0
  325. package/dist/client/agent-chat-adapter.d.ts +1 -1
  326. package/dist/client/agent-chat-adapter.js +153 -7
  327. package/dist/client/agent-page/AgentWorkspaceContent.d.ts +1 -1
  328. package/dist/client/agent-page/AgentWorkspaceContent.js +13 -13
  329. package/dist/client/assistant-ui-recovery.d.ts +2 -1
  330. package/dist/client/assistant-ui-recovery.js +7 -3
  331. package/dist/client/chat/run-recovery.js +5 -1
  332. package/dist/client/embed-auth.js +6 -2
  333. package/dist/client/error-format.js +12 -0
  334. package/dist/client/integrations/IntegrationsPanel.js +40 -6
  335. package/dist/client/onboarding/FirstRunOnboarding.js +11 -4
  336. package/dist/client/org/OrgSwitcher.js +2 -2
  337. package/dist/client/org/TeamPage.js +92 -72
  338. package/dist/client/require-session.d.ts +1 -1
  339. package/dist/client/require-session.js +4 -4
  340. package/dist/client/resources/McpConnectionSuggestion.d.ts +1 -0
  341. package/dist/client/resources/McpConnectionSuggestion.js +27 -10
  342. package/dist/client/resources/McpIntegrationDialog.js +77 -45
  343. package/dist/client/resources/mcp-integration-catalog.d.ts +13 -1
  344. package/dist/client/resources/mcp-integration-catalog.js +255 -2
  345. package/dist/client/resources/mcp-integration-logos.js +18 -2
  346. package/dist/client/resources/use-mcp-servers.d.ts +5 -0
  347. package/dist/client/resources/use-mcp-servers.js +36 -0
  348. package/dist/client/settings/AccountSettingsCard.js +42 -36
  349. package/dist/client/settings/AutomationsSection.js +1 -1
  350. package/dist/client/settings/DemoModeSection.d.ts +3 -1
  351. package/dist/client/settings/DemoModeSection.js +4 -1
  352. package/dist/client/settings/ExtensionsSettingsContent.js +1 -1
  353. package/dist/client/settings/SchedulingTimezoneField.d.ts +3 -1
  354. package/dist/client/settings/SchedulingTimezoneField.js +9 -5
  355. package/dist/client/settings/SettingsPanel.d.ts +4 -1
  356. package/dist/client/settings/SettingsPanel.js +21 -21
  357. package/dist/client/settings/SettingsTabsPage.d.ts +2 -2
  358. package/dist/client/settings/SettingsTabsPage.js +98 -45
  359. package/dist/client/settings/VoiceTranscriptionSection.js +6 -1
  360. package/dist/client/settings/useSettingsPanelController.js +47 -8
  361. package/dist/collab/routes.d.ts +1 -1
  362. package/dist/db/client.d.ts +9 -0
  363. package/dist/db/client.js +51 -16
  364. package/dist/db/create-get-db.js +2 -2
  365. package/dist/db/ddl-guard.d.ts +11 -10
  366. package/dist/db/ddl-guard.js +40 -12
  367. package/dist/deploy/build.d.ts +2 -0
  368. package/dist/deploy/build.js +97 -4
  369. package/dist/deploy/workspace-deploy.js +0 -2
  370. package/dist/guards/no-env-credentials.js +9 -0
  371. package/dist/ingestion/index.d.ts +1 -1
  372. package/dist/ingestion/pptx.d.ts +68 -0
  373. package/dist/ingestion/pptx.js +660 -213
  374. package/dist/ingestion/website.d.ts +30 -0
  375. package/dist/integrations/plugin.js +9 -6
  376. package/dist/localization/default-messages.d.ts +59 -0
  377. package/dist/localization/default-messages.js +62 -2
  378. package/dist/mcp/screen-memory-stdio.d.ts +7 -7
  379. package/dist/mcp-client/oauth-routes.d.ts +2 -0
  380. package/dist/mcp-client/oauth-routes.js +74 -7
  381. package/dist/mcp-client/routes.d.ts +1 -0
  382. package/dist/mcp-client/routes.js +49 -0
  383. package/dist/navigation/index.js +16 -5
  384. package/dist/notifications/routes.d.ts +1 -1
  385. package/dist/observability/routes.d.ts +3 -3
  386. package/dist/onboarding/app-profile.js +11 -0
  387. package/dist/progress/routes.d.ts +1 -1
  388. package/dist/provider-api/actions/custom-provider-registration.d.ts +13 -13
  389. package/dist/provider-api/actions/provider-api.d.ts +11 -11
  390. package/dist/resources/store.js +15 -1
  391. package/dist/scripts/call-agent.js +45 -4
  392. package/dist/secrets/routes.d.ts +6 -6
  393. package/dist/server/agent-chat/action-filters-a2a.d.ts +1 -1
  394. package/dist/server/agent-chat/action-filters-a2a.js +36 -1
  395. package/dist/server/agent-chat-plugin.js +29 -8
  396. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  397. package/dist/server/auth.js +55 -17
  398. package/dist/server/better-auth-instance.js +5 -3
  399. package/dist/server/core-routes-plugin.d.ts +8 -1
  400. package/dist/server/core-routes-plugin.js +28 -3
  401. package/dist/server/credential-provider.d.ts +3 -3
  402. package/dist/server/credential-provider.js +90 -4
  403. package/dist/server/identity-sso.js +2 -1
  404. package/dist/server/onboarding-html.d.ts +2 -0
  405. package/dist/server/onboarding-html.js +171 -62
  406. package/dist/server/realtime-token.d.ts +1 -1
  407. package/dist/server/self-dispatch.d.ts +5 -4
  408. package/dist/server/self-dispatch.js +25 -14
  409. package/dist/server/ssr-handler.d.ts +1 -1
  410. package/dist/server/ssr-handler.js +1 -1
  411. package/dist/server/workspace-provider-oauth.js +1 -1
  412. package/dist/setup-connections/onboarding.js +1 -1
  413. package/dist/shared/cache-control.d.ts +26 -2
  414. package/dist/shared/cache-control.js +43 -2
  415. package/dist/shared/index.d.ts +1 -1
  416. package/dist/shared/index.js +1 -1
  417. package/dist/shared/password-policy.d.ts +3 -0
  418. package/dist/shared/password-policy.js +3 -0
  419. package/dist/shared/sign-in-journey.d.ts +5 -2
  420. package/dist/shared/sign-in-journey.js +10 -4
  421. package/dist/sharing/actions/set-resource-visibility.js +16 -4
  422. package/dist/sharing/registry.d.ts +14 -0
  423. package/dist/styles/agent-native.css +6 -0
  424. package/dist/templates/chat/.agents/skills/turn-into-app/SKILL.md +296 -0
  425. package/dist/templates/chat/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  426. package/dist/templates/chat/.agents/skills/turn-into-skill/SKILL.md +112 -0
  427. package/dist/templates/chat/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  428. package/dist/templates/chat/app/components/layout/Layout.tsx +1 -1
  429. package/dist/templates/chat/app/hooks/use-navigation-state.ts +1 -1
  430. package/dist/templates/chat/app/root.tsx +1 -1
  431. package/dist/templates/chat/app/routes/agent.tsx +7 -7
  432. package/dist/templates/chat/app/routes/extensions._index.tsx +1 -1
  433. package/dist/templates/chat/app/routes/settings.$.tsx +1 -0
  434. package/dist/templates/chat/app/routes/team.tsx +1 -1
  435. package/dist/templates/default/.agents/skills/turn-into-app/SKILL.md +296 -0
  436. package/dist/templates/default/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  437. package/dist/templates/default/.agents/skills/turn-into-skill/SKILL.md +112 -0
  438. package/dist/templates/default/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  439. package/dist/templates/headless/.agents/skills/turn-into-app/SKILL.md +296 -0
  440. package/dist/templates/headless/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  441. package/dist/templates/headless/.agents/skills/turn-into-skill/SKILL.md +112 -0
  442. package/dist/templates/headless/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  443. package/dist/templates/workspace-core/.agents/skills/adding-workspace-apps/SKILL.md +6 -0
  444. package/dist/templates/workspace-core/.agents/skills/address-feedback/SKILL.md +37 -6
  445. package/dist/templates/workspace-core/.agents/skills/authentication/SKILL.md +4 -2
  446. package/dist/templates/workspace-core/.agents/skills/performance/SKILL.md +51 -0
  447. package/dist/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +296 -0
  448. package/dist/templates/workspace-core/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  449. package/dist/templates/workspace-core/.agents/skills/turn-into-skill/SKILL.md +112 -0
  450. package/dist/templates/workspace-core/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  451. package/dist/templates/workspace-root/AGENTS.md +7 -0
  452. package/dist/user-profile/actions/change-password.js +8 -3
  453. package/dist/user-profile/actions/set-password.js +5 -1
  454. package/dist/vite/action-types-plugin.js +59 -0
  455. package/docs/content/authentication.mdx +4 -5
  456. package/docs/content/skills-guide.mdx +13 -0
  457. package/docs/content/template-analytics-developers.mdx +1 -1
  458. package/docs/content/template-calendar-developers.mdx +1 -1
  459. package/docs/content/template-chat-developers.mdx +2 -2
  460. package/docs/content/template-content-developers.mdx +1 -1
  461. package/docs/content/template-mail-developers.mdx +1 -1
  462. package/docs/content/template-plan-developers.mdx +1 -1
  463. package/docs/content/toolkit-command-navigation.mdx +6 -6
  464. package/docs/content/toolkit-org-team.mdx +1 -1
  465. package/docs/content/toolkit-settings.mdx +8 -8
  466. package/docs/content/toolkit-setup-connections.mdx +1 -1
  467. package/package.json +6 -2
  468. package/src/templates/chat/.agents/skills/turn-into-app/SKILL.md +296 -0
  469. package/src/templates/chat/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  470. package/src/templates/chat/.agents/skills/turn-into-skill/SKILL.md +112 -0
  471. package/src/templates/chat/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  472. package/src/templates/chat/app/components/layout/Layout.tsx +1 -1
  473. package/src/templates/chat/app/hooks/use-navigation-state.ts +1 -1
  474. package/src/templates/chat/app/root.tsx +1 -1
  475. package/src/templates/chat/app/routes/agent.tsx +7 -7
  476. package/src/templates/chat/app/routes/extensions._index.tsx +1 -1
  477. package/src/templates/chat/app/routes/settings.$.tsx +1 -0
  478. package/src/templates/chat/app/routes/team.tsx +1 -1
  479. package/src/templates/default/.agents/skills/turn-into-app/SKILL.md +296 -0
  480. package/src/templates/default/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  481. package/src/templates/default/.agents/skills/turn-into-skill/SKILL.md +112 -0
  482. package/src/templates/default/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  483. package/src/templates/headless/.agents/skills/turn-into-app/SKILL.md +296 -0
  484. package/src/templates/headless/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  485. package/src/templates/headless/.agents/skills/turn-into-skill/SKILL.md +112 -0
  486. package/src/templates/headless/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  487. package/src/templates/workspace-core/.agents/skills/adding-workspace-apps/SKILL.md +6 -0
  488. package/src/templates/workspace-core/.agents/skills/address-feedback/SKILL.md +37 -6
  489. package/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +4 -2
  490. package/src/templates/workspace-core/.agents/skills/performance/SKILL.md +51 -0
  491. package/src/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +296 -0
  492. package/src/templates/workspace-core/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  493. package/src/templates/workspace-core/.agents/skills/turn-into-skill/SKILL.md +112 -0
  494. package/src/templates/workspace-core/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  495. package/src/templates/workspace-root/AGENTS.md +7 -0
  496. package/corpus/templates/analytics/.agents/skills/dashboard-management/references/template-catalog-and-demo.md +0 -62
  497. package/corpus/templates/analytics/actions/install-dashboard-template.ts +0 -369
  498. package/corpus/templates/analytics/actions/list-dashboard-templates.ts +0 -47
  499. package/corpus/templates/analytics/actions/list-native-v2-dashboard-templates.ts +0 -34
  500. package/corpus/templates/analytics/app/routes/catalog.tsx +0 -240
  501. package/src/templates/default/actions/navigate.spec.ts +0 -53
@@ -15,7 +15,10 @@ import {
15
15
  uploadPromptFiles,
16
16
  type UploadedFile,
17
17
  } from "@/components/editor/PromptDialog";
18
- import { useDecks } from "@/context/DeckContext";
18
+ import {
19
+ describeDeckPersistenceFailure,
20
+ useDecks,
21
+ } from "@/context/DeckContext";
19
22
  import { useAgentGenerating } from "@/hooks/use-agent-generating";
20
23
  import { useDesignSystems } from "@/hooks/use-design-systems";
21
24
  import { useWorkspaceDefaults } from "@/hooks/use-workspace-defaults";
@@ -26,6 +29,8 @@ import {
26
29
  type RecentReference,
27
30
  } from "@/lib/recent-references";
28
31
 
32
+ import { MAX_REFERENCE_FILE_BYTES } from "../../../shared/upload-types";
33
+
29
34
  type FirstDeckStep = "prompt" | "references";
30
35
 
31
36
  export function FirstDeckOnboardingFlow({
@@ -141,12 +146,15 @@ export function FirstDeckOnboardingFlow({
141
146
  onUnauthenticated: () => {
142
147
  toast.error(t("home.signInTitle"));
143
148
  },
144
- onPersistenceFailure: (failedPrompt) => {
149
+ onPersistenceFailure: (failedPrompt, _failedFiles, failure) => {
145
150
  setPromptInitialText(failedPrompt);
146
151
  setPromptInitialTextKey(Date.now());
147
152
  setStep("prompt");
148
153
  toast.error(t("home.generationStartFailed"), {
149
- description: t("home.generationStartFailedDescription"),
154
+ description: describeDeckPersistenceFailure(
155
+ failure,
156
+ t("home.generationStartFailedDescription"),
157
+ ),
150
158
  });
151
159
  },
152
160
  });
@@ -297,6 +305,8 @@ export function FirstDeckOnboardingFlow({
297
305
  className="mt-8"
298
306
  autoFocus
299
307
  attachmentsEnabled
308
+ maxDocumentAttachmentBytes={MAX_REFERENCE_FILE_BYTES}
309
+ documentAttachmentLimitLabel="Slides reference files"
300
310
  disabled={uploading}
301
311
  placeholder={t("home.newDeckPlaceholder")}
302
312
  onSubmit={handlePromptSubmit}
@@ -18,6 +18,7 @@ import type {
18
18
  import type { AspectRatio } from "@/lib/aspect-ratios";
19
19
  import {
20
20
  findLegacyAnimationContainer,
21
+ getElementPath,
21
22
  resolveSlideAnimationElement,
22
23
  } from "@/lib/slide-animation-elements";
23
24
 
@@ -43,6 +44,31 @@ function getAnimationSteps(slide: Slide): SlideAnimation[] | null {
43
44
  const doc = new DOMParser().parseFromString(slide.content, "text/html");
44
45
  const root = doc.querySelector(".fmd-slide");
45
46
  if (!root) return null;
47
+
48
+ const paragraphs = Array.from(
49
+ root.querySelectorAll(".fmd-pptx-text p[data-pptx-paragraph]"),
50
+ ).filter((paragraph) => {
51
+ const textBox = paragraph.closest(".fmd-pptx-text");
52
+ return (
53
+ (textBox?.querySelectorAll("p[data-pptx-paragraph]").length ?? 0) > 1
54
+ );
55
+ });
56
+ if (paragraphs.length > 1) {
57
+ return paragraphs.flatMap((paragraph, index) => {
58
+ const elementPath = getElementPath(root, paragraph);
59
+ return elementPath
60
+ ? [
61
+ {
62
+ id: `auto-paragraph-${index}`,
63
+ elementIndex: index,
64
+ elementPath,
65
+ type: "slide-up" as AnimationType,
66
+ },
67
+ ]
68
+ : [];
69
+ });
70
+ }
71
+
46
72
  const container = findLegacyAnimationContainer(root);
47
73
  if (!container) return null;
48
74
  return Array.from(container.children).map((_, i) => ({
@@ -103,7 +129,7 @@ function annotateStepsForPresentation(
103
129
  })
104
130
  .join("\n");
105
131
 
106
- const styleTag = `<style>[data-pstep] { opacity: 0; pointer-events: none; }\n${styleLines}</style>`;
132
+ const styleTag = `<style>[data-pstep] { opacity: 0; pointer-events: none; visibility: visible !important; }\n${styleLines}</style>`;
107
133
  return styleTag + doc.body.innerHTML;
108
134
  }
109
135
 
@@ -138,6 +138,25 @@ export interface Deck {
138
138
  aspectRatio?: AspectRatio;
139
139
  }
140
140
 
141
+ export type DeckPersistenceResult =
142
+ | { persisted: true }
143
+ | { persisted: false; reason: "request-failed"; error: unknown }
144
+ | { persisted: false; reason: "not-found" };
145
+
146
+ export function describeDeckPersistenceFailure(
147
+ result: DeckPersistenceResult,
148
+ fallback: string,
149
+ ): string {
150
+ if (result.persisted || result.reason === "not-found") return fallback;
151
+ if (result.error instanceof Error && result.error.message.trim()) {
152
+ return result.error.message;
153
+ }
154
+ if (typeof result.error === "string" && result.error.trim()) {
155
+ return result.error;
156
+ }
157
+ return fallback;
158
+ }
159
+
141
160
  interface DeckContextType {
142
161
  decks: Deck[];
143
162
  loading: boolean;
@@ -146,7 +165,7 @@ interface DeckContextType {
146
165
  title?: string,
147
166
  options?: { noDefaultSlides?: boolean; designSystemId?: string | null },
148
167
  ) => Deck;
149
- ensureDeckPersisted: (id: string) => Promise<boolean>;
168
+ ensureDeckPersisted: (id: string) => Promise<DeckPersistenceResult>;
150
169
  /**
151
170
  * Optimistically duplicate a deck. Inserts a copy into local state with the
152
171
  * supplied `newId` immediately so the UI can navigate without awaiting the
@@ -167,6 +186,7 @@ interface DeckContextType {
167
186
  ) => void;
168
187
  reloadDecks: () => Promise<void>;
169
188
  reloadDecksWithStatus: () => Promise<DeckReloadStatus>;
189
+ refreshOpenDeck: (deckId: string) => Promise<Deck | null>;
170
190
  getDeck: (id: string) => Deck | undefined;
171
191
  addSlide: (
172
192
  deckId: string,
@@ -885,7 +905,22 @@ async function fetchDecksForCurrentRoute(): Promise<Deck[] | null> {
885
905
  }
886
906
 
887
907
  async function deleteDeckFromAPI(id: string): Promise<void> {
888
- await callAction("delete-deck", { id }, { method: "DELETE" });
908
+ try {
909
+ await callAction("delete-deck", { id }, { method: "DELETE" });
910
+ } catch (error) {
911
+ // Deleting an optimistic deck is intentionally idempotent. A create can
912
+ // fail after the server committed the row, or before it created one.
913
+ if (
914
+ !(
915
+ error &&
916
+ typeof error === "object" &&
917
+ "status" in error &&
918
+ (error as { status?: unknown }).status === 404
919
+ )
920
+ ) {
921
+ throw error;
922
+ }
923
+ }
889
924
  }
890
925
 
891
926
  async function createDeckOnAPI(deck: Deck): Promise<void> {
@@ -1081,7 +1116,7 @@ export function DeckProvider({ children }: { children: ReactNode }) {
1081
1116
  const deletion = pendingCreate
1082
1117
  ? pendingCreate.then(
1083
1118
  () => deleteDeckFromAPI(deckId),
1084
- () => undefined,
1119
+ () => deleteDeckFromAPI(deckId),
1085
1120
  )
1086
1121
  : deleteDeckFromAPI(deckId);
1087
1122
  void deletion.catch((err) => {
@@ -1267,11 +1302,11 @@ export function DeckProvider({ children }: { children: ReactNode }) {
1267
1302
  // - Dirty deck / unsaved local create → additive merge only: surface
1268
1303
  // agent-added slides without ever overwriting or dropping local slides.
1269
1304
  const refetchOpenDeckIfChanged = useCallback(
1270
- async (currentOpenId: string) => {
1305
+ async (currentOpenId: string): Promise<Deck | null> => {
1271
1306
  const serverDeck = await fetchDeckFromAPI(currentOpenId);
1272
1307
  // Null means 404 (row not created yet), a transient failure, or a
1273
1308
  // still-pending create — nothing authoritative to reconcile.
1274
- if (!serverDeck) return;
1309
+ if (!serverDeck) return null;
1275
1310
  const clientDeck = decksRef.current.find((d) => d.id === currentOpenId);
1276
1311
 
1277
1312
  const hasLocalEdits =
@@ -1281,7 +1316,7 @@ export function DeckProvider({ children }: { children: ReactNode }) {
1281
1316
  if (hasLocalEdits && clientDeck) {
1282
1317
  // Content-preserving: only ADD server slides missing locally.
1283
1318
  const merged = mergeServerAddedSlides(clientDeck, serverDeck);
1284
- if (merged === clientDeck) return; // nothing new to surface
1319
+ if (merged === clientDeck) return serverDeck; // nothing new to surface
1285
1320
  lastExternalUpdateRef.current = Date.now();
1286
1321
  setDecks((prev) => {
1287
1322
  const idx = prev.findIndex((d) => d.id === currentOpenId);
@@ -1290,16 +1325,17 @@ export function DeckProvider({ children }: { children: ReactNode }) {
1290
1325
  next[idx] = merged;
1291
1326
  return next;
1292
1327
  });
1293
- return;
1328
+ return serverDeck;
1294
1329
  }
1295
1330
 
1296
1331
  const changed =
1297
1332
  !clientDeck ||
1298
1333
  clientDeck.updatedAt !== serverDeck.updatedAt ||
1299
- clientDeck.slides.length !== serverDeck.slides.length;
1300
- if (!changed) return;
1334
+ deckContentSignature(clientDeck) !== deckContentSignature(serverDeck);
1335
+ if (!changed) return serverDeck;
1301
1336
  lastExternalUpdateRef.current = Date.now();
1302
1337
  applyRemoteDeckUpdate(serverDeck);
1338
+ return serverDeck;
1303
1339
  },
1304
1340
  [applyRemoteDeckUpdate],
1305
1341
  );
@@ -1728,19 +1764,33 @@ export function DeckProvider({ children }: { children: ReactNode }) {
1728
1764
  [noteLocalCreate, setDecksLocal],
1729
1765
  );
1730
1766
 
1731
- const ensureDeckPersisted = useCallback(async (id: string) => {
1732
- const pendingCreate = pendingCreatePromisesRef.current.get(id);
1733
- if (pendingCreate) {
1734
- try {
1735
- await pendingCreate;
1736
- return true;
1737
- } catch {
1738
- return false;
1767
+ const ensureDeckPersisted = useCallback(
1768
+ async (id: string): Promise<DeckPersistenceResult> => {
1769
+ const pendingCreate = pendingCreatePromisesRef.current.get(id);
1770
+ if (pendingCreate) {
1771
+ try {
1772
+ await pendingCreate;
1773
+ return { persisted: true };
1774
+ } catch (error) {
1775
+ return { persisted: false, reason: "request-failed", error };
1776
+ }
1739
1777
  }
1740
- }
1741
1778
 
1742
- return (await fetchDeckFromAPI(id)) !== null;
1743
- }, []);
1779
+ try {
1780
+ const result = await callAction<unknown>(
1781
+ "get-deck",
1782
+ { id },
1783
+ { method: "GET" },
1784
+ );
1785
+ return normalizeActionDeck(result)
1786
+ ? { persisted: true }
1787
+ : { persisted: false, reason: "not-found" };
1788
+ } catch (error) {
1789
+ return { persisted: false, reason: "request-failed", error };
1790
+ }
1791
+ },
1792
+ [],
1793
+ );
1744
1794
 
1745
1795
  const duplicateDeck = useCallback(
1746
1796
  (sourceDeckId: string, newId: string, title?: string): Deck | null => {
@@ -2150,6 +2200,7 @@ export function DeckProvider({ children }: { children: ReactNode }) {
2150
2200
  updateDeck,
2151
2201
  reloadDecks,
2152
2202
  reloadDecksWithStatus,
2203
+ refreshOpenDeck: refetchOpenDeckIfChanged,
2153
2204
  getDeck,
2154
2205
  addSlide,
2155
2206
  updateSlide,
@@ -14,6 +14,12 @@
14
14
 
15
15
  @source "./**/*.{ts,tsx}";
16
16
 
17
+ /* Keep the editable agent prompt readable even if the generated text utility
18
+ is missing or loses a cascade tie during the hosted build. */
19
+ .agent-composer-root [data-agent-composer-slot="editor-input"] {
20
+ color: hsl(var(--foreground));
21
+ }
22
+
17
23
  /* Hide the sidebar's built-in collapsed tab strip — AgentToggleButton in the
18
24
  toolbar serves this purpose instead, so we don't want a redundant bar. */
19
25
  button[title="Open agent sidebar"] {
@@ -684,6 +684,7 @@ const messages = {
684
684
  googleSlidesReferenceConnect:
685
685
  "Connect Google Drive to import a Slides deck.",
686
686
  googleSlidesReferenceChoose: "Choose Google Slides deck",
687
+ googleSlidesReferenceUrl: "Paste a Google Slides link",
687
688
  googleSlidesReferencePicking: "Working...",
688
689
  googleSlidesReferenceConnected:
689
690
  "Connected. Choose a Google Slides deck to import as a reusable reference.",
@@ -4,7 +4,7 @@ import { flushSync } from "react-dom";
4
4
 
5
5
  import type { NewDeckReferenceSelection } from "@/components/editor/NewDeckReferenceStep";
6
6
  import type { UploadedFile } from "@/components/editor/PromptDialog";
7
- import type { Deck } from "@/context/DeckContext";
7
+ import type { Deck, DeckPersistenceResult } from "@/context/DeckContext";
8
8
  import { createDeckAgentMessage } from "@/lib/agent-visible-message";
9
9
 
10
10
  interface DesignSystemGenerationContextResult {
@@ -100,7 +100,7 @@ function describeUploadedFilesForAgent(
100
100
  "",
101
101
  "File handling rules:",
102
102
  `- PPTX files: call \`import-pptx --filePath \"<path>\" --deckId ${deckId}\` before adding or editing slides.`,
103
- `- PDF and DOCX files: call \`import-file --filePath \"<path>\" --format auto --deckId ${deckId}\` and use the returned extracted text as source material. The returned text is capped for reliability; re-run with maxChars only if more context is needed.`,
103
+ `- PDF and DOCX files: call \`import-file --filePath \"<path>\" --format auto --deckId ${deckId}\` and use the returned extracted text as source material. For a visual PDF whose original layout should be preserved, pass \`--importIntoDeck true\` instead of rebuilding the pages from extracted text.`,
104
104
  "- Text-like files: use the uploaded-text-file blocks already included in the prompt; do not call import-file for them.",
105
105
  '- Image files with an embeddable URL can be inserted directly into slide HTML as `<img src="...">` or used as visual references.',
106
106
  "- Image files without a URL are visual/reference assets only; do not claim to have processed a PPTX/PDF/DOCX unless the relevant import action succeeds.",
@@ -150,13 +150,17 @@ export interface StartDeckGenerationOptions {
150
150
  selectedReferenceDeckId?: string | null;
151
151
  designSystems: Array<{ id: string; title: string }>;
152
152
  createDeck: CreateDeck;
153
- ensureDeckPersisted: (id: string) => Promise<boolean>;
153
+ ensureDeckPersisted: (id: string) => Promise<DeckPersistenceResult>;
154
154
  deleteDeck: (id: string) => void;
155
155
  navigate: Navigate;
156
156
  agentSubmit: SubmitAgent;
157
157
  onPromptClosed: () => void;
158
158
  onUnauthenticated: (prompt: string, hadFiles: boolean) => void;
159
- onPersistenceFailure: (prompt: string, files: UploadedFile[]) => void;
159
+ onPersistenceFailure: (
160
+ prompt: string,
161
+ files: UploadedFile[],
162
+ failure: DeckPersistenceResult,
163
+ ) => void;
160
164
  }
161
165
 
162
166
  /** Create the optimistic deck, hydrate references, and start the agent run. */
@@ -214,8 +218,8 @@ export async function startDeckGeneration({
214
218
  onPromptClosed();
215
219
 
216
220
  const persisted = await ensureDeckPersisted(deck.id);
217
- if (!persisted) {
218
- onPersistenceFailure(prompt, filesForGeneration);
221
+ if (!persisted.persisted) {
222
+ onPersistenceFailure(prompt, filesForGeneration, persisted);
219
223
  deleteDeck(deckId);
220
224
  return "failed";
221
225
  }
@@ -0,0 +1,15 @@
1
+ import { getAspectRatioDims, type AspectRatio } from "./aspect-ratios";
2
+
3
+ const LISTING_FRAME_RATIO = 16 / 9;
4
+
5
+ export function getDeckListingPreviewFrameStyle(aspectRatio?: AspectRatio) {
6
+ const dimensions = getAspectRatioDims(aspectRatio);
7
+ const isListingRatio =
8
+ dimensions.width / dimensions.height >= LISTING_FRAME_RATIO;
9
+
10
+ return {
11
+ aspectRatio: `${dimensions.width} / ${dimensions.height}`,
12
+ height: "100%",
13
+ width: isListingRatio ? "100%" : "auto",
14
+ };
15
+ }
@@ -0,0 +1,9 @@
1
+ export type DeckShareLinkKind = "editor" | "presentation";
2
+
3
+ export function getDeckShareLinkOrder(
4
+ visibility?: "private" | "org" | "public",
5
+ ): { primary: DeckShareLinkKind; secondary: DeckShareLinkKind } {
6
+ return visibility === "public"
7
+ ? { primary: "presentation", secondary: "editor" }
8
+ : { primary: "editor", secondary: "presentation" };
9
+ }
@@ -313,6 +313,94 @@ function widenNoWrapTextElements(root: HTMLElement) {
313
313
  }
314
314
  }
315
315
 
316
+ /**
317
+ * dom-to-pptx serializes CSS gradients as one malformed diagonal SVG. Imported
318
+ * slides use a repeated master grid, so materialize that grid as a transparent
319
+ * image before handing the clone to the exporter and leave the real text and
320
+ * image objects editable.
321
+ */
322
+ function materializeImportedBackgroundGrid(root: HTMLElement) {
323
+ const slideRoot = root.matches(".fmd-imported-pptx")
324
+ ? root
325
+ : root.querySelector<HTMLElement>(".fmd-imported-pptx");
326
+ if (!slideRoot) return;
327
+ const computed = window.getComputedStyle(slideRoot);
328
+ if (!computed.backgroundImage.includes("linear-gradient")) return;
329
+
330
+ const color = computed.backgroundImage.match(/rgb\([^)]*\)/)?.[0];
331
+ const size = computed.backgroundSize
332
+ .split(",")[0]
333
+ ?.trim()
334
+ .split(/\s+/)
335
+ .map((value) => Number.parseFloat(value));
336
+ const position = computed.backgroundPosition
337
+ .split(",")[0]
338
+ ?.trim()
339
+ .split(/\s+/)
340
+ .map((value) => Number.parseFloat(value));
341
+ const declaredLineWidth = computed.backgroundImage.match(
342
+ /\b0(?:px)?\s+([\d.]+)px\b/i,
343
+ )?.[1];
344
+ const lineWidth = declaredLineWidth
345
+ ? Number.parseFloat(declaredLineWidth)
346
+ : Number.NaN;
347
+ if (
348
+ !color ||
349
+ !size ||
350
+ size.length < 2 ||
351
+ !Number.isFinite(size[0]) ||
352
+ !Number.isFinite(size[1]) ||
353
+ size[0] <= 0 ||
354
+ size[1] <= 0 ||
355
+ !position ||
356
+ position.length < 2 ||
357
+ !Number.isFinite(position[0]) ||
358
+ !Number.isFinite(position[1]) ||
359
+ !Number.isFinite(lineWidth)
360
+ ) {
361
+ return;
362
+ }
363
+
364
+ const canvas = document.createElement("canvas");
365
+ canvas.width = Math.max(1, Math.round(slideRoot.clientWidth));
366
+ canvas.height = Math.max(1, Math.round(slideRoot.clientHeight));
367
+ const context = canvas.getContext("2d");
368
+ if (!context) return;
369
+ context.strokeStyle = color;
370
+ context.lineWidth = Math.max(0.5, lineWidth);
371
+
372
+ for (let x = position[0]; x < canvas.width; x += size[0]) {
373
+ context.beginPath();
374
+ context.moveTo(x + context.lineWidth / 2, 0);
375
+ context.lineTo(x + context.lineWidth / 2, canvas.height);
376
+ context.stroke();
377
+ }
378
+ for (let y = position[1]; y < canvas.height; y += size[1]) {
379
+ context.beginPath();
380
+ context.moveTo(0, y + context.lineWidth / 2);
381
+ context.lineTo(canvas.width, y + context.lineWidth / 2);
382
+ context.stroke();
383
+ }
384
+
385
+ const gridImage = document.createElement("img");
386
+ gridImage.alt = "";
387
+ gridImage.src = canvas.toDataURL("image/png");
388
+ Object.assign(gridImage.style, {
389
+ height: "100%",
390
+ left: "0",
391
+ pointerEvents: "none",
392
+ position: "absolute",
393
+ top: "0",
394
+ width: "100%",
395
+ zIndex: "0",
396
+ });
397
+ slideRoot.insertBefore(gridImage, slideRoot.firstChild);
398
+ slideRoot.style.backgroundImage = "none";
399
+ slideRoot.style.backgroundSize = "auto";
400
+ slideRoot.style.backgroundPosition = "0 0";
401
+ slideRoot.style.backgroundRepeat = "no-repeat";
402
+ }
403
+
316
404
  export async function buildDeckPptxBlob(
317
405
  deckTitle: string,
318
406
  slides: PptxExportSlide[],
@@ -341,6 +429,7 @@ export async function buildDeckPptxBlob(
341
429
  height: dims.height,
342
430
  });
343
431
  exportClones.push(clone);
432
+ materializeImportedBackgroundGrid(clone.element);
344
433
  widenNoWrapTextElements(clone.element);
345
434
  await replaceInlineSvgsWithImages(clone.element);
346
435
  await preloadImagesWithCors(clone.element);
@@ -118,6 +118,9 @@ export function animationElementKey(path: number[]): string {
118
118
  }
119
119
 
120
120
  export function findLegacyAnimationContainer(root: Element): Element | null {
121
+ const marked = root.querySelector(".fmd-animation-container");
122
+ if (marked && marked.children.length >= 1) return marked;
123
+
121
124
  const children = Array.from(root.children);
122
125
  for (let i = children.length - 1; i >= 0; i--) {
123
126
  if (children[i].children.length >= 2) return children[i];
@@ -155,6 +155,7 @@ export default function DeckEditor() {
155
155
  getDeck,
156
156
  reloadDecks,
157
157
  reloadDecksWithStatus,
158
+ refreshOpenDeck,
158
159
  updateDeck,
159
160
  updateSlide,
160
161
  deleteSlide,
@@ -396,6 +397,22 @@ export default function DeckEditor() {
396
397
  }
397
398
  }, [refetchOrg, reloadDecks]);
398
399
 
400
+ // The final generation write can race the last sync event. Pull the
401
+ // authoritative open deck when the run settles so a stale canvas does not
402
+ // require a browser refresh to reveal completed slides.
403
+ useEffect(() => {
404
+ if (
405
+ !id ||
406
+ !shouldClearNewDeckGeneratingState({
407
+ generating,
408
+ generationStarted: newDeckGenerationStarted.current,
409
+ })
410
+ ) {
411
+ return;
412
+ }
413
+ void refreshOpenDeck(id);
414
+ }, [generating, id, refreshOpenDeck]);
415
+
399
416
  // Clean up the generating URL param/ref when generation completes or when
400
417
  // the first slide lands, so partial progress is visible during long decks.
401
418
  useEffect(() => {