@agent-native/core 0.169.0 → 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 (496) 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/bigquery-table-info.ts +3 -2
  6. package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +1 -1
  7. package/corpus/templates/analytics/actions/search-bigquery-schema.ts +130 -4
  8. package/corpus/templates/analytics/agent-native.config.ts +1 -0
  9. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +36 -23
  10. package/corpus/templates/analytics/app/i18n-data.ts +28 -0
  11. package/corpus/templates/analytics/app/lib/dashboard-visibility.ts +41 -0
  12. package/corpus/templates/analytics/app/pages/Agents.tsx +25 -1
  13. package/corpus/templates/analytics/app/pages/DashboardOverview.tsx +34 -9
  14. package/corpus/templates/analytics/app/routes/$.tsx +10 -0
  15. package/corpus/templates/analytics/app/routes.ts +3 -1
  16. package/corpus/templates/analytics/changelog/2026-08-21-dashboard-filters-keep-other-users-dashboards-out-of-mine.md +6 -0
  17. package/corpus/templates/analytics/changelog/2026-08-22-fixed-the-agent-native-templates-first-party-dashboard-panel.md +6 -0
  18. package/corpus/templates/analytics/changelog/2026-08-22-org-admin-panels-no-longer-report-a-database-error-as-a-per.md +9 -0
  19. package/corpus/templates/analytics/changelog/2026-08-22-slack-requests-report-invalid-inputs.md +6 -0
  20. package/corpus/templates/analytics/changelog/2026-08-22-unknown-analytics-links-now-return-a-real-not-found-status.md +6 -0
  21. package/corpus/templates/analytics/docs/schemas/first-party-analytics.md +2 -1
  22. package/corpus/templates/analytics/docs/schemas/tracked-events.md +2 -0
  23. package/corpus/templates/analytics/scripts/emit-netlify-dashboard-report-cron.ts +29 -7
  24. package/corpus/templates/analytics/server/handlers/slack.ts +59 -5
  25. package/corpus/templates/analytics/server/lib/db-admin-connections.ts +11 -6
  26. package/corpus/templates/analytics/server/lib/first-party-analytics.ts +132 -2
  27. package/corpus/templates/analytics/server/lib/real-data-actions.ts +14 -3
  28. package/corpus/templates/analytics/server/lib/slack.ts +4 -2
  29. package/corpus/templates/analytics/server/plugins/agent-chat.ts +33 -3
  30. package/corpus/templates/analytics/vitest.config.ts +6 -1
  31. package/corpus/templates/assets/.agents/skills/secrets/SKILL.md +11 -4
  32. package/corpus/templates/assets/app/routes/library.tsx +5 -3
  33. package/corpus/templates/assets/app/routes.ts +3 -1
  34. package/corpus/templates/assets/changelog/2026-08-22-library-page-loads-again-instead-of-crashing-on-open.md +6 -0
  35. package/corpus/templates/assets/vitest.config.ts +6 -1
  36. package/corpus/templates/brain/.agents/skills/secrets/SKILL.md +11 -4
  37. package/corpus/templates/brain/app/components/ui/pointer-lock.ts +1 -0
  38. package/corpus/templates/brain/app/routes/sources.tsx +8 -3
  39. package/corpus/templates/brain/changelog/2026-08-22-tuning-or-adding-a-source-no-longer-leaves-the-sources-page.md +6 -0
  40. package/corpus/templates/brain/server/lib/brain.ts +27 -2
  41. package/corpus/templates/brain/vitest.config.ts +1 -0
  42. package/corpus/templates/calendar/.agents/skills/secrets/SKILL.md +11 -4
  43. package/corpus/templates/calendar/actions/list-booking-links.ts +83 -4
  44. package/corpus/templates/calendar/actions/update-booking-link.ts +4 -3
  45. package/corpus/templates/calendar/app/components/calendar/EventDetailPanel.tsx +11 -3
  46. package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +1 -1
  47. package/corpus/templates/calendar/app/components/calendar/GoogleConnectBanner.tsx +103 -44
  48. package/corpus/templates/calendar/app/components/calendar/OutOfOfficeEvent.tsx +28 -24
  49. package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +9 -2
  50. package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +47 -58
  51. package/corpus/templates/calendar/app/hooks/use-booking-links.ts +5 -1
  52. package/corpus/templates/calendar/app/lib/event-layout.ts +52 -26
  53. package/corpus/templates/calendar/app/pages/BookingLinksPage.tsx +126 -98
  54. package/corpus/templates/calendar/app/pages/CalendarView.tsx +1 -0
  55. package/corpus/templates/calendar/app/pages/Settings.tsx +88 -81
  56. package/corpus/templates/calendar/app/routes.ts +3 -1
  57. package/corpus/templates/calendar/changelog/2026-08-22-booking-link-visibility-respects-shared-access.md +6 -0
  58. package/corpus/templates/calendar/changelog/2026-08-22-clicking-an-out-of-office-event-s-marker-no-longer-creates-a.md +6 -0
  59. package/corpus/templates/calendar/changelog/2026-08-22-event-detail-views-now-show-your-calendar-timezone.md +6 -0
  60. package/corpus/templates/calendar/changelog/2026-08-22-google-calendar-can-now-connect-with-the-shared-google-oauth.md +6 -0
  61. package/corpus/templates/calendar/changelog/2026-08-22-overlapping-events-now-show-each-others-boundaries.md +6 -0
  62. package/corpus/templates/calendar/changelog/2026-08-22-public-booking-pages-now-offer-time-slots-from-the-host-s-we.md +6 -0
  63. package/corpus/templates/calendar/server/handlers/bookings.ts +5 -7
  64. package/corpus/templates/calendar/server/handlers/google-auth.ts +10 -2
  65. package/corpus/templates/calendar/server/lib/google-calendar.ts +139 -14
  66. package/corpus/templates/calendar/server/onboarding.ts +85 -0
  67. package/corpus/templates/calendar/server/plugins/agent-chat.ts +2 -0
  68. package/corpus/templates/calendar/shared/api.ts +9 -1
  69. package/corpus/templates/chat/.agents/skills/secrets/SKILL.md +11 -4
  70. package/corpus/templates/chat/app/routes.ts +3 -1
  71. package/corpus/templates/chat/vitest.config.ts +8 -0
  72. package/corpus/templates/clips/.agents/skills/secrets/SKILL.md +11 -4
  73. package/corpus/templates/clips/actions/get-meeting.ts +9 -4
  74. package/corpus/templates/clips/actions/list-recordings.ts +16 -3
  75. package/corpus/templates/clips/actions/search-meetings.ts +1 -0
  76. package/corpus/templates/clips/actions/stop-meeting-recording.ts +87 -6
  77. package/corpus/templates/clips/actions/view-screen.ts +8 -1
  78. package/corpus/templates/clips/app/components/library/search-bar.tsx +1 -1
  79. package/corpus/templates/clips/app/components/meetings/meeting-history-row.tsx +32 -1
  80. package/corpus/templates/clips/app/components/player/delete-recording-menu.tsx +1 -1
  81. package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +29 -1
  82. package/corpus/templates/clips/app/i18n/en-US.ts +5 -0
  83. package/corpus/templates/clips/app/routes/_app.meetings.$meetingId.tsx +33 -4
  84. package/corpus/templates/clips/app/routes/_app.meetings._index.tsx +1 -0
  85. package/corpus/templates/clips/app/routes/access-request.approve.tsx +16 -9
  86. package/corpus/templates/clips/app/routes/embed.$shareId.tsx +17 -7
  87. package/corpus/templates/clips/app/routes/share.$shareId.tsx +17 -7
  88. package/corpus/templates/clips/changelog/2026-08-21-camera-bubble-black-circle.md +6 -0
  89. package/corpus/templates/clips/changelog/2026-08-22-screen-recordings-respect-the-microphone-toggle.md +6 -0
  90. package/corpus/templates/clips/changelog/2026-08-22-the-recordings-library-no-longer-fails-right-after-server-start.md +6 -0
  91. package/corpus/templates/clips/changelog/2026-08-23-the-agent-can-see-your-library-right-after-server-start.md +6 -0
  92. package/corpus/templates/clips/chrome-extension/src/background.ts +1 -2
  93. package/corpus/templates/clips/chrome-extension/src/native-transcription.ts +39 -7
  94. package/corpus/templates/clips/chrome-extension/src/offscreen.ts +21 -25
  95. package/corpus/templates/clips/desktop/src/app.tsx +53 -24
  96. package/corpus/templates/clips/desktop/src/lib/bubble-playback.ts +68 -0
  97. package/corpus/templates/clips/desktop/src/lib/recorder.ts +3 -0
  98. package/corpus/templates/clips/desktop/src/lib/transcription-capture.ts +72 -14
  99. package/corpus/templates/clips/desktop/src/lib/updater.ts +8 -3
  100. package/corpus/templates/clips/desktop/src/overlays/bubble.tsx +162 -20
  101. package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +43 -6
  102. package/corpus/templates/clips/desktop/src-tauri/src/native_screen/custom_capture.rs +150 -13
  103. package/corpus/templates/clips/desktop/src-tauri/src/tray.rs +12 -0
  104. package/corpus/templates/clips/server/lib/calendar-event-meetings.ts +28 -3
  105. package/corpus/templates/clips/server/lib/emails.ts +17 -33
  106. package/corpus/templates/content/.agents/skills/secrets/SKILL.md +11 -4
  107. package/corpus/templates/content/app/components/editor/VisualEditor.tsx +140 -15
  108. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +12 -14
  109. package/corpus/templates/content/app/components/ui/pointer-lock.ts +1 -0
  110. package/corpus/templates/content/app/hooks/use-content-database.ts +18 -2
  111. package/corpus/templates/content/app/hooks/use-local-storage.ts +38 -22
  112. package/corpus/templates/content/app/i18n-data.ts +25 -0
  113. package/corpus/templates/content/app/routes.ts +3 -1
  114. package/corpus/templates/content/changelog/2026-08-22-code-blocks-inserted-from-the-slash-menu-no-longer-get-stuck.md +6 -0
  115. package/corpus/templates/content/changelog/2026-08-22-the-sidebar-page-tree-no-longer-flashes-empty-after-creating-a-page.md +6 -0
  116. package/corpus/templates/content/docs/solutions/2026-08-21-content-mermaid-rendering-shape.md +233 -0
  117. package/corpus/templates/content/server/plugins/agent-chat.ts +9 -2
  118. package/corpus/templates/content/vitest.config.ts +7 -1
  119. package/corpus/templates/crm/.agents/skills/secrets/SKILL.md +11 -4
  120. package/corpus/templates/design/.agents/skills/secrets/SKILL.md +11 -4
  121. package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +1386 -92
  122. package/corpus/templates/design/actions/generate-design.ts +98 -47
  123. package/corpus/templates/design/actions/get-design-system.ts +6 -1
  124. package/corpus/templates/design/actions/refresh-design-system-with-builder.ts +146 -0
  125. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +70 -26
  126. package/corpus/templates/design/app/components/design/EditPanel.tsx +15 -47
  127. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +284 -136
  128. package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +2060 -144
  129. package/corpus/templates/design/app/components/design/editor/DesignBottomToolbar.tsx +6 -2
  130. package/corpus/templates/design/app/components/design/editor/DesignWorkspaceRail.tsx +4 -4
  131. package/corpus/templates/design/app/components/design/keyboard-shortcuts.ts +10 -8
  132. package/corpus/templates/design/app/components/design/multi-screen/alt-hover-measurement.ts +19 -2
  133. package/corpus/templates/design/app/components/design/multi-screen/types.ts +9 -2
  134. package/corpus/templates/design/app/components/layout/Header.tsx +15 -0
  135. package/corpus/templates/design/app/components/layout/Layout.tsx +7 -2
  136. package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +13 -8
  137. package/corpus/templates/design/app/i18n-data.ts +11 -10
  138. package/corpus/templates/design/app/i18n-keyboard-shortcuts.ts +12 -0
  139. package/corpus/templates/design/app/lib/design-system-data.ts +68 -0
  140. package/corpus/templates/design/app/pages/DesignEditor.tsx +99 -57
  141. package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +39 -8
  142. package/corpus/templates/design/app/pages/DesignSystems.tsx +137 -43
  143. package/corpus/templates/design/app/pages/Index.tsx +3 -1
  144. package/corpus/templates/design/app/pages/Templates.tsx +0 -10
  145. package/corpus/templates/design/app/pages/design-editor/code-layer-state.ts +10 -0
  146. package/corpus/templates/design/app/pages/design-editor/collab-sync.ts +50 -0
  147. package/corpus/templates/design/app/pages/design-editor/commands/apply-design-editor-command.ts +1 -1
  148. package/corpus/templates/design/app/pages/design-editor/commands/apply-file-content-update.ts +10 -8
  149. package/corpus/templates/design/app/pages/design-editor/commands/apply-local-content-update.ts +6 -6
  150. package/corpus/templates/design/app/pages/design-editor/commands/apply-pending-visual-styles-with-agent.ts +1 -1
  151. package/corpus/templates/design/app/pages/design-editor/commands/commit-visual-styles.ts +18 -7
  152. package/corpus/templates/design/app/pages/design-editor/commands/escape-hotkey.ts +4 -90
  153. package/corpus/templates/design/app/pages/design-editor/commands/layer-marquee-selection-change.ts +2 -1
  154. package/corpus/templates/design/app/pages/design-editor/commands/layer-selection-change.ts +4 -3
  155. package/corpus/templates/design/app/pages/design-editor/commands/screen-element-select.ts +12 -2
  156. package/corpus/templates/design/app/pages/design-editor/commands/screen-visual-style-change.ts +9 -2
  157. package/corpus/templates/design/app/pages/design-editor/commands/send-runtime-layer-move-semantic-handoff.ts +1 -1
  158. package/corpus/templates/design/app/pages/design-editor/commands/send-runtime-layer-semantic-handoff.ts +1 -1
  159. package/corpus/templates/design/app/pages/design-editor/commands/send-runtime-layer-state-semantic-handoff.ts +1 -1
  160. package/corpus/templates/design/app/pages/design-editor/commands/start-sidebar-resize.ts +1 -1
  161. package/corpus/templates/design/app/pages/design-editor/editor-state.ts +11 -1
  162. package/corpus/templates/design/app/pages/design-editor/effects/adopt-db-file-content.ts +11 -19
  163. package/corpus/templates/design/app/pages/design-editor/effects/observe-collab-text.ts +6 -6
  164. package/corpus/templates/design/app/pages/design-editor/effects/publish-agent-selection-context.ts +1 -1
  165. package/corpus/templates/design/app/pages/design-editor/effects/seed-collab-content.ts +12 -15
  166. package/corpus/templates/design/app/pages/design-editor/preview-navigation.ts +25 -0
  167. package/corpus/templates/design/app/pages/design-editor/selection-state.ts +5 -59
  168. package/corpus/templates/design/app/pages/design-editor/tool-state.ts +8 -0
  169. package/corpus/templates/design/app/pages/design-editor/types.ts +3 -3
  170. package/corpus/templates/design/app/routes.ts +3 -1
  171. package/corpus/templates/design/changelog/2026-08-20-canvas-edits-patch-the-frame-instead-of-rebuilding-it.md +6 -0
  172. package/corpus/templates/design/changelog/2026-08-21-builder-design-system-imports-reconcile-after-indexing.md +6 -0
  173. package/corpus/templates/design/changelog/2026-08-21-draw-mode-needs-shift-y.md +6 -0
  174. package/corpus/templates/design/changelog/2026-08-21-eyedropper-shortcut.md +6 -0
  175. package/corpus/templates/design/changelog/2026-08-21-figma-style-alignment-guides-and-snapping.md +6 -0
  176. package/corpus/templates/design/changelog/2026-08-21-group-transforms-keep-the-selection.md +6 -0
  177. package/corpus/templates/design/changelog/2026-08-21-inspector-fields-keep-focus-on-enter.md +6 -0
  178. package/corpus/templates/design/changelog/2026-08-21-pen-alt-keeps-the-incoming-handle.md +6 -0
  179. package/corpus/templates/design/changelog/2026-08-21-pen-on-the-board-creates-one-vector.md +6 -0
  180. package/corpus/templates/design/changelog/2026-08-21-scale-a-multi-selection-from-the-group-handles.md +6 -0
  181. package/corpus/templates/design/changelog/2026-08-21-scale-resizes-text-with-the-object.md +6 -0
  182. package/corpus/templates/design/changelog/2026-08-21-selecting-another-object-keeps-the-scale-tool-armed.md +6 -0
  183. package/corpus/templates/design/changelog/2026-08-21-the-shape-tool-remembers-the-shape-you-picked.md +6 -0
  184. package/corpus/templates/design/changelog/2026-08-21-vectors-drawn-in-a-frame-land-where-you-drew-them.md +6 -0
  185. package/corpus/templates/design/changelog/2026-08-22-multi-screen-generation-no-longer-loses-a-saved-screens-layo.md +6 -0
  186. package/corpus/templates/design/changelog/2026-08-22-rename-and-search-fields-are-labeled-for-screen-readers.md +6 -0
  187. package/corpus/templates/design/package.json +2 -0
  188. package/corpus/templates/design/server/lib/builder-design-system-proxy.ts +311 -0
  189. package/corpus/templates/design/shared/canvas-math.ts +612 -206
  190. package/corpus/templates/design/shared/pen-path.ts +37 -0
  191. package/corpus/templates/design/vitest.config.ts +7 -1
  192. package/corpus/templates/dispatch/.agents/skills/secrets/SKILL.md +11 -4
  193. package/corpus/templates/dispatch/actions/list-workspace-connections.ts +34 -3
  194. package/corpus/templates/dispatch/app/routes/integrations.tsx +55 -21
  195. package/corpus/templates/dispatch/app/routes.ts +3 -1
  196. package/corpus/templates/factory/.agents/skills/secrets/SKILL.md +11 -4
  197. package/corpus/templates/factory/.env.example +2 -7
  198. package/corpus/templates/factory/AGENTS.md +3 -0
  199. package/corpus/templates/factory/README.md +5 -3
  200. package/corpus/templates/factory/actions/create-factory.ts +16 -3
  201. package/corpus/templates/factory/actions/get-slack-feedback-context.ts +2 -0
  202. package/corpus/templates/factory/actions/get-triage-item.ts +2 -0
  203. package/corpus/templates/factory/actions/list-factory-audit.ts +116 -36
  204. package/corpus/templates/factory/actions/list-factory-automations.ts +2 -1
  205. package/corpus/templates/factory/actions/list-triage-items.ts +22 -19
  206. package/corpus/templates/factory/actions/run-factory-automation.ts +7 -3
  207. package/corpus/templates/factory/actions/save-factory-automation.ts +5 -2
  208. package/corpus/templates/factory/actions/save-triage-config.ts +2 -8
  209. package/corpus/templates/factory/actions/start-builder-for-item.ts +21 -0
  210. package/corpus/templates/factory/app/components/factory/FactoryAuditView.tsx +229 -297
  211. package/corpus/templates/factory/app/components/factory/FactorySettingsView.tsx +397 -247
  212. package/corpus/templates/factory/app/components/factory/FactorySourceSettingsGroup.tsx +33 -0
  213. package/corpus/templates/factory/app/components/factory/NewFactoryForm.tsx +202 -162
  214. package/corpus/templates/factory/app/i18n/en-US.ts +32 -4
  215. package/corpus/templates/factory/app/routes/factory.tsx +84 -11
  216. package/corpus/templates/factory/app/routes.ts +3 -1
  217. package/corpus/templates/factory/changelog/2026-08-21-activity-runs-use-automation-display-names.md +6 -0
  218. package/corpus/templates/factory/changelog/2026-08-21-create-and-settings-source-cards.md +6 -0
  219. package/corpus/templates/factory/changelog/2026-08-21-keep-automations-visible-while-running.md +6 -0
  220. package/corpus/templates/factory/changelog/2026-08-21-nested-factory-automations-can-poll.md +6 -0
  221. package/corpus/templates/factory/changelog/2026-08-21-settings-sticky-unsaved-bar.md +6 -0
  222. package/corpus/templates/factory/server/connectors/credentials.ts +10 -5
  223. package/corpus/templates/factory/server/lib/factory-audit-report.ts +412 -0
  224. package/corpus/templates/factory/server/lib/factory-config-reconcile.ts +321 -0
  225. package/corpus/templates/factory/server/lib/factory-scope.ts +25 -2
  226. package/corpus/templates/factory/server/lib/require-factory-automation.ts +13 -4
  227. package/corpus/templates/factory/server/plugins/factory-migrations.ts +148 -4
  228. package/corpus/templates/factory/server/plugins/factory-scheduler-job.ts +4 -6
  229. package/corpus/templates/factory/vitest.config.ts +17 -2
  230. package/corpus/templates/forms/.agents/skills/secrets/SKILL.md +11 -4
  231. package/corpus/templates/forms/app/routes/_app.settings.tsx +4 -1
  232. package/corpus/templates/forms/changelog/2026-08-22-the-extensions-link-now-opens-the-extensions-tab-instead-o.md +6 -0
  233. package/corpus/templates/forms/server/lib/public-form-ssr.ts +11 -1
  234. package/corpus/templates/forms/vitest.config.ts +1 -0
  235. package/corpus/templates/macros/.agents/skills/secrets/SKILL.md +11 -4
  236. package/corpus/templates/macros/app/routes.ts +3 -1
  237. package/corpus/templates/macros/vitest.config.ts +6 -1
  238. package/corpus/templates/mail/.agents/skills/secrets/SKILL.md +11 -4
  239. package/corpus/templates/mail/actions/manage-gmail-filters.ts +10 -2
  240. package/corpus/templates/mail/app/components/GoogleConnectBanner.tsx +100 -37
  241. package/corpus/templates/mail/app/components/email/IntegrationsSidebar.tsx +14 -2
  242. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +66 -36
  243. package/corpus/templates/mail/app/hooks/use-emails.ts +13 -3
  244. package/corpus/templates/mail/app/hooks/use-google-auth.ts +2 -0
  245. package/corpus/templates/mail/app/lib/google-oauth-setup.ts +17 -0
  246. package/corpus/templates/mail/app/pages/InboxPage.tsx +69 -9
  247. package/corpus/templates/mail/app/routes/$.tsx +9 -0
  248. package/corpus/templates/mail/app/routes/$view.$threadId.tsx +23 -1
  249. package/corpus/templates/mail/app/routes/$view.tsx +47 -1
  250. package/corpus/templates/mail/app/routes.ts +3 -1
  251. package/corpus/templates/mail/changelog/2026-08-22-gmail-can-now-connect-with-the-shared-google-oauth.md +6 -0
  252. package/corpus/templates/mail/changelog/2026-08-22-gmail-filters-now-shows-the-real-error.md +6 -0
  253. package/corpus/templates/mail/changelog/2026-08-22-unknown-mail-urls-now-show-the-404-page.md +6 -0
  254. package/corpus/templates/mail/server/handlers/google-auth.ts +11 -2
  255. package/corpus/templates/mail/server/lib/google-auth.ts +92 -12
  256. package/corpus/templates/mail/server/onboarding.ts +66 -18
  257. package/corpus/templates/mail/vitest.config.ts +6 -1
  258. package/corpus/templates/plan/.agents/skills/secrets/SKILL.md +11 -4
  259. package/corpus/templates/plan/app/routes/settings.tsx +4 -1
  260. package/corpus/templates/plan/app/routes.ts +3 -1
  261. package/corpus/templates/plan/changelog/2026-08-22-the-extensions-link-now-opens-the-extensions-tab-instead-o.md +6 -0
  262. package/corpus/templates/plan/netlify.toml +1 -1
  263. package/corpus/templates/slides/.agents/skills/secrets/SKILL.md +11 -4
  264. package/corpus/templates/slides/actions/patch-deck.ts +79 -10
  265. package/corpus/templates/slides/actions/update-slide.ts +11 -1
  266. package/corpus/templates/slides/app/components/deck/SlideRenderer.tsx +14 -4
  267. package/corpus/templates/slides/app/components/editor/ExportMenu.tsx +10 -52
  268. package/corpus/templates/slides/app/components/editor/GoogleDocImportHint.tsx +8 -53
  269. package/corpus/templates/slides/app/components/editor/GoogleDriveConnectionCta.tsx +9 -75
  270. package/corpus/templates/slides/app/components/editor/GoogleSlidesReferenceImport.tsx +8 -60
  271. package/corpus/templates/slides/app/components/editor/SlideContextToolbar.tsx +10 -2
  272. package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +19 -7
  273. package/corpus/templates/slides/app/lib/sanitize-slide-html.ts +49 -36
  274. package/corpus/templates/slides/app/routes/access-request.approve.tsx +16 -9
  275. package/corpus/templates/slides/app/routes.ts +3 -1
  276. package/corpus/templates/slides/changelog/2026-08-22-already-uploaded-chat-images-are-no-longer-dropped.md +6 -0
  277. package/corpus/templates/slides/changelog/2026-08-22-google-drive-and-slides-can-now-connect-with-the-shared-google-oauth.md +6 -0
  278. package/corpus/templates/slides/changelog/2026-08-22-multi-slide-repairs-now-report-slides-that-still-overflow.md +6 -0
  279. package/corpus/templates/slides/changelog/2026-08-22-update-slide-now-reports-which-batched-edit-was-skipped.md +6 -0
  280. package/corpus/templates/slides/server/handlers/google-docs-auth.ts +52 -1
  281. package/corpus/templates/slides/server/lib/chat-attachments.ts +29 -3
  282. package/corpus/templates/slides/server/lib/google-docs-oauth.ts +66 -16
  283. package/corpus/templates/slides/server/lib/slide-content-patch.ts +13 -2
  284. package/corpus/templates/slides/server/plugins/agent-chat.ts +5 -2
  285. package/corpus/templates/slides/tsconfig.json +5 -0
  286. package/corpus/templates/slides/vitest.config.ts +6 -1
  287. package/corpus/templates/tasks/.agents/skills/secrets/SKILL.md +11 -4
  288. package/corpus/templates/tasks/app/routes/settings.tsx +4 -1
  289. package/corpus/templates/tasks/app/routes.ts +3 -1
  290. package/corpus/templates/tasks/changelog/2026-08-22-the-extensions-link-now-opens-the-extensions-tab-instead-o.md +6 -0
  291. package/corpus/templates/tasks/vitest.config.ts +7 -1
  292. package/dist/action.d.ts +91 -0
  293. package/dist/action.js +50 -0
  294. package/dist/agent/abort-reasons.d.ts +38 -0
  295. package/dist/agent/abort-reasons.js +49 -0
  296. package/dist/agent/engine/ai-sdk-engine.js +8 -5
  297. package/dist/agent/engine/anthropic-engine.js +7 -5
  298. package/dist/agent/engine/credential-errors.d.ts +1 -1
  299. package/dist/agent/engine/credential-errors.js +2 -2
  300. package/dist/agent/engine/first-event-timeout.d.ts +42 -17
  301. package/dist/agent/engine/first-event-timeout.js +67 -25
  302. package/dist/agent/production-agent.d.ts +23 -0
  303. package/dist/agent/production-agent.js +107 -102
  304. package/dist/agent/run-loop-with-resume.d.ts +2 -28
  305. package/dist/agent/run-loop-with-resume.js +25 -40
  306. package/dist/agent/run-manager.js +5 -4
  307. package/dist/agent/run-store.d.ts +55 -0
  308. package/dist/agent/run-store.js +124 -1
  309. package/dist/agent/tool-search.js +2 -1
  310. package/dist/agent/types.d.ts +9 -4
  311. package/dist/app-config/configuration-error.d.ts +11 -0
  312. package/dist/app-config/configuration-error.js +14 -0
  313. package/dist/app-config/index.d.ts +1 -0
  314. package/dist/app-config/index.js +1 -0
  315. package/dist/app-config/integrations.d.ts +1 -0
  316. package/dist/app-config/integrations.js +10 -0
  317. package/dist/app-config/plugins.d.ts +34 -0
  318. package/dist/app-config/plugins.js +39 -0
  319. package/dist/app-config/run-lifecycle-invariants.d.ts +18 -9
  320. package/dist/app-config/run-lifecycle-invariants.js +18 -25
  321. package/dist/app-config/schema.d.ts +16 -0
  322. package/dist/app-config/schema.js +2 -0
  323. package/dist/chat-threads/schema-migrations.js +20 -0
  324. package/dist/chat-threads/store.js +21 -4
  325. package/dist/cli/native-dependencies.d.ts +4 -0
  326. package/dist/cli/native-dependencies.js +15 -0
  327. package/dist/client/AssistantChat.js +47 -15
  328. package/dist/client/ConnectBuilderCard.d.ts +3 -1
  329. package/dist/client/ConnectBuilderCard.js +6 -3
  330. package/dist/client/EnvironmentBadge.d.ts +1 -1
  331. package/dist/client/EnvironmentBadge.js +40 -5
  332. package/dist/client/MultiTabAssistantChat.d.ts +1 -1
  333. package/dist/client/MultiTabAssistantChat.js +35 -14
  334. package/dist/client/agent-chat/index.d.ts +1 -1
  335. package/dist/client/agent-chat/index.js +1 -1
  336. package/dist/client/agent-page/use-jobs.d.ts +2 -1
  337. package/dist/client/agent-page/use-jobs.js +3 -5
  338. package/dist/client/agent-sidebar-state.js +3 -1
  339. package/dist/client/blocks/library/code-tabs.js +5 -0
  340. package/dist/client/blocks/library/code.js +1 -0
  341. package/dist/client/chat/message-components.d.ts +7 -0
  342. package/dist/client/chat/message-components.js +1 -1
  343. package/dist/client/chat/run-recovery.js +5 -2
  344. package/dist/client/chat/tool-call-display.js +9 -3
  345. package/dist/client/chat-first/apps-rail.js +2 -2
  346. package/dist/client/chat-model-groups.d.ts +12 -0
  347. package/dist/client/chat-model-groups.js +3 -2
  348. package/dist/client/error-format.js +12 -0
  349. package/dist/client/integrations/GoogleProductLogo.d.ts +5 -0
  350. package/dist/client/integrations/GoogleProductLogo.js +45 -0
  351. package/dist/client/integrations/index.d.ts +2 -0
  352. package/dist/client/integrations/index.js +2 -0
  353. package/dist/client/integrations/workspace-provider-oauth.d.ts +8 -0
  354. package/dist/client/integrations/workspace-provider-oauth.js +13 -0
  355. package/dist/client/navigation/index.d.ts +1 -0
  356. package/dist/client/navigation/index.js +1 -0
  357. package/dist/client/resources/mcp-integration-catalog.js +0 -29
  358. package/dist/client/route-state.js +6 -0
  359. package/dist/client/settings/SettingsTabsPage.js +10 -6
  360. package/dist/client/sharing/ShareButton.js +11 -2
  361. package/dist/client/use-chat-models.d.ts +6 -0
  362. package/dist/client/use-chat-models.js +10 -0
  363. package/dist/client/use-db-sync.js +27 -9
  364. package/dist/client/workspace-app-navigation.d.ts +10 -0
  365. package/dist/client/workspace-app-navigation.js +38 -0
  366. package/dist/collab/struct-routes.d.ts +1 -1
  367. package/dist/connections/catalog.d.ts +111 -9
  368. package/dist/connections/catalog.js +86 -30
  369. package/dist/db/create-get-db.js +18 -0
  370. package/dist/db/ddl-guard.d.ts +0 -4
  371. package/dist/db/ddl-guard.js +46 -0
  372. package/dist/deploy/build.d.ts +32 -0
  373. package/dist/deploy/build.js +241 -16
  374. package/dist/deploy/function-bundle.d.ts +45 -0
  375. package/dist/deploy/function-bundle.js +337 -0
  376. package/dist/deploy/workspace-deploy.js +19 -1
  377. package/dist/eject/workspace-connections.js +4 -0
  378. package/dist/email-catalog/registry.d.ts +4 -0
  379. package/dist/email-catalog/registry.js +79 -14
  380. package/dist/extensions/content-patch.js +14 -2
  381. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  382. package/dist/integrations/plugin.d.ts +10 -0
  383. package/dist/integrations/plugin.js +40 -6
  384. package/dist/jobs/actions/run-automation-now.d.ts +2 -1
  385. package/dist/jobs/actions/run-automation-now.js +11 -5
  386. package/dist/jobs/frontmatter.js +53 -2
  387. package/dist/jobs/run-now.d.ts +11 -1
  388. package/dist/jobs/run-now.js +42 -7
  389. package/dist/jobs/scheduler.d.ts +1 -0
  390. package/dist/jobs/scheduler.js +2 -1
  391. package/dist/localization/core-messages/ar-SA.js +4 -1
  392. package/dist/localization/core-messages/de-DE.js +4 -1
  393. package/dist/localization/core-messages/en-US.d.ts +4 -1
  394. package/dist/localization/core-messages/en-US.js +4 -1
  395. package/dist/localization/core-messages/es-ES.js +4 -1
  396. package/dist/localization/core-messages/fr-FR.js +4 -1
  397. package/dist/localization/core-messages/hi-IN.js +4 -1
  398. package/dist/localization/core-messages/ja-JP.js +4 -1
  399. package/dist/localization/core-messages/ko-KR.js +4 -1
  400. package/dist/localization/core-messages/pt-BR.js +4 -1
  401. package/dist/localization/core-messages/zh-CN.js +4 -1
  402. package/dist/localization/core-messages/zh-TW.js +4 -1
  403. package/dist/localization/core-messages.d.ts +4 -1
  404. package/dist/localization/default-messages.d.ts +2 -5
  405. package/dist/localization/default-messages.js +2 -5
  406. package/dist/mcp/build-server.d.ts +9 -0
  407. package/dist/mcp/build-server.js +37 -8
  408. package/dist/mcp-client/oauth-client.d.ts +7 -0
  409. package/dist/mcp-client/oauth-client.js +12 -1
  410. package/dist/notifications/routes.d.ts +1 -1
  411. package/dist/oauth-tokens/index.d.ts +1 -1
  412. package/dist/oauth-tokens/index.js +1 -1
  413. package/dist/oauth-tokens/lifecycle.d.ts +11 -0
  414. package/dist/oauth-tokens/lifecycle.js +17 -0
  415. package/dist/oauth-tokens/store.js +7 -0
  416. package/dist/observability/posthog-ai.d.ts +15 -1
  417. package/dist/observability/posthog-ai.js +24 -12
  418. package/dist/observability/traces.js +158 -28
  419. package/dist/onboarding/app-profile.js +2 -2
  420. package/dist/onboarding/plugin.js +10 -2
  421. package/dist/onboarding/types.d.ts +2 -0
  422. package/dist/provider-api/actions/custom-provider-registration.d.ts +12 -12
  423. package/dist/provider-api/actions/provider-api.d.ts +11 -11
  424. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  425. package/dist/provider-api/index.js +2 -0
  426. package/dist/resources/handlers.d.ts +1 -1
  427. package/dist/resources/store.js +13 -4
  428. package/dist/scripts/agent-engines/list-agent-engines.js +29 -3
  429. package/dist/scripts/db/check-scoping.js +9 -6
  430. package/dist/secrets/register-framework-secrets.js +1 -1
  431. package/dist/secrets/routes.d.ts +6 -6
  432. package/dist/server/action-discovery.js +5 -0
  433. package/dist/server/agent-chat/action-filters-a2a.d.ts +27 -3
  434. package/dist/server/agent-chat/action-filters-a2a.js +48 -9
  435. package/dist/server/agent-chat-plugin.js +36 -9
  436. package/dist/server/agent-discovery.js +43 -20
  437. package/dist/server/auth.js +18 -16
  438. package/dist/server/beta-opt-out-html.js +45 -4
  439. package/dist/server/better-auth-instance.d.ts +2 -1
  440. package/dist/server/better-auth-instance.js +23 -7
  441. package/dist/server/builder-browser.d.ts +4 -0
  442. package/dist/server/builder-browser.js +23 -1
  443. package/dist/server/builder-design-systems.d.ts +4 -1
  444. package/dist/server/builder-design-systems.js +87 -6
  445. package/dist/server/builder-oauth.d.ts +1 -7
  446. package/dist/server/builder-oauth.js +80 -163
  447. package/dist/server/core-routes-plugin.d.ts +29 -0
  448. package/dist/server/core-routes-plugin.js +113 -21
  449. package/dist/server/default-plugins.d.ts +18 -0
  450. package/dist/server/default-plugins.js +22 -0
  451. package/dist/server/edge.d.ts +1 -0
  452. package/dist/server/edge.js +1 -0
  453. package/dist/server/framework-request-handler.js +31 -3
  454. package/dist/server/google-oauth.d.ts +3 -0
  455. package/dist/server/google-oauth.js +3 -0
  456. package/dist/server/index.d.ts +4 -4
  457. package/dist/server/index.js +3 -3
  458. package/dist/server/onboarding-html.js +37 -3
  459. package/dist/server/workspace-provider-oauth.d.ts +6 -1
  460. package/dist/server/workspace-provider-oauth.js +72 -20
  461. package/dist/shared/agent-sidebar-url.d.ts +1 -0
  462. package/dist/shared/agent-sidebar-url.js +1 -0
  463. package/dist/shared/environment-lanes.d.ts +2 -0
  464. package/dist/shared/environment-lanes.js +3 -1
  465. package/dist/shared/index.d.ts +3 -1
  466. package/dist/shared/index.js +3 -1
  467. package/dist/shared/surface-visibility.d.ts +31 -0
  468. package/dist/shared/surface-visibility.js +57 -0
  469. package/dist/templates/chat/.agents/skills/secrets/SKILL.md +11 -4
  470. package/dist/templates/chat/app/routes.ts +3 -1
  471. package/dist/templates/chat/vitest.config.ts +8 -0
  472. package/dist/templates/default/.agents/skills/secrets/SKILL.md +11 -4
  473. package/dist/templates/default/app/routes.ts +3 -1
  474. package/dist/templates/headless/.agents/skills/secrets/SKILL.md +11 -4
  475. package/dist/templates/workspace-core/.agents/skills/secrets/SKILL.md +11 -4
  476. package/dist/tracking/registry.d.ts +11 -0
  477. package/dist/tracking/registry.js +5 -2
  478. package/dist/triggers/actions.js +10 -3
  479. package/dist/usage/store.js +23 -3
  480. package/dist/user-profile/actions/get-auth-methods.js +18 -5
  481. package/dist/vite/client.js +24 -5
  482. package/docs/content/actions-access-control.mdx +43 -4
  483. package/docs/content/actions-defining.mdx +16 -0
  484. package/docs/content/template-clips-capture-everywhere.mdx +29 -30
  485. package/docs/content/template-clips-developers.mdx +4 -4
  486. package/docs/content/template-clips.mdx +3 -1
  487. package/package.json +3 -3
  488. package/src/eject/workspace-connections.ts +4 -0
  489. package/src/templates/chat/.agents/skills/secrets/SKILL.md +11 -4
  490. package/src/templates/chat/app/routes.ts +3 -1
  491. package/src/templates/chat/vitest.config.ts +8 -0
  492. package/src/templates/default/.agents/skills/secrets/SKILL.md +11 -4
  493. package/src/templates/default/app/routes.ts +3 -1
  494. package/src/templates/headless/.agents/skills/secrets/SKILL.md +11 -4
  495. package/src/templates/workspace-core/.agents/skills/secrets/SKILL.md +11 -4
  496. /package/corpus/templates/dispatch/app/routes/{apps.$appId.tsx → apps.$appId.$.tsx} +0 -0
