@agent-native/core 0.169.1 → 0.170.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 (459) hide show
  1. package/agent-native.eject.json +4 -1
  2. package/bin/agent-native.js +23 -5
  3. package/corpus/README.md +1 -1
  4. package/corpus/templates/analytics/.agents/skills/secrets/SKILL.md +11 -4
  5. package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +1 -1
  6. package/corpus/templates/analytics/app/i18n-data.ts +28 -0
  7. package/corpus/templates/analytics/app/pages/Agents.tsx +25 -1
  8. package/corpus/templates/analytics/app/routes/$.tsx +10 -0
  9. package/corpus/templates/analytics/app/routes.ts +3 -1
  10. package/corpus/templates/analytics/changelog/2026-08-22-fixed-the-agent-native-templates-first-party-dashboard-panel.md +6 -0
  11. package/corpus/templates/analytics/changelog/2026-08-22-org-admin-panels-no-longer-report-a-database-error-as-a-per.md +9 -0
  12. package/corpus/templates/analytics/changelog/2026-08-22-slack-requests-report-invalid-inputs.md +6 -0
  13. package/corpus/templates/analytics/changelog/2026-08-22-unknown-analytics-links-now-return-a-real-not-found-status.md +6 -0
  14. package/corpus/templates/analytics/docs/schemas/first-party-analytics.md +2 -1
  15. package/corpus/templates/analytics/docs/schemas/tracked-events.md +2 -0
  16. package/corpus/templates/analytics/scripts/emit-netlify-dashboard-report-cron.ts +29 -7
  17. package/corpus/templates/analytics/server/handlers/slack.ts +59 -5
  18. package/corpus/templates/analytics/server/lib/db-admin-connections.ts +11 -6
  19. package/corpus/templates/analytics/server/lib/first-party-analytics.ts +132 -2
  20. package/corpus/templates/analytics/server/lib/slack.ts +4 -2
  21. package/corpus/templates/analytics/vitest.config.ts +6 -1
  22. package/corpus/templates/assets/.agents/skills/secrets/SKILL.md +11 -4
  23. package/corpus/templates/assets/app/routes/library.tsx +5 -3
  24. package/corpus/templates/assets/app/routes.ts +3 -1
  25. package/corpus/templates/assets/changelog/2026-08-22-library-page-loads-again-instead-of-crashing-on-open.md +6 -0
  26. package/corpus/templates/assets/vitest.config.ts +6 -1
  27. package/corpus/templates/brain/.agents/skills/secrets/SKILL.md +11 -4
  28. package/corpus/templates/brain/app/components/ui/pointer-lock.ts +1 -0
  29. package/corpus/templates/brain/app/routes/sources.tsx +8 -3
  30. package/corpus/templates/brain/changelog/2026-08-22-tuning-or-adding-a-source-no-longer-leaves-the-sources-page.md +6 -0
  31. package/corpus/templates/brain/vitest.config.ts +1 -0
  32. package/corpus/templates/calendar/.agents/skills/secrets/SKILL.md +11 -4
  33. package/corpus/templates/calendar/actions/list-booking-links.ts +83 -4
  34. package/corpus/templates/calendar/actions/update-booking-link.ts +4 -3
  35. package/corpus/templates/calendar/app/components/calendar/EventDetailPanel.tsx +11 -3
  36. package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +1 -1
  37. package/corpus/templates/calendar/app/components/calendar/GoogleConnectBanner.tsx +103 -44
  38. package/corpus/templates/calendar/app/components/calendar/OutOfOfficeEvent.tsx +28 -24
  39. package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +9 -2
  40. package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +47 -58
  41. package/corpus/templates/calendar/app/hooks/use-booking-links.ts +5 -1
  42. package/corpus/templates/calendar/app/lib/event-layout.ts +52 -26
  43. package/corpus/templates/calendar/app/pages/BookingLinksPage.tsx +126 -98
  44. package/corpus/templates/calendar/app/pages/CalendarView.tsx +1 -0
  45. package/corpus/templates/calendar/app/pages/Settings.tsx +88 -81
  46. package/corpus/templates/calendar/app/routes.ts +3 -1
  47. package/corpus/templates/calendar/changelog/2026-08-22-booking-link-visibility-respects-shared-access.md +6 -0
  48. package/corpus/templates/calendar/changelog/2026-08-22-clicking-an-out-of-office-event-s-marker-no-longer-creates-a.md +6 -0
  49. package/corpus/templates/calendar/changelog/2026-08-22-event-detail-views-now-show-your-calendar-timezone.md +6 -0
  50. package/corpus/templates/calendar/changelog/2026-08-22-google-calendar-can-now-connect-with-the-shared-google-oauth.md +6 -0
  51. package/corpus/templates/calendar/changelog/2026-08-22-overlapping-events-now-show-each-others-boundaries.md +6 -0
  52. package/corpus/templates/calendar/changelog/2026-08-22-public-booking-pages-now-offer-time-slots-from-the-host-s-we.md +6 -0
  53. package/corpus/templates/calendar/server/handlers/bookings.ts +5 -7
  54. package/corpus/templates/calendar/server/handlers/google-auth.ts +10 -2
  55. package/corpus/templates/calendar/server/lib/google-calendar.ts +139 -14
  56. package/corpus/templates/calendar/server/onboarding.ts +85 -0
  57. package/corpus/templates/calendar/server/plugins/agent-chat.ts +2 -0
  58. package/corpus/templates/calendar/shared/api.ts +9 -1
  59. package/corpus/templates/chat/.agents/skills/secrets/SKILL.md +11 -4
  60. package/corpus/templates/chat/app/routes.ts +3 -1
  61. package/corpus/templates/chat/vitest.config.ts +8 -0
  62. package/corpus/templates/clips/.agents/skills/secrets/SKILL.md +11 -4
  63. package/corpus/templates/clips/actions/get-meeting.ts +9 -4
  64. package/corpus/templates/clips/actions/list-recordings.ts +16 -3
  65. package/corpus/templates/clips/actions/search-meetings.ts +1 -0
  66. package/corpus/templates/clips/actions/view-screen.ts +8 -1
  67. package/corpus/templates/clips/app/components/meetings/meeting-history-row.tsx +32 -1
  68. package/corpus/templates/clips/app/components/player/delete-recording-menu.tsx +1 -1
  69. package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +29 -1
  70. package/corpus/templates/clips/app/i18n/en-US.ts +5 -0
  71. package/corpus/templates/clips/app/routes/_app.meetings.$meetingId.tsx +33 -4
  72. package/corpus/templates/clips/app/routes/_app.meetings._index.tsx +1 -0
  73. package/corpus/templates/clips/app/routes/access-request.approve.tsx +16 -9
  74. package/corpus/templates/clips/app/routes/embed.$shareId.tsx +17 -7
  75. package/corpus/templates/clips/app/routes/share.$shareId.tsx +17 -7
  76. package/corpus/templates/clips/changelog/2026-08-21-camera-bubble-black-circle.md +6 -0
  77. package/corpus/templates/clips/changelog/2026-08-22-screen-recordings-respect-the-microphone-toggle.md +6 -0
  78. package/corpus/templates/clips/changelog/2026-08-22-the-recordings-library-no-longer-fails-right-after-server-start.md +6 -0
  79. package/corpus/templates/clips/changelog/2026-08-23-the-agent-can-see-your-library-right-after-server-start.md +6 -0
  80. package/corpus/templates/clips/chrome-extension/src/background.ts +1 -2
  81. package/corpus/templates/clips/chrome-extension/src/native-transcription.ts +39 -7
  82. package/corpus/templates/clips/chrome-extension/src/offscreen.ts +21 -25
  83. package/corpus/templates/clips/desktop/src/app.tsx +53 -24
  84. package/corpus/templates/clips/desktop/src/lib/bubble-playback.ts +68 -0
  85. package/corpus/templates/clips/desktop/src/lib/recorder.ts +3 -0
  86. package/corpus/templates/clips/desktop/src/lib/transcription-capture.ts +72 -14
  87. package/corpus/templates/clips/desktop/src/lib/updater.ts +8 -3
  88. package/corpus/templates/clips/desktop/src/overlays/bubble.tsx +162 -20
  89. package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +43 -6
  90. package/corpus/templates/clips/desktop/src-tauri/src/native_screen/custom_capture.rs +150 -13
  91. package/corpus/templates/clips/desktop/src-tauri/src/tray.rs +12 -0
  92. package/corpus/templates/clips/server/lib/calendar-event-meetings.ts +28 -3
  93. package/corpus/templates/clips/server/lib/emails.ts +17 -33
  94. package/corpus/templates/content/.agents/skills/secrets/SKILL.md +11 -4
  95. package/corpus/templates/content/app/components/editor/VisualEditor.tsx +140 -15
  96. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +12 -14
  97. package/corpus/templates/content/app/components/ui/pointer-lock.ts +1 -0
  98. package/corpus/templates/content/app/hooks/use-content-database.ts +18 -2
  99. package/corpus/templates/content/app/hooks/use-local-storage.ts +38 -22
  100. package/corpus/templates/content/app/i18n-data.ts +25 -0
  101. package/corpus/templates/content/app/routes.ts +3 -1
  102. package/corpus/templates/content/changelog/2026-08-22-code-blocks-inserted-from-the-slash-menu-no-longer-get-stuck.md +6 -0
  103. package/corpus/templates/content/changelog/2026-08-22-the-sidebar-page-tree-no-longer-flashes-empty-after-creating-a-page.md +6 -0
  104. package/corpus/templates/content/docs/solutions/2026-08-21-content-mermaid-rendering-shape.md +233 -0
  105. package/corpus/templates/content/server/plugins/agent-chat.ts +9 -2
  106. package/corpus/templates/content/vitest.config.ts +7 -1
  107. package/corpus/templates/crm/.agents/skills/secrets/SKILL.md +11 -4
  108. package/corpus/templates/design/.agents/skills/secrets/SKILL.md +11 -4
  109. package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +1383 -88
  110. package/corpus/templates/design/actions/generate-design.ts +98 -47
  111. package/corpus/templates/design/actions/get-design-system.ts +6 -1
  112. package/corpus/templates/design/actions/refresh-design-system-with-builder.ts +146 -0
  113. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +70 -26
  114. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +284 -136
  115. package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +2057 -141
  116. package/corpus/templates/design/app/components/design/editor/DesignBottomToolbar.tsx +6 -2
  117. package/corpus/templates/design/app/components/design/editor/DesignWorkspaceRail.tsx +4 -4
  118. package/corpus/templates/design/app/components/design/keyboard-shortcuts.ts +10 -1
  119. package/corpus/templates/design/app/components/design/multi-screen/alt-hover-measurement.ts +19 -2
  120. package/corpus/templates/design/app/components/design/multi-screen/types.ts +9 -2
  121. package/corpus/templates/design/app/components/layout/Header.tsx +15 -0
  122. package/corpus/templates/design/app/components/layout/Layout.tsx +7 -2
  123. package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +11 -4
  124. package/corpus/templates/design/app/i18n-data.ts +1 -0
  125. package/corpus/templates/design/app/i18n-keyboard-shortcuts.ts +12 -0
  126. package/corpus/templates/design/app/lib/design-system-data.ts +68 -0
  127. package/corpus/templates/design/app/pages/DesignEditor.tsx +77 -35
  128. package/corpus/templates/design/app/pages/DesignSystems.tsx +136 -42
  129. package/corpus/templates/design/app/pages/Index.tsx +2 -0
  130. package/corpus/templates/design/app/pages/Templates.tsx +0 -10
  131. package/corpus/templates/design/app/pages/design-editor/code-layer-state.ts +10 -0
  132. package/corpus/templates/design/app/pages/design-editor/collab-sync.ts +50 -0
  133. package/corpus/templates/design/app/pages/design-editor/commands/apply-design-editor-command.ts +1 -1
  134. package/corpus/templates/design/app/pages/design-editor/commands/apply-file-content-update.ts +10 -8
  135. package/corpus/templates/design/app/pages/design-editor/commands/apply-local-content-update.ts +6 -6
  136. package/corpus/templates/design/app/pages/design-editor/commands/apply-pending-visual-styles-with-agent.ts +1 -1
  137. package/corpus/templates/design/app/pages/design-editor/commands/commit-visual-styles.ts +18 -7
  138. package/corpus/templates/design/app/pages/design-editor/commands/escape-hotkey.ts +4 -90
  139. package/corpus/templates/design/app/pages/design-editor/commands/layer-marquee-selection-change.ts +2 -1
  140. package/corpus/templates/design/app/pages/design-editor/commands/layer-selection-change.ts +4 -3
  141. package/corpus/templates/design/app/pages/design-editor/commands/screen-element-select.ts +12 -2
  142. package/corpus/templates/design/app/pages/design-editor/commands/screen-visual-style-change.ts +9 -2
  143. package/corpus/templates/design/app/pages/design-editor/commands/send-runtime-layer-move-semantic-handoff.ts +1 -1
  144. package/corpus/templates/design/app/pages/design-editor/commands/send-runtime-layer-semantic-handoff.ts +1 -1
  145. package/corpus/templates/design/app/pages/design-editor/commands/send-runtime-layer-state-semantic-handoff.ts +1 -1
  146. package/corpus/templates/design/app/pages/design-editor/commands/start-sidebar-resize.ts +1 -1
  147. package/corpus/templates/design/app/pages/design-editor/editor-state.ts +11 -1
  148. package/corpus/templates/design/app/pages/design-editor/effects/adopt-db-file-content.ts +11 -19
  149. package/corpus/templates/design/app/pages/design-editor/effects/observe-collab-text.ts +6 -6
  150. package/corpus/templates/design/app/pages/design-editor/effects/publish-agent-selection-context.ts +1 -1
  151. package/corpus/templates/design/app/pages/design-editor/effects/seed-collab-content.ts +12 -15
  152. package/corpus/templates/design/app/pages/design-editor/selection-state.ts +5 -59
  153. package/corpus/templates/design/app/pages/design-editor/tool-state.ts +8 -0
  154. package/corpus/templates/design/app/pages/design-editor/types.ts +3 -3
  155. package/corpus/templates/design/app/routes.ts +3 -1
  156. package/corpus/templates/design/changelog/2026-08-20-canvas-edits-patch-the-frame-instead-of-rebuilding-it.md +6 -0
  157. package/corpus/templates/design/changelog/2026-08-21-builder-design-system-imports-reconcile-after-indexing.md +6 -0
  158. package/corpus/templates/design/changelog/2026-08-21-draw-mode-needs-shift-y.md +6 -0
  159. package/corpus/templates/design/changelog/2026-08-21-eyedropper-shortcut.md +6 -0
  160. package/corpus/templates/design/changelog/2026-08-21-figma-style-alignment-guides-and-snapping.md +6 -0
  161. package/corpus/templates/design/changelog/2026-08-21-group-transforms-keep-the-selection.md +6 -0
  162. package/corpus/templates/design/changelog/2026-08-21-inspector-fields-keep-focus-on-enter.md +6 -0
  163. package/corpus/templates/design/changelog/2026-08-21-pen-alt-keeps-the-incoming-handle.md +6 -0
  164. package/corpus/templates/design/changelog/2026-08-21-pen-on-the-board-creates-one-vector.md +6 -0
  165. package/corpus/templates/design/changelog/2026-08-21-scale-a-multi-selection-from-the-group-handles.md +6 -0
  166. package/corpus/templates/design/changelog/2026-08-21-scale-resizes-text-with-the-object.md +6 -0
  167. package/corpus/templates/design/changelog/2026-08-21-selecting-another-object-keeps-the-scale-tool-armed.md +6 -0
  168. package/corpus/templates/design/changelog/2026-08-21-the-shape-tool-remembers-the-shape-you-picked.md +6 -0
  169. package/corpus/templates/design/changelog/2026-08-21-vectors-drawn-in-a-frame-land-where-you-drew-them.md +6 -0
  170. package/corpus/templates/design/changelog/2026-08-22-multi-screen-generation-no-longer-loses-a-saved-screens-layo.md +6 -0
  171. package/corpus/templates/design/changelog/2026-08-22-rename-and-search-fields-are-labeled-for-screen-readers.md +6 -0
  172. package/corpus/templates/design/package.json +2 -0
  173. package/corpus/templates/design/server/lib/builder-design-system-proxy.ts +311 -0
  174. package/corpus/templates/design/shared/canvas-math.ts +612 -206
  175. package/corpus/templates/design/shared/pen-path.ts +37 -0
  176. package/corpus/templates/design/vitest.config.ts +7 -1
  177. package/corpus/templates/dispatch/.agents/skills/secrets/SKILL.md +11 -4
  178. package/corpus/templates/dispatch/actions/list-workspace-connections.ts +34 -3
  179. package/corpus/templates/dispatch/app/routes/integrations.tsx +55 -21
  180. package/corpus/templates/dispatch/app/routes.ts +3 -1
  181. package/corpus/templates/factory/.agents/skills/secrets/SKILL.md +11 -4
  182. package/corpus/templates/factory/.env.example +2 -7
  183. package/corpus/templates/factory/AGENTS.md +3 -0
  184. package/corpus/templates/factory/README.md +5 -3
  185. package/corpus/templates/factory/actions/create-factory.ts +16 -3
  186. package/corpus/templates/factory/actions/get-slack-feedback-context.ts +2 -0
  187. package/corpus/templates/factory/actions/get-triage-item.ts +2 -0
  188. package/corpus/templates/factory/actions/list-factory-audit.ts +116 -36
  189. package/corpus/templates/factory/actions/list-factory-automations.ts +2 -1
  190. package/corpus/templates/factory/actions/list-triage-items.ts +22 -19
  191. package/corpus/templates/factory/actions/run-factory-automation.ts +7 -3
  192. package/corpus/templates/factory/actions/save-factory-automation.ts +5 -2
  193. package/corpus/templates/factory/actions/save-triage-config.ts +2 -8
  194. package/corpus/templates/factory/actions/start-builder-for-item.ts +21 -0
  195. package/corpus/templates/factory/app/components/factory/FactoryAuditView.tsx +229 -297
  196. package/corpus/templates/factory/app/components/factory/FactorySettingsView.tsx +397 -247
  197. package/corpus/templates/factory/app/components/factory/FactorySourceSettingsGroup.tsx +33 -0
  198. package/corpus/templates/factory/app/components/factory/NewFactoryForm.tsx +202 -162
  199. package/corpus/templates/factory/app/i18n/en-US.ts +32 -4
  200. package/corpus/templates/factory/app/routes/factory.tsx +84 -11
  201. package/corpus/templates/factory/app/routes.ts +3 -1
  202. package/corpus/templates/factory/changelog/2026-08-21-activity-runs-use-automation-display-names.md +6 -0
  203. package/corpus/templates/factory/changelog/2026-08-21-create-and-settings-source-cards.md +6 -0
  204. package/corpus/templates/factory/changelog/2026-08-21-keep-automations-visible-while-running.md +6 -0
  205. package/corpus/templates/factory/changelog/2026-08-21-nested-factory-automations-can-poll.md +6 -0
  206. package/corpus/templates/factory/changelog/2026-08-21-settings-sticky-unsaved-bar.md +6 -0
  207. package/corpus/templates/factory/server/connectors/credentials.ts +10 -5
  208. package/corpus/templates/factory/server/lib/factory-audit-report.ts +412 -0
  209. package/corpus/templates/factory/server/lib/factory-config-reconcile.ts +321 -0
  210. package/corpus/templates/factory/server/lib/factory-scope.ts +25 -2
  211. package/corpus/templates/factory/server/lib/require-factory-automation.ts +13 -4
  212. package/corpus/templates/factory/server/plugins/factory-migrations.ts +148 -4
  213. package/corpus/templates/factory/server/plugins/factory-scheduler-job.ts +4 -6
  214. package/corpus/templates/factory/vitest.config.ts +17 -2
  215. package/corpus/templates/forms/.agents/skills/secrets/SKILL.md +11 -4
  216. package/corpus/templates/forms/app/routes/_app.settings.tsx +4 -1
  217. package/corpus/templates/forms/changelog/2026-08-22-the-extensions-link-now-opens-the-extensions-tab-instead-o.md +6 -0
  218. package/corpus/templates/forms/server/lib/public-form-ssr.ts +11 -1
  219. package/corpus/templates/forms/vitest.config.ts +1 -0
  220. package/corpus/templates/macros/.agents/skills/secrets/SKILL.md +11 -4
  221. package/corpus/templates/macros/app/routes.ts +3 -1
  222. package/corpus/templates/macros/vitest.config.ts +6 -1
  223. package/corpus/templates/mail/.agents/skills/secrets/SKILL.md +11 -4
  224. package/corpus/templates/mail/actions/manage-gmail-filters.ts +10 -2
  225. package/corpus/templates/mail/app/components/GoogleConnectBanner.tsx +100 -37
  226. package/corpus/templates/mail/app/components/email/IntegrationsSidebar.tsx +14 -2
  227. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +66 -36
  228. package/corpus/templates/mail/app/hooks/use-google-auth.ts +2 -0
  229. package/corpus/templates/mail/app/lib/google-oauth-setup.ts +17 -0
  230. package/corpus/templates/mail/app/pages/InboxPage.tsx +69 -9
  231. package/corpus/templates/mail/app/routes/$.tsx +9 -0
  232. package/corpus/templates/mail/app/routes/$view.$threadId.tsx +23 -1
  233. package/corpus/templates/mail/app/routes/$view.tsx +47 -1
  234. package/corpus/templates/mail/app/routes.ts +3 -1
  235. package/corpus/templates/mail/changelog/2026-08-22-gmail-can-now-connect-with-the-shared-google-oauth.md +6 -0
  236. package/corpus/templates/mail/changelog/2026-08-22-gmail-filters-now-shows-the-real-error.md +6 -0
  237. package/corpus/templates/mail/changelog/2026-08-22-unknown-mail-urls-now-show-the-404-page.md +6 -0
  238. package/corpus/templates/mail/server/handlers/google-auth.ts +11 -2
  239. package/corpus/templates/mail/server/lib/google-auth.ts +92 -12
  240. package/corpus/templates/mail/server/onboarding.ts +66 -18
  241. package/corpus/templates/mail/vitest.config.ts +6 -1
  242. package/corpus/templates/plan/.agents/skills/secrets/SKILL.md +11 -4
  243. package/corpus/templates/plan/app/routes/settings.tsx +4 -1
  244. package/corpus/templates/plan/app/routes.ts +3 -1
  245. package/corpus/templates/plan/changelog/2026-08-22-the-extensions-link-now-opens-the-extensions-tab-instead-o.md +6 -0
  246. package/corpus/templates/plan/netlify.toml +1 -1
  247. package/corpus/templates/slides/.agents/skills/secrets/SKILL.md +11 -4
  248. package/corpus/templates/slides/actions/patch-deck.ts +79 -10
  249. package/corpus/templates/slides/actions/update-slide.ts +11 -1
  250. package/corpus/templates/slides/app/components/deck/SlideRenderer.tsx +14 -4
  251. package/corpus/templates/slides/app/components/editor/ExportMenu.tsx +10 -52
  252. package/corpus/templates/slides/app/components/editor/GoogleDocImportHint.tsx +8 -53
  253. package/corpus/templates/slides/app/components/editor/GoogleDriveConnectionCta.tsx +9 -75
  254. package/corpus/templates/slides/app/components/editor/GoogleSlidesReferenceImport.tsx +8 -60
  255. package/corpus/templates/slides/app/components/editor/SlideContextToolbar.tsx +10 -2
  256. package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +19 -7
  257. package/corpus/templates/slides/app/lib/sanitize-slide-html.ts +49 -36
  258. package/corpus/templates/slides/app/routes/access-request.approve.tsx +16 -9
  259. package/corpus/templates/slides/app/routes.ts +3 -1
  260. package/corpus/templates/slides/changelog/2026-08-22-already-uploaded-chat-images-are-no-longer-dropped.md +6 -0
  261. package/corpus/templates/slides/changelog/2026-08-22-google-drive-and-slides-can-now-connect-with-the-shared-google-oauth.md +6 -0
  262. package/corpus/templates/slides/changelog/2026-08-22-multi-slide-repairs-now-report-slides-that-still-overflow.md +6 -0
  263. package/corpus/templates/slides/changelog/2026-08-22-update-slide-now-reports-which-batched-edit-was-skipped.md +6 -0
  264. package/corpus/templates/slides/server/handlers/google-docs-auth.ts +52 -1
  265. package/corpus/templates/slides/server/lib/chat-attachments.ts +29 -3
  266. package/corpus/templates/slides/server/lib/google-docs-oauth.ts +66 -16
  267. package/corpus/templates/slides/server/lib/slide-content-patch.ts +13 -2
  268. package/corpus/templates/slides/server/plugins/agent-chat.ts +5 -2
  269. package/corpus/templates/slides/tsconfig.json +5 -0
  270. package/corpus/templates/slides/vitest.config.ts +6 -1
  271. package/corpus/templates/tasks/.agents/skills/secrets/SKILL.md +11 -4
  272. package/corpus/templates/tasks/app/routes/settings.tsx +4 -1
  273. package/corpus/templates/tasks/app/routes.ts +3 -1
  274. package/corpus/templates/tasks/changelog/2026-08-22-the-extensions-link-now-opens-the-extensions-tab-instead-o.md +6 -0
  275. package/corpus/templates/tasks/vitest.config.ts +7 -1
  276. package/dist/action.d.ts +91 -0
  277. package/dist/action.js +50 -0
  278. package/dist/agent/abort-reasons.d.ts +38 -0
  279. package/dist/agent/abort-reasons.js +49 -0
  280. package/dist/agent/engine/ai-sdk-engine.js +8 -5
  281. package/dist/agent/engine/anthropic-engine.js +7 -5
  282. package/dist/agent/engine/first-event-timeout.d.ts +42 -17
  283. package/dist/agent/engine/first-event-timeout.js +67 -25
  284. package/dist/agent/production-agent.d.ts +23 -0
  285. package/dist/agent/production-agent.js +107 -102
  286. package/dist/agent/run-loop-with-resume.d.ts +2 -28
  287. package/dist/agent/run-loop-with-resume.js +25 -40
  288. package/dist/agent/run-manager.js +5 -4
  289. package/dist/agent/run-store.d.ts +55 -0
  290. package/dist/agent/run-store.js +124 -1
  291. package/dist/agent/tool-search.js +2 -1
  292. package/dist/agent/types.d.ts +9 -4
  293. package/dist/app-config/configuration-error.d.ts +11 -0
  294. package/dist/app-config/configuration-error.js +14 -0
  295. package/dist/app-config/index.d.ts +1 -0
  296. package/dist/app-config/index.js +1 -0
  297. package/dist/app-config/integrations.d.ts +1 -0
  298. package/dist/app-config/integrations.js +10 -0
  299. package/dist/app-config/plugins.d.ts +34 -0
  300. package/dist/app-config/plugins.js +39 -0
  301. package/dist/app-config/run-lifecycle-invariants.d.ts +18 -9
  302. package/dist/app-config/run-lifecycle-invariants.js +18 -25
  303. package/dist/app-config/schema.d.ts +16 -0
  304. package/dist/app-config/schema.js +2 -0
  305. package/dist/chat-threads/schema-migrations.js +20 -0
  306. package/dist/chat-threads/store.js +21 -4
  307. package/dist/cli/native-dependencies.d.ts +4 -0
  308. package/dist/cli/native-dependencies.js +15 -0
  309. package/dist/client/EnvironmentBadge.d.ts +1 -1
  310. package/dist/client/EnvironmentBadge.js +40 -5
  311. package/dist/client/MultiTabAssistantChat.d.ts +1 -1
  312. package/dist/client/MultiTabAssistantChat.js +35 -14
  313. package/dist/client/agent-chat/index.d.ts +1 -1
  314. package/dist/client/agent-chat/index.js +1 -1
  315. package/dist/client/agent-page/use-jobs.d.ts +2 -1
  316. package/dist/client/agent-page/use-jobs.js +3 -5
  317. package/dist/client/agent-sidebar-state.js +3 -1
  318. package/dist/client/blocks/library/code-tabs.js +5 -0
  319. package/dist/client/blocks/library/code.js +1 -0
  320. package/dist/client/chat-first/apps-rail.js +2 -2
  321. package/dist/client/chat-model-groups.d.ts +12 -0
  322. package/dist/client/chat-model-groups.js +3 -2
  323. package/dist/client/integrations/GoogleProductLogo.d.ts +5 -0
  324. package/dist/client/integrations/GoogleProductLogo.js +45 -0
  325. package/dist/client/integrations/index.d.ts +2 -0
  326. package/dist/client/integrations/index.js +2 -0
  327. package/dist/client/integrations/workspace-provider-oauth.d.ts +8 -0
  328. package/dist/client/integrations/workspace-provider-oauth.js +13 -0
  329. package/dist/client/resources/mcp-integration-catalog.js +0 -29
  330. package/dist/client/settings/SettingsTabsPage.js +10 -6
  331. package/dist/client/sharing/ShareButton.js +11 -2
  332. package/dist/client/use-chat-models.d.ts +6 -0
  333. package/dist/client/use-chat-models.js +10 -0
  334. package/dist/client/use-db-sync.js +27 -9
  335. package/dist/connections/catalog.d.ts +111 -9
  336. package/dist/connections/catalog.js +86 -30
  337. package/dist/db/create-get-db.js +18 -0
  338. package/dist/db/ddl-guard.d.ts +0 -4
  339. package/dist/db/ddl-guard.js +46 -0
  340. package/dist/deploy/build.d.ts +19 -0
  341. package/dist/deploy/build.js +190 -16
  342. package/dist/deploy/function-bundle.d.ts +45 -0
  343. package/dist/deploy/function-bundle.js +337 -0
  344. package/dist/deploy/workspace-deploy.js +19 -1
  345. package/dist/eject/workspace-connections.js +4 -0
  346. package/dist/email-catalog/registry.d.ts +4 -0
  347. package/dist/email-catalog/registry.js +79 -14
  348. package/dist/extensions/content-patch.js +14 -2
  349. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  350. package/dist/integrations/plugin.d.ts +10 -0
  351. package/dist/integrations/plugin.js +40 -6
  352. package/dist/jobs/actions/run-automation-now.d.ts +2 -1
  353. package/dist/jobs/actions/run-automation-now.js +11 -5
  354. package/dist/jobs/frontmatter.js +53 -2
  355. package/dist/jobs/run-now.d.ts +11 -1
  356. package/dist/jobs/run-now.js +42 -7
  357. package/dist/jobs/scheduler.d.ts +1 -0
  358. package/dist/jobs/scheduler.js +2 -1
  359. package/dist/localization/core-messages/ar-SA.js +3 -0
  360. package/dist/localization/core-messages/de-DE.js +3 -0
  361. package/dist/localization/core-messages/en-US.d.ts +3 -0
  362. package/dist/localization/core-messages/en-US.js +3 -0
  363. package/dist/localization/core-messages/es-ES.js +3 -0
  364. package/dist/localization/core-messages/fr-FR.js +3 -0
  365. package/dist/localization/core-messages/hi-IN.js +3 -0
  366. package/dist/localization/core-messages/ja-JP.js +3 -0
  367. package/dist/localization/core-messages/ko-KR.js +3 -0
  368. package/dist/localization/core-messages/pt-BR.js +3 -0
  369. package/dist/localization/core-messages/zh-CN.js +3 -0
  370. package/dist/localization/core-messages/zh-TW.js +3 -0
  371. package/dist/localization/core-messages.d.ts +3 -0
  372. package/dist/localization/default-messages.d.ts +2 -5
  373. package/dist/localization/default-messages.js +2 -5
  374. package/dist/mcp/build-server.d.ts +9 -0
  375. package/dist/mcp/build-server.js +37 -8
  376. package/dist/mcp-client/oauth-client.d.ts +7 -0
  377. package/dist/mcp-client/oauth-client.js +12 -1
  378. package/dist/oauth-tokens/index.d.ts +1 -1
  379. package/dist/oauth-tokens/index.js +1 -1
  380. package/dist/oauth-tokens/lifecycle.d.ts +11 -0
  381. package/dist/oauth-tokens/lifecycle.js +17 -0
  382. package/dist/oauth-tokens/store.js +7 -0
  383. package/dist/observability/posthog-ai.d.ts +15 -1
  384. package/dist/observability/posthog-ai.js +24 -12
  385. package/dist/observability/routes.d.ts +3 -3
  386. package/dist/observability/traces.js +158 -28
  387. package/dist/onboarding/app-profile.js +2 -2
  388. package/dist/onboarding/plugin.js +10 -2
  389. package/dist/onboarding/types.d.ts +2 -0
  390. package/dist/provider-api/actions/custom-provider-registration.d.ts +1 -1
  391. package/dist/provider-api/actions/provider-api.d.ts +2 -2
  392. package/dist/provider-api/index.js +2 -0
  393. package/dist/resources/store.js +13 -4
  394. package/dist/scripts/agent-engines/list-agent-engines.js +29 -3
  395. package/dist/secrets/register-framework-secrets.js +1 -1
  396. package/dist/server/action-discovery.js +5 -0
  397. package/dist/server/agent-chat/action-filters-a2a.d.ts +27 -3
  398. package/dist/server/agent-chat/action-filters-a2a.js +48 -9
  399. package/dist/server/agent-chat-plugin.js +36 -9
  400. package/dist/server/agent-discovery.js +43 -20
  401. package/dist/server/auth.js +18 -16
  402. package/dist/server/beta-opt-out-html.js +45 -4
  403. package/dist/server/better-auth-instance.d.ts +2 -1
  404. package/dist/server/better-auth-instance.js +23 -7
  405. package/dist/server/builder-design-systems.d.ts +4 -1
  406. package/dist/server/builder-design-systems.js +87 -6
  407. package/dist/server/builder-oauth.d.ts +1 -7
  408. package/dist/server/builder-oauth.js +80 -163
  409. package/dist/server/core-routes-plugin.d.ts +29 -0
  410. package/dist/server/core-routes-plugin.js +100 -20
  411. package/dist/server/default-plugins.d.ts +18 -0
  412. package/dist/server/default-plugins.js +22 -0
  413. package/dist/server/edge.d.ts +1 -0
  414. package/dist/server/edge.js +1 -0
  415. package/dist/server/framework-request-handler.js +31 -3
  416. package/dist/server/google-oauth.d.ts +3 -0
  417. package/dist/server/google-oauth.js +3 -0
  418. package/dist/server/index.d.ts +4 -4
  419. package/dist/server/index.js +3 -3
  420. package/dist/server/onboarding-html.js +37 -3
  421. package/dist/server/realtime-token.d.ts +1 -1
  422. package/dist/server/transcribe-voice.d.ts +1 -1
  423. package/dist/server/workspace-provider-oauth.d.ts +6 -1
  424. package/dist/server/workspace-provider-oauth.js +72 -20
  425. package/dist/shared/agent-sidebar-url.d.ts +1 -0
  426. package/dist/shared/agent-sidebar-url.js +1 -0
  427. package/dist/shared/environment-lanes.d.ts +2 -0
  428. package/dist/shared/environment-lanes.js +3 -1
  429. package/dist/shared/index.d.ts +3 -1
  430. package/dist/shared/index.js +3 -1
  431. package/dist/shared/surface-visibility.d.ts +31 -0
  432. package/dist/shared/surface-visibility.js +57 -0
  433. package/dist/templates/chat/.agents/skills/secrets/SKILL.md +11 -4
  434. package/dist/templates/chat/app/routes.ts +3 -1
  435. package/dist/templates/chat/vitest.config.ts +8 -0
  436. package/dist/templates/default/.agents/skills/secrets/SKILL.md +11 -4
  437. package/dist/templates/default/app/routes.ts +3 -1
  438. package/dist/templates/headless/.agents/skills/secrets/SKILL.md +11 -4
  439. package/dist/templates/workspace-core/.agents/skills/secrets/SKILL.md +11 -4
  440. package/dist/tracking/registry.d.ts +11 -0
  441. package/dist/tracking/registry.js +5 -2
  442. package/dist/triggers/actions.js +10 -3
  443. package/dist/usage/store.js +23 -3
  444. package/dist/user-profile/actions/get-auth-methods.js +18 -5
  445. package/dist/vite/client.js +24 -5
  446. package/docs/content/actions-access-control.mdx +43 -4
  447. package/docs/content/actions-defining.mdx +16 -0
  448. package/docs/content/template-clips-capture-everywhere.mdx +29 -30
  449. package/docs/content/template-clips-developers.mdx +4 -4
  450. package/docs/content/template-clips.mdx +3 -1
  451. package/package.json +2 -2
  452. package/src/eject/workspace-connections.ts +4 -0
  453. package/src/templates/chat/.agents/skills/secrets/SKILL.md +11 -4
  454. package/src/templates/chat/app/routes.ts +3 -1
  455. package/src/templates/chat/vitest.config.ts +8 -0
  456. package/src/templates/default/.agents/skills/secrets/SKILL.md +11 -4
  457. package/src/templates/default/app/routes.ts +3 -1
  458. package/src/templates/headless/.agents/skills/secrets/SKILL.md +11 -4
  459. package/src/templates/workspace-core/.agents/skills/secrets/SKILL.md +11 -4
