@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
@@ -1,58 +1,58 @@
1
- import { finishMcpOAuthAuthorization, getMcpOAuthAccessToken, readMcpOAuthCredentials, revokeMcpOAuthCredentials, saveMcpOAuthCredentials, startMcpOAuthAuthorization, validateMcpOAuthCallbackIssuer, } from "../mcp-client/oauth-client.js";
1
+ import { createHash } from "node:crypto";
2
+ import { finishMcpOAuthAuthorization, getMcpOAuthAccessToken, markMcpOAuthReconnectRequired, readMcpOAuthCredentials, revokeMcpOAuthCredentials, saveMcpOAuthCredentials, startMcpOAuthAuthorization, validateMcpOAuthCallbackIssuer, } from "../mcp-client/oauth-client.js";
2
3
  import { getOAuthTokens } from "../oauth-tokens/store.js";
3
- import { getSetting, mutateSetting, putSetting } from "../settings/store.js";
4
+ import { resolveOrgIdForEmail } from "../org/context.js";
4
5
  export const BUILDER_OAUTH_ISSUER = "https://mcp.builder.io";
5
6
  export const BUILDER_OAUTH_RESOURCE = "https://api.builder.io";
6
- export const BUILDER_OAUTH_PROTECTED_RESOURCE_METADATA = "https://mcp.builder.io/.well-known/oauth-protected-resource/api";
7
- export const BUILDER_OAUTH_AUTHORIZATION_METADATA = "https://mcp.builder.io/.well-known/oauth-authorization-server";
8
- export const BUILDER_OAUTH_AUTHORIZATION_ENDPOINT = "https://mcp.builder.io/oauth/authorize";
9
- export const BUILDER_OAUTH_TOKEN_ENDPOINT = "https://mcp.builder.io/oauth/token";
10
- export const BUILDER_OAUTH_REGISTRATION_ENDPOINT = "https://mcp.builder.io/oauth/register";
11
- export const BUILDER_OAUTH_REVOCATION_ENDPOINT = "https://mcp.builder.io/oauth/revoke";
12
7
  export const BUILDER_OAUTH_SCOPE = "builder:ai:invoke";
13
8
  export const BUILDER_OAUTH_SCOPES = [BUILDER_OAUTH_SCOPE];
9
+ // Folded with the owner so each owner gets their own (provider, account_id)
10
+ // row; a bare shared key would let only the first connector hold a grant.
14
11
  const BUILDER_OAUTH_KEY = "builder-general-resource-v1";