@@ -44,7 +44,7 @@ function AppRows({ apps, defaultAppIds, activeAppId, layout, onDragStart, onDrop
44
44
  const pinned = layout.pinnedIds.includes(app.id);
45
45
  const index = orderedApps.indexOf(app);
46
46
  return (_jsxs(ContextMenu, { children: [_jsx(ContextMenuTrigger, { asChild: true, children: _jsxs("li", { draggable: true, "data-chat-first-app": true, "data-app-id": app.id, className: cn("group flex h-8 w-full min-w-0 items-center gap-1 rounded-md px-0 text-sm", active
47
- ? "font-medium text-sidebar-foreground"
47
+ ? "bg-sidebar-accent font-medium text-sidebar-accent-foreground"
48
48
  : "text-sidebar-foreground/75 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground"), onDragStart: (event) => {
49
49
  event.dataTransfer.effectAllowed = "move";
50
50
  onDragStart(app.id);
@@ -136,7 +136,7 @@ export const ChatFirstAppsRail = memo(function ChatFirstAppsRail({ apps, default
136
136
  return (_jsx(TooltipProvider, { children: _jsxs("section", { "data-chat-first-apps-rail": true, className: "flex flex-col items-center gap-1 px-1.5 pt-2", "aria-label": copy("workspaceApps"), children: [loading && apps.length === 0
137
137
  ? [0, 1, 2].map((index) => (_jsx(Skeleton, { className: "size-9 rounded-md" }, index)))
138
138
  : visibleApps.map((app) => (_jsxs(Tooltip, { delayDuration: 0, children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", "data-chat-first-app": true, "data-app-id": app.id, className: cn("flex size-9 items-center justify-center rounded-md", activeAppId === app.id
139
- ? "text-sidebar-foreground"
139
+ ? "bg-sidebar-accent text-sidebar-accent-foreground"
140
140
  : "text-sidebar-foreground/70 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground"), onClick: () => onOpenApp(app), "aria-label": copy("openApp", { name: app.name }), children: _jsx(ChatFirstRailAppIcon, { app: app, activeAppId: activeAppId, renderIcon: renderIcon }) }) }), _jsx(TooltipContent, { side: "right", children: app.name })] }, app.id))), onOpenAllApps ? (_jsxs(Tooltip, { delayDuration: 0, children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", "data-chat-first-all-apps": true, className: "flex size-9 items-center justify-center rounded-md text-sidebar-foreground/70 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground", onClick: onOpenAllApps, "aria-label": copy("allApps"), children: _jsx(IconApps, { size: 16, "aria-hidden": "true" }) }) }), _jsx(TooltipContent, { side: "right", children: copy("allApps") })] })) : null, error ? (_jsx("span", { className: "size-1.5 rounded-full bg-destructive", title: error, "aria-label": error })) : null] }) }));
141
141
  }
142
142
  return (_jsxs("section", { "data-chat-first-apps-rail": true, className: "mt-3 px-2 pb-2 pt-2", "aria-label": copy("workspaceApps"), children: [_jsxs("div", { className: "mb-1 flex items-center gap-1.5 px-2 text-[11px] font-medium text-sidebar-foreground/50", children: [_jsx("span", { children: copy("workspaceApps") }), _jsx("span", { className: "ml-auto", children: createTrigger })] }), loading && apps.length === 0 ? (_jsx("div", { className: "space-y-0.5 px-2", children: [0, 1, 2].map((index) => (_jsx(Skeleton, { className: "h-8 w-full rounded-md" }, index))) })) : apps.length === 0 ? (_jsxs("div", { className: "px-2", children: [_jsx("p", { className: "text-xs text-sidebar-foreground/55", children: copy("noWorkspaceApps") }), createAppTrigger ? (createTrigger) : onCreateApp ? (_jsxs("button", { type: "button", className: "mt-1 inline-flex h-6 items-center gap-1.5 rounded-md border border-sidebar-border px-2 text-xs text-sidebar-foreground/75 hover:bg-sidebar-accent hover:text-sidebar-foreground", onClick: onCreateApp, children: [_jsx(IconPlus, { size: 13, "aria-hidden": "true" }), copy("createApp")] })) : (createTrigger)] })) : (_jsx(AppRows, { apps: visibleApps, defaultAppIds: defaultAppIds, activeAppId: activeAppId, layout: layout, onDragStart: setDraggedAppId, onDrop: reorderApps, onDragEnd: () => setDraggedAppId(null), onOpenApp: onOpenApp, onRemoveApp: onRemoveApp, onTogglePinned: togglePinned, onMove: moveApp, renderIcon: renderIcon, copy: copy })), hasMoreApps || showAllApps ? (_jsxs("button", { type: "button", className: "mt-0.5 flex h-8 w-full items-center gap-2 rounded-md px-2 text-xs text-sidebar-foreground/50 hover:bg-sidebar-accent hover:text-sidebar-foreground", onClick: () => setShowAllApps((value) => !value), children: [showAllApps ? (_jsx(IconChevronUp, { size: 14, "aria-hidden": "true" })) : (_jsx(IconChevronDown, { size: 14, "aria-hidden": "true" })), showAllApps ? copy("showLess") : copy("showMore")] })) : null, onOpenAllApps ? (_jsx("div", { className: "mt-1 border-t border-sidebar-border/60 pt-1", children: _jsxs("button", { type: "button", "data-chat-first-all-apps": true, className: "flex h-8 w-full items-center gap-2 rounded-md px-2 text-xs text-sidebar-foreground/55 hover:bg-sidebar-accent hover:text-sidebar-foreground", onClick: onOpenAllApps, children: [_jsx(IconApps, { size: 14, "aria-hidden": "true" }), _jsx("span", { children: copy("allApps") })] }) })) : null, error ? (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("button", { type: "button", className: "mt-1 flex items-center gap-1 px-2 text-[10px] text-destructive/80", onClick: onRetry, "aria-label": error, children: [_jsx("span", { className: "size-1.5 rounded-full bg-destructive" }), onRetry ? copy("retry") : copy("appsLoadError")] }) }), _jsx(TooltipContent, { side: "right", children: error })] })) : null] }));
@@ -10,6 +10,18 @@ export interface ChatModelEngineEntry {
10
10
  supportedModels?: readonly string[];
11
11
  requiredEnvVars?: readonly string[];
12
12
  packageInstalled?: boolean;
13
+ /**
14
+ * Server-resolved readiness. The env-key fallback below cannot see
15
+ * vault-stored credentials or the deploy-injected Builder gateway lane, so
16
+ * an engine running on either is reported unconfigured without this.
17
+ *
18
+ * Undefined means the server could not resolve it — including a credential
19
+ * read that threw, reported in `configuredError`. That deliberately falls
20
+ * through to the env heuristic rather than reading as "needs an API key".
21
+ */
22
+ configured?: boolean;
23
+ /** Why readiness is unknown, when the server's lookup failed. */
24
+ configuredError?: string;
13
25
  }
14
26
  export interface BuildChatModelGroupsOptions {
15
27
  engines: readonly ChatModelEngineEntry[];
@@ -143,8 +143,9 @@ export function buildChatModelGroups({ engines, configuredKeys, builderConnected
143
143
  engine: engine.name,
144
144
  label: engine.label,
145
145
  models: sortModelsByCost(addCurrentModel(engine.supportedModels ?? [], engine.name, currentEngineName, currentModel)),
146
- configured: requiredEnvVars.length === 0 ||
147
- requiredEnvVars.some((key) => configured.has(key)),
146
+ configured: engine.configured ??
147
+ (requiredEnvVars.length === 0 ||
148
+ requiredEnvVars.some((key) => configured.has(key))),
148
149
  };
149
150
  })
150
151
  .filter((group) => group.models.length > 0);
@@ -80,6 +80,18 @@ const KNOWN_CHAT_ERROR_KEYS = new Map([
80
80
  "No LLM provider is connected. Open this app's Manage agent > LLM, then connect Builder.io or add a provider key.",
81
81
  "agentChat.errorMessages.noProviderConnected",
82
82
  ],
83
+ [
84
+ "No LLM provider is connected. Open this app's Manage agent > LLM, then connect Builder.io (free tier available) or add a provider key.",
85
+ "agentChat.errorMessages.noProviderConnected",
86
+ ],
87
+ [
88
+ "No LLM provider is connected. Open Settings > Agent > AI providers, then connect Builder.io or add a provider key.",
89
+ "agentChat.errorMessages.noProviderConnected",
90
+ ],
91
+ [
92
+ "No LLM provider is connected. Open Settings > Agent > AI providers, then connect Builder.io (free tier available) or add a provider key.",
93
+ "agentChat.errorMessages.noProviderConnected",
94
+ ],
83
95
  [
84
96
  "The provider behind this model rejected the request. Pick a different model, then retry.",
85
97
  "agentChat.errorMessages.builderModelUnauthorized",
@@ -0,0 +1,5 @@
1
+ import type { SVGProps } from "react";
2
+ export type GoogleProduct = "calendar" | "docs" | "drive" | "gmail" | "sheets" | "slides";
3
+ export declare function GoogleProductLogo({ product, className, ...props }: {
4
+ product: GoogleProduct;
5
+ } & Omit<SVGProps<SVGSVGElement>, "children">): import("react").JSX.Element;
@@ -0,0 +1,45 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ const GOOGLE_MARK_COLORS = {
3
+ // guard:allow-raw-color - official Google product mark color
4
+ blue: "#4285F4",
5
+ // guard:allow-raw-color - official Google product mark color
6
+ blueDark: "#1A73E8",
7
+ // guard:allow-raw-color - official Google product mark color
8
+ blueLight: "#8AB4F8",
9
+ // guard:allow-raw-color - official Google product mark color
10
+ border: "#DADCE0",
11
+ // guard:allow-raw-color - official Google product mark color
12
+ green: "#34A853",
13
+ // guard:allow-raw-color - official Google product mark color
14
+ greenDark: "#188038",
15
+ // guard:allow-raw-color - official Google product mark color
16
+ red: "#EA4335",
17
+ // guard:allow-raw-color - official Google product mark color
18
+ yellow: "#FBBC04",
19
+ // guard:allow-raw-color - official Google product mark color
20
+ yellowDark: "#F9AB00",
21
+ };
22
+ const commonProps = {
23
+ viewBox: "0 0 24 24",
24
+ fill: "none",
25
+ xmlns: "http://www.w3.org/2000/svg",
26
+ "aria-hidden": true,
27
+ focusable: false,
28
+ };
29
+ export function GoogleProductLogo({ product, className, ...props }) {
30
+ const svgProps = { ...commonProps, className, ...props };
31
+ switch (product) {
32
+ case "gmail":
33
+ return (_jsxs("svg", { ...svgProps, children: [_jsx("path", { d: "M3.5 5.25h17A1.5 1.5 0 0 1 22 6.75v10.5a1.5 1.5 0 0 1-1.5 1.5h-17A1.5 1.5 0 0 1 2 17.25V6.75a1.5 1.5 0 0 1 1.5-1.5Z", fill: "white", stroke: GOOGLE_MARK_COLORS.border }), _jsx("path", { d: "m3 7 9 6.75L21 7", stroke: GOOGLE_MARK_COLORS.red, strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }), _jsx("path", { d: "M3 17.75V7m18 10.75V7", stroke: GOOGLE_MARK_COLORS.blue, strokeWidth: "2", strokeLinecap: "round" }), _jsx("path", { d: "m3 7 4.25 3.2", stroke: GOOGLE_MARK_COLORS.yellow, strokeWidth: "2", strokeLinecap: "round" }), _jsx("path", { d: "m21 7-4.25 3.2", stroke: GOOGLE_MARK_COLORS.green, strokeWidth: "2", strokeLinecap: "round" })] }));
34
+ case "calendar":
35
+ return (_jsxs("svg", { ...svgProps, children: [_jsx("rect", { x: "3", y: "4", width: "18", height: "17", rx: "2.5", fill: GOOGLE_MARK_COLORS.blue }), _jsx("path", { d: "M3 9h18", stroke: "white", strokeWidth: "2" }), _jsx("path", { d: "M7 3v3M17 3v3", stroke: GOOGLE_MARK_COLORS.blueDark, strokeWidth: "2", strokeLinecap: "round" }), _jsx("text", { x: "12", y: "17", textAnchor: "middle", fill: "white", fontFamily: "Arial, sans-serif", fontSize: "8", fontWeight: "700", children: "31" })] }));
36
+ case "drive":
37
+ return (_jsxs("svg", { ...svgProps, children: [_jsx("path", { d: "M8.1 3.5h4.65l8.45 14.65h-4.65L8.1 3.5Z", fill: GOOGLE_MARK_COLORS.yellow }), _jsx("path", { d: "M8.1 3.5 3.2 12l4.65 8.05 4.9-8.5L8.1 3.5Z", fill: GOOGLE_MARK_COLORS.green }), _jsx("path", { d: "M3.2 12h9.55l3.8 6.15H6.75L3.2 12Z", fill: GOOGLE_MARK_COLORS.blue })] }));
38
+ case "docs":
39
+ return (_jsxs("svg", { ...svgProps, children: [_jsx("path", { d: "M6 2.5h8l4 4v15H6a2 2 0 0 1-2-2v-15a2 2 0 0 1 2-2Z", fill: GOOGLE_MARK_COLORS.blue }), _jsx("path", { d: "M14 2.5v4h4", fill: GOOGLE_MARK_COLORS.blueLight }), _jsx("path", { d: "M8 11h8M8 14.5h8M8 18h5", stroke: "white", strokeWidth: "1.4", strokeLinecap: "round" })] }));
40
+ case "sheets":
41
+ return (_jsxs("svg", { ...svgProps, children: [_jsx("path", { d: "M6 2.5h8l4 4v15H6a2 2 0 0 1-2-2v-15a2 2 0 0 1 2-2Z", fill: GOOGLE_MARK_COLORS.green }), _jsx("path", { d: "M14 2.5v4h4", fill: GOOGLE_MARK_COLORS.greenDark }), _jsx("path", { d: "M8 10h8v8H8v-8Zm0 2.7h8M8 15.3h8M10.7 10v8", stroke: "white", strokeWidth: "1.2" })] }));
42
+ case "slides":
43
+ return (_jsxs("svg", { ...svgProps, children: [_jsx("path", { d: "M6 2.5h8l4 4v15H6a2 2 0 0 1-2-2v-15a2 2 0 0 1 2-2Z", fill: GOOGLE_MARK_COLORS.yellowDark }), _jsx("path", { d: "M14 2.5v4h4", fill: GOOGLE_MARK_COLORS.yellow }), _jsx("path", { d: "M8 17V11m3 6v-3m3 3v-7", stroke: "white", strokeWidth: "1.7", strokeLinecap: "round" })] }));
44
+ }
45
+ }
@@ -1,6 +1,8 @@
1
1
  export { IntegrationsPanel, McpIntegrationsLanding, McpIntegrationsSection, type McpIntegrationsLandingProps, type McpIntegrationsSectionProps, } from "./IntegrationsPanel.js";
2
2
  export { IntegrationGrid, type IntegrationGridItem, type IntegrationGridProps, } from "./IntegrationGrid.js";
3
3
  export { IntegrationConnectionChoice, type IntegrationConnectionChoiceProps, } from "./IntegrationConnectionChoice.js";
4
+ export { GoogleProductLogo, type GoogleProduct } from "./GoogleProductLogo.js";
5
+ export { startWorkspaceProviderOAuth, workspaceProviderOAuthUrl, type WorkspaceProviderOAuthOptions, type WorkspaceProviderOAuthScope, } from "./workspace-provider-oauth.js";
4
6
  export { useIntegrationStatus } from "./useIntegrationStatus.js";
5
7
  export type { IntegrationStatus } from "./useIntegrationStatus.js";
6
8
  export { listIntegrationEnvStatuses, listIntegrationStatuses, saveIntegrationEnvVars, setIntegrationEnabled, setupIntegration, disconnectManagedIntegrationInstallation, listManagedIntegrationInstallations, managedIntegrationOAuthUrl, managedSlackAgentManifestUrl, listManagedIntegrationScopes, saveManagedIntegrationScope, listManagedIntegrationBudgets, listManagedIntegrationMemory, forgetManagedIntegrationMemory, saveManagedIntegrationBudget, testManagedIntegrationInstallation, IntegrationClientError, type ClientIntegrationInstallation, type ClientIntegrationScope, type ClientIntegrationUsageBudget, type ClientIntegrationMemory, type ClientIntegrationStatus, type IntegrationEnvStatus, type SavedEnvVarsResult, } from "./api.js";
@@ -1,5 +1,7 @@
1
1
  export { IntegrationsPanel, McpIntegrationsLanding, McpIntegrationsSection, } from "./IntegrationsPanel.js";
2
2
  export { IntegrationGrid, } from "./IntegrationGrid.js";
3
3
  export { IntegrationConnectionChoice, } from "./IntegrationConnectionChoice.js";
4
+ export { GoogleProductLogo } from "./GoogleProductLogo.js";
5
+ export { startWorkspaceProviderOAuth, workspaceProviderOAuthUrl, } from "./workspace-provider-oauth.js";
4
6
  export { useIntegrationStatus } from "./useIntegrationStatus.js";
5
7
  export { listIntegrationEnvStatuses, listIntegrationStatuses, saveIntegrationEnvVars, setIntegrationEnabled, setupIntegration, disconnectManagedIntegrationInstallation, listManagedIntegrationInstallations, managedIntegrationOAuthUrl, managedSlackAgentManifestUrl, listManagedIntegrationScopes, saveManagedIntegrationScope, listManagedIntegrationBudgets, listManagedIntegrationMemory, forgetManagedIntegrationMemory, saveManagedIntegrationBudget, testManagedIntegrationInstallation, IntegrationClientError, } from "./api.js";
@@ -0,0 +1,8 @@
1
+ export type WorkspaceProviderOAuthScope = "user" | "organization" | "app";
2
+ export interface WorkspaceProviderOAuthOptions {
3
+ appId: string;
4
+ returnPath?: string;
5
+ scope?: WorkspaceProviderOAuthScope;
6
+ }
7
+ export declare function workspaceProviderOAuthUrl(provider: string, options: WorkspaceProviderOAuthOptions): string;
8
+ export declare function startWorkspaceProviderOAuth(provider: string, options: WorkspaceProviderOAuthOptions): void;
@@ -0,0 +1,13 @@
1
+ import { agentNativePath } from "../api-path.js";
2
+ export function workspaceProviderOAuthUrl(provider, options) {
3
+ const params = new URLSearchParams({
4
+ appId: options.appId,
5
+ scope: options.scope ?? "user",
6
+ });
7
+ if (options.returnPath)
8
+ params.set("return", options.returnPath);
9
+ return agentNativePath(`/_agent-native/connections/oauth/${provider}/start?${params.toString()}`);
10
+ }
11
+ export function startWorkspaceProviderOAuth(provider, options) {
12
+ window.location.assign(workspaceProviderOAuthUrl(provider, options));
13
+ }
@@ -1,5 +1,6 @@
1
1
  export { agentNativePath, appApiPath, appBasePath, appPath, } from "../api-path.js";
2
2
  export { useAgentRouteState, useSemanticNavigationState, type AgentRouteLocation, type SemanticNavigationCommandEnvelope, type UseAgentRouteStateOptions, type UseAgentRouteStateResult, type UseSemanticNavigationStateOptions, type UseSemanticNavigationStateResult, } from "../route-state.js";
3
+ export { AGENT_NATIVE_WORKSPACE_APP_ROUTE_MESSAGE_TYPE, postAgentNativeWorkspaceAppRoute, type AgentNativeWorkspaceAppRouteMessage, } from "../workspace-app-navigation.js";
3
4
  export { COMMAND_MENU_OPEN_EVENT, CommandMenu, openAgentSidebar, openAgentSettings, openCommandMenu, submitToAgent, useCommandMenuShortcut, type CommandMenuProps, type CommandMenuDoc, type CommandDocsGroupProps, type CommandGroupProps, type CommandItemProps, type CommandShortcutProps, } from "../CommandMenu.js";
4
5
  export { buildOpenRouteLink, buildOpenRoutePath, buildLegacyAgentSettingsRoute, buildResourceRoute, buildSettingsRoute, buildStandardAppRoute, buildTeamRoute, createStandardOpenPathResolver, STANDARD_APP_ROUTES, STANDARD_SETTINGS_TABS, type BuildResourceRouteOptions, type BuildStandardAppRouteOptions, type NavigationLink, type NavigationTarget, type StandardAppRouteId, type StandardOpenPathResolverOptions, type StandardOpenPathRoute, type StandardSettingsTabId, } from "../../navigation/index.js";
5
6
  export { postNavigate, isInAgentEmbed, AGENT_NAVIGATE_MESSAGE_TYPE, type AgentNavigateMessage, } from "../embed.js";
@@ -1,5 +1,6 @@
1
1
  export { agentNativePath, appApiPath, appBasePath, appPath, } from "../api-path.js";
2
2
  export { useAgentRouteState, useSemanticNavigationState, } from "../route-state.js";
3
+ export { AGENT_NATIVE_WORKSPACE_APP_ROUTE_MESSAGE_TYPE, postAgentNativeWorkspaceAppRoute, } from "../workspace-app-navigation.js";
3
4
  export { COMMAND_MENU_OPEN_EVENT, CommandMenu, openAgentSidebar, openAgentSettings, openCommandMenu, submitToAgent, useCommandMenuShortcut, } from "../CommandMenu.js";
4
5
  export { buildOpenRouteLink, buildOpenRoutePath, buildLegacyAgentSettingsRoute, buildResourceRoute, buildSettingsRoute, buildStandardAppRoute, buildTeamRoute, createStandardOpenPathResolver, STANDARD_APP_ROUTES, STANDARD_SETTINGS_TABS, } from "../../navigation/index.js";
5
6
  export { postNavigate, isInAgentEmbed, AGENT_NAVIGATE_MESSAGE_TYPE, } from "../embed.js";
@@ -383,34 +383,6 @@ export const DEFAULT_MCP_INTEGRATIONS = [
383
383
  "Grafana Cloud",
384
384
  ],
385
385
  },
386
- {
387
- id: "google-workspace",
388
- name: "Google Workspace",
389
- provider: "google-workspace",
390
- description: "Search Google Workspace data through its remote MCP server.",
391
- descriptionKey: "mcpIntegrations.catalog.googleWorkspace.description",
392
- useCase: "Workspace search across Gmail, Drive, Calendar, Chat, Docs, Sheets, Slides",
393
- useCaseKey: "mcpIntegrations.catalog.googleWorkspace.useCase",
394
- url: "https://workspacemcp.googleapis.com/mcp/v1",
395
- authMode: "oauth",
396
- connectionMode: "manual",
397
- availability: "beta",
398
- verification: "restricted",
399
- logoUrl: mcpIntegrationLogo("google-workspace"),
400
- docsUrl: "https://developers.google.com/workspace/guides/configure-mcp-servers",
401
- setupNoteKey: "mcpIntegrations.catalog.googleWorkspace.setupNote",
402
- brandAliases: ["Google", "Gmail", "Google Drive", "Google Calendar"],
403
- keywords: [
404
- "email",
405
- "gmail",
406
- "drive",
407
- "calendar",
408
- "chat",
409
- "docs",
410
- "sheets",
411
- "slides",
412
- ],
413
- },
414
386
  {
415
387
  id: "gitlab",
416
388
  name: "GitLab",
@@ -900,7 +872,6 @@ const MCP_LINK_HOSTS = {
900
872
  sentry: ["sentry.io", "sentry.dev"],
901
873
  gong: ["gong.io"],
902
874
  grafana: ["grafana.com", "grafana.net"],
903
- "google-workspace": ["google.com", "googleapis.com"],
904
875
  "builder-cms": ["builder.io"],
905
876
  notion: ["notion.so", "notion.site"],
906
877
  granola: ["granola.ai"],
@@ -4,6 +4,7 @@ import { useLocation, useNavigate, } from "react-router";
4
4
  import { isWorkspaceAppPath } from "./api-path.js";
5
5
  import { deleteClientAppState, readClientAppState, setClientAppState, } from "./application-state.js";
6
6
  import { navigateWithAgentChatViewTransition, } from "./chat-view-transition.js";
7
+ import { postAgentNativeWorkspaceAppRoute } from "./workspace-app-navigation.js";
7
8
  const SAFE_BROWSER_TAB_ID_RE = /^[A-Za-z0-9_-]{1,96}$/;
8
9
  function normalizeBrowserTabId(browserTabId) {
9
10
  if (typeof browserTabId !== "string")
@@ -195,6 +196,11 @@ export function useAgentRouteState(options) {
195
196
  const location = useLocation();
196
197
  const navigate = useNavigate();
197
198
  const browserTabId = useMemo(() => normalizeBrowserTabId(options.browserTabId), [options.browserTabId]);
199
+ useEffect(() => {
200
+ if (options.enabled === false)
201
+ return;
202
+ postAgentNativeWorkspaceAppRoute(`${location.pathname}${location.search}${location.hash}`);
203
+ }, [location.hash, location.pathname, location.search, options.enabled]);
198
204
  const navigationKeys = useMemo(() => {
199
205
  const scopedKey = appStateKeyForBrowserTab(navigationKey, browserTabId);
200
206
  const keys = [scopedKey];
@@ -200,18 +200,22 @@ export function SettingsTabsPage({ general, account, team, whatsNew, extraTabs =
200
200
  ? defaultTab
201
201
  : (tabs[0]?.id ?? "general");
202
202
  const tabGroups = useMemo(() => {
203
- const groups = [];
203
+ // Keyed by group id so tabs sharing a group merge into one section even
204
+ // when another group's tabs sit between them in `tabs` — adjacency-only
205
+ // merging left same-id groups duplicated (and rendered with duplicate
206
+ // React keys) whenever the tab list interleaved groups.
207
+ const groupsById = new Map();
204
208
  for (const tab of tabs) {
205
209
  const groupId = tab.group ?? "app";
206
- const previousGroup = groups.at(-1);
207
- if (previousGroup?.id === groupId) {
208
- previousGroup.tabs.push(tab);
210
+ const group = groupsById.get(groupId);
211
+ if (group) {
212
+ group.tabs.push(tab);
209
213
  }
210
214
  else {
211
- groups.push({ id: groupId, tabs: [tab] });
215
+ groupsById.set(groupId, { id: groupId, tabs: [tab] });
212
216
  }
213
217
  }
214
- return groups;
218
+ return Array.from(groupsById.values());
215
219
  }, [tabs]);
216
220
  const tabGroupLabels = {
217
221
  app: "Personal",
@@ -133,7 +133,14 @@ function SharePanel(props) {
133
133
  const { controller } = props;
134
134
  const { inviteEmail, setInviteEmail: onInviteEmailChange, activeShareTab, handleShareTabChange, data, policy, visibility, canManage, role, setRole, notifyPeople, setNotifyPeople, shareMessage, setShareMessage, messageOpen, setMessageOpen, shareError, setShareError, suggestionsOpen, setSuggestionsOpen, inFlight, memberSearch, memberSuggestions, groupSuggestions, selectGroup, knownMembers, shares, handleVisibility, handleHideInSearch, handleAdd, handleChangeRole, handleRemove, } = controller;
135
135
  const hasInviteEmail = inviteEmail.trim().length > 0;
136
- const isLoading = data === undefined;
136
+ // `data` stays undefined after a failed read, so a stuck skeleton is
137
+ // indistinguishable from loading unless the error comes off the query itself.
138
+ // `isError` alone is not that signal: it is also true when a refetch fails
139
+ // while React Query still holds usable data, and this panel refetches on open
140
+ // and after every mutation — blocking on that would swap a working panel for
141
+ // a retry screen on one transient failure.
142
+ const loadFailed = controller.sharesQuery.isError && data === undefined;
143
+ const isLoading = !loadFailed && data === undefined;
137
144
  const meta = visibilityMeta(visibility, t, props.visibilityCopy);
138
145
  const peopleAccessLabel = props.peopleAccessLabel ??
139
146
  t("agentChat.share.peopleWithAccess", {
@@ -151,7 +158,9 @@ function SharePanel(props) {
151
158
  const hasTabs = extraTabs.length > 0;
152
159
  const shareTabLabel = props.shareTabs?.shareLabel ??
153
160
  t("agentChat.share.shareLink", { defaultValue: "Share link" });
154
- const sharePanel = isLoading ? (_jsxs("div", { children: [showShareLinks ? (_jsx("div", { className: "mb-4 h-9 rounded-md bg-muted animate-pulse" })) : null, _jsx("div", { className: "mb-2 text-sm font-semibold", children: generalAccessLabel }), _jsx("div", { className: "mb-4 h-9 rounded-md bg-muted animate-pulse" }), _jsx("div", { className: "mb-2 text-sm font-semibold", children: peopleAccessLabel }), _jsx("div", { className: "mb-4 h-7 rounded-md bg-muted animate-pulse" })] })) : (_jsxs("div", { children: [showShareLinks && shareUrlPlacement === "top" ? shareLinks : null, _jsxs("div", { className: "mb-4", children: [_jsx("div", { className: "mb-2 text-sm font-semibold", children: generalAccessLabel }), _jsxs("div", { className: "flex items-center gap-3", children: [_jsx("span", { "aria-hidden": true, className: "inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-muted text-muted-foreground", children: _jsx(meta.Icon, { size: 16, strokeWidth: 1.75 }) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx(VisibilitySelect, { value: visibility, onChange: handleVisibility, disabled: !canManage, visibilityCopy: props.visibilityCopy, allowPublic: policy.allowPublic }), _jsxs("div", { className: "mt-0.5 flex flex-wrap items-center gap-x-2 gap-y-1 text-xs text-muted-foreground", children: [_jsx("span", { className: "sr-only", children: meta.description }), visibility === "org" && props.hideInSearchControl ? (_jsx(AdvancedAccessPopover, { control: props.hideInSearchControl, canManage: canManage, onToggle: handleHideInSearch })) : null] })] })] })] }), _jsxs("div", { className: "mb-4 space-y-4", children: [_jsx("div", { className: "text-sm font-semibold", children: peopleAccessLabel }), canManage ? (_jsxs("div", { className: "space-y-2", children: [_jsxs("div", { className: "flex items-stretch gap-2", children: [_jsx(MemberAutocomplete, { value: inviteEmail, open: suggestionsOpen, onOpenChange: setSuggestionsOpen, onValueChange: (next) => {
161
+ const sharePanel = loadFailed ? (_jsxs("div", { children: [showShareLinks && shareUrlPlacement === "top" ? shareLinks : null, _jsxs("div", { role: "alert", className: "flex items-center justify-between gap-2 rounded-md border border-border bg-muted/30 px-3 py-2", children: [_jsx("span", { className: "text-xs text-muted-foreground", children: t("agentChat.share.loadFailed", {
162
+ defaultValue: "Couldn't load sharing settings.",
163
+ }) }), _jsx("button", { type: "button", onClick: () => controller.sharesQuery.refetch(), disabled: controller.sharesQuery.isFetching, className: cn(BUTTON_BASE, "h-7 px-2 text-xs text-muted-foreground hover:bg-accent hover:text-accent-foreground"), children: t("agentChat.common.retry") })] }), showShareLinks && shareUrlPlacement === "bottom" ? shareLinks : null] })) : isLoading ? (_jsxs("div", { children: [showShareLinks ? (_jsx("div", { className: "mb-4 h-9 rounded-md bg-muted animate-pulse" })) : null, _jsx("div", { className: "mb-2 text-sm font-semibold", children: generalAccessLabel }), _jsx("div", { className: "mb-4 h-9 rounded-md bg-muted animate-pulse" }), _jsx("div", { className: "mb-2 text-sm font-semibold", children: peopleAccessLabel }), _jsx("div", { className: "mb-4 h-7 rounded-md bg-muted animate-pulse" })] })) : (_jsxs("div", { children: [showShareLinks && shareUrlPlacement === "top" ? shareLinks : null, _jsxs("div", { className: "mb-4", children: [_jsx("div", { className: "mb-2 text-sm font-semibold", children: generalAccessLabel }), _jsxs("div", { className: "flex items-center gap-3", children: [_jsx("span", { "aria-hidden": true, className: "inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-muted text-muted-foreground", children: _jsx(meta.Icon, { size: 16, strokeWidth: 1.75 }) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx(VisibilitySelect, { value: visibility, onChange: handleVisibility, disabled: !canManage, visibilityCopy: props.visibilityCopy, allowPublic: policy.allowPublic }), _jsxs("div", { className: "mt-0.5 flex flex-wrap items-center gap-x-2 gap-y-1 text-xs text-muted-foreground", children: [_jsx("span", { className: "sr-only", children: meta.description }), visibility === "org" && props.hideInSearchControl ? (_jsx(AdvancedAccessPopover, { control: props.hideInSearchControl, canManage: canManage, onToggle: handleHideInSearch })) : null] })] })] })] }), _jsxs("div", { className: "mb-4 space-y-4", children: [_jsx("div", { className: "text-sm font-semibold", children: peopleAccessLabel }), canManage ? (_jsxs("div", { className: "space-y-2", children: [_jsxs("div", { className: "flex items-stretch gap-2", children: [_jsx(MemberAutocomplete, { value: inviteEmail, open: suggestionsOpen, onOpenChange: setSuggestionsOpen, onValueChange: (next) => {
155
164
  onInviteEmailChange(next);
156
165
  if (shareError)
157
166
  setShareError(null);
@@ -24,6 +24,12 @@ interface Options {
24
24
  */
25
25
  enabled?: boolean;
26
26
  }
27
+ /**
28
+ * `useChatModels` takes the raw localStorage key while `MultiTabAssistantChat`
29
+ * takes only the namespace suffix — a surface that hand-writes either one stops
30
+ * sharing the selection with the chat it sits next to.
31
+ */
32
+ export declare function chatModelSelectionStorageKey(namespace?: string | null): string;
27
33
  export declare const CHAT_MODEL_SELECTION_CHANGED_EVENT = "agent-native:chat-model-selection-changed";
28
34
  /**
29
35
  * Fetches available engines/models from the agent server and exposes the same
@@ -5,6 +5,16 @@ import { buildChatModelGroups, } from "./chat-model-groups.js";
5
5
  import { fetchBuilderStatus, fetchEnvironmentStatus, } from "./client-status-requests.js";
6
6
  import { callAction } from "./use-action.js";
7
7
  const DEFAULT_STORAGE_KEY = "agent-native:chat-models:selection";
8
+ /**
9
+ * `useChatModels` takes the raw localStorage key while `MultiTabAssistantChat`
10
+ * takes only the namespace suffix — a surface that hand-writes either one stops
11
+ * sharing the selection with the chat it sits next to.
12
+ */
13
+ export function chatModelSelectionStorageKey(namespace) {
14
+ return namespace
15
+ ? `${DEFAULT_STORAGE_KEY}:${namespace}`
16
+ : DEFAULT_STORAGE_KEY;
17
+ }
8
18
  export const CHAT_MODEL_SELECTION_CHANGED_EVENT = "agent-native:chat-model-selection-changed";
9
19
  const MODEL_DISCOVERY_RETRY_DELAYS_MS = [250, 1_000];
10
20
  async function fetchEngineCatalog() {
@@ -1,6 +1,7 @@
1
1
  import { useEffect, useRef, useState } from "react";
2
2
  import { ensureDemoModeFetchInterceptor } from "../demo/fetch-interceptor.js";
3
3
  import { parseHandshakeFrame, parseTokenFrame, REALTIME_PROTOCOL_VERSION, REALTIME_SSE_HANDSHAKE_EVENT, REALTIME_SSE_TOKEN_EVENT, } from "../realtime-protocol.js";
4
+ import { addSurfaceVisibilityListener, isHostSurfaceHidden, isSurfaceHidden, } from "../shared/surface-visibility.js";
4
5
  import { agentNativePath } from "./api-path.js";
5
6
  import { getBrowserTabId } from "./browser-tab-id.js";
6
7
  import { ensureEmbedAuthFetchInterceptor, isEmbedAuthActive, } from "./embed-auth.js";
@@ -103,7 +104,7 @@ function getPollAbortMs(interval) {
103
104
  return Math.max(POLL_ABORT_MIN_MS, interval * 4);
104
105
  }
105
106
  function isDocumentHidden() {
106
- return (typeof document !== "undefined" && document.visibilityState === "hidden");
107
+ return isSurfaceHidden();
107
108
  }
108
109
  function resolveSseUrl(sseUrl) {
109
110
  if (sseUrl === false)
@@ -269,6 +270,7 @@ class SyncTransport {
269
270
  subscribers = new Map();
270
271
  cursorRef = { ...INITIAL_SYNC_CURSOR };
271
272
  timer = null;
273
+ removeVisibilityListener;
272
274
  stopped = false;
273
275
  inFlight = false;
274
276
  eventSource = null;
@@ -470,6 +472,17 @@ class SyncTransport {
470
472
  // -------------------------------------------------------------------------
471
473
  // Derived settings (aggregate over active subscribers)
472
474
  // -------------------------------------------------------------------------
475
+ /**
476
+ * Whether this transport must do nothing at all right now. A host that has
477
+ * stashed the surface off screen is a stronger statement than a backgrounded
478
+ * browser tab, so it pauses regardless of `pauseWhenHidden` — an embedder
479
+ * only sets it for a surface the user genuinely cannot see.
480
+ */
481
+ shouldStayIdle() {
482
+ if (isHostSurfaceHidden())
483
+ return true;
484
+ return this.effectivePauseWhenHidden && isDocumentHidden();
485
+ }
473
486
  get effectivePauseWhenHidden() {
474
487
  // Pause only if every subscriber has opted in.
475
488
  for (const sub of this.subscribers.values()) {
@@ -550,7 +563,7 @@ class SyncTransport {
550
563
  schedulePoll() {
551
564
  if (this.stopped)
552
565
  return;
553
- if (this.effectivePauseWhenHidden && isDocumentHidden())
566
+ if (this.shouldStayIdle())
554
567
  return;
555
568
  if (this.timer)
556
569
  clearTimeout(this.timer);
@@ -743,7 +756,7 @@ class SyncTransport {
743
756
  if (this.stopped ||
744
757
  this.eventSource ||
745
758
  typeof EventSource === "undefined" ||
746
- (this.effectivePauseWhenHidden && isDocumentHidden())) {
759
+ this.shouldStayIdle()) {
747
760
  return;
748
761
  }
749
762
  // One tab per origin holds the stream; the rest follow it over
@@ -896,6 +909,10 @@ class SyncTransport {
896
909
  async poll() {
897
910
  if (this.stopped || this.inFlight)
898
911
  return;
912
+ // Re-checked here, not only at the schedule sites: whatever path
913
+ // reached poll(), a host-hidden surface must not issue a request.
914
+ if (this.shouldStayIdle())
915
+ return;
899
916
  this.inFlight = true;
900
917
  try {
901
918
  if (this.mode === "hosted" && this.gateway && !this.token) {
@@ -947,7 +964,7 @@ class SyncTransport {
947
964
  }
948
965
  }
949
966
  pollNow() {
950
- if (this.effectivePauseWhenHidden && isDocumentHidden())
967
+ if (this.shouldStayIdle())
951
968
  return;
952
969
  if (this.authFailureDelayMs() > 0) {
953
970
  this.schedulePoll();
@@ -961,11 +978,11 @@ class SyncTransport {
961
978
  void this.poll();
962
979
  }
963
980
  handleVisibilityChange = () => {
964
- if (document.visibilityState === "visible") {
981
+ if (!isSurfaceHidden()) {
965
982
  this.connectEvents();
966
983
  this.pollNow();
967
984
  }
968
- else if (this.effectivePauseWhenHidden) {
985
+ else if (this.shouldStayIdle()) {
969
986
  this.closeEvents();
970
987
  // A hidden leader stops streaming, so it must not keep holding the
971
988
  // origin's stream slot — that would leave every visible tab following a
@@ -1030,13 +1047,13 @@ class SyncTransport {
1030
1047
  // already mounts useDbSync, so this needs zero per-template wiring.
1031
1048
  ensureEmbedAuthFetchInterceptor();
1032
1049
  ensureDemoModeFetchInterceptor();
1033
- if (!this.effectivePauseWhenHidden || !isDocumentHidden()) {
1050
+ if (!this.shouldStayIdle()) {
1034
1051
  this.connectEvents();
1035
1052
  void this.poll();
1036
1053
  }
1037
1054
  window.addEventListener("focus", this.handleFocus);
1038
1055
  window.addEventListener("agentNative.chatRunning", this.handleChatRunning);
1039
- document.addEventListener("visibilitychange", this.handleVisibilityChange);
1056
+ this.removeVisibilityListener = addSurfaceVisibilityListener(this.handleVisibilityChange);
1040
1057
  }
1041
1058
  teardown() {
1042
1059
  this.stopped = true;
@@ -1060,7 +1077,8 @@ class SyncTransport {
1060
1077
  }
1061
1078
  window.removeEventListener("focus", this.handleFocus);
1062
1079
  window.removeEventListener("agentNative.chatRunning", this.handleChatRunning);
1063
- document.removeEventListener("visibilitychange", this.handleVisibilityChange);
1080
+ this.removeVisibilityListener?.();
1081
+ this.removeVisibilityListener = undefined;
1064
1082
  }
1065
1083
  }
1066
1084
  /**
@@ -0,0 +1,10 @@
1
+ export declare const AGENT_NATIVE_WORKSPACE_APP_ROUTE_MESSAGE_TYPE: "agent-native:workspace-app-route";
2
+ export interface AgentNativeWorkspaceAppRouteMessage {
3
+ type: typeof AGENT_NATIVE_WORKSPACE_APP_ROUTE_MESSAGE_TYPE;
4
+ path: string;
5
+ }
6
+ /**
7
+ * Report an app-local route to its immediate embedding host. The host checks
8
+ * the iframe source and origin before applying the route to its own URL.
9
+ */
10
+ export declare function postAgentNativeWorkspaceAppRoute(path: string): boolean;
@@ -0,0 +1,38 @@
1
+ export const AGENT_NATIVE_WORKSPACE_APP_ROUTE_MESSAGE_TYPE = "agent-native:workspace-app-route";
2
+ function normalizeWorkspaceAppRoute(path) {
3
+ if (typeof path !== "string" ||
4
+ !path.startsWith("/") ||
5
+ path.startsWith("//")) {
6
+ return null;
7
+ }
8
+ if (/[\u0000-\u001f\u007f]/.test(path))
9
+ return null;
10
+ try {
11
+ const url = new URL(path, "http://agent-native.invalid");
12
+ return `${url.pathname}${url.search}${url.hash}`;
13
+ }
14
+ catch {
15
+ // coercion-ok: malformed route input is not reported to the host.
16
+ return null;
17
+ }
18
+ }
19
+ /**
20
+ * Report an app-local route to its immediate embedding host. The host checks
21
+ * the iframe source and origin before applying the route to its own URL.
22
+ */
23
+ export function postAgentNativeWorkspaceAppRoute(path) {
24
+ if (typeof window === "undefined")
25
+ return false;
26
+ const parentWindow = window.parent;
27
+ if (!parentWindow || parentWindow === window)
28
+ return false;
29
+ const normalizedPath = normalizeWorkspaceAppRoute(path);
30
+ if (!normalizedPath)
31
+ return false;
32
+ const message = {
33
+ type: AGENT_NATIVE_WORKSPACE_APP_ROUTE_MESSAGE_TYPE,
34
+ path: normalizedPath,
35
+ };
36
+ parentWindow.postMessage(message, "*");
37
+ return true;
38
+ }
@@ -13,8 +13,8 @@
13
13
  * Body: { json: any, fieldName?: string, type?: "map"|"array", requestSource?: string }
14
14
  */
15
15
  export declare const postCollabJson: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
16
- ok?: undefined;
17
16
  error: string;
17
+ ok?: undefined;
18
18
  } | {
19
19
  error?: undefined;
20
20
  ok: boolean;