@@ -1,4 +1,6 @@
1
1
  import { type RouteConfig } from "@react-router/dev/routes";
2
2
  import { flatRoutes } from "@react-router/fs-routes";
3
3
 
4
- export default flatRoutes() satisfies RouteConfig;
4
+ export default flatRoutes({
5
+ ignoredRouteFiles: ["**/*.test.{ts,tsx}", "**/*.spec.{ts,tsx}"],
6
+ }) satisfies RouteConfig;
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-08-22
4
+ ---
5
+
6
+ The Extensions link now opens the Extensions tab in Settings instead of silently landing on General.
@@ -1,6 +1,6 @@
1
1
  [build]
2
2
  ignore = "node ./scripts/netlify-ignore-build.mjs plan"
3
- command = "export DATABASE_URL=${NETLIFY_DATABASE_URL:-$DATABASE_URL} && pnpm install && NITRO_PRESET=netlify pnpm --filter plan build && if [ \"${CONTEXT:-}\" = \"production\" ] || [ \"${AGENT_NATIVE_RUN_RELEASE_MIGRATIONS:-}\" = \"1\" ]; then pnpm --filter plan migrate:production; fi"
3
+ command = "if [ \"${agentNativePrebuiltBuild:-}\" = \"true\" ]; then export DATABASE_URL=\"${agentNativePrebuiltDatabaseUrl:?}\" BETTER_AUTH_SECRET=\"${agentNativePrebuiltAuthSecret:?}\"; else export DATABASE_URL=${NETLIFY_DATABASE_URL:-$DATABASE_URL}; fi && pnpm install && NITRO_PRESET=netlify pnpm --filter plan build && if { [ \"${CONTEXT:-}\" = \"production\" ] || [ \"${AGENT_NATIVE_RUN_RELEASE_MIGRATIONS:-}\" = \"1\" ]; } && [ \"${agentNativePrebuiltBuild:-}\" != \"true\" ]; then pnpm --filter plan migrate:production; fi"
4
4
  publish = "templates/plan/dist"
