@agent-native/core 0.169.1 → 0.171.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 (463) hide show
  1. package/agent-native.eject.json +4 -1
  2. package/bin/agent-native.js +23 -5
  3. package/corpus/README.md +1 -1
  4. package/corpus/templates/analytics/.agents/skills/secrets/SKILL.md +11 -4
  5. package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +1 -1
  6. package/corpus/templates/analytics/app/i18n-data.ts +28 -0
  7. package/corpus/templates/analytics/app/pages/Agents.tsx +25 -1
  8. package/corpus/templates/analytics/app/routes/$.tsx +10 -0
  9. package/corpus/templates/analytics/app/routes.ts +3 -1
  10. package/corpus/templates/analytics/changelog/2026-08-22-fixed-the-agent-native-templates-first-party-dashboard-panel.md +6 -0
  11. package/corpus/templates/analytics/changelog/2026-08-22-org-admin-panels-no-longer-report-a-database-error-as-a-per.md +9 -0
  12. package/corpus/templates/analytics/changelog/2026-08-22-slack-requests-report-invalid-inputs.md +6 -0
  13. package/corpus/templates/analytics/changelog/2026-08-22-unknown-analytics-links-now-return-a-real-not-found-status.md +6 -0
  14. package/corpus/templates/analytics/docs/schemas/first-party-analytics.md +2 -1
  15. package/corpus/templates/analytics/docs/schemas/tracked-events.md +2 -0
  16. package/corpus/templates/analytics/scripts/emit-netlify-dashboard-report-cron.ts +29 -7
  17. package/corpus/templates/analytics/server/handlers/slack.ts +59 -5
  18. package/corpus/templates/analytics/server/lib/db-admin-connections.ts +11 -6
  19. package/corpus/templates/analytics/server/lib/first-party-analytics.ts +132 -2
  20. package/corpus/templates/analytics/server/lib/slack.ts +4 -2
  21. package/corpus/templates/analytics/vitest.config.ts +6 -1
  22. package/corpus/templates/assets/.agents/skills/secrets/SKILL.md +11 -4
  23. package/corpus/templates/assets/app/routes/library.tsx +5 -3
  24. package/corpus/templates/assets/app/routes.ts +3 -1
  25. package/corpus/templates/assets/changelog/2026-08-22-library-page-loads-again-instead-of-crashing-on-open.md +6 -0
  26. package/corpus/templates/assets/vitest.config.ts +6 -1
  27. package/corpus/templates/brain/.agents/skills/secrets/SKILL.md +11 -4
  28. package/corpus/templates/brain/app/components/ui/pointer-lock.ts +1 -0
  29. package/corpus/templates/brain/app/routes/sources.tsx +8 -3
  30. package/corpus/templates/brain/changelog/2026-08-22-tuning-or-adding-a-source-no-longer-leaves-the-sources-page.md +6 -0
  31. package/corpus/templates/brain/vitest.config.ts +1 -0
  32. package/corpus/templates/calendar/.agents/skills/secrets/SKILL.md +11 -4
  33. package/corpus/templates/calendar/actions/list-booking-links.ts +83 -4
  34. package/corpus/templates/calendar/actions/update-booking-link.ts +4 -3
  35. package/corpus/templates/calendar/app/components/calendar/EventDetailPanel.tsx +11 -3
  36. package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +1 -1
  37. package/corpus/templates/calendar/app/components/calendar/GoogleConnectBanner.tsx +103 -44
  38. package/corpus/templates/calendar/app/components/calendar/OutOfOfficeEvent.tsx +28 -24
  39. package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +9 -2
  40. package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +47 -58
  41. package/corpus/templates/calendar/app/hooks/use-booking-links.ts +5 -1
  42. package/corpus/templates/calendar/app/lib/event-layout.ts +52 -26
  43. package/corpus/templates/calendar/app/pages/BookingLinksPage.tsx +126 -98
  44. package/corpus/templates/calendar/app/pages/CalendarView.tsx +1 -0
  45. package/corpus/templates/calendar/app/pages/Settings.tsx +88 -81
  46. package/corpus/templates/calendar/app/routes.ts +3 -1
  47. package/corpus/templates/calendar/changelog/2026-08-22-booking-link-visibility-respects-shared-access.md +6 -0
  48. package/corpus/templates/calendar/changelog/2026-08-22-clicking-an-out-of-office-event-s-marker-no-longer-creates-a.md +6 -0
  49. package/corpus/templates/calendar/changelog/2026-08-22-event-detail-views-now-show-your-calendar-timezone.md +6 -0
  50. package/corpus/templates/calendar/changelog/2026-08-22-google-calendar-can-now-connect-with-the-shared-google-oauth.md +6 -0
  51. package/corpus/templates/calendar/changelog/2026-08-22-overlapping-events-now-show-each-others-boundaries.md +6 -0
  52. package/corpus/templates/calendar/changelog/2026-08-22-public-booking-pages-now-offer-time-slots-from-the-host-s-we.md +6 -0
  53. package/corpus/templates/calendar/server/handlers/bookings.ts +5 -7
  54. package/corpus/templates/calendar/server/handlers/google-auth.ts +10 -2
  55. package/corpus/templates/calendar/server/lib/google-calendar.ts +139 -14
  56. package/corpus/templates/calendar/server/onboarding.ts +85 -0
  57. package/corpus/templates/calendar/server/plugins/agent-chat.ts +2 -0
  58. package/corpus/templates/calendar/shared/api.ts +9 -1
  59. package/corpus/templates/chat/.agents/skills/secrets/SKILL.md +11 -4
  60. package/corpus/templates/chat/app/routes.ts +3 -1
  61. package/corpus/templates/chat/vitest.config.ts +8 -0
  62. package/corpus/templates/clips/.agents/skills/secrets/SKILL.md +11 -4
  63. package/corpus/templates/clips/actions/get-meeting.ts +9 -4
  64. package/corpus/templates/clips/actions/list-recordings.ts +16 -3
  65. package/corpus/templates/clips/actions/search-meetings.ts +1 -0
  66. package/corpus/templates/clips/actions/view-screen.ts +8 -1
  67. package/corpus/templates/clips/app/components/meetings/meeting-history-row.tsx +32 -1
  68. package/corpus/templates/clips/app/components/player/delete-recording-menu.tsx +1 -1
  69. package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +29 -1
  70. package/corpus/templates/clips/app/i18n/en-US.ts +5 -0
  71. package/corpus/templates/clips/app/routes/_app.meetings.$meetingId.tsx +33 -4
  72. package/corpus/templates/clips/app/routes/_app.meetings._index.tsx +1 -0
  73. package/corpus/templates/clips/app/routes/access-request.approve.tsx +16 -9
  74. package/corpus/templates/clips/app/routes/embed.$shareId.tsx +17 -7
  75. package/corpus/templates/clips/app/routes/share.$shareId.tsx +17 -7
  76. package/corpus/templates/clips/changelog/2026-08-21-camera-bubble-black-circle.md +6 -0
  77. package/corpus/templates/clips/changelog/2026-08-22-screen-recordings-respect-the-microphone-toggle.md +6 -0
  78. package/corpus/templates/clips/changelog/2026-08-22-the-recordings-library-no-longer-fails-right-after-server-start.md +6 -0
  79. package/corpus/templates/clips/changelog/2026-08-23-the-agent-can-see-your-library-right-after-server-start.md +6 -0
  80. package/corpus/templates/clips/chrome-extension/src/background.ts +1 -2
  81. package/corpus/templates/clips/chrome-extension/src/native-transcription.ts +39 -7
  82. package/corpus/templates/clips/chrome-extension/src/offscreen.ts +21 -25
  83. package/corpus/templates/clips/desktop/src/app.tsx +53 -24
  84. package/corpus/templates/clips/desktop/src/lib/bubble-playback.ts +68 -0
  85. package/corpus/templates/clips/desktop/src/lib/recorder.ts +3 -0
  86. package/corpus/templates/clips/desktop/src/lib/transcription-capture.ts +72 -14
  87. package/corpus/templates/clips/desktop/src/lib/updater.ts +8 -3
  88. package/corpus/templates/clips/desktop/src/overlays/bubble.tsx +162 -20
  89. package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +43 -6
  90. package/corpus/templates/clips/desktop/src-tauri/src/native_screen/custom_capture.rs +150 -13
  91. package/corpus/templates/clips/desktop/src-tauri/src/tray.rs +12 -0
  92. package/corpus/templates/clips/server/lib/calendar-event-meetings.ts +28 -3
  93. package/corpus/templates/clips/server/lib/emails.ts +17 -33
  94. package/corpus/templates/content/.agents/skills/secrets/SKILL.md +11 -4
  95. package/corpus/templates/content/app/components/editor/VisualEditor.tsx +140 -15
  96. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +12 -14
  97. package/corpus/templates/content/app/components/ui/pointer-lock.ts +1 -0
  98. package/corpus/templates/content/app/hooks/use-content-database.ts +18 -2
  99. package/corpus/templates/content/app/hooks/use-local-storage.ts +38 -22
  100. package/corpus/templates/content/app/i18n-data.ts +25 -0
  101. package/corpus/templates/content/app/routes.ts +3 -1
  102. package/corpus/templates/content/changelog/2026-08-22-code-blocks-inserted-from-the-slash-menu-no-longer-get-stuck.md +6 -0
  103. package/corpus/templates/content/changelog/2026-08-22-the-sidebar-page-tree-no-longer-flashes-empty-after-creating-a-page.md +6 -0
  104. package/corpus/templates/content/docs/solutions/2026-08-21-content-mermaid-rendering-shape.md +233 -0
  105. package/corpus/templates/content/server/plugins/agent-chat.ts +9 -2
  106. package/corpus/templates/content/vitest.config.ts +7 -1
  107. package/corpus/templates/crm/.agents/skills/secrets/SKILL.md +11 -4
  108. package/corpus/templates/design/.agents/skills/secrets/SKILL.md +11 -4
  109. package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +1383 -88
  110. package/corpus/templates/design/actions/generate-design.ts +98 -47
  111. package/corpus/templates/design/actions/get-design-system.ts +6 -1
  112. package/corpus/templates/design/actions/refresh-design-system-with-builder.ts +146 -0
  113. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +70 -26
  114. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +284 -136
  115. package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +2057 -141
  116. package/corpus/templates/design/app/components/design/editor/DesignBottomToolbar.tsx +6 -2
  117. package/corpus/templates/design/app/components/design/editor/DesignWorkspaceRail.tsx +4 -4
  118. package/corpus/templates/design/app/components/design/keyboard-shortcuts.ts +10 -1
  119. package/corpus/templates/design/app/components/design/multi-screen/alt-hover-measurement.ts +19 -2
  120. package/corpus/templates/design/app/components/design/multi-screen/types.ts +9 -2
  121. package/corpus/templates/design/app/components/layout/Header.tsx +15 -0
  122. package/corpus/templates/design/app/components/layout/Layout.tsx +7 -2
  123. package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +11 -4
  124. package/corpus/templates/design/app/i18n-data.ts +1 -0
  125. package/corpus/templates/design/app/i18n-keyboard-shortcuts.ts +12 -0
  126. package/corpus/templates/design/app/lib/design-system-data.ts +68 -0
  127. package/corpus/templates/design/app/pages/DesignEditor.tsx +77 -35
  128. package/corpus/templates/design/app/pages/DesignSystems.tsx +136 -42
  129. package/corpus/templates/design/app/pages/Index.tsx +2 -0
  130. package/corpus/templates/design/app/pages/Templates.tsx +0 -10
  131. package/corpus/templates/design/app/pages/design-editor/code-layer-state.ts +10 -0
  132. package/corpus/templates/design/app/pages/design-editor/collab-sync.ts +50 -0
  133. package/corpus/templates/design/app/pages/design-editor/commands/apply-design-editor-command.ts +1 -1
  134. package/corpus/templates/design/app/pages/design-editor/commands/apply-file-content-update.ts +10 -8
  135. package/corpus/templates/design/app/pages/design-editor/commands/apply-local-content-update.ts +6 -6
  136. package/corpus/templates/design/app/pages/design-editor/commands/apply-pending-visual-styles-with-agent.ts +1 -1
  137. package/corpus/templates/design/app/pages/design-editor/commands/commit-visual-styles.ts +18 -7
  138. package/corpus/templates/design/app/pages/design-editor/commands/escape-hotkey.ts +4 -90
  139. package/corpus/templates/design/app/pages/design-editor/commands/layer-marquee-selection-change.ts +2 -1
  140. package/corpus/templates/design/app/pages/design-editor/commands/layer-selection-change.ts +4 -3
  141. package/corpus/templates/design/app/pages/design-editor/commands/screen-element-select.ts +12 -2
  142. package/corpus/templates/design/app/pages/design-editor/commands/screen-visual-style-change.ts +9 -2
  143. package/corpus/templates/design/app/pages/design-editor/commands/send-runtime-layer-move-semantic-handoff.ts +1 -1
  144. package/corpus/templates/design/app/pages/design-editor/commands/send-runtime-layer-semantic-handoff.ts +1 -1
  145. package/corpus/templates/design/app/pages/design-editor/commands/send-runtime-layer-state-semantic-handoff.ts +1 -1
  146. package/corpus/templates/design/app/pages/design-editor/commands/start-sidebar-resize.ts +1 -1
  147. package/corpus/templates/design/app/pages/design-editor/editor-state.ts +11 -1
  148. package/corpus/templates/design/app/pages/design-editor/effects/adopt-db-file-content.ts +11 -19
  149. package/corpus/templates/design/app/pages/design-editor/effects/observe-collab-text.ts +6 -6
  150. package/corpus/templates/design/app/pages/design-editor/effects/publish-agent-selection-context.ts +1 -1
  151. package/corpus/templates/design/app/pages/design-editor/effects/seed-collab-content.ts +12 -15
  152. package/corpus/templates/design/app/pages/design-editor/selection-state.ts +5 -59
  153. package/corpus/templates/design/app/pages/design-editor/tool-state.ts +8 -0
  154. package/corpus/templates/design/app/pages/design-editor/types.ts +3 -3
  155. package/corpus/templates/design/app/routes.ts +3 -1
  156. package/corpus/templates/design/changelog/2026-08-20-canvas-edits-patch-the-frame-instead-of-rebuilding-it.md +6 -0
  157. package/corpus/templates/design/changelog/2026-08-21-builder-design-system-imports-reconcile-after-indexing.md +6 -0
  158. package/corpus/templates/design/changelog/2026-08-21-draw-mode-needs-shift-y.md +6 -0
  159. package/corpus/templates/design/changelog/2026-08-21-eyedropper-shortcut.md +6 -0
  160. package/corpus/templates/design/changelog/2026-08-21-figma-style-alignment-guides-and-snapping.md +6 -0
  161. package/corpus/templates/design/changelog/2026-08-21-group-transforms-keep-the-selection.md +6 -0
  162. package/corpus/templates/design/changelog/2026-08-21-inspector-fields-keep-focus-on-enter.md +6 -0
  163. package/corpus/templates/design/changelog/2026-08-21-pen-alt-keeps-the-incoming-handle.md +6 -0
  164. package/corpus/templates/design/changelog/2026-08-21-pen-on-the-board-creates-one-vector.md +6 -0
  165. package/corpus/templates/design/changelog/2026-08-21-scale-a-multi-selection-from-the-group-handles.md +6 -0
  166. package/corpus/templates/design/changelog/2026-08-21-scale-resizes-text-with-the-object.md +6 -0
  167. package/corpus/templates/design/changelog/2026-08-21-selecting-another-object-keeps-the-scale-tool-armed.md +6 -0
  168. package/corpus/templates/design/changelog/2026-08-21-the-shape-tool-remembers-the-shape-you-picked.md +6 -0
  169. package/corpus/templates/design/changelog/2026-08-21-vectors-drawn-in-a-frame-land-where-you-drew-them.md +6 -0
  170. package/corpus/templates/design/changelog/2026-08-22-multi-screen-generation-no-longer-loses-a-saved-screens-layo.md +6 -0
  171. package/corpus/templates/design/changelog/2026-08-22-rename-and-search-fields-are-labeled-for-screen-readers.md +6 -0
  172. package/corpus/templates/design/package.json +2 -0
  173. package/corpus/templates/design/server/lib/builder-design-system-proxy.ts +311 -0
  174. package/corpus/templates/design/shared/canvas-math.ts +612 -206
  175. package/corpus/templates/design/shared/pen-path.ts +37 -0
  176. package/corpus/templates/design/vitest.config.ts +7 -1
  177. package/corpus/templates/dispatch/.agents/skills/secrets/SKILL.md +11 -4
  178. package/corpus/templates/dispatch/actions/list-workspace-connections.ts +34 -3
  179. package/corpus/templates/dispatch/app/routes/integrations.tsx +55 -21
  180. package/corpus/templates/dispatch/app/routes.ts +3 -1
  181. package/corpus/templates/factory/.agents/skills/secrets/SKILL.md +11 -4
  182. package/corpus/templates/factory/.env.example +2 -7
  183. package/corpus/templates/factory/AGENTS.md +3 -0
  184. package/corpus/templates/factory/README.md +5 -3
  185. package/corpus/templates/factory/actions/create-factory.ts +16 -3
  186. package/corpus/templates/factory/actions/get-slack-feedback-context.ts +2 -0
  187. package/corpus/templates/factory/actions/get-triage-item.ts +2 -0
  188. package/corpus/templates/factory/actions/list-factory-audit.ts +116 -36
  189. package/corpus/templates/factory/actions/list-factory-automations.ts +2 -1
  190. package/corpus/templates/factory/actions/list-triage-items.ts +22 -19
  191. package/corpus/templates/factory/actions/run-factory-automation.ts +7 -3
  192. package/corpus/templates/factory/actions/save-factory-automation.ts +5 -2
  193. package/corpus/templates/factory/actions/save-triage-config.ts +2 -8
  194. package/corpus/templates/factory/actions/start-builder-for-item.ts +21 -0
  195. package/corpus/templates/factory/app/components/factory/FactoryAuditView.tsx +229 -297
  196. package/corpus/templates/factory/app/components/factory/FactorySettingsView.tsx +397 -247
  197. package/corpus/templates/factory/app/components/factory/FactorySourceSettingsGroup.tsx +33 -0
  198. package/corpus/templates/factory/app/components/factory/NewFactoryForm.tsx +202 -162
  199. package/corpus/templates/factory/app/i18n/en-US.ts +32 -4
  200. package/corpus/templates/factory/app/routes/factory.tsx +84 -11
  201. package/corpus/templates/factory/app/routes.ts +3 -1
  202. package/corpus/templates/factory/changelog/2026-08-21-activity-runs-use-automation-display-names.md +6 -0
  203. package/corpus/templates/factory/changelog/2026-08-21-create-and-settings-source-cards.md +6 -0
  204. package/corpus/templates/factory/changelog/2026-08-21-keep-automations-visible-while-running.md +6 -0
  205. package/corpus/templates/factory/changelog/2026-08-21-nested-factory-automations-can-poll.md +6 -0
  206. package/corpus/templates/factory/changelog/2026-08-21-settings-sticky-unsaved-bar.md +6 -0
  207. package/corpus/templates/factory/server/connectors/credentials.ts +10 -5
  208. package/corpus/templates/factory/server/lib/factory-audit-report.ts +412 -0
  209. package/corpus/templates/factory/server/lib/factory-config-reconcile.ts +321 -0
  210. package/corpus/templates/factory/server/lib/factory-scope.ts +25 -2
  211. package/corpus/templates/factory/server/lib/require-factory-automation.ts +13 -4
  212. package/corpus/templates/factory/server/plugins/factory-migrations.ts +148 -4
  213. package/corpus/templates/factory/server/plugins/factory-scheduler-job.ts +4 -6
  214. package/corpus/templates/factory/vitest.config.ts +17 -2
  215. package/corpus/templates/forms/.agents/skills/secrets/SKILL.md +11 -4
  216. package/corpus/templates/forms/app/routes/_app.settings.tsx +4 -1
  217. package/corpus/templates/forms/changelog/2026-08-22-the-extensions-link-now-opens-the-extensions-tab-instead-o.md +6 -0
  218. package/corpus/templates/forms/server/lib/public-form-ssr.ts +11 -1
  219. package/corpus/templates/forms/vitest.config.ts +1 -0
  220. package/corpus/templates/macros/.agents/skills/secrets/SKILL.md +11 -4
  221. package/corpus/templates/macros/app/routes.ts +3 -1
  222. package/corpus/templates/macros/vitest.config.ts +6 -1
  223. package/corpus/templates/mail/.agents/skills/secrets/SKILL.md +11 -4
  224. package/corpus/templates/mail/actions/manage-gmail-filters.ts +10 -2
  225. package/corpus/templates/mail/app/components/GoogleConnectBanner.tsx +100 -37
  226. package/corpus/templates/mail/app/components/email/IntegrationsSidebar.tsx +14 -2
  227. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +66 -36
  228. package/corpus/templates/mail/app/hooks/use-google-auth.ts +2 -0
  229. package/corpus/templates/mail/app/lib/google-oauth-setup.ts +17 -0
  230. package/corpus/templates/mail/app/pages/InboxPage.tsx +69 -9
  231. package/corpus/templates/mail/app/routes/$.tsx +9 -0
  232. package/corpus/templates/mail/app/routes/$view.$threadId.tsx +23 -1
  233. package/corpus/templates/mail/app/routes/$view.tsx +47 -1
  234. package/corpus/templates/mail/app/routes.ts +3 -1
  235. package/corpus/templates/mail/changelog/2026-08-22-gmail-can-now-connect-with-the-shared-google-oauth.md +6 -0
  236. package/corpus/templates/mail/changelog/2026-08-22-gmail-filters-now-shows-the-real-error.md +6 -0
  237. package/corpus/templates/mail/changelog/2026-08-22-unknown-mail-urls-now-show-the-404-page.md +6 -0
  238. package/corpus/templates/mail/server/handlers/google-auth.ts +11 -2
  239. package/corpus/templates/mail/server/lib/google-auth.ts +92 -12
  240. package/corpus/templates/mail/server/onboarding.ts +66 -18
  241. package/corpus/templates/mail/vitest.config.ts +6 -1
  242. package/corpus/templates/plan/.agents/skills/secrets/SKILL.md +11 -4
  243. package/corpus/templates/plan/app/routes/settings.tsx +4 -1
  244. package/corpus/templates/plan/app/routes.ts +3 -1
  245. package/corpus/templates/plan/changelog/2026-08-22-the-extensions-link-now-opens-the-extensions-tab-instead-o.md +6 -0
  246. package/corpus/templates/plan/netlify.toml +1 -1
  247. package/corpus/templates/slides/.agents/skills/secrets/SKILL.md +11 -4
  248. package/corpus/templates/slides/actions/patch-deck.ts +79 -10
  249. package/corpus/templates/slides/actions/update-slide.ts +11 -1
  250. package/corpus/templates/slides/app/components/deck/SlideRenderer.tsx +14 -4
  251. package/corpus/templates/slides/app/components/editor/ExportMenu.tsx +10 -52
  252. package/corpus/templates/slides/app/components/editor/GoogleDocImportHint.tsx +8 -53
  253. package/corpus/templates/slides/app/components/editor/GoogleDriveConnectionCta.tsx +9 -75
  254. package/corpus/templates/slides/app/components/editor/GoogleSlidesReferenceImport.tsx +8 -60
  255. package/corpus/templates/slides/app/components/editor/SlideContextToolbar.tsx +10 -2
  256. package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +19 -7
  257. package/corpus/templates/slides/app/lib/sanitize-slide-html.ts +49 -36
  258. package/corpus/templates/slides/app/routes/access-request.approve.tsx +16 -9
  259. package/corpus/templates/slides/app/routes.ts +3 -1
  260. package/corpus/templates/slides/changelog/2026-08-22-already-uploaded-chat-images-are-no-longer-dropped.md +6 -0
  261. package/corpus/templates/slides/changelog/2026-08-22-google-drive-and-slides-can-now-connect-with-the-shared-google-oauth.md +6 -0
  262. package/corpus/templates/slides/changelog/2026-08-22-multi-slide-repairs-now-report-slides-that-still-overflow.md +6 -0
  263. package/corpus/templates/slides/changelog/2026-08-22-update-slide-now-reports-which-batched-edit-was-skipped.md +6 -0
  264. package/corpus/templates/slides/server/handlers/google-docs-auth.ts +52 -1
  265. package/corpus/templates/slides/server/lib/chat-attachments.ts +29 -3
  266. package/corpus/templates/slides/server/lib/google-docs-oauth.ts +66 -16
  267. package/corpus/templates/slides/server/lib/slide-content-patch.ts +13 -2
  268. package/corpus/templates/slides/server/plugins/agent-chat.ts +5 -2
  269. package/corpus/templates/slides/tsconfig.json +5 -0
  270. package/corpus/templates/slides/vitest.config.ts +6 -1
  271. package/corpus/templates/tasks/.agents/skills/secrets/SKILL.md +11 -4
  272. package/corpus/templates/tasks/app/routes/settings.tsx +4 -1
  273. package/corpus/templates/tasks/app/routes.ts +3 -1
  274. package/corpus/templates/tasks/changelog/2026-08-22-the-extensions-link-now-opens-the-extensions-tab-instead-o.md +6 -0
  275. package/corpus/templates/tasks/vitest.config.ts +7 -1
  276. package/dist/action.d.ts +91 -0
  277. package/dist/action.js +50 -0
  278. package/dist/agent/abort-reasons.d.ts +38 -0
  279. package/dist/agent/abort-reasons.js +49 -0
  280. package/dist/agent/engine/ai-sdk-engine.js +8 -5
  281. package/dist/agent/engine/anthropic-engine.js +7 -5
  282. package/dist/agent/engine/first-event-timeout.d.ts +42 -17
  283. package/dist/agent/engine/first-event-timeout.js +67 -25
  284. package/dist/agent/production-agent.d.ts +23 -0
  285. package/dist/agent/production-agent.js +107 -102
  286. package/dist/agent/run-loop-with-resume.d.ts +2 -28
  287. package/dist/agent/run-loop-with-resume.js +25 -40
  288. package/dist/agent/run-manager.js +5 -4
  289. package/dist/agent/run-store.d.ts +55 -0
  290. package/dist/agent/run-store.js +124 -1
  291. package/dist/agent/tool-search.js +2 -1
  292. package/dist/agent/types.d.ts +9 -4
  293. package/dist/app-config/auth.d.ts +1 -0
  294. package/dist/app-config/auth.js +7 -0
  295. package/dist/app-config/configuration-error.d.ts +11 -0
  296. package/dist/app-config/configuration-error.js +14 -0
  297. package/dist/app-config/index.d.ts +1 -0
  298. package/dist/app-config/index.js +1 -0
  299. package/dist/app-config/integrations.d.ts +1 -0
  300. package/dist/app-config/integrations.js +10 -0
  301. package/dist/app-config/plugins.d.ts +34 -0
  302. package/dist/app-config/plugins.js +39 -0
  303. package/dist/app-config/run-lifecycle-invariants.d.ts +18 -9
  304. package/dist/app-config/run-lifecycle-invariants.js +18 -25
  305. package/dist/app-config/schema.d.ts +17 -0
  306. package/dist/app-config/schema.js +2 -0
  307. package/dist/chat-threads/schema-migrations.js +20 -0
  308. package/dist/chat-threads/store.js +21 -4
  309. package/dist/cli/native-dependencies.d.ts +4 -0
  310. package/dist/cli/native-dependencies.js +15 -0
  311. package/dist/client/EnvironmentBadge.d.ts +1 -1
  312. package/dist/client/EnvironmentBadge.js +40 -5
  313. package/dist/client/MultiTabAssistantChat.d.ts +1 -1
  314. package/dist/client/MultiTabAssistantChat.js +35 -14
  315. package/dist/client/agent-chat/index.d.ts +1 -1
  316. package/dist/client/agent-chat/index.js +1 -1
  317. package/dist/client/agent-page/use-jobs.d.ts +2 -1
  318. package/dist/client/agent-page/use-jobs.js +3 -5
  319. package/dist/client/agent-sidebar-state.js +3 -1
  320. package/dist/client/blocks/library/code-tabs.js +5 -0
  321. package/dist/client/blocks/library/code.js +1 -0
  322. package/dist/client/chat-first/apps-rail.js +2 -2
  323. package/dist/client/chat-model-groups.d.ts +12 -0
  324. package/dist/client/chat-model-groups.js +3 -2
  325. package/dist/client/integrations/GoogleProductLogo.d.ts +5 -0
  326. package/dist/client/integrations/GoogleProductLogo.js +45 -0
  327. package/dist/client/integrations/index.d.ts +2 -0
  328. package/dist/client/integrations/index.js +2 -0
  329. package/dist/client/integrations/workspace-provider-oauth.d.ts +8 -0
  330. package/dist/client/integrations/workspace-provider-oauth.js +13 -0
  331. package/dist/client/resources/mcp-integration-catalog.js +0 -29
  332. package/dist/client/settings/SettingsTabsPage.js +10 -6
  333. package/dist/client/sharing/ShareButton.js +11 -2
  334. package/dist/client/use-chat-models.d.ts +6 -0
  335. package/dist/client/use-chat-models.js +10 -0
  336. package/dist/client/use-db-sync.js +27 -9
  337. package/dist/collab/routes.d.ts +1 -1
  338. package/dist/collab/struct-routes.d.ts +1 -1
  339. package/dist/connections/catalog.d.ts +111 -9
  340. package/dist/connections/catalog.js +86 -30
  341. package/dist/db/create-get-db.js +18 -0
  342. package/dist/db/ddl-guard.d.ts +0 -4
  343. package/dist/db/ddl-guard.js +46 -0
  344. package/dist/deploy/build.d.ts +19 -0
  345. package/dist/deploy/build.js +190 -16
  346. package/dist/deploy/function-bundle.d.ts +45 -0
  347. package/dist/deploy/function-bundle.js +337 -0
  348. package/dist/deploy/workspace-deploy.js +19 -1
  349. package/dist/eject/workspace-connections.js +4 -0
  350. package/dist/email-catalog/registry.d.ts +4 -0
  351. package/dist/email-catalog/registry.js +79 -14
  352. package/dist/extensions/content-patch.js +14 -2
  353. package/dist/integrations/plugin.d.ts +10 -0
  354. package/dist/integrations/plugin.js +40 -6
  355. package/dist/jobs/actions/run-automation-now.d.ts +2 -1
  356. package/dist/jobs/actions/run-automation-now.js +11 -5
  357. package/dist/jobs/frontmatter.js +53 -2
  358. package/dist/jobs/run-now.d.ts +11 -1
  359. package/dist/jobs/run-now.js +42 -7
  360. package/dist/jobs/scheduler.d.ts +1 -0
  361. package/dist/jobs/scheduler.js +2 -1
  362. package/dist/localization/core-messages/ar-SA.js +3 -0
  363. package/dist/localization/core-messages/de-DE.js +3 -0
  364. package/dist/localization/core-messages/en-US.d.ts +3 -0
  365. package/dist/localization/core-messages/en-US.js +3 -0
  366. package/dist/localization/core-messages/es-ES.js +3 -0
  367. package/dist/localization/core-messages/fr-FR.js +3 -0
  368. package/dist/localization/core-messages/hi-IN.js +3 -0
  369. package/dist/localization/core-messages/ja-JP.js +3 -0
  370. package/dist/localization/core-messages/ko-KR.js +3 -0
  371. package/dist/localization/core-messages/pt-BR.js +3 -0
  372. package/dist/localization/core-messages/zh-CN.js +3 -0
  373. package/dist/localization/core-messages/zh-TW.js +3 -0
  374. package/dist/localization/core-messages.d.ts +3 -0
  375. package/dist/localization/default-messages.d.ts +2 -5
  376. package/dist/localization/default-messages.js +2 -5
  377. package/dist/mcp/build-server.d.ts +9 -0
  378. package/dist/mcp/build-server.js +37 -8
  379. package/dist/mcp-client/oauth-client.d.ts +7 -0
  380. package/dist/mcp-client/oauth-client.js +12 -1
  381. package/dist/oauth-tokens/index.d.ts +1 -1
  382. package/dist/oauth-tokens/index.js +1 -1
  383. package/dist/oauth-tokens/lifecycle.d.ts +11 -0
  384. package/dist/oauth-tokens/lifecycle.js +17 -0
  385. package/dist/oauth-tokens/store.js +7 -0
  386. package/dist/observability/posthog-ai.d.ts +15 -1
  387. package/dist/observability/posthog-ai.js +24 -12
  388. package/dist/observability/traces.js +158 -28
  389. package/dist/onboarding/app-profile.js +2 -2
  390. package/dist/onboarding/plugin.js +10 -2
  391. package/dist/onboarding/types.d.ts +2 -0
  392. package/dist/provider-api/actions/custom-provider-registration.d.ts +1 -1
  393. package/dist/provider-api/actions/provider-api.d.ts +2 -2
  394. package/dist/provider-api/index.js +2 -0
  395. package/dist/resources/handlers.d.ts +2 -2
  396. package/dist/resources/store.js +13 -4
  397. package/dist/scripts/agent-engines/list-agent-engines.js +29 -3
  398. package/dist/secrets/register-framework-secrets.js +1 -1
  399. package/dist/server/action-discovery.js +5 -0
  400. package/dist/server/agent-chat/action-filters-a2a.d.ts +27 -3
  401. package/dist/server/agent-chat/action-filters-a2a.js +48 -9
  402. package/dist/server/agent-chat-plugin.js +36 -9
  403. package/dist/server/agent-discovery.js +43 -20
  404. package/dist/server/auth.js +18 -16
  405. package/dist/server/beta-opt-out-html.js +45 -4
  406. package/dist/server/better-auth-instance.d.ts +2 -1
  407. package/dist/server/better-auth-instance.js +37 -7
  408. package/dist/server/builder-design-systems.d.ts +4 -1
  409. package/dist/server/builder-design-systems.js +87 -6
  410. package/dist/server/builder-oauth.d.ts +1 -7
  411. package/dist/server/builder-oauth.js +80 -163
  412. package/dist/server/core-routes-plugin.d.ts +29 -0
  413. package/dist/server/core-routes-plugin.js +100 -20
  414. package/dist/server/default-plugins.d.ts +18 -0
  415. package/dist/server/default-plugins.js +22 -0
  416. package/dist/server/edge.d.ts +1 -0
  417. package/dist/server/edge.js +1 -0
  418. package/dist/server/framework-request-handler.js +31 -3
  419. package/dist/server/google-oauth.d.ts +3 -0
  420. package/dist/server/google-oauth.js +3 -0
  421. package/dist/server/index.d.ts +4 -4
  422. package/dist/server/index.js +3 -3
  423. package/dist/server/onboarding-html.js +37 -3
  424. package/dist/server/realtime-token.d.ts +1 -1
  425. package/dist/server/workspace-provider-oauth.d.ts +6 -1
  426. package/dist/server/workspace-provider-oauth.js +72 -20
  427. package/dist/shared/agent-sidebar-url.d.ts +1 -0
  428. package/dist/shared/agent-sidebar-url.js +1 -0
  429. package/dist/shared/environment-lanes.d.ts +2 -0
  430. package/dist/shared/environment-lanes.js +3 -1
  431. package/dist/shared/index.d.ts +3 -1
  432. package/dist/shared/index.js +3 -1
  433. package/dist/shared/surface-visibility.d.ts +31 -0
  434. package/dist/shared/surface-visibility.js +57 -0
  435. package/dist/templates/chat/.agents/skills/secrets/SKILL.md +11 -4
  436. package/dist/templates/chat/app/routes.ts +3 -1
  437. package/dist/templates/chat/vitest.config.ts +8 -0
  438. package/dist/templates/default/.agents/skills/secrets/SKILL.md +11 -4
  439. package/dist/templates/default/app/routes.ts +3 -1
  440. package/dist/templates/headless/.agents/skills/secrets/SKILL.md +11 -4
  441. package/dist/templates/workspace-core/.agents/skills/secrets/SKILL.md +11 -4
  442. package/dist/tracking/registry.d.ts +11 -0
  443. package/dist/tracking/registry.js +5 -2
  444. package/dist/triggers/actions.js +10 -3
  445. package/dist/usage/store.js +23 -3
  446. package/dist/user-profile/actions/get-auth-methods.js +18 -5
  447. package/dist/vite/client.js +33 -7
  448. package/docs/content/actions-access-control.mdx +43 -4
  449. package/docs/content/actions-defining.mdx +16 -0
  450. package/docs/content/authentication.mdx +40 -21
  451. package/docs/content/environment-variables.mdx +1 -0
  452. package/docs/content/template-clips-capture-everywhere.mdx +29 -30
  453. package/docs/content/template-clips-developers.mdx +4 -4
  454. package/docs/content/template-clips.mdx +3 -1
  455. package/package.json +2 -2
  456. package/src/eject/workspace-connections.ts +4 -0
  457. package/src/templates/chat/.agents/skills/secrets/SKILL.md +11 -4
  458. package/src/templates/chat/app/routes.ts +3 -1
  459. package/src/templates/chat/vitest.config.ts +8 -0
  460. package/src/templates/default/.agents/skills/secrets/SKILL.md +11 -4
  461. package/src/templates/default/app/routes.ts +3 -1
  462. package/src/templates/headless/.agents/skills/secrets/SKILL.md +11 -4
  463. package/src/templates/workspace-core/.agents/skills/secrets/SKILL.md +11 -4
