@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
@@ -121,6 +121,8 @@ function getPollAbortMs(interval) {
121
121
  return Math.max(POLL_ABORT_MIN_MS, interval * 4);
122
122
  }
123
123
  const ACTIVE_RUN_CLEAR_TIMEOUT_MS = 5_000;
124
+ const ACTIVE_RUN_CLEAR_STABLE_POLLS = 2;
125
+ const ACTIVE_RUN_CLEAR_RETRY_DELAY_MS = 1_000;
124
126
  const ACTIVE_RUN_STUCK_THRESHOLD_MS = 90_000;
125
127
  const BACKGROUND_ACTIVE_RUN_STUCK_THRESHOLD_MS = 13 * 60_000;
126
128
  const ACTIVE_RUN_POLL_INTERVAL_MS = 150;
@@ -303,6 +305,7 @@ export async function waitForThreadRunToClear(apiUrl, threadId) {
303
305
  return true;
304
306
  const deadline = Date.now() + ACTIVE_RUN_CLEAR_TIMEOUT_MS;
305
307
  let activeRunToResume = null;
308
+ let consecutiveClearPolls = 0;
306
309
  const resumeActiveRun = (info) => {
307
310
  if (!info.runId)
308
311
  return;
@@ -323,11 +326,22 @@ export async function waitForThreadRunToClear(apiUrl, threadId) {
323
326
  const res = await fetch(`${apiUrl}/runs/active?threadId=${encodeURIComponent(threadId)}`);
324
327
  if (res.ok) {
325
328
  const info = (await res.json());
326
- if (!info?.active ||
329
+ const runLooksClear = !info?.active ||
327
330
  info?.status !== "running" ||
328
- activeRunLooksStale(info))
329
- return true;
330
- if (info.runId) {
331
+ activeRunLooksStale(info);
332
+ if (runLooksClear) {
333
+ consecutiveClearPolls += 1;
334
+ // A terminal/no-active snapshot can briefly appear between a
335
+ // foreground run and its server-owned continuation. Require two
336
+ // consecutive clear polls before releasing a queued follow-up.
337
+ if (consecutiveClearPolls >= ACTIVE_RUN_CLEAR_STABLE_POLLS) {
338
+ return true;
339
+ }
340
+ }
341
+ else {
342
+ consecutiveClearPolls = 0;
343
+ }
344
+ if (!runLooksClear && info.runId) {
331
345
  activeRunToResume = info;
332
346
  if (info.awaitingRedispatch === true) {
333
347
  // This is not the brief terminal-write lag the 5s waiter was built
@@ -340,8 +354,12 @@ export async function waitForThreadRunToClear(apiUrl, threadId) {
340
354
  }
341
355
  }
342
356
  }
357
+ else {
358
+ consecutiveClearPolls = 0;
359
+ }
343
360
  }
344
361
  catch {
362
+ consecutiveClearPolls = 0;
345
363
  // Transient poll failure — try again until the short grace period ends.
346
364
  }
347
365
  await new Promise((resolve) => window.setTimeout(resolve, ACTIVE_RUN_POLL_INTERVAL_MS));
@@ -1730,6 +1748,15 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
1730
1748
  tabId,
1731
1749
  onActiveRunChange: setHasActiveServerRun,
1732
1750
  });
1751
+ // Server truth must participate in submit gating, not only in the missing
1752
+ // final-response warning. The local lifecycle can clear during a transport
1753
+ // handoff while the server still owns the turn.
1754
+ const serverRunState = useRunStuckDetection({
1755
+ threadId: threadId ?? null,
1756
+ enabled: isActiveComposer,
1757
+ apiUrl,
1758
+ });
1759
+ const serverRunActive = serverRunState.runId != null && serverRunState.status === "running";
1733
1760
  // Real running state drives submission/queue gating; UI running also covers
1734
1761
  // short auto-continuation gaps so the latest assistant message does not flash
1735
1762
  // into a done state while the agent is still working.
@@ -1739,19 +1766,10 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
1739
1766
  isReconnecting,
1740
1767
  optimisticRunning,
1741
1768
  isAutoResuming,
1742
- hasActiveServerRun,
1769
+ hasActiveServerRun: hasActiveServerRun || serverRunActive,
1743
1770
  hasTerminalRunError: runErrorInfo !== null,
1744
1771
  });
1745
1772
  const textStreaming = showRunningInUI || externalStreaming;
1746
- // Server truth about this thread's run, used to suppress the "agent stopped
1747
- // without sending a final message" notice while the server still has the
1748
- // turn in flight. The poll backs itself off to 15s while nothing is running.
1749
- const serverRunState = useRunStuckDetection({
1750
- threadId: threadId ?? null,
1751
- enabled: isActiveComposer,
1752
- apiUrl,
1753
- });
1754
- const serverRunActive = serverRunState.runId != null && serverRunState.status === "running";
1755
1773
  const storedActiveRun = getActiveRun();
1756
1774
  const activeChatRunId = (serverRunState.status === "running" ? serverRunState.runId : null) ??