5
5
  functions = "templates/plan/.netlify/functions-internal"
6
6
 
@@ -19,10 +19,17 @@ data, and generated extension/app content may mention credential **names** such
19
19
  as `OPENAI_API_KEY`, but must not contain real API keys, tokens, webhook URLs,
20
20
  signing secrets, OAuth refresh tokens, or private Builder/customer data.
21
21
 
22
- Secret values are supplied at runtime through deployment configuration, the
23
- encrypted `app_secrets` vault, `saveCredential` / `resolveCredential`, OAuth, or
24
- `${keys.NAME}` substitution. Examples must use obvious placeholders such as
25
- `<OPENAI_API_KEY>` or `${keys.SLACK_WEBHOOK}`, not real-looking copied values.
22
+ Provider secret values are supplied at runtime through the encrypted
23
+ `app_secrets` vault, `saveCredential` / `resolveCredential`, OAuth, or
24
+ `${keys.NAME}` substitution. Deployment configuration is reserved for
25
+ deploy-level secrets and non-provider configuration. Examples must use obvious
26
+ placeholders such as `<OPENAI_API_KEY>` or `${keys.SLACK_WEBHOOK}`, not
27
+ real-looking copied values.
28
+
29
+ Provider credentials and provider account identifiers are workspace data. Use
30
+ standard workspace connections and org/workspace vault scopes; never put them
31
+ in `.env` or deployment environment variables, and never add a provider-specific
32
+ action or startup bootstrap just to write a credential for one organization.
26
33
 