@@ -705,6 +705,67 @@ function backgroundAwareStaleCutoffSql() {
705
705
  // working, and nothing recovers it. Those get the wider background window.
706
706
  return `(CAST(? AS BIGINT) - CASE WHEN dispatch_mode = 'background-processing' AND dispatch_payload IS NOT NULL THEN ${BACKGROUND_PROCESSING_RUN_STALE_MS} WHEN dispatch_mode LIKE 'background%' THEN ${BACKGROUND_RUN_STALE_MS} ELSE ${RUN_STALE_MS} END)`;
707
707
  }
708
+ /**
709
+ * Which stale window the reaper applied to a row, in ms.
710
+ *
711
+ * MIRRORS `backgroundAwareStaleCutoffSql`, which decides the same thing in SQL
712
+ * because it has to run inside the conditional UPDATE. Kept beside it and
713
+ * covered by a test asserting the three cases agree — a drift here reports the
714
+ * wrong window on a real incident, which is worse than reporting none.
715
+ */
716
+ export function staleWindowMsForRow(row) {
717
+ if (typeof row.maxStaleMs === "number")
718
+ return row.maxStaleMs;
719
+ const mode = row.dispatchMode ?? "";
720
+ if (mode === "background-processing" && row.hasDispatchPayload)
721
+ return BACKGROUND_PROCESSING_RUN_STALE_MS;
722
+ if (mode.startsWith("background"))
723
+ return BACKGROUND_RUN_STALE_MS;
724
+ return RUN_STALE_MS;
725
+ }
726
+ /**
727
+ * The liveness forensics for one reap, as a compact `key=value` line.
728
+ *
729
+ * THE FIELD THAT MATTERS IS `hbAheadOfProgress`. A worker that died takes its
730
+ * heartbeat with it, so heartbeat and last-progress stop together and this is
731
+ * ~0. A worker still running while the agent loop stops producing keeps
732
+ * heartbeating, and this grows without bound — those are opposite bugs that
733
+ * look identical in `agent_runs` today. Production showed runs where the
734
+ * heartbeat ran 3,000s past the last progress; nothing recorded that, so
735
+ * nothing could act on it.
736
+ *
737
+ * Numbers, booleans and an enum only — no prompt, no result, no user content —
738
+ * so this obeys the same privacy rule as event properties and log lines.
739
+ */
740
+ export function describeStaleReap(row) {
741
+ const { now } = row;
742
+ const started = row.startedAt ?? null;
743
+ const heartbeat = row.heartbeatAt ?? null;
744
+ const progress = row.lastProgressAt ?? null;
745
+ const liveness = Math.max(progress ?? started ?? 0, heartbeat ?? started ?? 0);
746
+ const parts = [
747
+ `window=${staleWindowMsForRow(row)}`,
748
+ `dispatch=${row.dispatchMode ?? "none"}`,
749
+ `redispatchable=${row.hasDispatchPayload ? "1" : "0"}`,
750
+ ];
751
+ if (heartbeat != null)
752
+ parts.push(`sinceHeartbeat=${now - heartbeat}`);
753
+ if (progress != null)
754
+ parts.push(`sinceProgress=${now - progress}`);
755
+ // The discriminator. Negative would mean progress outlived the heartbeat,
756
+ // which is possible and equally worth seeing.
757
+ if (heartbeat != null && progress != null)
758
+ parts.push(`hbAheadOfProgress=${heartbeat - progress}`);
759
+ // Only when it is a real duration. A liveness basis before `started_at` means
760
+ // clock skew or a mocked row, and printing a negative age reads as a fact
761
+ // about the run rather than a fact about the clock.
762
+ if (started != null && liveness >= started)
763
+ parts.push(`runAge=${liveness - started}`);
764
+ parts.push(`inFlight=${row.inFlightSince != null ? "1" : "0"}`);
765
+ if (row.inFlightSince != null)
766
+ parts.push(`inFlightFor=${now - row.inFlightSince}`);
767
+ return parts.join(" ");
768
+ }
708
769
  function terminalRunEventExclusionSql(runIdColumn = "id") {
709
770
  return `NOT EXISTS (
710
771
  SELECT 1 FROM agent_run_events terminal_events
@@ -1302,6 +1363,24 @@ export const RUN_DIAG_STAGE = {
1302
1363
  * no boundary previously recorded anywhere.
1303
1364
  */
1304
1365
  runBoundaryReached: "run_boundary_reached",
1366
+ /**
1367
+ * A stale reaper flipped this run to `errored`. Detail carries the liveness
1368
+ * forensics — see `describeStaleReap`.
1369
+ *
1370
+ * WHY THIS EXISTS. `stale_run` is the single largest terminal outcome on the
1371
+ * one-shot automation path (14 of 27 runs in one production deployment) and
1372
+ * the row records nothing about WHY: `error_detail` is a fixed sentence for
1373
+ * every reap, so a correct reap and a false one are indistinguishable after
1374
+ * the fact. Every question worth asking needed a number nobody stored — was
1375
+ * the worker dead, or was it heartbeating happily while the loop stopped
1376
+ * producing? which of the three stale windows fired? was the in-flight grace
1377
+ * in play? One production run heartbeated 3,309s past a 600s hard abort and
1378
+ * there is no way to tell from the row what kept it alive.
1379
+ *
1380
+ * Diagnostics only: nothing reads this to make a decision, and it cannot
1381
+ * change whether a row is reaped.
1382
+ */
1383
+ staleRunReaped: "stale_run_reaped",
1305
1384
  };
1306
1385
  /**
1307
1386
  * Record the last reached pipeline stage (+ optional short detail) for a run.
@@ -1732,15 +1811,59 @@ async function reapSingleStaleRun(runId, maxStaleMs) {
1732
1811
  });
1733
1812
  reaped = (rowsAffected ?? 0) > 0;
1734
1813
  }
1814
+ // FORENSICS, on the reap path only. A speculative `reapIfStale` that reaps
1815
+ // nothing does no extra work; an actual reap is rare enough to afford one
1816
+ // read.
1817
+ //
1818
+ // ONE diagnostic write, not two. `diag_stage` holds a single value, so an
1819
+ // independent forensics write would overwrite the recovery outcome that
1820
+ // already lands here — trading the answer to "did a successor get created"
1821
+ // for the answer to "why did it die". Both fit in one line, so both are
1822
+ // recorded: the recovery outcome keeps its own stage name and leading
1823
+ // position, and the liveness numbers are appended.
1824
+ let forensics = "";
1825
+ if (reaped) {
1826
+ forensics = await client
1827
+ .execute({
1828
+ sql: `SELECT started_at, heartbeat_at, last_progress_at, in_flight_since,
1829
+ dispatch_mode, dispatch_payload
1830
+ FROM agent_runs WHERE id = ?`,
1831
+ args: [runId],
1832
+ })
1833
+ .then((res) => {
1834
+ const row = res.rows[0];
1835
+ if (!row)
1836
+ return "forensics=row_missing";
1837
+ const num = (v) => (v == null ? null : Number(v));
1838
+ return describeStaleReap({
1839
+ startedAt: num(row.started_at),
1840
+ heartbeatAt: num(row.heartbeat_at),
1841
+ lastProgressAt: num(row.last_progress_at),
1842
+ inFlightSince: num(row.in_flight_since),
1843
+ dispatchMode: row.dispatch_mode ?? null,
1844
+ hasDispatchPayload: row.dispatch_payload != null,
1845
+ ...(typeof maxStaleMs === "number" ? { maxStaleMs } : {}),
1846
+ now: completedAt,
1847
+ });
1848
+ })
1849
+ // Best-effort throughout: a diagnostic that could fail a reap would be
1850
+ // strictly worse than no diagnostic. But an empty string reads as "reaped
1851
+ // with nothing worth saying" — the exact ambiguity these forensics exist
1852
+ // to remove — so an unreadable row says so instead of going quiet.
1853
+ .catch((err) => `forensics=unreadable ${(err instanceof Error ? err.message : String(err)).slice(0, 120)}`);
1854
+ }
1735
1855
  if (reaped && outcome && outcome.outcome !== "not_background") {
1736
1856
  const detail = outcome.outcome === "recovered"
1737
1857
  ? `recovered successorRunId=${outcome.successorRunId}`
1738
1858
  : `declined reason=${outcome.outcome}`;
1739
- await recordRunDiagnostic(runId, RUN_DIAG_STAGE.staleRunRecoveryAttempted, detail).catch(() => { });
1859
+ await recordRunDiagnostic(runId, RUN_DIAG_STAGE.staleRunRecoveryAttempted, forensics ? `${detail} ${forensics}` : detail).catch(() => { });
1740
1860
  if (outcome.outcome === "recovered") {
1741
1861
  attemptStaleRunRecoveryDispatch(outcome.successorRunId);
1742
1862
  }
1743
1863
  }
1864
+ else if (reaped && forensics) {
1865
+ await recordRunDiagnostic(runId, RUN_DIAG_STAGE.staleRunReaped, forensics).catch(() => { });
1866
+ }
1744
1867
  return reaped;
1745
1868
  }
1746
1869
  /**
@@ -1,3 +1,4 @@
1
+ import { isActionHiddenFromEveryAgentSurface } from "../action.js";
1
2
  import { parseMcpToolName } from "../mcp-client/manager.js";
2
3
  import { isMcpToolAllowedForRequest } from "../mcp-client/visibility.js";
3
4
  import { getRequestRunContext } from "../server/request-context.js";
@@ -84,7 +85,7 @@ export function searchToolRegistry(registry, args = {}, options = {}) {
84
85
  for (const [name, entry] of Object.entries(registry)) {
85
86
  if (!entry?.tool || name === TOOL_SEARCH_ACTION_NAME)
86
87
  continue;
87
- if (entry.agentTool === false)
88
+ if (isActionHiddenFromEveryAgentSurface(entry))
88
89
  continue;
89
90
  if (name.startsWith("mcp__") && !isMcpToolAllowedForRequest(name)) {
90
91
  continue;
@@ -291,12 +291,17 @@ export type AgentChatEvent = {
291
291
  * without producing any forwarded event, so the backstop's clock saw pure
292
292
  * silence and killed demonstrably-alive runs at 150s. `trackInFlightWork`
293
293
  * counts this pair exactly like `tool_start`/`tool_done`: an engine call
294
- * in flight suspends the backstop, bounded by the in-loop watchdog the
295
- * same way a tool call is bounded by its own timeout.
294
+ * in flight suspends the backstop.
295
+ *
296
+ * WHAT BOUNDS THE SUSPENDED WINDOW, now that the in-loop watchdogs are
297
+ * gone: the engine's own first-event abort covers a call that never
298
+ * speaks, and the chunk/run budget covers everything after that. An
299
+ * in-stream wedge AFTER the first frame is therefore caught by the budget
300
+ * rather than by a dedicated clock — a deliberate trade, because no clock
301
+ * here could tell it apart from a model composing a large tool argument.
296
302
  *
297
303
  * Deliberately NOT a keepalive: a keepalive proves the transport is up,
298
- * this proves the loop is inside a model call it will be held accountable
299
- * for by `MODEL_STREAM_NO_PROGRESS_TIMEOUT_MS`.
304
+ * this proves the loop is inside a model call.
300
305
  */
301
306
  type: "model_stream";
302
307
  status: "start" | "end";
@@ -1,4 +1,5 @@
1
1
  import { z } from "zod";
2
2
  export declare const authConfig: z.ZodObject<{
3
3
  disableDesktopSsoFallbackInDevelopment: z.ZodDefault<z.ZodBoolean>;
4
+ requireEmailVerification: z.ZodOptional<z.ZodBoolean>;
4
5
  }, z.core.$strip>;
@@ -4,4 +4,11 @@ export const authConfig = z.object({
4
4
  env: "AGENT_NATIVE_DISABLE_DESKTOP_SSO_FALLBACK",
5
5
  doc: "Disable the loopback Desktop SSO fallback in development so isolated acceptance runs can use their configured local identity. Ignored in production.",
6
6
  }),
7
+ // Deliberately optional rather than defaulted: unset means "derive from the
8
+ // deployment", which is not a boolean. A default here would erase the
9
+ // difference between an operator who chose a policy and one who never spoke.
10
+ requireEmailVerification: z.boolean().optional().meta({
11
+ env: "AUTH_REQUIRE_EMAIL_VERIFICATION",
12
+ doc: "Whether password signup must verify the email address before it gets a session. Unset derives it: hosted deployments require it, local development skips it. Setting it false accepts an unverified email as a login credential, including in production.",
13
+ }),
7
14
  });
@@ -0,0 +1,11 @@
1
+ /**
2
+ * An invalid deployment configuration value, as opposed to a runtime failure.
3
+ *
4
+ * Best-effort regions that log and continue — plugin auto-mount, most of all —
5
+ * must rethrow this rather than absorb it: a typo in a deployment variable
6
+ * silently drops whole route trees, so the deployment looks accepted while the
7
+ * app is missing.
8
+ */
9
+ export declare class AppConfigurationError extends Error {
10
+ constructor(message: string);
11
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * An invalid deployment configuration value, as opposed to a runtime failure.
3
+ *
4
+ * Best-effort regions that log and continue — plugin auto-mount, most of all —
5
+ * must rethrow this rather than absorb it: a typo in a deployment variable
6
+ * silently drops whole route trees, so the deployment looks accepted while the
7
+ * app is missing.
8
+ */
9
+ export class AppConfigurationError extends Error {
10
+ constructor(message) {
11
+ super(message);
12
+ this.name = "AppConfigurationError";
13
+ }
14
+ }
@@ -1,2 +1,3 @@
1
1
  export { defineAppConfig, getAppConfig, resetAppConfigForTests, } from "./store.js";
2
+ export { AppConfigurationError } from "./configuration-error.js";
2
3
  export { appConfigSchema, type AppConfig, type AppConfigInput, } from "./schema.js";
@@ -1,2 +1,3 @@
1
1
  export { defineAppConfig, getAppConfig, resetAppConfigForTests, } from "./store.js";
2
+ export { AppConfigurationError } from "./configuration-error.js";
2
3
  export { appConfigSchema, } from "./schema.js";
@@ -2,4 +2,5 @@ import { z } from "zod";
2
2
  /** Inbound integration webhook policy. */
3
3
  export declare const integrationsConfig: z.ZodObject<{
4
4
  allowUnverifiedWebhooks: z.ZodDefault<z.ZodBoolean>;
5
+ platforms: z.ZodOptional<z.ZodArray<z.ZodString>>;
5
6
  }, z.core.$strip>;
@@ -8,4 +8,14 @@ export const integrationsConfig = z.object({
8
8
  env: ["AGENT_NATIVE_ALLOW_UNVERIFIED_WEBHOOKS"],
9
9
  doc: "Skip inbound webhook signature verification. Development only — every adapter that reads this treats it as a bypass of sender authentication.",
10
10
  }),
11
+ // Blank counts as unset everywhere in the env layer, so this cannot express
12
+ // "mount no platforms" — refuse the whole slot with `plugins.disabled`
13
+ // instead.
14
+ platforms: z
15
+ .array(z.string().min(1))
16
+ .optional()
17
+ .meta({
18
+ env: ["AGENT_NATIVE_INTEGRATION_PLATFORMS"],
19
+ doc: "Integration platforms to mount, comma-separated, each matched against an adapter's `platform` id (slack, telegram, whatsapp, microsoft-teams, discord, google-docs, email). Unset mounts every adapter; a name no adapter provides throws at plugin init.",
20
+ }),
11
21
  });
@@ -0,0 +1,34 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * The framework's default plugin slots, mirroring `DEFAULT_PLUGIN_REGISTRY`.
4
+ *
5
+ * Spelled out here rather than imported: that registry lives in the deploy
6
+ * layer, which reaches for `node:fs`, and this schema is parsed on edge
7
+ * runtimes too. `plugins.spec.ts` fails when the two lists drift.
8
+ */
9
+ export declare const DEFAULT_PLUGIN_SLOTS: readonly ["agent-chat", "auth", "context-xray", "core-routes", "integrations", "observational-memory", "onboarding", "org", "resources", "sentry", "terminal"];
10
+ export type DefaultPluginSlot = (typeof DEFAULT_PLUGIN_SLOTS)[number];
11
+ /**
12
+ * Which framework default plugins this deployment refuses.
13
+ *
14
+ * A refused slot mounts nothing, so every route it owns 404s and the UI and
15
+ * agent surfaces that call them stop working — `agent-chat`, `auth`, and
16
+ * `core-routes` carry most of an app with them. Only the framework's own
17
+ * default is withheld: an app that ships `server/plugins/<slot>.ts` mounted
18
+ * that plugin deliberately and keeps it.
19
+ */
20
+ export declare const pluginsConfig: z.ZodObject<{
21
+ disabled: z.ZodDefault<z.ZodArray<z.ZodEnum<{
22
+ "agent-chat": "agent-chat";
23
+ auth: "auth";
24
+ "context-xray": "context-xray";
25
+ "core-routes": "core-routes";
26
+ integrations: "integrations";
27
+ "observational-memory": "observational-memory";
28
+ onboarding: "onboarding";
29
+ org: "org";
30
+ resources: "resources";
31
+ sentry: "sentry";
32
+ terminal: "terminal";
33
+ }>>>;
34
+ }, z.core.$strip>;
@@ -0,0 +1,39 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * The framework's default plugin slots, mirroring `DEFAULT_PLUGIN_REGISTRY`.
4
+ *
5
+ * Spelled out here rather than imported: that registry lives in the deploy
6
+ * layer, which reaches for `node:fs`, and this schema is parsed on edge
7
+ * runtimes too. `plugins.spec.ts` fails when the two lists drift.
8
+ */
9
+ export const DEFAULT_PLUGIN_SLOTS = [
10
+ "agent-chat",
11
+ "auth",
12
+ "context-xray",
13
+ "core-routes",
14
+ "integrations",
15
+ "observational-memory",
16
+ "onboarding",
17
+ "org",
18
+ "resources",
19
+ "sentry",
20
+ "terminal",
21
+ ];
22
+ /**
23
+ * Which framework default plugins this deployment refuses.
24
+ *
25
+ * A refused slot mounts nothing, so every route it owns 404s and the UI and
26
+ * agent surfaces that call them stop working — `agent-chat`, `auth`, and
27
+ * `core-routes` carry most of an app with them. Only the framework's own
28
+ * default is withheld: an app that ships `server/plugins/<slot>.ts` mounted
29
+ * that plugin deliberately and keeps it.
30
+ */
31
+ export const pluginsConfig = z.object({
32
+ disabled: z
33
+ .array(z.enum(DEFAULT_PLUGIN_SLOTS))
34
+ .default([])
35
+ .meta({
36
+ env: ["AGENT_NATIVE_DISABLED_PLUGINS"],
37
+ doc: "Framework default plugins this deployment refuses to auto-mount, comma-separated. A refused slot mounts none of its routes; an app supplying its own `server/plugins/<slot>.ts` is unaffected.",
38
+ }),
39
+ });
@@ -111,16 +111,25 @@ export declare const BACKGROUND_SOFT_TIMEOUT_CEILING_MS: number;
111
111
  */
112
112
  export declare const RUN_NO_PROGRESS_HARD_TIMEOUT_MS = 150000;
113
113
  /**
114
- * Default in-loop watchdog for silence while an action's arguments stream in.
115
- * Read through `resolveActionPreparationNoProgressTimeoutMs`, never directly:
116
- * a host diagnosing a timeout has to be able to see and change this number.
117
- */
118
- export declare const ACTION_PREPARATION_NO_PROGRESS_TIMEOUT_MS = 90000;
119
- /**
120
- * Default in-loop watchdog for silence between engine stream frames. Read
121
- * through `resolveModelStreamNoProgressTimeoutMs`, never directly.
114
+ * THE IN-LOOP NO-PROGRESS WATCHDOGS ARE GONE, and their absence is the design.
115
+ *
116
+ * Two 90s bounds used to live here — one on silence between engine frames,
117
+ * one on a tool input whose byte count stopped growing. Both inferred a dead
118
+ * stream from the absence of a particular event, and on the Anthropic
119
+ * transport that inference cannot be made: the SDK drops the provider's `ping`
120
+ * keepalives before any consumer sees them (`core/streaming.js`), so a model
121
+ * composing a large tool argument is indistinguishable from a wedged socket.
122
+ * Only a tool declared for eager input streaming emits anything at all while
123
+ * its arguments are generated, so the silent case is ORDINARY, not
124
+ * exceptional.
125
+ *
126
+ * They were added to make runs more reliable and did the opposite: of 27
127
+ * one-shot analyst runs in production, 2 completed. Deleting them leaves the
128
+ * bounds that key off evidence rather than absence — the engine's own
129
+ * first-event abort, the run-manager backstop outside the stream, the per-tool
130
+ * execution timeout, the chunk budget, and the stale reaper. Reintroducing a
131
+ * clock here needs a liveness signal this process can actually observe.
122
132
  */
123
- export declare const MODEL_STREAM_NO_PROGRESS_TIMEOUT_MS = 90000;
124
133
  /**
125
134
  * Consecutive chunks allowed to end on the SAME terminal error code having
126
135
  * produced nothing before the chain stops.
@@ -110,16 +110,25 @@ export const BACKGROUND_SOFT_TIMEOUT_CEILING_MS = 13 * 60_000;
110
110
  */
111
111
  export const RUN_NO_PROGRESS_HARD_TIMEOUT_MS = 150_000;
112
112
  /**
113
- * Default in-loop watchdog for silence while an action's arguments stream in.
114
- * Read through `resolveActionPreparationNoProgressTimeoutMs`, never directly:
115
- * a host diagnosing a timeout has to be able to see and change this number.
116
- */
117
- export const ACTION_PREPARATION_NO_PROGRESS_TIMEOUT_MS = 90_000;
118
- /**
119
- * Default in-loop watchdog for silence between engine stream frames. Read
120
- * through `resolveModelStreamNoProgressTimeoutMs`, never directly.
113
+ * THE IN-LOOP NO-PROGRESS WATCHDOGS ARE GONE, and their absence is the design.
114
+ *
115
+ * Two 90s bounds used to live here — one on silence between engine frames,
116
+ * one on a tool input whose byte count stopped growing. Both inferred a dead
117
+ * stream from the absence of a particular event, and on the Anthropic
118
+ * transport that inference cannot be made: the SDK drops the provider's `ping`
119
+ * keepalives before any consumer sees them (`core/streaming.js`), so a model
120
+ * composing a large tool argument is indistinguishable from a wedged socket.
121
+ * Only a tool declared for eager input streaming emits anything at all while
122
+ * its arguments are generated, so the silent case is ORDINARY, not
123
+ * exceptional.
124
+ *
125
+ * They were added to make runs more reliable and did the opposite: of 27
126
+ * one-shot analyst runs in production, 2 completed. Deleting them leaves the
127
+ * bounds that key off evidence rather than absence — the engine's own
128
+ * first-event abort, the run-manager backstop outside the stream, the per-tool
129
+ * execution timeout, the chunk budget, and the stale reaper. Reintroducing a
130
+ * clock here needs a liveness signal this process can actually observe.
121
131
  */
122
- export const MODEL_STREAM_NO_PROGRESS_TIMEOUT_MS = 90_000;
123
132
  /**
124
133
  * Consecutive chunks allowed to end on the SAME terminal error code having
125
134
  * produced nothing before the chain stops.
@@ -226,8 +235,6 @@ export function assertRunLifecycleInvariants(agent) {
226
235
  // the relationship below extended to cover it.
227
236
  const { backgroundNoProgressTimeoutMs, backgroundRunHardTimeoutMs } = agent;
228
237
  const backgroundSoftTimeoutCeilingMs = BACKGROUND_SOFT_TIMEOUT_CEILING_MS;
229
- const modelStreamNoProgressTimeoutMs = MODEL_STREAM_NO_PROGRESS_TIMEOUT_MS;
230
- const actionPreparationNoProgressTimeoutMs = ACTION_PREPARATION_NO_PROGRESS_TIMEOUT_MS;
231
238
  const maxBackgroundRunContinuations = MAX_BACKGROUND_RUN_CONTINUATIONS;
232
239
  const maxConsecutiveNoProgressContinuations = MAX_CONSECUTIVE_NO_PROGRESS_CONTINUATIONS;
233
240
  const maxTurnWallClockMs = MAX_TURN_WALL_CLOCK_MS;
@@ -244,20 +251,6 @@ export function assertRunLifecycleInvariants(agent) {
244
251
  };
245
252
  // A disabled backstop (0) has no ordering to satisfy — it never fires.
246
253
  if (backgroundNoProgressTimeoutMs > 0) {
247
- require("in-loop watchdog before the run-manager backstop", {
248
- key: "agent.modelStreamNoProgressTimeoutMs",
249
- value: modelStreamNoProgressTimeoutMs,
250
- }, {
251
- key: "agent.backgroundNoProgressTimeoutMs",
252
- value: backgroundNoProgressTimeoutMs,
253
- }, "the in-loop watchdog emits a boundary the agent loop itself recovers; the run-manager backstop is the coarser one above it");
254
- require("action-preparation watchdog before the run-manager backstop", {
255
- key: "agent.actionPreparationNoProgressTimeoutMs",
256
- value: actionPreparationNoProgressTimeoutMs,
257
- }, {
258
- key: "agent.backgroundNoProgressTimeoutMs",
259
- value: backgroundNoProgressTimeoutMs,
260
- }, "a stalled argument stream must be caught by the watchdog that knows which tool stalled");
261
254
  require("background backstop inside the background chunk budget", {
262
255
  key: "agent.backgroundNoProgressTimeoutMs",
263
256
  value: backgroundNoProgressTimeoutMs,
@@ -38,14 +38,31 @@ export declare const appConfigSchema: z.ZodObject<{
38
38
  }, z.core.$strip>>;
39
39
  auth: z.ZodPrefault<z.ZodObject<{
40
40
  disableDesktopSsoFallbackInDevelopment: z.ZodDefault<z.ZodBoolean>;
41
+ requireEmailVerification: z.ZodOptional<z.ZodBoolean>;
41
42
  }, z.core.$strip>>;
42
43
  integrations: z.ZodPrefault<z.ZodObject<{
43
44
  allowUnverifiedWebhooks: z.ZodDefault<z.ZodBoolean>;
45
+ platforms: z.ZodOptional<z.ZodArray<z.ZodString>>;
44
46
  }, z.core.$strip>>;
45
47
  migration: z.ZodPrefault<z.ZodObject<{
46
48
  releaseMigrations: z.ZodDefault<z.ZodBoolean>;
47
49
  betaSchemaOwner: z.ZodOptional<z.ZodString>;
48
50
  }, z.core.$strip>>;
51
+ plugins: z.ZodPrefault<z.ZodObject<{
52
+ disabled: z.ZodDefault<z.ZodArray<z.ZodEnum<{
53
+ "agent-chat": "agent-chat";
54
+ auth: "auth";
55
+ "context-xray": "context-xray";
56
+ "core-routes": "core-routes";
57
+ integrations: "integrations";
58
+ "observational-memory": "observational-memory";
59
+ onboarding: "onboarding";
60
+ org: "org";
61
+ resources: "resources";
62
+ sentry: "sentry";
63
+ terminal: "terminal";
64
+ }>>>;
65
+ }, z.core.$strip>>;
49
66
  privateBlob: z.ZodPrefault<z.ZodObject<{
50
67
  provider: z.ZodOptional<z.ZodString>;
51
68
  publicUploadFallback: z.ZodDefault<z.ZodBoolean>;
@@ -5,6 +5,7 @@ import { appConfig } from "./app.js";
5
5
  import { authConfig } from "./auth.js";
6
6
  import { integrationsConfig } from "./integrations.js";
7
7
  import { migrationConfig } from "./migration.js";
8
+ import { pluginsConfig } from "./plugins.js";
8
9
  import { privateBlobConfig } from "./private-blob.js";
9
10
  import { workspaceConfig } from "./workspace.js";
10
11
  /**
@@ -30,6 +31,7 @@ export const appConfigSchema = z.object({
30
31
  auth: authConfig.prefault({}),
31
32
  integrations: integrationsConfig.prefault({}),
32
33
  migration: migrationConfig.prefault({}),
34
+ plugins: pluginsConfig.prefault({}),
33
35
  privateBlob: privateBlobConfig.prefault({}),
34
36
  workspace: workspaceConfig.prefault({}),
35
37
  });
@@ -57,4 +57,24 @@ export const CHAT_THREAD_SCHEMA_MIGRATIONS = [
57
57
  ON chat_threads (share_token_hash)
58
58
  `,
59
59
  },