1757
1775
  (activeRunMatchesThread(storedActiveRun, threadId)
@@ -3318,6 +3336,7 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
3318
3336
  dequeueInFlightRef.current = true;
3319
3337
  let cancelled = false;
3320
3338
  let started = false;
3339
+ let retryTimer = null;
3321
3340
  const timer = window.setTimeout(() => {
3322
3341
  started = true;
3323
3342
  void (async () => {
@@ -3329,8 +3348,19 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
3329
3348
  // complete. Starting the queued turn during that window can reconnect
3330
3349
  // to the old run and replay the old answer under the new prompt.
3331
3350
  const runCleared = await waitForThreadRunToClear(apiUrl, threadId);
3332
- if (cancelled || !runCleared)
3351
+ if (cancelled)
3333
3352
  return;
3353
+ if (!runCleared) {
3354
+ // The server still owns this turn (including a deferred durable
3355
+ // successor). Keep the queued message visible and retry after a
3356
+ // short delay so one transient idle snapshot cannot strand it.
3357
+ retryTimer = window.setTimeout(() => {
3358
+ if (!cancelled) {
3359
+ setQueueWakeVersion((version) => version + 1);
3360
+ }
3361
+ }, ACTIVE_RUN_CLEAR_RETRY_DELAY_MS);
3362
+ return;
3363
+ }
3334
3364
  if (queueStopVersionRef.current !== stopVersion ||
3335
3365
  queuedMessagesRef.current[0]?.id !== next.id) {
3336
3366
  return;
@@ -3391,6 +3421,8 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
3391
3421
  return () => {
3392
3422
  cancelled = true;
3393
3423
  window.clearTimeout(timer);
3424
+ if (retryTimer !== null)
3425
+ window.clearTimeout(retryTimer);
3394
3426
  if (!started) {
3395
3427
  dequeueInFlightRef.current = false;
3396
3428
  }
@@ -12,10 +12,12 @@ export interface ConnectBuilderCardProps {
12
12
  /** The user's feature/change request, forwarded to the selected coding
13
13
  * agent when they click Send. Empty for generic "connect Builder" prompts. */
14
14
  prompt?: string;
15
+ /** Formatted staged chat context forwarded with the Builder request. */
16
+ context?: string;
15
17
  }
16
18
  /**
17
19
  * Rich inline card rendered for the `connect-builder` tool call. Shows the
18
20
  * Builder handoff when available, or routes local development requests to the
19
21
  * external coding agent.
20
22
  */
21
- export declare function ConnectBuilderCard({ configured: initialConfigured, builderEnabled: initialBuilderEnabled, connectUrl: initialConnectUrl, orgName: initialOrgName, prompt, }: ConnectBuilderCardProps): React.JSX.Element;
23
+ export declare function ConnectBuilderCard({ configured: initialConfigured, builderEnabled: initialBuilderEnabled, connectUrl: initialConnectUrl, orgName: initialOrgName, prompt, context, }: ConnectBuilderCardProps): React.JSX.Element;
@@ -30,7 +30,7 @@ function hasElectronShellBridge() {
30
30
  * Builder handoff when available, or routes local development requests to the
31
31
  * external coding agent.
32
32
  */
33
- export function ConnectBuilderCard({ configured: initialConfigured, builderEnabled: initialBuilderEnabled = true, connectUrl: initialConnectUrl, orgName: initialOrgName, prompt = "", }) {
33
+ export function ConnectBuilderCard({ configured: initialConfigured, builderEnabled: initialBuilderEnabled = true, connectUrl: initialConnectUrl, orgName: initialOrgName, prompt = "", context = "", }) {
34
34
  // The connect-poll state machine is shared — the tool-call result is
35
35
  // frozen at render time, so the hook's mount-time fetch + focus refresh
36
36
  // is what catches a flow the user completed in another tab.
@@ -89,7 +89,10 @@ export function ConnectBuilderCard({ configured: initialConfigured, builderEnabl
89
89
  const res = await fetch(new URL(agentNativePath("/_agent-native/builder/run"), origin).href, {
90
90
  method: "POST",
91
91
  headers: { "Content-Type": "application/json" },
92
- body: JSON.stringify({ prompt }),
92
+ body: JSON.stringify({
93
+ prompt,
94
+ ...(context.trim() ? { context } : {}),
95
+ }),
93
96
  });
94
97
  const data = await res.json().catch(() => ({}));
95
98
  if (!res.ok) {
@@ -108,7 +111,7 @@ export function ConnectBuilderCard({ configured: initialConfigured, builderEnabl
108
111
  setSendErr(e instanceof Error ? e.message : "Send failed");
109
112
  setSending(false);
110
113
  }
111
- }, [prompt]);
114
+ }, [context, prompt]);
112
115
  const handleJoinWaitlist = useCallback(async () => {
113
116
  setJoiningWaitlist(true);
114
117
  setWaitlistErr(null);
@@ -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;
@@ -1,13 +1,13 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Button } from "@agent-native/toolkit/ui/button";
3
3
  import { Popover, PopoverContent, PopoverTrigger, } from "@agent-native/toolkit/ui/popover";
4
- import { useEffect, useMemo, useRef } from "react";
5
- import { BETA_OPT_OUT_QUERY_PARAM, BETA_OPT_OUT_STORAGE_KEY, buildEnvironmentOptOutUrl, buildEnvironmentUrl, resolveEnvironmentTargets, } from "../shared/environment-lanes.js";
4
+ import { useEffect, useMemo, useRef, useState } from "react";
5
+ import { BETA_FORCE_QUERY_PARAM, BETA_FORCE_SESSION_STORAGE_KEY, BETA_OPT_OUT_QUERY_PARAM, BETA_OPT_OUT_STORAGE_KEY, buildEnvironmentOptOutUrl, buildEnvironmentUrl, resolveEnvironmentTargets, } from "../shared/environment-lanes.js";
6
6
  import { trackEvent } from "./analytics.js";
7
7
  import { injectedAgentNativeConfig } from "./app-config.js";
8
8
  import { useSession } from "./use-session.js";
9
9
  import { cn } from "./utils.js";
10
- export { BETA_OPT_OUT_DURATION_MS, BETA_OPT_OUT_QUERY_PARAM, BETA_OPT_OUT_STORAGE_KEY, buildEnvironmentOptOutUrl, buildEnvironmentUrl, resolveEnvironmentTargets, } from "../shared/environment-lanes.js";
10
+ 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, } from "../shared/environment-lanes.js";
11
11
  export function isBuilderIoEmployee(email) {
12
12
  return email?.trim().toLowerCase().endsWith("@builder.io") ?? false;
13
13
  }
@@ -50,6 +50,29 @@ function readBetaOptOutUntil(now = Date.now()) {
50
50
  }
51
51
  return null;
52
52
  }
53
+ function rememberForcedProductionSession(sourceHref) {
54
+ let forcedByQuery = false;
55
+ try {
56
+ forcedByQuery =
57
+ new URL(sourceHref).searchParams.get(BETA_FORCE_QUERY_PARAM) === "true";
58
+ }
59
+ catch {
60
+ // coercion-ok: the browser supplied an invalid location.
61
+ }
62
+ if (typeof window === "undefined")
63
+ return forcedByQuery;
64
+ try {
65
+ if (forcedByQuery) {
66
+ window.sessionStorage.setItem(BETA_FORCE_SESSION_STORAGE_KEY, "1");
67
+ }
68
+ return (forcedByQuery ||
69
+ window.sessionStorage.getItem(BETA_FORCE_SESSION_STORAGE_KEY) === "1");
70
+ }
71
+ catch {
72
+ // coercion-ok: session storage is optional; the current URL remains authoritative.
73
+ return forcedByQuery;
74
+ }
75
+ }
53
76
  function consumeBetaOptOutQueryParam(sourceHref, now = Date.now()) {
54
77
  let target;
55
78
  try {
@@ -81,8 +104,11 @@ function EnvironmentLink({ label, href }) {
81
104
  return (_jsx(Button, { asChild: true, className: "w-full justify-center", size: "sm", variant: "outline", children: _jsx("a", { href: href, children: label }) }));
82
105
  }
83
106
  function EnvironmentBadgeContent({ environment, targets, }) {
107
+ const [isHidden, setIsHidden] = useState(false);
84
108
  if (typeof window === "undefined")
85
109
  return null;
110
+ if (isHidden)
111
+ return null;
86
112
  const currentHref = window.location.href;
87
113
  const betaHref = buildEnvironmentUrl(currentHref, targets.betaHost);
88
114
  const productionHref = buildEnvironmentOptOutUrl(currentHref, targets.productionHost);
@@ -94,7 +120,7 @@ function EnvironmentBadgeContent({ environment, targets, }) {
94
120
  : "You're on Agent Native Production";
95
121
  return (_jsxs(Popover, { children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx(Button, { "aria-label": `Open ${title.toLowerCase()} switcher`, className: cn(environmentBadgePlacementClasses, environment === "beta"
96
122
  ? "border-primary/80"
97
- : "border-border/80 bg-background/95 text-foreground"), size: "sm", variant: environment === "beta" ? "default" : "outline", children: label }) }), _jsxs(PopoverContent, { align: "start", className: "w-[280px] p-5", side: "top", sideOffset: 8, children: [_jsx("div", { className: "mb-1 text-sm font-semibold leading-5", children: title }), _jsx("div", { className: "mb-4 text-sm text-muted-foreground", children: "Choose where you want to continue." }), _jsx("div", { className: "grid gap-2", children: environment === "beta" ? (_jsx(EnvironmentLink, { href: productionHref, label: "Switch to production" })) : (_jsx(EnvironmentLink, { href: betaHref, label: "Go to beta" })) })] })] }));
123
+ : "border-border/80 bg-background/95 text-foreground"), size: "sm", variant: environment === "beta" ? "default" : "outline", children: label }) }), _jsxs(PopoverContent, { align: "start", className: "w-[280px] p-5", side: "top", sideOffset: 8, children: [_jsx("div", { className: "mb-1 text-sm font-semibold leading-5", children: title }), _jsx("div", { className: "mb-4 text-sm text-muted-foreground", children: "Choose where you want to continue." }), _jsxs("div", { className: "grid gap-2", children: [environment === "beta" ? (_jsx(EnvironmentLink, { href: productionHref, label: "Switch to production" })) : (_jsx(EnvironmentLink, { href: betaHref, label: "Go to beta" })), _jsx(Button, { className: "mt-2 -mb-2 w-full justify-center text-muted-foreground", onClick: () => setIsHidden(true), size: "sm", type: "button", variant: "ghost", children: "Hide badge" })] })] })] }));
98
124
  }