27
34
  ## Credential Modeling Preflight
28
35
 
@@ -37,6 +37,12 @@ import {
37
37
  assertHumanReadableDeckTitle,
38
38
  repairGeneratedDeckTitle,
39
39
  } from "../shared/deck-title.js";
40
+ import { hashSlideContent } from "../shared/slide-fit.js";
41
+ import {
42
+ awaitLayoutFitCheck,
43
+ formatOverflowForTool,
44
+ type SlideFitResult,
45
+ } from "./_await-fit-check.js";
40
46
 
41
47
  // ---------------------------------------------------------------------------
42
48
  // Per-deck write lock — same pattern as add-slide.ts so all client and agent
@@ -850,21 +856,84 @@ export default defineAction({
850
856
  }
851
857
  });
852
858
 
859
+ // Start the freshness window right after the SQL write and before
860
+ // notifying editors — same ordering as add-slide/update-slide — so a
861
+ // fast render landing before this line isn't discarded as stale.
862
+ const fitSince = Date.now();
863
+
853
864
  notifyClients(deckId);
854
865
 
855
- return {
866
+ const updatedSlideIds = [
867
+ ...new Set(
868
+ operations.flatMap((operation) =>
869
+ operation.op === "patch-slide" || operation.op === "add-slide"
870
+ ? [operation.slideId]
871
+ : [],
872
+ ),
873
+ ),
874
+ ];
875
+
876
+ // Only slides whose HTML actually changed can newly overflow — an
877
+ // add-slide always sets content; a patch-slide only when this batch's
878
+ // operation included `fields.content`. Re-check every one of them in
879
+ // parallel: a deck-wide restyle can touch dozens of slides, and polling
880
+ // them one at a time would serialize N fit-check timeouts.
881
+ const contentChangedSlideIds = [
882
+ ...new Set(
883
+ operations.flatMap((operation) =>
884
+ operation.op === "add-slide" ||
885
+ (operation.op === "patch-slide" &&
886
+ operation.fields.content !== undefined)
887
+ ? [operation.slideId]
888
+ : [],
889
+ ),
890
+ ),
891
+ ];
892
+ const finalSlides: Array<{ id?: unknown; content?: unknown }> =
893
+ Array.isArray(deck.slides) ? deck.slides : [];
894
+ const fitResults: SlideFitResult[] = await Promise.all(
895
+ contentChangedSlideIds.map((slideId) => {
896
+ const slide = finalSlides.find((s) => s.id === slideId);
897
+ return awaitLayoutFitCheck(
898
+ slideId,
899
+ fitSince,
900
+ 5000,
901
+ hashSlideContent(
902
+ typeof slide?.content === "string" ? slide.content : "",
903
+ ),
904
+ );
905
+ }),
906
+ );
907
+ const overflows = fitResults.filter(
908
+ (fit): fit is Extract<SlideFitResult, { status: "overflows" }> =>
909
+ fit.status === "overflows",
910
+ );
911
+
912
+ const base = {
856
913
  ok: true,
857
914
  deckId,
858
915
  updatedAt: now,
859
- updatedSlideIds: [
860
- ...new Set(
861
- operations.flatMap((operation) =>
862
- operation.op === "patch-slide" || operation.op === "add-slide"
863
- ? [operation.slideId]
864
- : [],
865
- ),
866
- ),
867
- ],
916
+ updatedSlideIds,
917
+ };
918
+
919
+ if (overflows.length === 0) return base;
920
+
921
+ return {
922
+ ...base,
923
+ layoutOverflow: {
924
+ overflows: overflows.map(({ measurement }) => ({
925
+ slideId: measurement.slideId,
926
+ verticalOverflow: measurement.verticalOverflow,
927
+ horizontalOverflow: measurement.horizontalOverflow ?? 0,
928
+ contentWidth: measurement.contentWidth,
929
+ contentHeight: measurement.contentHeight,
930
+ viewportWidth: measurement.viewportWidth,
931
+ viewportHeight: measurement.viewportHeight,
932
+ })),
933
+ },
934
+ message: overflows
935
+ .map(({ measurement }) => formatOverflowForTool(deckId, measurement))
936
+ .join("\n\n"),
868
937
  };
869
938
  });