60
+ {
61
+ version: 3,
62
+ name: "chat-threads-source-backfill",
63
+ // Retires a `thread_data NOT LIKE '%…%'` filter the local-only list used to
64
+ // carry for integration rows written before `source_platform` existed. That
65
+ // predicate forced Postgres to detoast the full message-history blob for
66
+ // every scanned row, so the sidebar list cost seconds regardless of LIMIT.
67
+ // Paying the scan once here keeps the read path off the blob forever.
68
+ //
69
+ // The matching `LOWER(...)` expression indexes deliberately do NOT live
70
+ // here: they are built CONCURRENTLY in the store's ensure path, and
71
+ // Postgres forbids that inside the transaction `runMigrations` wraps
72
+ // around these statements.
73
+ sql: `
74
+ UPDATE chat_threads
75
+ SET source_platform = 'integration'
76
+ WHERE source_platform IS NULL
77
+ AND thread_data LIKE '%"integrationDeliveryAttempted":true%'
78
+ `,
79
+ },
60
80
  ];
@@ -118,6 +118,20 @@ async function ensureTable() {
118
118
  // scope) and sort by updated_at. Probe pg_indexes first (no lock)
119
119
  // and skip the SHARE-locking CREATE INDEX when already present.
120
120
  await ensureIndexExists("chat_threads_owner_updated_idx", `CREATE INDEX IF NOT EXISTS chat_threads_owner_updated_idx ON chat_threads (owner_email, updated_at)`);
121
+ // `owner_email` is stored as the user typed it, so access scoping
122
+ // compares `LOWER(owner_email)`. A plain btree on the raw column cannot
123
+ // serve that predicate — without the expression index the list falls
124
+ // back to scanning every row in the (shared, multi-tenant) table.
125
+ //
126
+ // NOT built CONCURRENTLY, despite the SHARE lock. This ensure path runs
127
+ // at release over the pooled Neon endpoint, and a transaction-pooled
128
+ // connection cannot carry `CREATE INDEX CONCURRENTLY` to completion:
129
+ // the statement returned without creating anything and the verifying
130
+ // probe failed the whole release, so no docs production deploy could
131
+ // publish. Release already runs locking DDL; a plain build here is the
132
+ // form that actually lands.
133
+ await ensureIndexExists("chat_threads_owner_lower_updated_idx", `CREATE INDEX IF NOT EXISTS chat_threads_owner_lower_updated_idx ON chat_threads (LOWER(owner_email), updated_at)`);
134
+ await ensureIndexExists("chat_thread_shares_principal_lower_idx", `CREATE INDEX IF NOT EXISTS chat_thread_shares_principal_lower_idx ON chat_thread_shares (resource_id, principal_type, LOWER(principal_id))`);
121
135
  await ensureIndexExists("chat_threads_scope_updated_idx", `CREATE INDEX IF NOT EXISTS chat_threads_scope_updated_idx ON chat_threads (scope_type, scope_id, updated_at)`);
122
136
  await ensureIndexExists("chat_threads_source_updated_idx", `CREATE INDEX IF NOT EXISTS chat_threads_source_updated_idx ON chat_threads (owner_email, source_app_id, updated_at)`);
123
137
  // Public share-link resolution looks threads up by token hash;
@@ -175,6 +189,8 @@ async function ensureTable() {
175
189
  // idempotent across restarts.
176
190
  for (const ddl of [
177
191
  `CREATE INDEX IF NOT EXISTS chat_threads_owner_updated_idx ON chat_threads (owner_email, updated_at)`,
192
+ `CREATE INDEX IF NOT EXISTS chat_threads_owner_lower_updated_idx ON chat_threads (LOWER(owner_email), updated_at)`,
193
+ `CREATE INDEX IF NOT EXISTS chat_thread_shares_principal_lower_idx ON chat_thread_shares (resource_id, principal_type, LOWER(principal_id))`,
178
194
  `CREATE INDEX IF NOT EXISTS chat_threads_scope_updated_idx ON chat_threads (scope_type, scope_id, updated_at)`,
179
195
  `CREATE INDEX IF NOT EXISTS chat_threads_source_updated_idx ON chat_threads (owner_email, source_app_id, updated_at)`,
180
196
  `CREATE INDEX IF NOT EXISTS chat_threads_share_token_idx ON chat_threads (share_token_hash)`,
@@ -600,8 +616,11 @@ export async function listThreads(ownerEmail, options = {}, legacyOffset) {
600
616
  const offset = opts.offset ?? 0;
601
617
  const client = getDbExec();
602
618
  // `message_count > 0` is the authoritative "has messages" signal maintained
603
- // on every write. The local-only view adds a narrowly scoped legacy marker
604
- // check below because older integration rows predate persisted source fields.
619
+ // on every write. `source_platform` is the authoritative external-source
620
+ // signal: schema migration 3 backfilled the integration rows that predate the
621
+ // column, so nothing here may filter on `thread_data`. Matching that blob
622
+ // detoasts the whole message history for every scanned row — before LIMIT
623
+ // applies — which is what made this list cost seconds instead of milliseconds.
605
624
  const access = chatThreadAccessSql(ownerEmail, opts.orgId ?? getRequestOrgId());
606
625
  const filters = [access.sql, `message_count > 0`];
607
626
  const args = [...access.args];
@@ -610,7 +629,6 @@ export async function listThreads(ownerEmail, options = {}, legacyOffset) {
610
629
  }
611
630
  if (opts.includeExternal === false) {
612
631
  filters.push(`source_platform IS NULL`);
613
- filters.push(`thread_data NOT LIKE '%"integrationDeliveryAttempted":true%'`);
614
632
  if (opts.sourceAppId) {
615
633
  filters.push(`(source_app_id IS NULL OR source_app_id = ?)`);
616
634
  args.push(opts.sourceAppId);
@@ -654,7 +672,6 @@ export async function searchThreads(ownerEmail, query, limit = 50, options = {})
654
672
  }
655
673
  if (options.includeExternal === false) {
656
674
  filters.push(`source_platform IS NULL`);
657
- filters.push(`thread_data NOT LIKE '%"integrationDeliveryAttempted":true%'`);
658
675
  if (options.sourceAppId) {
659
676
  filters.push(`(source_app_id IS NULL OR source_app_id = ?)`);
660
677
  args.push(options.sourceAppId);
@@ -1,6 +1,10 @@
1
1
  type NativeDependencyCheck = {
2
2
  status: "absent";
3
3
  packageName: string;
4
+ } | {
5
+ status: "stubbed";
6
+ packageName: string;
7
+ packageDir: string;
4
8
  } | {
5
9
  status: "healthy";
6
10
  packageName: string;
@@ -57,6 +57,18 @@ function probeBetterSqlite3(packageDir) {
57
57
  return error;
58
58
  }
59
59
  }
60
+ /**
61
+ * Whether this `better-sqlite3` is the build-time serverless stub rather than a
62
+ * real install. The stub's constructor throws by design, so probing it would
63
+ * report a broken native binding and send the CLI into a pointless rebuild.
64
+ */
65
+ function isServerlessStub(packageDir) {
66
+ const manifestPath = path.join(packageDir, "package.json");
67
+ if (!fs.existsSync(manifestPath))
68
+ return false;
69
+ const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
70
+ return manifest.agentNativeServerlessStub === true;
71
+ }
60
72
  export function checkNativeDependencies(fromDirectory = corePackageDirectory()) {
61
73
  const packageDir = resolvePackageDirectory(BETTER_SQLITE3, fromDirectory) ??
62
74
  (path.resolve(fromDirectory) === corePackageDirectory()
@@ -65,6 +77,9 @@ export function checkNativeDependencies(fromDirectory = corePackageDirectory())
65
77
  if (!packageDir) {
66
78
  return { status: "absent", packageName: BETTER_SQLITE3 };
67
79
  }
80
+ if (isServerlessStub(packageDir)) {
81
+ return { status: "stubbed", packageName: BETTER_SQLITE3, packageDir };
82
+ }
68
83
  const error = probeBetterSqlite3(packageDir);
69
84
  return error === null
70
85
  ? { status: "healthy", packageName: BETTER_SQLITE3, packageDir }
@@ -1,5 +1,5 @@
1
1
  import type { AgentNativeDeploymentEnvironment, AgentNativeConfig } from "../config.js";
2
- export { BETA_OPT_OUT_DURATION_MS, BETA_OPT_OUT_QUERY_PARAM, BETA_OPT_OUT_STORAGE_KEY, buildEnvironmentOptOutUrl, buildEnvironmentUrl, resolveEnvironmentTargets, type EnvironmentBadgeTargets, } from "../shared/environment-lanes.js";
2
+ export { BETA_FORCE_QUERY_PARAM, BETA_FORCE_SESSION_STORAGE_KEY, BETA_OPT_OUT_DURATION_MS, BETA_OPT_OUT_QUERY_PARAM, BETA_OPT_OUT_STORAGE_KEY, buildEnvironmentOptOutUrl, buildEnvironmentUrl, resolveEnvironmentTargets, type EnvironmentBadgeTargets, } from "../shared/environment-lanes.js";
3
3
  export declare function isBuilderIoEmployee(email: string | null | undefined): boolean;
4
4
  export declare function isAgentNativeDesktopUserAgent(userAgent: string | undefined): boolean;
5
5
  export declare function resolveEnvironmentChannel(config: AgentNativeConfig, hostname: string | undefined): Extract<AgentNativeDeploymentEnvironment, "local" | "beta" | "production"> | null;