15
- const REFRESH_SKEW_MS = 60_000;
16
- const REFRESH_LEASE_MS = 15_000;
17
- const REFRESH_WAIT_MS = 50;
18
- function ownerOptions(ownerEmail) {
19
- const scopeId = ownerEmail.trim().toLowerCase();
20
- if (!scopeId)
12
+ // Builder's general AI resource metadata lives at a non-default path; the
13
+ // default api.builder.io well-known describes its Figma integration instead.
14
+ // Point discovery here so live metadata resolves to the api.builder.io resource
15
+ // and the mcp.builder.io authorization server.
16
+ const BUILDER_OAUTH_PROTECTED_RESOURCE_METADATA = "https://mcp.builder.io/.well-known/oauth-protected-resource/api";
17
+ // The Builder connection is shared by everyone in the caller's org: the
18
+ // credential is scoped to the org so every member reads the same token. Every
19
+ // user belongs to an org, so a missing org is a broken invariant, not a case
20
+ // to fall back on.
21
+ function normalizeOwnerEmail(ownerEmail) {
22
+ const email = ownerEmail.trim().toLowerCase();
23
+ if (!email)
21
24
  throw new Error("Builder OAuth owner email is required");
25
+ return email;
26
+ }
27
+ // Read paths use this: a caller with no org simply has no Builder session, so
28
+ // engine detection and status checks get null instead of an exception.
29
+ async function resolveOwnerOptions(ownerEmail) {
30
+ const email = normalizeOwnerEmail(ownerEmail);
31
+ const orgId = await resolveOrgIdForEmail(email);
32
+ if (!orgId)
33
+ return null;
34
+ return orgOwnerOptions(orgId);
35
+ }
36
+ // Write paths use this: storing a Builder credential without an org is a broken
37
+ // invariant, so a missing org fails loudly rather than silently dropping it.
38
+ async function ownerOptions(ownerEmail) {
39
+ const options = await resolveOwnerOptions(ownerEmail);
40
+ if (!options) {
41
+ throw new Error(`Builder OAuth requires an organization for ${normalizeOwnerEmail(ownerEmail)}`);
42
+ }
43
+ return options;
44
+ }
45
+ function orgOwnerOptions(orgId) {
22
46
  return {
23
- key: BUILDER_OAUTH_KEY,
24
- scope: "user",
25
- scopeId,
47
+ key: builderOAuthKey(orgId),
48
+ scope: "org",
49
+ scopeId: orgId,
26
50
  serverUrl: BUILDER_OAUTH_RESOURCE,
27
51
  };
28
52
  }
29
- function refreshLeaseKey(ownerEmail) {
30
- return `builder-oauth-refresh:user:${ownerOptions(ownerEmail).scopeId}`;
31
- }
32
- function reconnectKey(ownerEmail) {
33
- return `builder-oauth-reconnect:user:${ownerOptions(ownerEmail).scopeId}`;
34
- }
35
- function discoveryState() {
36
- return {
37
- authorizationServerUrl: BUILDER_OAUTH_ISSUER,
38
- authorizationServerMetadata: {
39
- issuer: BUILDER_OAUTH_ISSUER,
40
- authorization_endpoint: BUILDER_OAUTH_AUTHORIZATION_ENDPOINT,
41
- token_endpoint: BUILDER_OAUTH_TOKEN_ENDPOINT,
42
- registration_endpoint: BUILDER_OAUTH_REGISTRATION_ENDPOINT,
43
- revocation_endpoint: BUILDER_OAUTH_REVOCATION_ENDPOINT,
44
- // MCP SDK auth() reads these from the provided discovery blob and throws
45
- // if they are missing — do not omit them when skipping live metadata fetch.
46
- response_types_supported: ["code"],
47
- grant_types_supported: ["authorization_code", "refresh_token"],
48
- code_challenge_methods_supported: ["S256"],
49
- },
50
- resourceMetadataUrl: BUILDER_OAUTH_PROTECTED_RESOURCE_METADATA,
51
- resourceMetadata: {
52
- resource: BUILDER_OAUTH_RESOURCE,
53
- authorization_servers: [BUILDER_OAUTH_ISSUER],
54
- },
55
- };
53
+ function builderOAuthKey(orgId) {
54
+ const digest = createHash("sha256").update(orgId).digest("hex");
55
+ return `${BUILDER_OAUTH_KEY}:o:${digest}`;
56
56
  }
57
57
  function scopesFrom(credentials) {
58
58
  const declared = credentials.tokens.scope;
@@ -72,35 +72,11 @@ function isBuilderDiscoveryState(value) {
72
72
  if (!value || typeof value !== "object")
73
73
  return false;
74
74
  const discovery = value;
75
- const authorizationServers = discovery.resourceMetadata?.authorization_servers;
76
- const responseTypes = discovery.authorizationServerMetadata?.response_types_supported;
77
- const grantTypes = discovery.authorizationServerMetadata?.grant_types_supported;
78
- const challengeMethods = discovery.authorizationServerMetadata?.code_challenge_methods_supported;
79
- const resource = typeof discovery.resourceMetadata?.resource === "string"
80
- ? discovery.resourceMetadata.resource
81
- : null;
82
- return (discovery?.authorizationServerUrl === BUILDER_OAUTH_ISSUER &&
75
+ const resource = discovery.resourceMetadata?.resource;
76
+ return (discovery.authorizationServerUrl === BUILDER_OAUTH_ISSUER &&
83
77
  discovery.authorizationServerMetadata?.issuer === BUILDER_OAUTH_ISSUER &&
84
- discovery.authorizationServerMetadata?.authorization_endpoint ===
85
- BUILDER_OAUTH_AUTHORIZATION_ENDPOINT &&
86
- discovery.authorizationServerMetadata?.token_endpoint ===
87
- BUILDER_OAUTH_TOKEN_ENDPOINT &&
88
- discovery.authorizationServerMetadata?.registration_endpoint ===
89
- BUILDER_OAUTH_REGISTRATION_ENDPOINT &&
90
- discovery.authorizationServerMetadata?.revocation_endpoint ===
91
- BUILDER_OAUTH_REVOCATION_ENDPOINT &&
92
- Array.isArray(responseTypes) &&
93
- responseTypes.includes("code") &&
94
- Array.isArray(grantTypes) &&
95
- grantTypes.includes("authorization_code") &&
96
- Array.isArray(challengeMethods) &&
97
- challengeMethods.includes("S256") &&
98
- discovery.resourceMetadataUrl ===
99
- BUILDER_OAUTH_PROTECTED_RESOURCE_METADATA &&
100
- !!resource &&
101
- resourceUrlsMatch(resource, BUILDER_OAUTH_RESOURCE) &&
102
- Array.isArray(authorizationServers) &&
103
- authorizationServers.includes(BUILDER_OAUTH_ISSUER));
78
+ typeof resource === "string" &&
79
+ resourceUrlsMatch(resource, BUILDER_OAUTH_RESOURCE));
104
80
  }
105
81
  function isBuilderCredential(credentials) {
106
82
  return (resourceUrlsMatch(credentials.serverUrl, BUILDER_OAUTH_RESOURCE) &&
@@ -108,26 +84,16 @@ function isBuilderCredential(credentials) {
108
84
  credentials.tokens.issuer === BUILDER_OAUTH_ISSUER &&
109
85
  isBuilderDiscoveryState(credentials.discoveryState));
110
86
  }
111
- function sessionFrom(credentials) {
112
- if (!isBuilderCredential(credentials))
113
- return null;
114
- const accessToken = credentials.tokens.access_token;
115
- if (typeof accessToken !== "string" || !accessToken)
116
- return null;
117
- return {
118
- accessToken,
119
- expiresAt: credentials.tokenExpiresAt,
120
- scopes: scopesFrom(credentials),
121
- };
122
- }
123
87
  export async function startBuilderOAuthAuthorization(input) {
124
- ownerOptions(input.ownerEmail);
88
+ // Start scopes nothing, so it validates the email without an org lookup;
89
+ // the org scope is resolved when the grant is stored and read.
90
+ normalizeOwnerEmail(input.ownerEmail);
125
91
  const started = await startMcpOAuthAuthorization({
126
92
  serverUrl: BUILDER_OAUTH_RESOURCE,
127
93
  redirectUrl: input.redirectUri,
128
94
  state: input.state,
129
95
  scope: BUILDER_OAUTH_SCOPE,
130
- discoveryState: discoveryState(),
96
+ resourceMetadataUrl: BUILDER_OAUTH_PROTECTED_RESOURCE_METADATA,
131
97
  });
132
98
  return {
133
99
  authorizationUrl: started.authorizationUrl.toString(),
@@ -140,9 +106,6 @@ export async function startBuilderOAuthAuthorization(input) {
140
106
  };
141
107
  }
142
108
  export async function finishBuilderOAuthAuthorization(input) {
143
- if (!isBuilderDiscoveryState(input.pending.discoveryState)) {
144
- throw new Error("Builder OAuth pending flow has an invalid discovery binding");
145
- }
146
109
  validateMcpOAuthCallbackIssuer(input.pending.discoveryState, input.iss);
147
110
  const result = await finishMcpOAuthAuthorization({
148
111
  serverUrl: BUILDER_OAUTH_RESOURCE,
@@ -158,40 +121,41 @@ export async function finishBuilderOAuthAuthorization(input) {
158
121
  throw new Error("Builder OAuth exchange returned credentials for another resource");
159
122
  }
160
123
  await saveMcpOAuthCredentials({
161
- ...ownerOptions(input.ownerEmail),
124
+ ...(input.orgId
125
+ ? orgOwnerOptions(input.orgId)
126
+ : await ownerOptions(input.ownerEmail)),
162
127
  credentials: result.credentials,
163
128
  });
164
- await putSetting(reconnectKey(input.ownerEmail), {
165
- required: false,
166
- at: Date.now(),
167
- }).catch(() => {
168
- // coercion-ok: reconnect flag clear is best-effort after a successful grant.
169
- });
170
129
  }
171
130
  export async function markBuilderOAuthReconnectRequired(ownerEmail) {
172
- await putSetting(reconnectKey(ownerEmail), {
173
- required: true,
174
- at: Date.now(),
175
- });
176
- }
177
- export async function builderOAuthReconnectRequired(ownerEmail) {
178
- const row = await getSetting(reconnectKey(ownerEmail));
179
- return row?.required === true;
131
+ const options = await resolveOwnerOptions(ownerEmail);
132
+ if (!options)
133
+ return;
134
+ await markMcpOAuthReconnectRequired(options);
180
135
  }
181
136
  export async function getBuilderOAuthSession(ownerEmail) {
182
- if (await builderOAuthReconnectRequired(ownerEmail))
137
+ const options = await resolveOwnerOptions(ownerEmail);
138
+ if (!options)
139
+ return null;
140
+ // Delegates refresh single-flight and reconnect latching to the shared
141
+ // credential lifecycle; a null token covers missing, expired-unrefreshable,
142
+ // and reconnect_required alike.
143
+ const accessToken = await getMcpOAuthAccessToken(options);
144
+ if (!accessToken)
183
145
  return null;
184
- const credentials = await readMcpOAuthCredentials(ownerOptions(ownerEmail));
146
+ const credentials = await readMcpOAuthCredentials(options);
185
147
  if (!credentials || !isBuilderCredential(credentials))
186
148
  return null;
187
- if (typeof credentials.tokenExpiresAt === "number" &&
188
- credentials.tokenExpiresAt - Date.now() <= REFRESH_SKEW_MS) {
189
- return refreshBuilderOAuthSession(ownerEmail);
190
- }
191
- return sessionFrom(credentials);
149
+ return {
150
+ accessToken,
151
+ expiresAt: credentials.tokenExpiresAt,
152
+ scopes: scopesFrom(credentials),
153
+ };
192
154
  }
193
155
  export async function hasBuilderOAuthSession(ownerEmail) {
194
- const options = ownerOptions(ownerEmail);
156
+ const options = await resolveOwnerOptions(ownerEmail);
157
+ if (!options)
158
+ return false;
195
159
  const stored = await getOAuthTokens("mcp", options.key, `${options.scope}:${options.scopeId}`);
196
160
  return stored !== null;
197
161
  }
@@ -202,60 +166,13 @@ export async function resolveBuilderOAuthRequestAccess(input) {
202
166
  if (!session.scopes.includes(input.requiredScope)) {
203
167
  throw new Error(`Builder OAuth connection does not grant ${input.requiredScope}`);
204
168
  }
205
- return { ...session, ownerEmail: ownerOptions(input.ownerEmail).scopeId };
206
- }
207
- async function refreshBuilderOAuthSession(ownerEmail) {
208
- const owner = crypto.randomUUID();
209
- const leaseKey = refreshLeaseKey(ownerEmail);
210
- const lease = await mutateSetting(leaseKey, (current) => {
211
- if (typeof current?.expiresAt !== "number" ||
212
- current.expiresAt <= Date.now()) {
213
- return { owner, expiresAt: Date.now() + REFRESH_LEASE_MS };
214
- }
215
- return current;
216
- });
217
- if (lease.owner !== owner)
218
- return waitForRefreshedSession(ownerEmail);
219
- try {
220
- const options = ownerOptions(ownerEmail);
221
- const accessToken = await getMcpOAuthAccessToken(options);
222
- const next = await readMcpOAuthCredentials(options);
223
- if (!accessToken || !next || !isBuilderCredential(next)) {
224
- throw new Error("Builder OAuth refresh failed");
225
- }
226
- return sessionFrom(next);
227
- }
228
- catch {
229
- await markBuilderOAuthReconnectRequired(ownerEmail);
230
- return null;
231
- }
232
- finally {
233
- await mutateSetting(leaseKey, (current) => current?.owner === owner ? { owner: "", expiresAt: 0 } : (current ?? {}));
234
- }
235
- }
236
- async function waitForRefreshedSession(ownerEmail) {
237
- for (let waited = 0; waited < REFRESH_LEASE_MS; waited += REFRESH_WAIT_MS) {
238
- await new Promise((resolve) => setTimeout(resolve, REFRESH_WAIT_MS));
239
- const credentials = await readMcpOAuthCredentials(ownerOptions(ownerEmail));
240
- if (!credentials || !isBuilderCredential(credentials))
241
- return null;
242
- if (typeof credentials.tokenExpiresAt !== "number" ||
243
- credentials.tokenExpiresAt - Date.now() <= REFRESH_SKEW_MS) {
244
- continue;
245
- }
246
- return sessionFrom(credentials);
247
- }
248
- return null;
169
+ return { ...session, ownerEmail: input.ownerEmail.trim().toLowerCase() };
249
170
  }
250
171
  export async function deleteBuilderOAuthSession(ownerEmail) {
251
- const options = ownerOptions(ownerEmail);
172
+ const options = await resolveOwnerOptions(ownerEmail);
173
+ if (!options)
174
+ return { localDeleted: false, remoteRevoked: false };
252
175
  const result = await revokeMcpOAuthCredentials(options);
253
- await putSetting(reconnectKey(ownerEmail), {
254
- required: false,
255
- at: Date.now(),
256
- }).catch(() => {
257
- // coercion-ok: reconnect flag clear is best-effort after local revoke.
258
- });
259
176
  return {
260
177
  localDeleted: result.local === "deleted",
261
178
  remoteRevoked: result.remote === "succeeded",
@@ -305,6 +305,35 @@ export declare function readLegacyCoreRouteInitSettings(readSetting?: CoreRouteS
305
305
  */
306
306
  export declare function shouldRunCoreRouteBootDatabaseWork(env?: NodeJS.ProcessEnv): boolean;
307
307
  export declare function ensureS3FileUploadProvider(): void;
308
+ export interface OAuthCustodyBuilderKeyStatus {
309
+ privateKeyConfigured: boolean;
310
+ publicKeyConfigured: boolean;
311
+ orgName: string;
312
+ /**
313
+ * True when the key-pair lookup itself failed (credential store
314
+ * unreadable, org lookup error, a thrown import) rather than confirming
315
+ * no keys exist. privateKeyConfigured/publicKeyConfigured stay `false` in
316
+ * both cases — this is the only signal that tells "never configured"
317
+ * apart from "couldn't check right now", so a transient store blip can't
318
+ * read downstream as "the user never connected Builder keys".
319
+ */
320
+ keyLookupFailed: boolean;
321
+ }
322
+ /**
323
+ * Resolves the classic Builder key-pair status for a request that already
324
+ * has Builder MCP OAuth custody (the connection-status handler's `configured`
325
+ * is already `true` by the time this runs — OAuth alone proves the chat
326
+ * gateway). Exported so the connection-status route's OAuth-custody branch is
327
+ * unit-testable without standing up the full plugin.
328
+ */
329
+ export declare function resolveOAuthCustodyBuilderKeyStatus(dependencies?: {
330
+ resolveCredentialsDetailed: () => Promise<{
331
+ privateKey: string | null;
332
+ publicKey: string | null;
333
+ orgName: string | null;
334
+ lookupFailed: boolean;
335
+ }>;
336
+ }): Promise<OAuthCustodyBuilderKeyStatus>;
308
337
  export declare function createCoreRoutesPlugin(options?: CoreRoutesPluginOptions): NitroPluginDef;
309
338
  /**
310
339
  * Default core routes plugin — mount with no configuration needed.
@@ -42,7 +42,7 @@ import { readAnalyticsClientPlatformHeader, readBrowserSessionIdHeader, } from "
42
42
  import { getConfiguredAppBasePath, stripAppBasePath } from "./app-base-path.js";
43
43
  import { getAppName } from "./app-name.js";
44
44
  import { getSession } from "./auth.js";
45
- import { BUILDER_CONNECT_PARAM, BUILDER_ENV_KEYS, BUILDER_OPENER_PARAM, BUILDER_RELAY_FLOW_HEADER, BUILDER_RELAY_SIGNATURE_HEADER, BUILDER_RELAY_STATE_PARAM, BUILDER_RELAY_TIMESTAMP_HEADER, appendBuilderConnectToken, builderConnectTrackingProperties, createBuilderConnectState, createBuilderBrowserCallbackErrorPage, createBuilderBrowserCallbackPage, createBuilderRelayRequest, getBuilderConnectTrackingParams, getBuilderBrowserOriginForEvent, getBuilderBrowserStatusForEvent, isBuilderConnectCallbackUrlAllowed, isSignedBuilderConnectState, resolveBuilderBranchProjectId, resolveBuilderConnectCallbackUrl, resolveBuilderPreviewRelayParentOrigin, runBuilderAgent, verifyBuilderRelayRequest, verifyBuilderPreviewRelayStateForCallback, verifyBuilderConnectTokenAndGetOwner, } from "./builder-browser.js";
45
+ import { BUILDER_CONNECT_PARAM, BUILDER_ENV_KEYS, BUILDER_OPENER_PARAM, BUILDER_RELAY_FLOW_HEADER, BUILDER_RELAY_SIGNATURE_HEADER, BUILDER_RELAY_STATE_PARAM, BUILDER_RELAY_TIMESTAMP_HEADER, appendBuilderConnectToken, builderConnectTrackingProperties, createBuilderConnectState, createBuilderBrowserCallbackErrorPage, createBuilderBrowserCallbackPage, createBuilderRelayRequest, getBuilderConnectTrackingParams, getBuilderBrowserOriginForEvent, getBuilderBrowserStatusForEvent, isBuilderConnectCallbackUrlAllowed, isSignedBuilderConnectState, normalizeBuilderAgentContext, resolveBuilderBranchProjectId, resolveBuilderConnectCallbackUrl, resolveBuilderPreviewRelayParentOrigin, runBuilderAgent, verifyBuilderRelayRequest, verifyBuilderPreviewRelayStateForCallback, verifyBuilderConnectTokenAndGetOwner, } from "./builder-browser.js";
46
46
  import { BUILDER_OAUTH_SCOPE, deleteBuilderOAuthSession, finishBuilderOAuthAuthorization, hasBuilderOAuthSession, resolveBuilderOAuthRequestAccess, startBuilderOAuthAuthorization, } from "./builder-oauth.js";
47
47
  import { captureError, registerErrorCaptureProvider } from "./capture-error.js";
48
48
  import { getAllowedCorsOrigin, readCorsAllowedOrigins, } from "./cors-origins.js";
@@ -222,6 +222,33 @@ async function resolveAgentEngineStatusIdentity(event) {
222
222
  return { userEmail, orgId: undefined };
223
223
  }
224
224
  }
225
+ /**
226
+ * A Builder grant is shared by everyone in the caller's org, so establishing,
227
+ * overwriting, or revoking one requires org owner/admin authority. Returns the
228
+ * authorized org id and a denial message (null when allowed). The org id is
229
+ * captured at connect start so the grant is stored under the org that was
230
+ * authorized, not one re-resolved after the OAuth round trip. Fails closed: an
231
+ * unreadable owner/admin role is denied.
232
+ */
233
+ async function resolveBuilderOrgMutation(event) {
234
+ let orgId = null;
235
+ let role = null;
236
+ try {
237
+ const orgCtx = await getOrgContext(event);
238
+ orgId = orgCtx.orgId ?? null;
239
+ role = orgCtx.role ?? null;
240
+ }
241
+ catch {
242
+ // coercion-ok: org is missing, it will fail closed
243
+ }
244
+ if (role !== "owner" && role !== "admin") {
245
+ return {
246
+ orgId,
247
+ deny: "Only an organization owner or admin can change the shared Builder connection.",
248
+ };
249
+ }
250
+ return { orgId, deny: null };
251
+ }
225
252
  export function getFrameworkEnvKeys() {
226
253
  return [
227
254
  { key: "ENABLE_BUILDER", label: "Enable Builder.io features" },
@@ -927,6 +954,43 @@ export function ensureS3FileUploadProvider() {
927
954
  }
928
955
  registerFileUploadProvider(s3FileUploadProvider);
929
956
  }
957
+ /**
958
+ * Resolves the classic Builder key-pair status for a request that already
959
+ * has Builder MCP OAuth custody (the connection-status handler's `configured`
960
+ * is already `true` by the time this runs — OAuth alone proves the chat
961
+ * gateway). Exported so the connection-status route's OAuth-custody branch is
962
+ * unit-testable without standing up the full plugin.
963
+ */
964
+ export async function resolveOAuthCustodyBuilderKeyStatus(dependencies = {
965
+ resolveCredentialsDetailed: async () => {
966
+ const { resolveBuilderCredentialsDetailed } = await import("./credential-provider.js");
967
+ return resolveBuilderCredentialsDetailed();
968
+ },
969
+ }) {
970
+ try {
971
+ const creds = await dependencies.resolveCredentialsDetailed();
972
+ return {
973
+ privateKeyConfigured: !!creds.privateKey,
974
+ publicKeyConfigured: !!creds.publicKey,
975
+ orgName: typeof creds.orgName === "string" && creds.orgName
976
+ ? creds.orgName
977
+ : "Builder OAuth",
978
+ keyLookupFailed: creds.lookupFailed,
979
+ };
980
+ }
981
+ catch {
982
+ // OAuth already proves the chat gateway, so a thrown key-pair lookup
983
+ // here must not abort the response — but it is unreadable, not
984
+ // confirmed-absent, so keyLookupFailed has to say so (see the field doc
985
+ // above) instead of silently landing on the same `false`s as a real miss.
986
+ return {
987
+ privateKeyConfigured: false,
988
+ publicKeyConfigured: false,
989
+ orgName: "Builder OAuth",
990
+ keyLookupFailed: true,
991
+ };
992
+ }
993
+ }
930
994
  export function createCoreRoutesPlugin(options = {}) {
931
995
  return async (nitroApp) => {
932
996
  markDefaultPluginProvided(nitroApp, "core-routes");
@@ -1143,7 +1207,12 @@ export function createCoreRoutesPlugin(options = {}) {
1143
1207
  }
1144
1208
  for (const provider of [
1145
1209
  "figma",
1210
+ "gmail",
1211
+ "google_calendar",
1212
+ "google_docs",
1146
1213
  "google_drive",
1214
+ "google_sheets",
1215
+ "google_slides",
1147
1216
  "github",
1148
1217
  "hubspot",
1149
1218
  "salesforce",
@@ -1562,29 +1631,15 @@ export function createCoreRoutesPlugin(options = {}) {
1562
1631
  }
1563
1632
  }
1564
1633
  if (oauthAccess) {
1565
- let privateKeyConfigured = false;
1566
- let publicKeyConfigured = false;
1567
- let orgName = "Builder OAuth";
1568
- try {
1569
- const { resolveBuilderCredentials } = await import("./credential-provider.js");
1570
- const creds = await resolveBuilderCredentials();
1571
- privateKeyConfigured = !!creds.privateKey;
1572
- publicKeyConfigured = !!creds.publicKey;
1573
- if (typeof creds.orgName === "string" && creds.orgName) {
1574
- orgName = creds.orgName;
1575
- }
1576
- }
1577
- catch {
1578
- // coercion-ok: OAuth already proves the chat gateway; missing
1579
- // key flags only hide code-change send until secrets are readable.
1580
- }
1634
+ const keyStatus = await resolveOAuthCustodyBuilderKeyStatus();
1581
1635
  return withConnectToken({
1582
1636
  ...requestStatus,
1583
1637
  configured: true,
1584
1638
  credentialSource: "user",
1585
- privateKeyConfigured,
1586
- publicKeyConfigured,
1587
- orgName,
1639
+ privateKeyConfigured: keyStatus.privateKeyConfigured,
1640
+ publicKeyConfigured: keyStatus.publicKeyConfigured,
1641
+ keyLookupFailed: keyStatus.keyLookupFailed,
1642
+ orgName: keyStatus.orgName,
1588
1643
  spaces: [],
1589
1644
  });
1590
1645
  }
@@ -1870,6 +1925,21 @@ export function createCoreRoutesPlugin(options = {}) {
1870
1925
  parentOrigin: getBuilderBrowserOriginForEvent(event),
1871
1926
  });
1872
1927
  }
1928
+ const { orgId: connectOrgId, deny: orgConnectDenied } = await resolveBuilderOrgMutation(event);
1929
+ if (orgConnectDenied) {
1930
+ await trackBuilderLifecycle(event, "builder connect failed", ownerEmail, {
1931
+ ...builderConnectTrackingProperties(connectTracking),
1932
+ reason: "org_authorization_required",
1933
+ stage: "connect",
1934
+ });
1935
+ setResponseStatus(event, 403);
1936
+ setResponseHeader(event, "Content-Type", "text/html; charset=utf-8");
1937
+ return createBuilderBrowserCallbackErrorPage(orgConnectDenied, {
1938
+ title: "Not allowed to connect Builder for this organization",
1939
+ body: "Ask an organization owner or admin to connect Builder.",
1940
+ parentOrigin: getBuilderBrowserOriginForEvent(event),
1941
+ });
1942
+ }
1873
1943
  const state = createBuilderConnectState();
1874
1944
  // The standard OAuth client discovers Builder's protected-resource
1875
1945
  // metadata, dynamically registers, and creates its S256 verifier.
@@ -1886,7 +1956,7 @@ export function createCoreRoutesPlugin(options = {}) {
1886
1956
  authorizationUrl = started.authorizationUrl;
1887
1957
  await putSetting(`builder-connect-pending:${state}`, {
1888
1958
  ownerEmail,
1889
- orgId: null,
1959
+ orgId: connectOrgId,
1890
1960
  role: null,
1891
1961
  encryptedOAuthFlow: encryptSecretValue(JSON.stringify(oauthFlow)),
1892
1962
  redirectUri: callbackUrl,
@@ -1930,12 +2000,23 @@ export function createCoreRoutesPlugin(options = {}) {
1930
2000
  setResponseStatus(event, 405);
1931
2001
  return { error: "Method not allowed" };
1932
2002
  }
2003
+ await assertBodySize(event, 64 * 1024);
1933
2004
  const body = await readBody(event).catch(() => ({}));
1934
2005
  const prompt = typeof body?.prompt === "string" ? body.prompt : "";
1935
2006
  if (!prompt.trim()) {
1936
2007
  setResponseStatus(event, 400);
1937
2008
  return { error: "prompt is required" };
1938
2009
  }
2010
+ let context;
2011
+ try {
2012
+ context = normalizeBuilderAgentContext(body?.context);
2013
+ }
2014
+ catch (error) {
2015
+ setResponseStatus(event, 400);
2016
+ return {
2017
+ error: error instanceof Error ? error.message : "Invalid context",
2018
+ };
2019
+ }
1939
2020
  const session = await getSession(event).catch(() => null);
1940
2021
  if (!session?.email) {
1941
2022
  setResponseStatus(event, 401);
@@ -1973,6 +2054,7 @@ export function createCoreRoutesPlugin(options = {}) {
1973
2054
  try {
1974
2055
  const result = await runBuilderAgent({
1975
2056
  prompt,
2057
+ context,
1976
2058
  projectId,
1977
2059
  branchName: typeof body?.branchName === "string"
1978
2060
  ? body.branchName
@@ -2230,6 +2312,7 @@ export function createCoreRoutesPlugin(options = {}) {
2230
2312
  const oauthFlow = JSON.parse(decryptSecretValue(encryptedOAuthFlow));
2231
2313
  await finishBuilderOAuthAuthorization({
2232
2314
  ownerEmail,
2315
+ orgId: typeof consumed.orgId === "string" ? consumed.orgId : undefined,
2233
2316
  code,
2234
2317
  iss,
2235
2318
  pending: oauthFlow,
@@ -2271,6 +2354,15 @@ export function createCoreRoutesPlugin(options = {}) {
2271
2354
  }
2272
2355
  try {
2273
2356
  const hadOAuth = await hasBuilderOAuthSession(session.email);
2357
+ // Revoking an org-scoped grant takes the connection offline for
2358
+ // every member, so require org owner/admin before doing so.
2359
+ if (hadOAuth) {
2360
+ const { deny } = await resolveBuilderOrgMutation(event);
2361
+ if (deny) {
2362
+ setResponseStatus(event, 403);
2363
+ return { error: deny };
2364
+ }
2365
+ }
2274
2366
  const oauthResult = hadOAuth
2275
2367
  ? await deleteBuilderOAuthSession(session.email)
2276
2368
  : { localDeleted: false, remoteRevoked: false };
@@ -0,0 +1,18 @@
1
+ import type { DefaultPluginSlot } from "../app-config/plugins.js";
2
+ /**
3
+ * Which default plugin slots this deployment refuses, from `plugins.disabled`.
4
+ *
5
+ * Read on every call rather than captured once: `getAppConfig()` already caches
6
+ * the parse and drops that cache when the environment layer changes, and the
7
+ * auto-mount decision runs before some apps have called `defineAppConfig()`, so
8
+ * a module-level snapshot would freeze an empty list for the process.
9
+ */
10
+ export declare function getDisabledDefaultPlugins(): readonly DefaultPluginSlot[];
11
+ /**
12
+ * Whether the framework should withhold its default implementation of `slot`.
13
+ *
14
+ * Only the framework's own defaults are gated. An app that ships
15
+ * `server/plugins/<slot>.ts` mounted its plugin deliberately, and this switch
16
+ * does not reach in and unmount it.
17
+ */
18
+ export declare function isDefaultPluginDisabled(slot: string): boolean;
@@ -0,0 +1,22 @@
1
+ import { getAppConfig } from "../app-config/index.js";
2
+ /**
3
+ * Which default plugin slots this deployment refuses, from `plugins.disabled`.
4
+ *
5
+ * Read on every call rather than captured once: `getAppConfig()` already caches
6
+ * the parse and drops that cache when the environment layer changes, and the
7
+ * auto-mount decision runs before some apps have called `defineAppConfig()`, so
8
+ * a module-level snapshot would freeze an empty list for the process.
9
+ */
10
+ export function getDisabledDefaultPlugins() {
11
+ return getAppConfig().plugins.disabled;
12
+ }
13
+ /**
14
+ * Whether the framework should withhold its default implementation of `slot`.
15
+ *
16
+ * Only the framework's own defaults are gated. An app that ships
17
+ * `server/plugins/<slot>.ts` mounted its plugin deliberately, and this switch
18
+ * does not reach in and unmount it.
19
+ */
20
+ export function isDefaultPluginDisabled(slot) {
21
+ return getDisabledDefaultPlugins().includes(slot);
22
+ }
@@ -1,4 +1,5 @@
1
1
  export { createAuthPlugin, defaultAuthPlugin } from "./auth-plugin.js";
2
+ export { getDisabledDefaultPlugins, isDefaultPluginDisabled, } from "./default-plugins.js";
2
3
  export { BETTER_AUTH_MIGRATIONS, runBetterAuthMigrations, } from "./better-auth-migrations.js";
3
4
  export { runFrameworkReleaseMigrations } from "./release-migrations.js";
4
5
  export { createAgentChatPlugin, defaultAgentChatPlugin, refreshGlobalMcpManager, type AgentChatPluginOptions, } from "./agent-chat-plugin.js";
@@ -1,4 +1,5 @@
1
1
  export { createAuthPlugin, defaultAuthPlugin } from "./auth-plugin.js";
2
+ export { getDisabledDefaultPlugins, isDefaultPluginDisabled, } from "./default-plugins.js";
2
3
  export { BETTER_AUTH_MIGRATIONS, runBetterAuthMigrations, } from "./better-auth-migrations.js";
3
4
  export { runFrameworkReleaseMigrations } from "./release-migrations.js";
4
5
  export { createAgentChatPlugin, defaultAgentChatPlugin, refreshGlobalMcpManager, } from "./agent-chat-plugin.js";