99
125
  function LocalEnvironmentBadge() {
100
126
  return (_jsx("div", { "aria-label": "Local development environment", className: cn(environmentBadgePlacementClasses, "inline-flex items-center justify-center border border-border/80 bg-background/95 text-foreground"), role: "status", children: "dev" }));
@@ -107,6 +133,10 @@ function ProductionEnvironmentBadge({ targets, }) {
107
133
  isBuilderIoEmployee(session?.email);
108
134
  const didAutoRedirect = useRef(false);
109
135
  useEffect(() => {
136
+ if (typeof window === "undefined")
137
+ return;
138
+ if (rememberForcedProductionSession(window.location.href))
139
+ return;
110
140
  if (!isEligible || didAutoRedirect.current) {
111
141
  return;
112
142
  }
@@ -140,11 +170,16 @@ function ProductionEnvironmentBadge({ targets, }) {
140
170
  * lane for authenticated staff.
141
171
  */
142
172
  export function EnvironmentBadge({ showProduction = true, } = {}) {
173
+ const [hydrated, setHydrated] = useState(false);
143
174
  const config = useMemo(injectedAgentNativeConfig, []);
144
175
  const hostname = typeof window === "undefined" ? undefined : window.location.hostname;
145
176
  const environment = resolveEnvironmentChannel(config, hostname);
146
177
  const targets = resolveEnvironmentTargets(hostname);
147
- if (typeof window === "undefined" ||
178
+ useEffect(() => {
179
+ setHydrated(true);
180
+ }, []);
181
+ if (!hydrated ||
182
+ typeof window === "undefined" ||
148
183
  window.parent !== window ||
149
184
  !environment) {
150
185
  return null;
@@ -71,4 +71,4 @@ export type MultiTabAssistantChatProps = Omit<AssistantChatProps, "tabId" | "thr
71
71
  /** Cadence for hydrating agent-team sub-agent tab status. Default: 3000. */
72
72
  agentTeamPollMs?: number;
73
73
  };
74
- export declare function MultiTabAssistantChat({ showTabBar, renderHeader, renderOverlay, contentHidden, apiUrl, storageKey, restoreActiveThread, browserTabId, threadUrlSync, scope, isolateHistoryByScope, agentTeamPollMs, ...props }: MultiTabAssistantChatProps): React.JSX.Element;
74
+ export declare function MultiTabAssistantChat({ showTabBar, renderHeader, renderOverlay, contentHidden, apiUrl, storageKey, restoreActiveThread, browserTabId, threadUrlSync, scope, isolateHistoryByScope, agentTeamPollMs, availableModels: hostAvailableModels, modelListLoading: hostModelListLoading, onModelChange: hostOnModelChange, ...props }: MultiTabAssistantChatProps): React.JSX.Element;
@@ -17,7 +17,7 @@ import { DEFAULT_LOCALE, useOptionalLocale, useT } from "./i18n.js";
17
17
  import { RunStuckBanner } from "./RunStuckBanner.js";
18
18
  import { callAction } from "./use-action.js";
19
19
  import { useChangeVersion } from "./use-change-version.js";
20
- import { CHAT_MODEL_SELECTION_CHANGED_EVENT } from "./use-chat-models.js";
20
+ import { CHAT_MODEL_SELECTION_CHANGED_EVENT, chatModelSelectionStorageKey, } from "./use-chat-models.js";
21
21
  import { useChatThreads, } from "./use-chat-threads.js";
22
22
  import { usePollLoop } from "./use-poll-loop.js";
23
23
  import { cn } from "./utils.js";
@@ -43,7 +43,6 @@ function deliverPendingSend(ref, send) {
43
43
  ref.sendMessage(send.message, send.images);
44
44
  }
45
45
  }
46
- const MODEL_SELECTION_STORAGE_KEY = "agent-native:chat-models:selection";
47
46
  function readStoredModelSelection(key) {
48
47
  if (typeof window === "undefined")
49
48
  return undefined;
@@ -402,7 +401,7 @@ function runToAgentTeamTabInfo(run) {
402
401
  status: run.status ?? "unknown",
403
402
  };
404
403
  }
405
- export function MultiTabAssistantChat({ showTabBar = true, renderHeader, renderOverlay, contentHidden = false, apiUrl = agentNativePath("/_agent-native/agent-chat"), storageKey, restoreActiveThread = true, browserTabId, threadUrlSync = false, scope = null, isolateHistoryByScope = false, agentTeamPollMs = DEFAULT_AGENT_TEAM_POLL_MS, ...props }) {
404
+ export function MultiTabAssistantChat({ showTabBar = true, renderHeader, renderOverlay, contentHidden = false, apiUrl = agentNativePath("/_agent-native/agent-chat"), storageKey, restoreActiveThread = true, browserTabId, threadUrlSync = false, scope = null, isolateHistoryByScope = false, agentTeamPollMs = DEFAULT_AGENT_TEAM_POLL_MS, availableModels: hostAvailableModels, modelListLoading: hostModelListLoading, onModelChange: hostOnModelChange, ...props }) {
406
405
  const translate = useT();
407
406
  const contextNamespace = scope
408
407
  ? scope.contextKey?.trim() || `scope:${scope.type}:${scope.id}`
@@ -528,7 +527,7 @@ export function MultiTabAssistantChat({ showTabBar = true, renderHeader, renderO
528
527
  }, [switchThreadState, writeThreadUrl]);
529
528
  // Namespace all localStorage keys by storageKey when provided (for per-app isolation in frame)
530
529
  const keyPrefix = storageKey ? `:${storageKey}` : "";
531
- const modelSelectionKey = `${MODEL_SELECTION_STORAGE_KEY}${keyPrefix}`;
530
+ const modelSelectionKey = chatModelSelectionStorageKey(storageKey);
532
531
  // Track which tabs have been focused at least once (lazy mount for sub-agent tabs)
533
532
  const mountedTabsRef = useRef(new Set());
534
533
  const activeThreadIdRef = useRef(activeThreadId);
@@ -557,8 +556,16 @@ export function MultiTabAssistantChat({ showTabBar = true, renderHeader, renderO
557
556
  setPageOverlayScrolled(target.scrollTop > 1);
558
557
  }, [renderOverlay]);
559
558
  // ─── Model state ─────────────────────────────────────────────────────────
560
- const [availableModels, setAvailableModels] = useState([]);
561
- const [modelListLoading, setModelListLoading] = useState(true);
559
+ // A host that supplies its own catalog owns the whole picker: the server
560
+ // catalog must not be discovered or merged, or a host with no engine of its
561
+ // own silently gets this app's models instead.
562
+ const hostManagedModels = hostAvailableModels !== undefined;
563
+ const [discoveredModels, setDiscoveredModels] = useState([]);
564
+ const availableModels = hostAvailableModels ?? discoveredModels;
565
+ const [discoveredModelsLoading, setModelListLoading] = useState(true);
566
+ const modelListLoading = hostManagedModels
567
+ ? (hostModelListLoading ?? false)
568
+ : discoveredModelsLoading;
562
569
  const [defaultModel, setDefaultModel] = useState(DEFAULT_MODEL);
563
570
  const threadModelRef = useRef(new Map());
564
571
  const [persistedModelSelection, setPersistedModelSelection] = useState(() => readStoredModelSelection(modelSelectionKey));
@@ -666,6 +673,14 @@ export function MultiTabAssistantChat({ showTabBar = true, renderHeader, renderO
666
673
  persistModelSelection,
667
674
  props.selectedAgent,
668
675
  ]);
676
+ // A host that owns the model list still needs the internal selection updated:
677
+ // `selectedModel`/`selectedEngine` render from it and submitted turns read it,
678
+ // so routing a pick only to the host snaps the picker back to the previous
679
+ // model and sends that one.
680
+ const handleModelChangeWithHost = useCallback((model, engine) => {
681
+ handleModelChange(model, engine);
682
+ hostOnModelChange?.(model, engine);
683
+ }, [handleModelChange, hostOnModelChange]);
669
684
  const handleEffortChange = useCallback((effort) => {
670
685
  const threadId = activeThreadIdRef.current;
671
686
  if (!threadId)
@@ -689,15 +704,19 @@ export function MultiTabAssistantChat({ showTabBar = true, renderHeader, renderO
689
704
  resolveThreadModelSelection,
690
705
  ]);
691
706
  useEffect(() => {
692
- const preferredAgentModel = props.selectedAgent
693
- ? resolvePreferredAgentModel(props.selectedAgent, availableModels)
694
- : undefined;
695
- if (!preferredAgentModel)
696
- return;
697
707
  const threadId = activeThreadIdRef.current;
698
708
  const current = threadId
699
709
  ? resolveThreadModelSelection(threadId)
700
710
  : persistedModelSelection;
711
+ // Only correct a selection the agent cannot run. This effect re-runs on
712
+ // every selection change, so an unconditional rewrite pins the picker and
713
+ // each later user pick snaps straight back.
714
+ const preferredAgentModel = isClaudeCodeAgentId(props.selectedAgent) &&
715
+ isLunaModel(current?.model ?? "")
716
+ ? resolvePreferredAgentModel(props.selectedAgent, availableModels)
717
+ : undefined;
718
+ if (!preferredAgentModel)
719
+ return;
701
720
  if (current?.model === preferredAgentModel.model &&
702
721
  current.engine === preferredAgentModel.engine) {
703
722
  return;
@@ -721,6 +740,8 @@ export function MultiTabAssistantChat({ showTabBar = true, renderHeader, renderO
721
740
  resolveThreadModelSelection,
722
741
  ]);
723
742
  const refreshEngines = useCallback(() => {
743
+ if (hostManagedModels)
744
+ return;
724
745
  setModelListLoading(true);
725
746
  Promise.all([
726
747
  callAction("manage-agent-engine", { action: "list" }).catch(() => null),
@@ -751,12 +772,12 @@ export function MultiTabAssistantChat({ showTabBar = true, renderHeader, renderO
751
772
  currentEngineName,
752
773
  currentModel,
753
774
  });
754
- setAvailableModels(groups);
775
+ setDiscoveredModels(groups);
755
776
  setDefaultModel(currentModel ?? DEFAULT_MODEL);
756
777
  })
757
778
  .catch(() => { })
758
779
  .finally(() => setModelListLoading(false));
759
- }, []);
780
+ }, [hostManagedModels]);
760
781
  useEffect(() => {
761
782
  refreshEngines();
762
783
  window.addEventListener("agent-engine:configured-changed", refreshEngines);
@@ -1976,7 +1997,7 @@ export function MultiTabAssistantChat({ showTabBar = true, renderHeader, renderO
1976
1997
  ? clearActiveTab
1977
1998
  : undefined, isThreadStateLoading: isLoading, onMessageCountChange: (count) => setMessageCounts((prev) => prev[tabId] === count
1978
1999
  ? prev
1979
- : { ...prev, [tabId]: count }), onSaveThread: handleSaveThread, onGenerateTitle: handleGenerateTitle, onSlashCommand: handleSlashCommand, selectedModel: modelSelection?.model, selectedEngine: modelSelection?.engine, selectedEffort: modelSelection?.effort ?? DEFAULT_REASONING_EFFORT, composerSlot: props.composerSlot, defaultModel: defaultModel, availableModels: availableModels, modelListLoading: modelListLoading, onModelChange: handleModelChange, onEffortChange: handleEffortChange, onForkChat: () => handleForkChat(tabId),
2000
+ : { ...prev, [tabId]: count }), onSaveThread: handleSaveThread, onGenerateTitle: handleGenerateTitle, onSlashCommand: handleSlashCommand, selectedModel: modelSelection?.model, selectedEngine: modelSelection?.engine, selectedEffort: modelSelection?.effort ?? DEFAULT_REASONING_EFFORT, composerSlot: props.composerSlot, defaultModel: defaultModel, availableModels: availableModels, modelListLoading: modelListLoading, onModelChange: handleModelChangeWithHost, onEffortChange: handleEffortChange, onForkChat: () => handleForkChat(tabId),
1980
2001
  // Sub-agent tabs are read-only: sending a new message from the
1981
2002
  // sub-agent tab would start a fresh run on that thread and kill
1982
2003
  // the in-flight team chunk. Disable the composer and show a
@@ -11,7 +11,7 @@ export { buildRepositoryFromCodeAgentTranscript, type BuildRepositoryFromCodeAge
11
11
  export { compareCodeAgentTranscriptEvents, getCodeAgentTranscriptSeq, isCodeAgentRunActive, mergeCodeAgentTranscriptEvents, type CodeAgentRunStateLike, type CodeAgentTranscriptOrderEvent, } from "../../code-agents/transcript-order.js";
12
12
  export { CREDENTIAL_GAP_SIGNAL, isCredentialGapCodeAgentEvent, } from "../../code-agents/transcript-normalizer.js";
13
13
  export { useSendToAgentChat } from "../use-send-to-agent-chat.js";
14
- export { useChatModels, type UseChatModelsResult, type EngineModelGroup, } from "../use-chat-models.js";
14
+ export { chatModelSelectionStorageKey, useChatModels, type UseChatModelsResult, type EngineModelGroup, } from "../use-chat-models.js";
15
15
  export { CodeRequiredDialog, type CodeRequiredDialogProps, } from "../components/CodeRequiredDialog.js";
16
16
  export { ChatFirstAgentActivityPanel, type ChatFirstAgentActivityPanelProps, } from "../chat-first-agent-activity.js";
17
17
  export { ChatFirstSurfacePanelToggle } from "../chat-first-surface-panel-toggle.js";
@@ -11,7 +11,7 @@ export { buildRepositoryFromCodeAgentTranscript, } from "../../agent/thread-data
11
11
  export { compareCodeAgentTranscriptEvents, getCodeAgentTranscriptSeq, isCodeAgentRunActive, mergeCodeAgentTranscriptEvents, } from "../../code-agents/transcript-order.js";
12
12
  export { CREDENTIAL_GAP_SIGNAL, isCredentialGapCodeAgentEvent, } from "../../code-agents/transcript-normalizer.js";
13
13
  export { useSendToAgentChat } from "../use-send-to-agent-chat.js";
14
- export { useChatModels, } from "../use-chat-models.js";
14
+ export { chatModelSelectionStorageKey, useChatModels, } from "../use-chat-models.js";
15
15
  export { CodeRequiredDialog, } from "../components/CodeRequiredDialog.js";
16
16
  export { ChatFirstAgentActivityPanel, } from "../chat-first-agent-activity.js";
17
17
  export { ChatFirstSurfacePanelToggle } from "../chat-first-surface-panel-toggle.js";
@@ -57,7 +57,8 @@ export type ManageJobInput = {
57
57
  };
58
58
  export type ManageAutomationInput = ManageJobInput;
59
59
  export interface RunAutomationNowInput {
60
- name: string;
60
+ name?: string;
61
+ path?: string;
61
62
  scope: "personal" | "organization";
62
63
  }
63
64
  export interface RunAutomationNowResult {
@@ -87,12 +87,10 @@ export function useRunAutomationNow() {
87
87
  return useActionMutation("run-automation-now", {
88
88
  onSuccess: (_result, variables) => {
89
89
  const scope = variables.scope === "organization" ? "organization" : "personal";
90
+ const name = variables.name ??
91
+ variables.path?.replace(/^jobs\//, "").replace(/\.md$/, "");
90
92
  queryClient.invalidateQueries({
91
- queryKey: [
92
- "action",
93
- "list-automation-runs",
94
- { scope, name: variables.name },
95
- ],
93
+ queryKey: ["action", "list-automation-runs", { scope, name }],
96
94
  });
97
95
  queryClient.invalidateQueries({
98
96
  queryKey: ["action", "list-automations", { scope }],
@@ -1,4 +1,4 @@
1
- import { AGENT_SIDEBAR_QUERY_PARAM, AGENT_SIDEBAR_QUERY_VALUE_CLOSED, } from "../shared/agent-sidebar-url.js";
1
+ import { AGENT_SIDEBAR_QUERY_PARAM, AGENT_SIDEBAR_QUERY_VALUE_CLOSED, AGENT_SIDEBAR_QUERY_VALUE_OPEN, } from "../shared/agent-sidebar-url.js";
2
2
  import { hasChatThreadDeepLink } from "./chat-thread-url.js";
3
3
  export { hasChatThreadDeepLink } from "./chat-thread-url.js";
4
4
  export const SIDEBAR_OPEN_KEY = "agent-native-sidebar-open";
@@ -62,6 +62,8 @@ export function getAgentSidebarUrlOpenOverride() {
62
62
  const value = url.searchParams.get(AGENT_SIDEBAR_QUERY_PARAM);
63
63
  if (value === AGENT_SIDEBAR_QUERY_VALUE_CLOSED)
64
64
  return false;
65
+ if (value === AGENT_SIDEBAR_QUERY_VALUE_OPEN)
66
+ return true;
65
67
  }
66
68
  catch { }
67
69
  return null;
@@ -273,4 +273,9 @@ export const codeTabsBlock = defineBlock({
273
273
  label: "Code tabs",
274
274
  icon: IconCode,
275
275
  description: "A vertical file tab rail of syntax-highlighted code snippets, one tab per file with an optional language and caption.",
276
+ // `tabs` has schema min(1), so a fresh insert needs one starter tab — same
277
+ // shape `addTab` mints for a second tab.
278
+ empty: () => ({
279
+ tabs: [{ id: newCodeTabId(), label: "file-1.ts", code: "" }],
280
+ }),
276
281
  });
@@ -131,4 +131,5 @@ export const codeBlock = defineBlock({
131
131
  label: "Code",
132
132
  icon: IconCode,
133
133
  description: "A single syntax-highlighted code snippet, Notion-style: one border, a hover language switcher + copy, and collapse-to-N lines. Put several in a `tabs` block for a file rail.",
134
+ empty: () => ({ code: "" }),
134
135
  });
@@ -115,6 +115,13 @@ export declare function shouldShowMissingFinalResponse({ isCurrentTurnRunning, s
115
115
  hasActiveTool?: boolean;
116
116
  userStoppedRun?: boolean;
117
117
  }): boolean;
118
+ /**
119
+ * "The agent stopped" is derived from local client state, which dips to
120
+ * not-running at every chunk boundary and transport re-attach while the turn is
121
+ * still alive server-side. Requiring the shape to hold for a beat keeps the
122
+ * notice off the screen for those gaps without hiding a real stop for long.
123
+ */
124
+ export declare const MISSING_FINAL_RESPONSE_SETTLE_MS = 3000;
118
125
  export declare function useSettledFlag(active: boolean, delayMs: number): boolean;
119
126
  export declare function shouldShowAssistantWorkSummary({ isLast, isComplete, hasCollapsibleWork, hasUnresolvedTool, hasActiveTool, chatRunning, }: {
120
127
  isLast: boolean;
@@ -728,7 +728,7 @@ export function shouldShowMissingFinalResponse({ isCurrentTurnRunning, serverRun
728
728
  * still alive server-side. Requiring the shape to hold for a beat keeps the
729
729
  * notice off the screen for those gaps without hiding a real stop for long.
730
730
  */
731
- const MISSING_FINAL_RESPONSE_SETTLE_MS = 250;
731
+ export const MISSING_FINAL_RESPONSE_SETTLE_MS = 3_000;
732
732
  export function useSettledFlag(active, delayMs) {
733
733
  const [settled, setSettled] = useState(false);
734
734
  useEffect(() => {
@@ -120,6 +120,9 @@ function isMissingLlmProviderRunError(info) {
120
120
  ((code === "missing_credentials" || code === "missing_api_key") &&
121
121
  !text.trim()));
122
122
  }
123
+ function isDesktopChatRelayRunError(info) {
124
+ return [info.message, info.details].some((value) => typeof value === "string" && /desktop app chat relay failed/i.test(value));
125
+ }
123
126
  // ─── BuilderConnectCta ────────────────────────────────────────────────────────
124
127
  // Renders a single row with left-aligned copy and a right-aligned action.
125
128
  // Click opens the Builder OAuth popup via the shared
@@ -210,7 +213,7 @@ export function RunErrorRecoveryCard({ info, onContinue, onRetry, onFork, onDism
210
213
  });
211
214
  const canRecover = info.recoverable === true;
212
215
  const shouldShowBuilderReconnect = isBuilderReconnectRunError(info);
213
- const shouldShowMissingProviderSetup = isMissingLlmProviderRunError(info);
216
+ const shouldShowProviderSetup = isMissingLlmProviderRunError(info) || isDesktopChatRelayRunError(info);
214
217
  const isProviderAuthError = isProviderAuthenticationError([info.message, info.details].filter(Boolean).join("\n"), info.errorCode);
215
218
  // Blocked on something the reader goes and fixes elsewhere, then comes back
216
219
  // to. Recoverable runs and email verification keep a retry path; rejected
@@ -292,7 +295,7 @@ export function RunErrorRecoveryCard({ info, onContinue, onRetry, onFork, onDism
292
295
  onDismiss();
293
296
  }
294
297
  }, [builderReconnectResolved, onDismiss]);
295
- if (shouldShowMissingProviderSetup) {
298
+ if (shouldShowProviderSetup) {
296
299
  return (_jsxs("div", { className: "w-full", children: [_jsx(BuilderSetupCard, { fullWidth: true, layout: "sidebar", onConnected: handleMissingProviderConnected }), providerConnected ? (_jsx("div", { className: "flex justify-center px-3 pt-1", children: _jsxs("button", { type: "button", onClick: handleMissingProviderRetry, disabled: retryRequested, className: "inline-flex h-8 items-center gap-1.5 rounded-md bg-foreground px-3 text-xs font-medium text-background hover:opacity-90 disabled:cursor-wait disabled:opacity-60", children: [_jsx(IconRefresh, { size: 13 }), t("agentChat.common.retry")] }) })) : null] }));
297
300
  }
298
301
  return (_jsxs("div", { className: "rounded-lg border border-amber-500/25 bg-amber-500/[0.06] p-3 text-sm", children: [_jsxs("div", { className: "flex items-start gap-2", children: [_jsx("span", { className: "mt-0.5 flex h-6 w-6 shrink-0 items-center justify-center rounded-md bg-amber-500/10 text-amber-700 dark:text-amber-300", children: _jsx(IconAlertTriangle, { size: 14 }) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "font-medium text-foreground", children: runErrorHeadline(info, {
@@ -1,6 +1,7 @@
1
1
  import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { IconLoader2, IconAlertTriangle, IconCircleX, IconCheck, IconChevronRight, IconCopy, IconCode, IconBrandSlack, IconTerminal2, IconDatabase, IconSearch, IconFileCode, IconShieldCheck, IconX, } from "@tabler/icons-react";
3
3
  import React, { useState, useEffect, useCallback, useLayoutEffect, useRef, } from "react";
4
+ import { formatAgentChatContextItemsForPrompt } from "../agent-chat.js";
4
5
  import { AgentTaskCard } from "../AgentTaskCard.js";
5
6
  import { writeClipboardText } from "../clipboard.js";
6
7
  import { Popover, PopoverContent, PopoverTrigger, } from "../components/ui/popover.js";
@@ -12,6 +13,7 @@ import { findMcpIntegrationForToolName } from "../resources/mcp-integration-cata
12
13
  import { McpIntegrationLogo } from "../resources/McpIntegrationLogo.js";
13
14
  import { BashCell, EditCell, WriteCell, FilesChangedSummary, } from "../tool-cells/index.js";
14
15
  import { humanizeToolName, isCallAgentToolCallShadowed, isToolCallActive, } from "../tool-display.js";
16
+ import { useAgentChatContext } from "../use-agent-chat-context.js";
15
17
  import { cn } from "../utils.js";
16
18
  import { ActionChatUiSurface } from "./action-chat-ui-surface.js";
17
19
  import { SmoothMarkdownText, HighlightedCodeBlock, } from "./markdown-renderer.js";
@@ -280,6 +282,10 @@ function ApprovalAffordance({ toolName, toolCallId, approval, }) {
280
282
  }
281
283
  // ─── ToolCallDisplay ──────────────────────────────────────────────────────────
282
284
  export function ToolCallDisplay({ toolName, toolCallId, argsText, args, result, mcpApp, chatUI, isRunning, outcome, structuredMeta, activity, approval, repeatCount, isLatestRunning = isRunning, isActiveTail, }) {
285
+ const { items: agentChatContextItems } = useAgentChatContext(toolName === "connect-builder");
286
+ const builderContext = toolName === "connect-builder"
287
+ ? formatAgentChatContextItemsForPrompt(agentChatContextItems)
288
+ : "";
283
289
  const isDelegatedAgentCall = toolName === "call-agent" || toolName.startsWith("agent:");
284
290
  const effectiveIsRunning = isRunning ||
285
291
  (isDelegatedAgentCall &&
@@ -306,9 +312,9 @@ export function ToolCallDisplay({ toolName, toolCallId, argsText, args, result,
306
312
  if (toolKind === "write") {
307
313
  return wrapToolDisplay(_jsx(WriteCell, { meta: structuredMeta, isRunning: effectiveIsRunning }));
308
314
  }
309
- return wrapToolDisplay(_jsx(ToolCallDisplayGeneric, { toolName: toolName, toolCallId: toolCallId, argsText: argsText, args: args, result: result, mcpApp: mcpApp, chatUI: chatUI, isRunning: effectiveIsRunning, outcome: outcome, isActiveTail: showActiveTail, structuredMeta: structuredMeta, approval: approval, repeatCount: repeatCount }));
315
+ return wrapToolDisplay(_jsx(ToolCallDisplayGeneric, { toolName: toolName, toolCallId: toolCallId, argsText: argsText, args: args, result: result, mcpApp: mcpApp, chatUI: chatUI, isRunning: effectiveIsRunning, outcome: outcome, isActiveTail: showActiveTail, structuredMeta: structuredMeta, approval: approval, repeatCount: repeatCount, context: builderContext }));
310
316
  }
311
- function ToolCallDisplayGeneric({ toolName, toolCallId, argsText, args, result, mcpApp, chatUI, isRunning, outcome, isActiveTail, structuredMeta, approval, repeatCount, }) {
317
+ function ToolCallDisplayGeneric({ toolName, toolCallId, argsText, args, result, mcpApp, chatUI, isRunning, outcome, isActiveTail, structuredMeta, approval, repeatCount, context, }) {
312
318
  const t = useT();
313
319
  const suppressInlineOpenApp = React.useContext(SuppressInlineOpenAppContext);
314
320
  const isRawCallAgent = toolName === "call-agent";
@@ -339,7 +345,7 @@ function ToolCallDisplayGeneric({ toolName, toolCallId, argsText, args, result,
339
345
  return (_jsx(ConnectBuilderCard, { configured: !!parsed.configured, builderEnabled: parsed.builderEnabled !== false,
340
346
  // Ignore obsolete direct-auth URLs from older tool results. The
341
347
  // card fetches a fresh app-local connect URL on mount and click.
342
- connectUrl: parsed.connectUrl || "", orgName: parsed.orgName ?? null, prompt: typeof parsed.prompt === "string" ? parsed.prompt : "" }));
348
+ connectUrl: parsed.connectUrl || "", orgName: parsed.orgName ?? null, prompt: typeof parsed.prompt === "string" ? parsed.prompt : "", context: context }));
343
349
  }
344
350
  }
345
351
  catch {