870
939
  },
@@ -297,6 +297,11 @@ export default defineAction({
297
297
  // structure renders and merges with concurrent typing via the Yjs CRDT.
298
298
  let applied = false;
299
299
  let notFound = false;
300
+ // Per-edit outcomes for the `edits` batch (e.g. "insert-after:0" means
301
+ // that edit's marker matched nothing and it silently no-opped). Stays
302
+ // undefined for the legacy fullContent/find paths, which have no
303
+ // per-edit breakdown to report.
304
+ let editResults: string[] | undefined;
300
305
  const previousContent = String(slide.content ?? "");
301
306
 
302
307
  if (fullContent !== undefined) {
@@ -327,6 +332,7 @@ export default defineAction({
327
332
  });
328
333
  slide.content = nextContent;
329
334
  applied = patched.changed;
335
+ editResults = patched.applied;
330
336
  if (!applied) slide.content = previousContent;
331
337
  } else if (find !== undefined) {
332
338
  const idx = previousContent.indexOf(find);
@@ -461,6 +467,7 @@ export default defineAction({
461
467
  return {
462
468
  applied,
463
469
  notFound,
470
+ editResults,
464
471
  slide,
465
472
  slideIndex,
466
473
  contentHash: hashSlideContent(String(slide.content ?? "")),
@@ -473,6 +480,7 @@ export default defineAction({
473
480
  return {
474
481
  applied,
475
482
  notFound,
483
+ editResults,
476
484
  slide,
477
485
  slideIndex,
478
486
  contentHash: hashSlideContent(String(slide.content ?? "")),
@@ -486,13 +494,14 @@ export default defineAction({
486
494
  };
487
495
  }
488
496
 
489
- const { applied } = rmw;
497
+ const { applied, editResults } = rmw;
490
498
  if (!applied) {
491
499
  return {
492
500
  ok: true,
493
501
  deckId,
494
502
  slideId,
495
503
  applied: false,
504
+ editResults,
496
505
  contentHash: rmw.contentHash,
497
506
  deepLink: deckDeepLink(deckId),
498
507
  };
@@ -537,6 +546,7 @@ export default defineAction({
537
546
  deckId,
538
547
  slideId,
539
548
  applied,
549
+ editResults,
540
550
  contentHash: rmw.contentHash,
541
551
  deepLink: deckDeepLink(deckId),
542
552
  ...(rmw.contextMode
@@ -862,12 +862,22 @@ function MermaidHtmlContent({
862
862
  html: string;
863
863
  mermaidBlocks: string[];
864
864
  }) {
865
- // Split on mermaid placeholders and interleave HTML + MermaidRenderer
866
- const parts = html.split(/(<div data-mermaid-index="\d+"><\/div>)/);
865
+ // Split on mermaid placeholders and interleave HTML + MermaidRenderer. The
866
+ // per-fragment `{ __html }` objects are memoized for the same reason as
867
+ // BlankSlideContent's `dangerousHtml` above: a fresh literal each render
868
+ // re-assigns `innerHTML` and wipes the live contentEditable block.
869
+ const fragments = useMemo(
870
+ () =>
871
+ html
872
+ .split(/(<div data-mermaid-index="\d+"><\/div>)/)
873
+ .map((part) => ({ __html: part })),
874
+ [html],
875
+ );
867
876
 
868
877
  return (
869
878
  <>
870
- {parts.map((part, i) => {
879
+ {fragments.map((fragment, i) => {
880
+ const part = fragment.__html;
871
881
  const match = part.match(/data-mermaid-index="(\d+)"/);
872
882
  if (match) {
873
883
  const idx = parseInt(match[1], 10);
@@ -881,7 +891,7 @@ function MermaidHtmlContent({
881
891
  );
882
892
  }
883
893
  if (!part.trim()) return null;
884
- return <div key={i} dangerouslySetInnerHTML={{ __html: part }} />;
894
+ return <div key={i} dangerouslySetInnerHTML={fragment} />;
885
895
  })}
886
896
  </>
887
897
  );
@@ -1,8 +1,6 @@
1
- import {
2
- agentNativePath,
3
- appBasePath,
4
- } from "@agent-native/core/client/api-path";
1
+ import { appBasePath } from "@agent-native/core/client/api-path";
5
2
  import { useT } from "@agent-native/core/client/i18n";
3
+ import { startWorkspaceProviderOAuth } from "@agent-native/core/client/integrations";
6
4
  import {
7
5
  IconDownload,
8
6
  IconUpload,
@@ -193,53 +191,12 @@ export const ExportMenu = forwardRef<ExportMenuHandle, ExportMenuProps>(
193
191
  }
194
192
  };
195
193
 
196
- const handleConnectGoogle = async (target?: Window | null) => {
197
- const authUrl = new URL(
198
- agentNativePath("/_agent-native/google-docs/auth-url"),
199
- window.location.origin,
200
- );
201
- authUrl.searchParams.set(
202
- "return",
203
- window.location.pathname + window.location.search,
204
- );
205
-
206
- const popup =
207
- target ??
208
- window.open("", "google-docs-oauth", "popup,width=520,height=720");
209
- if (!popup) {
210
- toast.error(t("editorExport.exportFailed"), {
211
- description: t("editorExport.exportGoogleSlidesError"),
212
- });
213
- return;
214
- }
215
-
216
- try {
217
- const response = await fetch(authUrl.toString(), {
218
- credentials: "same-origin",
219
- });
220
- if (!response.ok) {
221
- throw new Error(
222
- await readErrorMessage(
223
- response,
224
- t("editorExport.exportGoogleSlidesError"),
225
- ),
226
- );
227
- }
228
- const data = (await response.json()) as { url?: unknown };
229
- if (typeof data.url !== "string") {
230
- throw new Error(t("editorExport.exportGoogleSlidesError"));
231
- }
232
- popup.location.href = data.url;
233
- } catch (err) {
234
- popup?.close();
235
- console.error("Google connection failed:", err);
236
- toast.error(t("editorExport.exportFailed"), {
237
- description:
238
- err instanceof Error
239
- ? err.message
240
- : t("editorExport.exportGoogleSlidesError"),
241
- });
242
- }
194
+ const handleConnectGoogle = () => {
195
+ startWorkspaceProviderOAuth("google_drive", {
196
+ appId: "slides",
197
+ returnPath: `${window.location.pathname}${window.location.search}`,
198
+ scope: "user",
199
+ });
243
200
  };
244
201
 
245
202
  const handleExportGoogleSlides = async () => {
@@ -253,7 +210,8 @@ export const ExportMenu = forwardRef<ExportMenuHandle, ExportMenuProps>(
253
210
  const result = await onExportGoogleSlides();
254
211
  if ("requiresConnection" in result && result.requiresConnection) {
255
212
  googleSlidesImportTarget.current = null;
256
- await handleConnectGoogle(target);
213
+ target?.close();
214
+ handleConnectGoogle();
257
215
  return;
258
216
  }
259
217
  if (result.url !== null) {
@@ -1,6 +1,6 @@
1
1
  import { agentNativePath } from "@agent-native/core/client/api-path";
2
- import { oauthRedirectUri } from "@agent-native/core/client/host";
3
2
  import { useT } from "@agent-native/core/client/i18n";
3
+ import { startWorkspaceProviderOAuth } from "@agent-native/core/client/integrations";
4
4
  import { extractGoogleDocUrls } from "@shared/google-docs";
5
5
  import {
6
6
  IconAlertCircle,
@@ -228,60 +228,15 @@ export function GoogleDocImportHint({
228
228
  return () => onSourceContextChange("");
229
229
  }, [onSourceContextChange]);
230
230
 
231
- const connect = useCallback(async () => {
231
+ const connect = useCallback(() => {
232
232
  setConnecting(true);
233
233
  setError(null);
234
- const popup = window.open(
235
- "about:blank",
236
- "google-docs-oauth",
237
- "popup,width=520,height=720",
238
- );
239
- try {
240
- const callbackUrl = oauthRedirectUri(
241
- "/_agent-native/google-docs/callback",
242
- );
243
- const authUrl = new URL(endpoint("/_agent-native/google-docs/auth-url"));
244
- authUrl.searchParams.set("redirect_uri", callbackUrl);
245
- authUrl.searchParams.set(
246
- "return",
247
- window.location.pathname + window.location.search,
248
- );
249
- const response = await fetch(authUrl.toString(), {
250
- credentials: "same-origin",
251
- });
252
- const data = await readJson<{
253
- url?: string;
254
- error?: string;
255
- message?: string;
256
- }>(response);
257
- if (!response.ok || !data.url) {
258
- throw new Error(
259
- errorFromResponse(response, data, "Could not start Google OAuth"),
260
- );
261
- }
262
- if (!popup) {
263
- window.location.href = data.url;
264
- return;
265
- }
266
- popup.location.href = data.url;
267
-
268
- const deadline = Date.now() + 90_000;
269
- while (Date.now() < deadline && !popup.closed) {
270
- await new Promise((resolve) => window.setTimeout(resolve, 1200));
271
- const next = await refreshStatus();
272
- if (next?.connected) {
273
- popup.close();
274
- return;
275
- }
276
- }
277
- await refreshStatus();
278
- } catch (caught) {
279
- popup?.close();
280
- setError(caught instanceof Error ? caught.message : String(caught));
281
- } finally {
282
- setConnecting(false);
283
- }
284
- }, [refreshStatus]);
234
+ startWorkspaceProviderOAuth("google_drive", {
235
+ appId: "slides",
236
+ returnPath: `${window.location.pathname}${window.location.search}`,
237
+ scope: "user",
238
+ });
239
+ }, []);
285
240
 
286
241
  const chooseDocument = useCallback(async () => {
287
242
  setChoosing(true);
@@ -1,6 +1,6 @@
1
1
  import { agentNativePath } from "@agent-native/core/client/api-path";
2
- import { oauthRedirectUri } from "@agent-native/core/client/host";
3
2
  import { useT } from "@agent-native/core/client/i18n";
3
+ import { startWorkspaceProviderOAuth } from "@agent-native/core/client/integrations";
4
4
  import {
5
5
  IconBrandGoogleDrive,
6
6
  IconLoader2,
@@ -19,12 +19,6 @@ interface GoogleDocsStatus {
19
19
  message?: string;
20
20
  }
21
21
 
22
- interface GoogleDocsAuthResponse {
23
- url?: string;
24
- error?: string;
25
- message?: string;
26
- }
27
-
28
22
  type JsonReadResult<T> = { ok: true; data: T } | { ok: false; error: Error };
29
23
 
30
24
  function endpoint(path: string): string {
@@ -54,13 +48,7 @@ function responseError(
54
48
  );
55
49
  }
56
50
 
57
- export interface GoogleDriveConnectionCtaProps {
58
- onConnected?: () => void;
59
- }
60
-
61
- export function GoogleDriveConnectionCta({
62
- onConnected,
63
- }: GoogleDriveConnectionCtaProps) {
51
+ export function GoogleDriveConnectionCta() {
64
52
  const t = useT();
65
53
  const [status, setStatus] = useState<GoogleDocsStatus | null>(null);
66
54
  const [loading, setLoading] = useState(true);
@@ -102,70 +90,16 @@ export function GoogleDriveConnectionCta({
102
90
 
103
91
  const needsReconnect =
104
92
  status?.connected === true && status.googleSlidesUrlImportReady === false;
105
- const requiresUrlImportAccess =
106
- status?.connected === true ||
107
- status?.googleSlidesUrlImportReady !== undefined;
108
-
109
- const connect = useCallback(async () => {
93
+ const connect = useCallback(() => {
110
94
  if (connecting) return;
111
95
  setConnecting(true);
112
96
  setError(null);
113
- const popup = window.open(
114
- "about:blank",
115
- "google-docs-oauth",
116
- "popup,width=520,height=720",
117
- );
118
- try {
119
- const authUrl = new URL(endpoint("/_agent-native/google-docs/auth-url"));
120
- authUrl.searchParams.set(
121
- "redirect_uri",
122
- oauthRedirectUri("/_agent-native/google-docs/callback"),
123
- );
124
- authUrl.searchParams.set(
125
- "return",
126
- window.location.pathname + window.location.search,
127
- );
128
- const response = await fetch(authUrl.toString(), {
129
- credentials: "same-origin",
130
- });
131
- const result = await readJson<GoogleDocsAuthResponse>(response);
132
- if (!result.ok) throw result.error;
133
- if (!response.ok || !result.data.url) {
134
- throw responseError(
135
- response,
136
- result.data,
137
- "Could not start Google OAuth",
138
- );
139
- }
140
- if (!popup) {
141
- window.location.href = result.data.url;
142
- return;
143
- }
144
- popup.location.href = result.data.url;
145
-
146
- const deadline = Date.now() + 90_000;
147
- while (Date.now() < deadline && !popup.closed) {
148
- await new Promise((resolve) => window.setTimeout(resolve, 1_200));
149
- const next = await refreshStatus();
150
- const nextHasUrlImportAccess =
151
- next?.googleSlidesUrlImportReady ?? !requiresUrlImportAccess;
152
- if (next?.connected && nextHasUrlImportAccess) {
153
- popup.close();
154
- onConnected?.();
155
- return;
156
- }
157
- }
158
- const next = await refreshStatus();
159
- const nextHasUrlImportAccess =
160
- next?.googleSlidesUrlImportReady ?? !requiresUrlImportAccess;
161
- if (next?.connected && nextHasUrlImportAccess) onConnected?.();
162
- } catch (caught) {
163
- popup?.close();
164
- setError(caught instanceof Error ? caught.message : String(caught));
165
- } finally {
166
- setConnecting(false);
167
- }
168
- }, [connecting, onConnected, refreshStatus, requiresUrlImportAccess]);
97
+ startWorkspaceProviderOAuth("google_drive", {
98
+ appId: "slides",
99
+ returnPath: `${window.location.pathname}${window.location.search}`,
100
+ scope: "user",
101
+ });
102
+ }, [connecting]);
169
103
 
170
104
  if (dismissed || loading || (status?.connected && !needsReconnect)) {
171
105
  return null;
@@ -1,7 +1,7 @@
1
1
  import { agentNativePath } from "@agent-native/core/client/api-path";
2
2
  import { useActionMutation } from "@agent-native/core/client/hooks";
3
- import { oauthRedirectUri } from "@agent-native/core/client/host";
4
3
  import { useT } from "@agent-native/core/client/i18n";
4
+ import { startWorkspaceProviderOAuth } from "@agent-native/core/client/integrations";
5
5
  import {
6
6
  IconBrandGoogleDrive,
7
7
  IconFolderOpen,
@@ -163,68 +163,16 @@ export function GoogleSlidesReferenceImport({
163
163
  [onBusyChange],
164
164
  );
165
165
 
166
- const connect = useCallback(async () => {
166
+ const connect = useCallback(() => {
167
167
  setConnecting(true);
168
168
  reportBusy(true);
169
169
  setError(null);
170
- const popup = window.open(
171
- "about:blank",
172
- "google-docs-oauth",
173
- "popup,width=520,height=720",
174
- );
175
- try {
176
- const callbackUrl = oauthRedirectUri(
177
- "/_agent-native/google-docs/callback",
178
- );
179
- const authUrl = new URL(endpoint("/_agent-native/google-docs/auth-url"));
180
- authUrl.searchParams.set("redirect_uri", callbackUrl);
181
- authUrl.searchParams.set(
182
- "return",
183
- window.location.pathname + window.location.search,
184
- );
185
- const response = await fetch(authUrl.toString(), {
186
- credentials: "same-origin",
187
- });
188
- const result = await readJson<{
189
- url?: string;
190
- error?: string;
191
- message?: string;
192
- }>(response);
193
- if (!result.ok) throw result.error;
194
- const data = result.data;
195
- if (!response.ok || !data?.url) {
196
- throw new Error(
197
- errorFromResponse(
198
- response,
199
- data ?? {},
200
- "Could not start Google OAuth",
201
- ),
202
- );
203
- }
204
- if (!popup) {
205
- window.location.href = data.url;
206
- return;
207
- }
208
- popup.location.href = data.url;
209
-
210
- const deadline = Date.now() + 90_000;
211
- while (Date.now() < deadline && !popup.closed) {
212
- await new Promise((resolve) => window.setTimeout(resolve, 1200));
213
- const next = await refreshStatus();
214
- if (next?.connected) {
215
- popup.close();
216
- return;
217
- }
218
- }
219
- await refreshStatus();
220
- } catch (caught) {
221
- popup?.close();
222
- setError(caught instanceof Error ? caught.message : String(caught));
223
- } finally {
224
- setConnecting(false);
225
- reportBusy(false);
226
- }
227
- }, [refreshStatus, reportBusy]);
170
+ startWorkspaceProviderOAuth("google_drive", {
171
+ appId: "slides",
172
+ returnPath: `${window.location.pathname}${window.location.search}`,
173
+ scope: "user",
174
+ });
175
+ }, [reportBusy]);
228
176
 
229
177
  const chooseDocument = useCallback(async () => {
230
178
  setChoosing(true);
@@ -386,7 +386,11 @@ export function SlideContextToolbar({
386
386
  </TooltipTrigger>
387
387
  <TooltipContent>{t("styleInspector.weight")}</TooltipContent>
388
388
  </Tooltip>
389
- <DropdownMenuContent align="start" className="w-36">
389
+ <DropdownMenuContent
390
+ align="start"
391
+ className="w-36"
392
+ {...inlineEditSurfaceProps}
393
+ >
390
394
  {fontWeightOptions(t).map((option) => (
391
395
  <DropdownMenuItem
392
396
  key={option.value}
@@ -481,7 +485,11 @@ export function SlideContextToolbar({
481
485
  </TooltipTrigger>
482
486
  <TooltipContent>{t("styleInspector.align")}</TooltipContent>
483
487
  </Tooltip>
484
- <DropdownMenuContent align="start" className="w-36">
488
+ <DropdownMenuContent
489
+ align="start"
490
+ className="w-36"
491
+ {...inlineEditSurfaceProps}
492
+ >
485
493
  {textAlignOptions(t).map((option) => (
486
494
  <DropdownMenuItem
487
495
  key={option.value}