@agent-native/core 0.76.3 → 0.76.5

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 (435) hide show
  1. package/corpus/core/CHANGELOG.md +25 -0
  2. package/corpus/core/package.json +1 -1
  3. package/corpus/core/src/agent/production-agent.ts +147 -56
  4. package/corpus/core/src/agent/run-store.ts +36 -0
  5. package/corpus/core/src/client/AgentPanel.tsx +3 -3
  6. package/corpus/core/src/client/AgentTaskCard.tsx +2 -1
  7. package/corpus/core/src/client/AppearancePicker.tsx +1 -1
  8. package/corpus/core/src/client/AssistantChat.tsx +3 -3
  9. package/corpus/core/src/client/CommandMenu.tsx +4 -4
  10. package/corpus/core/src/client/ErrorBoundary.tsx +1 -1
  11. package/corpus/core/src/client/MultiTabAssistantChat.tsx +11 -11
  12. package/corpus/core/src/client/NewWorkspaceAppFlow.tsx +5 -5
  13. package/corpus/core/src/client/components/ui/dropdown-menu.tsx +9 -9
  14. package/corpus/core/src/client/components/ui/sheet.tsx +1 -1
  15. package/corpus/core/src/client/composer/ComposerPlusMenu.tsx +6 -6
  16. package/corpus/core/src/client/composer/MentionPopover.tsx +4 -4
  17. package/corpus/core/src/client/composer/PastedTextChip.tsx +3 -3
  18. package/corpus/core/src/client/composer/PromptComposer.tsx +3 -3
  19. package/corpus/core/src/client/composer/TiptapComposer.tsx +16 -16
  20. package/corpus/core/src/client/guided-questions.tsx +6 -8
  21. package/corpus/core/src/client/i18n.tsx +2 -2
  22. package/corpus/core/src/client/integrations/IntegrationCard.tsx +2 -2
  23. package/corpus/core/src/client/integrations/IntegrationsPanel.tsx +4 -4
  24. package/corpus/core/src/client/notifications/NotificationsBell.tsx +3 -3
  25. package/corpus/core/src/client/onboarding/OnboardingBanner.tsx +3 -3
  26. package/corpus/core/src/client/onboarding/OnboardingPanel.tsx +17 -10
  27. package/corpus/core/src/client/org/OrgSwitcher.tsx +13 -11
  28. package/corpus/core/src/client/org/TeamPage.tsx +2 -2
  29. package/corpus/core/src/client/settings/AgentsSection.tsx +3 -3
  30. package/corpus/core/src/client/settings/AutomationsSection.tsx +3 -3
  31. package/corpus/core/src/client/settings/SecretsSection.tsx +2 -2
  32. package/corpus/core/src/client/settings/SettingsPanel.tsx +5 -7
  33. package/corpus/core/src/client/settings/SettingsSection.tsx +1 -1
  34. package/corpus/core/src/client/settings/UsageSection.tsx +3 -3
  35. package/corpus/core/src/client/settings/VoiceTranscriptionSection.tsx +3 -3
  36. package/corpus/core/src/client/sharing/ShareButton.tsx +7 -7
  37. package/corpus/core/src/client/sharing/ShareDialog.tsx +3 -3
  38. package/corpus/core/src/deploy/build.ts +31 -14
  39. package/corpus/core/src/styles/agent-conversation.css +10 -10
  40. package/corpus/core/src/styles/blocks.css +2 -2
  41. package/corpus/core/src/styles/rich-markdown-editor.css +2 -2
  42. package/corpus/templates/analytics/app/components/layout/MobileNav.tsx +1 -1
  43. package/corpus/templates/analytics/app/components/ui/alert-dialog.tsx +1 -1
  44. package/corpus/templates/analytics/app/components/ui/alert.tsx +1 -1
  45. package/corpus/templates/analytics/app/components/ui/breadcrumb.tsx +1 -1
  46. package/corpus/templates/analytics/app/components/ui/calendar.tsx +6 -6
  47. package/corpus/templates/analytics/app/components/ui/carousel.tsx +6 -6
  48. package/corpus/templates/analytics/app/components/ui/command.tsx +2 -2
  49. package/corpus/templates/analytics/app/components/ui/context-menu.tsx +9 -9
  50. package/corpus/templates/analytics/app/components/ui/date-picker.tsx +1 -1
  51. package/corpus/templates/analytics/app/components/ui/dialog.tsx +2 -2
  52. package/corpus/templates/analytics/app/components/ui/drawer.tsx +1 -1
  53. package/corpus/templates/analytics/app/components/ui/dropdown-menu.tsx +9 -9
  54. package/corpus/templates/analytics/app/components/ui/input-otp.tsx +1 -1
  55. package/corpus/templates/analytics/app/components/ui/menubar.tsx +9 -9
  56. package/corpus/templates/analytics/app/components/ui/navigation-menu.tsx +3 -3
  57. package/corpus/templates/analytics/app/components/ui/pagination.tsx +4 -4
  58. package/corpus/templates/analytics/app/components/ui/scroll-area.tsx +1 -1
  59. package/corpus/templates/analytics/app/components/ui/select.tsx +3 -3
  60. package/corpus/templates/analytics/app/components/ui/sheet.tsx +2 -2
  61. package/corpus/templates/analytics/app/components/ui/sidebar.tsx +6 -6
  62. package/corpus/templates/analytics/app/components/ui/table.tsx +2 -2
  63. package/corpus/templates/analytics/app/components/ui/toast.tsx +3 -3
  64. package/corpus/templates/assets/app/components/layout/Layout.tsx +2 -2
  65. package/corpus/templates/assets/app/components/layout/Sidebar.tsx +12 -12
  66. package/corpus/templates/assets/app/components/ui/alert-dialog.tsx +1 -1
  67. package/corpus/templates/assets/app/components/ui/alert.tsx +1 -1
  68. package/corpus/templates/assets/app/components/ui/breadcrumb.tsx +1 -1
  69. package/corpus/templates/assets/app/components/ui/dialog.tsx +2 -2
  70. package/corpus/templates/assets/app/components/ui/dropdown-menu.tsx +9 -9
  71. package/corpus/templates/assets/app/components/ui/pagination.tsx +4 -4
  72. package/corpus/templates/assets/app/components/ui/scroll-area.tsx +1 -1
  73. package/corpus/templates/assets/app/components/ui/select.tsx +3 -3
  74. package/corpus/templates/assets/app/components/ui/sheet.tsx +2 -2
  75. package/corpus/templates/assets/app/components/ui/table.tsx +2 -2
  76. package/corpus/templates/assets/app/routes/library.tsx +3 -3
  77. package/corpus/templates/assets/app/routes/settings.tsx +1 -1
  78. package/corpus/templates/brain/app/components/layout/Sidebar.tsx +5 -5
  79. package/corpus/templates/brain/app/components/ui/dropdown-menu.tsx +9 -9
  80. package/corpus/templates/brain/app/components/ui/select.tsx +3 -3
  81. package/corpus/templates/brain/app/components/ui/sheet.tsx +2 -2
  82. package/corpus/templates/brain/app/components/ui/table.tsx +2 -2
  83. package/corpus/templates/calendar/app/components/calendar/GoogleConnectBanner.tsx +6 -6
  84. package/corpus/templates/calendar/app/components/calendar/GoogleSetupWizard.tsx +3 -3
  85. package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +11 -9
  86. package/corpus/templates/calendar/app/components/ui/alert-dialog.tsx +1 -1
  87. package/corpus/templates/calendar/app/components/ui/alert.tsx +1 -1
  88. package/corpus/templates/calendar/app/components/ui/breadcrumb.tsx +1 -1
  89. package/corpus/templates/calendar/app/components/ui/calendar.tsx +5 -5
  90. package/corpus/templates/calendar/app/components/ui/carousel.tsx +6 -6
  91. package/corpus/templates/calendar/app/components/ui/command.tsx +2 -2
  92. package/corpus/templates/calendar/app/components/ui/context-menu.tsx +9 -9
  93. package/corpus/templates/calendar/app/components/ui/dialog.tsx +2 -2
  94. package/corpus/templates/calendar/app/components/ui/drawer.tsx +1 -1
  95. package/corpus/templates/calendar/app/components/ui/dropdown-menu.tsx +9 -9
  96. package/corpus/templates/calendar/app/components/ui/input-otp.tsx +1 -1
  97. package/corpus/templates/calendar/app/components/ui/menubar.tsx +9 -9
  98. package/corpus/templates/calendar/app/components/ui/navigation-menu.tsx +3 -3
  99. package/corpus/templates/calendar/app/components/ui/pagination.tsx +4 -4
  100. package/corpus/templates/calendar/app/components/ui/scroll-area.tsx +1 -1
  101. package/corpus/templates/calendar/app/components/ui/select.tsx +3 -3
  102. package/corpus/templates/calendar/app/components/ui/sheet.tsx +2 -2
  103. package/corpus/templates/calendar/app/components/ui/sidebar.tsx +6 -6
  104. package/corpus/templates/calendar/app/components/ui/sonner.tsx +1 -1
  105. package/corpus/templates/calendar/app/components/ui/table.tsx +2 -2
  106. package/corpus/templates/calendar/app/components/ui/toast.tsx +3 -3
  107. package/corpus/templates/calendar/app/pages/Settings.tsx +5 -5
  108. package/corpus/templates/chat/app/components/layout/Sidebar.tsx +9 -9
  109. package/corpus/templates/chat/app/components/ui/alert-dialog.tsx +1 -1
  110. package/corpus/templates/chat/app/components/ui/alert.tsx +1 -1
  111. package/corpus/templates/chat/app/components/ui/breadcrumb.tsx +1 -1
  112. package/corpus/templates/chat/app/components/ui/calendar.tsx +5 -5
  113. package/corpus/templates/chat/app/components/ui/carousel.tsx +6 -6
  114. package/corpus/templates/chat/app/components/ui/command.tsx +2 -2
  115. package/corpus/templates/chat/app/components/ui/context-menu.tsx +9 -9
  116. package/corpus/templates/chat/app/components/ui/dialog.tsx +2 -2
  117. package/corpus/templates/chat/app/components/ui/drawer.tsx +1 -1
  118. package/corpus/templates/chat/app/components/ui/dropdown-menu.tsx +9 -9
  119. package/corpus/templates/chat/app/components/ui/input-otp.tsx +1 -1
  120. package/corpus/templates/chat/app/components/ui/menubar.tsx +9 -9
  121. package/corpus/templates/chat/app/components/ui/navigation-menu.tsx +3 -3
  122. package/corpus/templates/chat/app/components/ui/pagination.tsx +4 -4
  123. package/corpus/templates/chat/app/components/ui/scroll-area.tsx +1 -1
  124. package/corpus/templates/chat/app/components/ui/select.tsx +3 -3
  125. package/corpus/templates/chat/app/components/ui/sheet.tsx +2 -2
  126. package/corpus/templates/chat/app/components/ui/sidebar.tsx +6 -6
  127. package/corpus/templates/chat/app/components/ui/table.tsx +2 -2
  128. package/corpus/templates/chat/app/components/ui/toast.tsx +3 -3
  129. package/corpus/templates/clips/app/components/capture-install-options.tsx +3 -3
  130. package/corpus/templates/clips/app/components/editable-recording-title.tsx +1 -1
  131. package/corpus/templates/clips/app/components/library/bulk-action-toolbar.tsx +3 -3
  132. package/corpus/templates/clips/app/components/library/folder-tree.tsx +5 -5
  133. package/corpus/templates/clips/app/components/library/library-layout.tsx +3 -3
  134. package/corpus/templates/clips/app/components/library/organization-switcher.tsx +4 -4
  135. package/corpus/templates/clips/app/components/library/recording-card.tsx +11 -11
  136. package/corpus/templates/clips/app/components/library/search-bar.tsx +4 -4
  137. package/corpus/templates/clips/app/components/library/space-card.tsx +1 -1
  138. package/corpus/templates/clips/app/components/library/tag-input.tsx +1 -1
  139. package/corpus/templates/clips/app/components/meetings/quick-ask-sidebar.tsx +2 -2
  140. package/corpus/templates/clips/app/components/recorder/camera-visualizer.tsx +2 -2
  141. package/corpus/templates/clips/app/components/recorder/microphone-visualizer.tsx +1 -1
  142. package/corpus/templates/clips/app/components/recorder/pre-record-panel.tsx +4 -4
  143. package/corpus/templates/clips/app/components/recorder/storage-setup-card.tsx +1 -1
  144. package/corpus/templates/clips/app/components/sharing/share-ui.tsx +2 -2
  145. package/corpus/templates/clips/app/components/ui/alert-dialog.tsx +1 -1
  146. package/corpus/templates/clips/app/components/ui/alert.tsx +1 -1
  147. package/corpus/templates/clips/app/components/ui/breadcrumb.tsx +1 -1
  148. package/corpus/templates/clips/app/components/ui/calendar.tsx +5 -5
  149. package/corpus/templates/clips/app/components/ui/carousel.tsx +6 -6
  150. package/corpus/templates/clips/app/components/ui/command.tsx +2 -2
  151. package/corpus/templates/clips/app/components/ui/context-menu.tsx +9 -9
  152. package/corpus/templates/clips/app/components/ui/dialog.tsx +2 -2
  153. package/corpus/templates/clips/app/components/ui/drawer.tsx +1 -1
  154. package/corpus/templates/clips/app/components/ui/dropdown-menu.tsx +9 -9
  155. package/corpus/templates/clips/app/components/ui/input-otp.tsx +1 -1
  156. package/corpus/templates/clips/app/components/ui/menubar.tsx +9 -9
  157. package/corpus/templates/clips/app/components/ui/navigation-menu.tsx +3 -3
  158. package/corpus/templates/clips/app/components/ui/pagination.tsx +4 -4
  159. package/corpus/templates/clips/app/components/ui/scroll-area.tsx +1 -1
  160. package/corpus/templates/clips/app/components/ui/select.tsx +3 -3
  161. package/corpus/templates/clips/app/components/ui/sheet.tsx +2 -2
  162. package/corpus/templates/clips/app/components/ui/sidebar.tsx +6 -6
  163. package/corpus/templates/clips/app/components/ui/table.tsx +2 -2
  164. package/corpus/templates/clips/app/components/ui/toast.tsx +3 -3
  165. package/corpus/templates/clips/app/components/workspace/branding-editor.tsx +1 -1
  166. package/corpus/templates/clips/app/components/workspace/insights-hub.tsx +2 -2
  167. package/corpus/templates/clips/app/components/workspace/invite-dialog.tsx +2 -2
  168. package/corpus/templates/clips/app/components/workspace/top-creators-table.tsx +6 -6
  169. package/corpus/templates/clips/app/components/workspace/top-videos-table.tsx +2 -2
  170. package/corpus/templates/clips/app/routes/_app.dictate.tsx +4 -4
  171. package/corpus/templates/clips/app/routes/_app.meetings._index.tsx +7 -7
  172. package/corpus/templates/clips/app/routes/_app.settings._index.tsx +1 -1
  173. package/corpus/templates/clips/app/routes/download.tsx +2 -2
  174. package/corpus/templates/clips/app/routes/invite.$token.tsx +2 -2
  175. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +3 -3
  176. package/corpus/templates/clips/app/routes/record.tsx +5 -5
  177. package/corpus/templates/clips/app/routes/share.$shareId.tsx +7 -7
  178. package/corpus/templates/content/app/components/EmptyState.tsx +1 -1
  179. package/corpus/templates/content/app/components/editor/DocumentToolbar.tsx +17 -17
  180. package/corpus/templates/content/app/components/layout/Layout.tsx +2 -2
  181. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +10 -9
  182. package/corpus/templates/content/app/components/sidebar/DocumentTreeItem.tsx +10 -6
  183. package/corpus/templates/content/app/components/sidebar/NotionButton.tsx +3 -3
  184. package/corpus/templates/content/app/components/ui/alert-dialog.tsx +1 -1
  185. package/corpus/templates/content/app/components/ui/dialog.tsx +2 -2
  186. package/corpus/templates/content/app/components/ui/dropdown-menu.tsx +9 -9
  187. package/corpus/templates/content/app/components/ui/scroll-area.tsx +1 -1
  188. package/corpus/templates/content/app/components/ui/sheet.tsx +2 -2
  189. package/corpus/templates/content/app/components/ui/table.tsx +2 -2
  190. package/corpus/templates/content/app/components/ui/toast.tsx +3 -3
  191. package/corpus/templates/design/app/components/layout/Layout.tsx +3 -3
  192. package/corpus/templates/design/app/components/layout/Sidebar.tsx +3 -3
  193. package/corpus/templates/design/app/components/ui/alert-dialog.tsx +1 -1
  194. package/corpus/templates/design/app/components/ui/alert.tsx +1 -1
  195. package/corpus/templates/design/app/components/ui/breadcrumb.tsx +1 -1
  196. package/corpus/templates/design/app/components/ui/calendar.tsx +5 -5
  197. package/corpus/templates/design/app/components/ui/carousel.tsx +6 -6
  198. package/corpus/templates/design/app/components/ui/command.tsx +2 -2
  199. package/corpus/templates/design/app/components/ui/context-menu.tsx +9 -9
  200. package/corpus/templates/design/app/components/ui/dialog.tsx +2 -2
  201. package/corpus/templates/design/app/components/ui/drawer.tsx +1 -1
  202. package/corpus/templates/design/app/components/ui/dropdown-menu.tsx +9 -9
  203. package/corpus/templates/design/app/components/ui/input-otp.tsx +1 -1
  204. package/corpus/templates/design/app/components/ui/menubar.tsx +9 -9
  205. package/corpus/templates/design/app/components/ui/navigation-menu.tsx +3 -3
  206. package/corpus/templates/design/app/components/ui/pagination.tsx +4 -4
  207. package/corpus/templates/design/app/components/ui/scroll-area.tsx +1 -1
  208. package/corpus/templates/design/app/components/ui/select.tsx +3 -3
  209. package/corpus/templates/design/app/components/ui/sheet.tsx +2 -2
  210. package/corpus/templates/design/app/components/ui/sidebar.tsx +6 -6
  211. package/corpus/templates/design/app/components/ui/table.tsx +2 -2
  212. package/corpus/templates/design/app/components/ui/toast.tsx +3 -3
  213. package/corpus/templates/design/app/pages/DesignSystems.tsx +6 -8
  214. package/corpus/templates/design/app/pages/Index.tsx +8 -8
  215. package/corpus/templates/design/app/pages/NotFound.tsx +1 -1
  216. package/corpus/templates/design/app/pages/Templates.tsx +2 -2
  217. package/corpus/templates/forms/app/components/layout/Sidebar.tsx +3 -3
  218. package/corpus/templates/forms/app/components/ui/alert-dialog.tsx +1 -1
  219. package/corpus/templates/forms/app/components/ui/alert.tsx +1 -1
  220. package/corpus/templates/forms/app/components/ui/breadcrumb.tsx +1 -1
  221. package/corpus/templates/forms/app/components/ui/calendar.tsx +9 -6
  222. package/corpus/templates/forms/app/components/ui/carousel.tsx +6 -6
  223. package/corpus/templates/forms/app/components/ui/command.tsx +2 -2
  224. package/corpus/templates/forms/app/components/ui/context-menu.tsx +9 -9
  225. package/corpus/templates/forms/app/components/ui/dialog.tsx +2 -2
  226. package/corpus/templates/forms/app/components/ui/drawer.tsx +1 -1
  227. package/corpus/templates/forms/app/components/ui/dropdown-menu.tsx +9 -9
  228. package/corpus/templates/forms/app/components/ui/input-otp.tsx +1 -1
  229. package/corpus/templates/forms/app/components/ui/menubar.tsx +9 -9
  230. package/corpus/templates/forms/app/components/ui/navigation-menu.tsx +3 -3
  231. package/corpus/templates/forms/app/components/ui/pagination.tsx +4 -4
  232. package/corpus/templates/forms/app/components/ui/scroll-area.tsx +1 -1
  233. package/corpus/templates/forms/app/components/ui/select.tsx +3 -3
  234. package/corpus/templates/forms/app/components/ui/sheet.tsx +2 -2
  235. package/corpus/templates/forms/app/components/ui/sidebar.tsx +6 -6
  236. package/corpus/templates/forms/app/components/ui/table.tsx +2 -2
  237. package/corpus/templates/forms/app/components/ui/toast.tsx +3 -3
  238. package/corpus/templates/forms/app/pages/FormBuilderPage.tsx +18 -18
  239. package/corpus/templates/forms/app/pages/FormsListPage.tsx +9 -9
  240. package/corpus/templates/macros/app/components/layout/AppLayout.tsx +4 -4
  241. package/corpus/templates/macros/app/components/ui/alert-dialog.tsx +1 -1
  242. package/corpus/templates/macros/app/components/ui/alert.tsx +1 -1
  243. package/corpus/templates/macros/app/components/ui/breadcrumb.tsx +1 -1
  244. package/corpus/templates/macros/app/components/ui/command.tsx +2 -2
  245. package/corpus/templates/macros/app/components/ui/context-menu.tsx +9 -9
  246. package/corpus/templates/macros/app/components/ui/dialog.tsx +2 -2
  247. package/corpus/templates/macros/app/components/ui/drawer.tsx +1 -1
  248. package/corpus/templates/macros/app/components/ui/dropdown-menu.tsx +9 -9
  249. package/corpus/templates/macros/app/components/ui/menubar.tsx +9 -9
  250. package/corpus/templates/macros/app/components/ui/navigation-menu.tsx +3 -3
  251. package/corpus/templates/macros/app/components/ui/pagination.tsx +4 -4
  252. package/corpus/templates/macros/app/components/ui/scroll-area.tsx +1 -1
  253. package/corpus/templates/macros/app/components/ui/select.tsx +3 -3
  254. package/corpus/templates/macros/app/components/ui/sheet.tsx +2 -2
  255. package/corpus/templates/macros/app/components/ui/table.tsx +2 -2
  256. package/corpus/templates/macros/app/components/ui/toast.tsx +3 -3
  257. package/corpus/templates/macros/app/routes/_index.tsx +2 -2
  258. package/corpus/templates/macros/app/routes/analytics.tsx +1 -1
  259. package/corpus/templates/mail/app/components/GoogleConnectBanner.tsx +6 -6
  260. package/corpus/templates/mail/app/components/email/AttachmentStrip.tsx +2 -2
  261. package/corpus/templates/mail/app/components/email/EmailListItem.tsx +5 -5
  262. package/corpus/templates/mail/app/components/email/IntegrationsSidebar.tsx +5 -5
  263. package/corpus/templates/mail/app/components/email/MobileActionBar.tsx +3 -3
  264. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +10 -10
  265. package/corpus/templates/mail/app/components/layout/CommandPalette.tsx +1 -1
  266. package/corpus/templates/mail/app/components/layout/SearchBar.tsx +3 -3
  267. package/corpus/templates/mail/app/components/ui/alert-dialog.tsx +1 -1
  268. package/corpus/templates/mail/app/components/ui/alert.tsx +1 -1
  269. package/corpus/templates/mail/app/components/ui/breadcrumb.tsx +1 -1
  270. package/corpus/templates/mail/app/components/ui/calendar.tsx +4 -4
  271. package/corpus/templates/mail/app/components/ui/carousel.tsx +6 -6
  272. package/corpus/templates/mail/app/components/ui/command.tsx +2 -2
  273. package/corpus/templates/mail/app/components/ui/context-menu.tsx +9 -9
  274. package/corpus/templates/mail/app/components/ui/dialog.tsx +2 -2
  275. package/corpus/templates/mail/app/components/ui/drawer.tsx +1 -1
  276. package/corpus/templates/mail/app/components/ui/dropdown-menu.tsx +9 -9
  277. package/corpus/templates/mail/app/components/ui/input-otp.tsx +1 -1
  278. package/corpus/templates/mail/app/components/ui/menubar.tsx +9 -9
  279. package/corpus/templates/mail/app/components/ui/navigation-menu.tsx +3 -3
  280. package/corpus/templates/mail/app/components/ui/pagination.tsx +4 -4
  281. package/corpus/templates/mail/app/components/ui/scroll-area.tsx +1 -1
  282. package/corpus/templates/mail/app/components/ui/select.tsx +3 -3
  283. package/corpus/templates/mail/app/components/ui/sheet.tsx +2 -2
  284. package/corpus/templates/mail/app/components/ui/sidebar.tsx +6 -6
  285. package/corpus/templates/mail/app/components/ui/sonner.tsx +2 -2
  286. package/corpus/templates/mail/app/components/ui/table.tsx +2 -2
  287. package/corpus/templates/mail/app/components/ui/toast.tsx +3 -3
  288. package/corpus/templates/plan/app/components/layout/Sidebar.tsx +10 -10
  289. package/corpus/templates/plan/app/components/ui/alert-dialog.tsx +1 -1
  290. package/corpus/templates/plan/app/components/ui/alert.tsx +1 -1
  291. package/corpus/templates/plan/app/components/ui/breadcrumb.tsx +1 -1
  292. package/corpus/templates/plan/app/components/ui/calendar.tsx +5 -5
  293. package/corpus/templates/plan/app/components/ui/carousel.tsx +6 -6
  294. package/corpus/templates/plan/app/components/ui/command.tsx +2 -2
  295. package/corpus/templates/plan/app/components/ui/context-menu.tsx +9 -9
  296. package/corpus/templates/plan/app/components/ui/dialog.tsx +2 -2
  297. package/corpus/templates/plan/app/components/ui/drawer.tsx +1 -1
  298. package/corpus/templates/plan/app/components/ui/dropdown-menu.tsx +9 -9
  299. package/corpus/templates/plan/app/components/ui/input-otp.tsx +1 -1
  300. package/corpus/templates/plan/app/components/ui/menubar.tsx +9 -9
  301. package/corpus/templates/plan/app/components/ui/navigation-menu.tsx +3 -3
  302. package/corpus/templates/plan/app/components/ui/pagination.tsx +4 -4
  303. package/corpus/templates/plan/app/components/ui/scroll-area.tsx +1 -1
  304. package/corpus/templates/plan/app/components/ui/select.tsx +3 -3
  305. package/corpus/templates/plan/app/components/ui/sheet.tsx +2 -2
  306. package/corpus/templates/plan/app/components/ui/sidebar.tsx +6 -6
  307. package/corpus/templates/plan/app/components/ui/table.tsx +2 -2
  308. package/corpus/templates/plan/app/components/ui/toast.tsx +3 -3
  309. package/corpus/templates/slides/app/components/layout/Layout.tsx +1 -1
  310. package/corpus/templates/slides/app/components/ui/alert-dialog.tsx +1 -1
  311. package/corpus/templates/slides/app/components/ui/alert.tsx +1 -1
  312. package/corpus/templates/slides/app/components/ui/breadcrumb.tsx +1 -1
  313. package/corpus/templates/slides/app/components/ui/calendar.tsx +5 -5
  314. package/corpus/templates/slides/app/components/ui/carousel.tsx +6 -6
  315. package/corpus/templates/slides/app/components/ui/command.tsx +2 -2
  316. package/corpus/templates/slides/app/components/ui/context-menu.tsx +9 -9
  317. package/corpus/templates/slides/app/components/ui/dialog.tsx +2 -2
  318. package/corpus/templates/slides/app/components/ui/drawer.tsx +1 -1
  319. package/corpus/templates/slides/app/components/ui/dropdown-menu.tsx +9 -9
  320. package/corpus/templates/slides/app/components/ui/input-otp.tsx +1 -1
  321. package/corpus/templates/slides/app/components/ui/menubar.tsx +9 -9
  322. package/corpus/templates/slides/app/components/ui/navigation-menu.tsx +3 -3
  323. package/corpus/templates/slides/app/components/ui/pagination.tsx +4 -4
  324. package/corpus/templates/slides/app/components/ui/scroll-area.tsx +1 -1
  325. package/corpus/templates/slides/app/components/ui/select.tsx +3 -3
  326. package/corpus/templates/slides/app/components/ui/sheet.tsx +2 -2
  327. package/corpus/templates/slides/app/components/ui/sidebar.tsx +6 -6
  328. package/corpus/templates/slides/app/components/ui/table.tsx +2 -2
  329. package/corpus/templates/slides/app/components/ui/toast.tsx +3 -3
  330. package/corpus/templates/videos/app/components/ui/alert-dialog.tsx +1 -1
  331. package/corpus/templates/videos/app/components/ui/alert.tsx +1 -1
  332. package/corpus/templates/videos/app/components/ui/breadcrumb.tsx +1 -1
  333. package/corpus/templates/videos/app/components/ui/calendar.tsx +5 -5
  334. package/corpus/templates/videos/app/components/ui/carousel.tsx +6 -6
  335. package/corpus/templates/videos/app/components/ui/command.tsx +2 -2
  336. package/corpus/templates/videos/app/components/ui/context-menu.tsx +9 -9
  337. package/corpus/templates/videos/app/components/ui/dialog.tsx +2 -2
  338. package/corpus/templates/videos/app/components/ui/drawer.tsx +1 -1
  339. package/corpus/templates/videos/app/components/ui/dropdown-menu.tsx +9 -9
  340. package/corpus/templates/videos/app/components/ui/input-otp.tsx +1 -1
  341. package/corpus/templates/videos/app/components/ui/menubar.tsx +9 -9
  342. package/corpus/templates/videos/app/components/ui/navigation-menu.tsx +3 -3
  343. package/corpus/templates/videos/app/components/ui/pagination.tsx +4 -4
  344. package/corpus/templates/videos/app/components/ui/scroll-area.tsx +1 -1
  345. package/corpus/templates/videos/app/components/ui/select.tsx +3 -3
  346. package/corpus/templates/videos/app/components/ui/sheet.tsx +2 -2
  347. package/corpus/templates/videos/app/components/ui/sidebar.tsx +6 -6
  348. package/corpus/templates/videos/app/components/ui/table.tsx +2 -2
  349. package/corpus/templates/videos/app/components/ui/toast.tsx +3 -3
  350. package/dist/agent/production-agent.d.ts +47 -0
  351. package/dist/agent/production-agent.d.ts.map +1 -1
  352. package/dist/agent/production-agent.js +112 -56
  353. package/dist/agent/production-agent.js.map +1 -1
  354. package/dist/agent/run-store.d.ts +21 -0
  355. package/dist/agent/run-store.d.ts.map +1 -1
  356. package/dist/agent/run-store.js +32 -0
  357. package/dist/agent/run-store.js.map +1 -1
  358. package/dist/client/AgentPanel.js +3 -3
  359. package/dist/client/AgentPanel.js.map +1 -1
  360. package/dist/client/AgentTaskCard.d.ts.map +1 -1
  361. package/dist/client/AgentTaskCard.js +1 -1
  362. package/dist/client/AgentTaskCard.js.map +1 -1
  363. package/dist/client/AppearancePicker.js +1 -1
  364. package/dist/client/AppearancePicker.js.map +1 -1
  365. package/dist/client/AssistantChat.js +3 -3
  366. package/dist/client/AssistantChat.js.map +1 -1
  367. package/dist/client/CommandMenu.js +4 -4
  368. package/dist/client/CommandMenu.js.map +1 -1
  369. package/dist/client/ErrorBoundary.js +1 -1
  370. package/dist/client/ErrorBoundary.js.map +1 -1
  371. package/dist/client/MultiTabAssistantChat.js +9 -9
  372. package/dist/client/MultiTabAssistantChat.js.map +1 -1
  373. package/dist/client/NewWorkspaceAppFlow.js +5 -5
  374. package/dist/client/NewWorkspaceAppFlow.js.map +1 -1
  375. package/dist/client/components/ui/dropdown-menu.js +6 -6
  376. package/dist/client/components/ui/dropdown-menu.js.map +1 -1
  377. package/dist/client/components/ui/sheet.js +1 -1
  378. package/dist/client/components/ui/sheet.js.map +1 -1
  379. package/dist/client/composer/ComposerPlusMenu.js +5 -5
  380. package/dist/client/composer/ComposerPlusMenu.js.map +1 -1
  381. package/dist/client/composer/MentionPopover.js +4 -4
  382. package/dist/client/composer/MentionPopover.js.map +1 -1
  383. package/dist/client/composer/PastedTextChip.js +2 -2
  384. package/dist/client/composer/PastedTextChip.js.map +1 -1
  385. package/dist/client/composer/PromptComposer.js +3 -3
  386. package/dist/client/composer/PromptComposer.js.map +1 -1
  387. package/dist/client/composer/TiptapComposer.js +12 -12
  388. package/dist/client/composer/TiptapComposer.js.map +1 -1
  389. package/dist/client/guided-questions.d.ts.map +1 -1
  390. package/dist/client/guided-questions.js +5 -5
  391. package/dist/client/guided-questions.js.map +1 -1
  392. package/dist/client/i18n.js +2 -2
  393. package/dist/client/i18n.js.map +1 -1
  394. package/dist/client/integrations/IntegrationCard.js +1 -1
  395. package/dist/client/integrations/IntegrationCard.js.map +1 -1
  396. package/dist/client/integrations/IntegrationsPanel.js +4 -4
  397. package/dist/client/integrations/IntegrationsPanel.js.map +1 -1
  398. package/dist/client/notifications/NotificationsBell.js +3 -3
  399. package/dist/client/notifications/NotificationsBell.js.map +1 -1
  400. package/dist/client/onboarding/OnboardingBanner.js +3 -3
  401. package/dist/client/onboarding/OnboardingBanner.js.map +1 -1
  402. package/dist/client/onboarding/OnboardingPanel.d.ts.map +1 -1
  403. package/dist/client/onboarding/OnboardingPanel.js +15 -10
  404. package/dist/client/onboarding/OnboardingPanel.js.map +1 -1
  405. package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
  406. package/dist/client/org/OrgSwitcher.js +7 -7
  407. package/dist/client/org/OrgSwitcher.js.map +1 -1
  408. package/dist/client/org/TeamPage.js +2 -2
  409. package/dist/client/org/TeamPage.js.map +1 -1
  410. package/dist/client/settings/AgentsSection.js +3 -3
  411. package/dist/client/settings/AgentsSection.js.map +1 -1
  412. package/dist/client/settings/AutomationsSection.js +2 -2
  413. package/dist/client/settings/AutomationsSection.js.map +1 -1
  414. package/dist/client/settings/SecretsSection.js +2 -2
  415. package/dist/client/settings/SecretsSection.js.map +1 -1
  416. package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
  417. package/dist/client/settings/SettingsPanel.js +4 -4
  418. package/dist/client/settings/SettingsPanel.js.map +1 -1
  419. package/dist/client/settings/SettingsSection.js +1 -1
  420. package/dist/client/settings/SettingsSection.js.map +1 -1
  421. package/dist/client/settings/UsageSection.js +2 -2
  422. package/dist/client/settings/UsageSection.js.map +1 -1
  423. package/dist/client/settings/VoiceTranscriptionSection.js +3 -3
  424. package/dist/client/settings/VoiceTranscriptionSection.js.map +1 -1
  425. package/dist/client/sharing/ShareButton.js +6 -6
  426. package/dist/client/sharing/ShareButton.js.map +1 -1
  427. package/dist/client/sharing/ShareDialog.js +3 -3
  428. package/dist/client/sharing/ShareDialog.js.map +1 -1
  429. package/dist/deploy/build.d.ts.map +1 -1
  430. package/dist/deploy/build.js +31 -14
  431. package/dist/deploy/build.js.map +1 -1
  432. package/dist/styles/agent-conversation.css +10 -10
  433. package/dist/styles/blocks.css +2 -2
  434. package/dist/styles/rich-markdown-editor.css +2 -2
  435. package/package.json +1 -1
@@ -1,5 +1,30 @@
1
1
  # @agent-native/core
2
2
 
3
+ ## 0.76.5
4
+
5
+ ### Patch Changes
6
+
7
+ - ba634f4: Durable background agent runs: add a foreground **circuit-breaker** so a dead
8
+ background worker can no longer break chat. A Netlify async background function
9
+ returns `202` the instant it enqueues the invocation, but the worker may never
10
+ execute — e.g. the generated function wrapper fails to import `./main.mjs` or
11
+ hand off to the Nitro `_process-run` route, so it never reaches
12
+ `claimBackgroundRun` and the run is reaped as "worker never claimed the run".
13
+ After a successful dispatch the foreground now polls briefly for the worker to
14
+ actually claim the run; if it doesn't within the grace window, the turn is
15
+ recovered **inline** (the same safe atomic-claim path used for a fast dispatch
16
+ failure), so a dead worker degrades to a working synchronous turn instead of a
17
+ reaped failure. Also harden the generated background-function wrapper to pass
18
+ Netlify's `context` through to the Nitro handler and wrap the handoff in
19
+ try/catch so a pre-route failure is logged loudly instead of silently swallowed
20
+ behind the async 202.
21
+
22
+ ## 0.76.4
23
+
24
+ ### Patch Changes
25
+
26
+ - 6067f27: Fix right-to-left (`ar-SA`) layout in shared framework chrome. Physical directional CSS in the agent panel, command menu, language picker, shadcn `ui/*` primitives, settings/composer/org/sharing/onboarding panels, and the agent-conversation/blocks/rich-markdown styles is converted to logical utilities (`ms`/`me`, `ps`/`pe`, `start`/`end`, `text-start`/`text-end`, `border-s`/`border-e`), and directional icons are mirrored with `rtl:-scale-x-100`. No change to left-to-right rendering (logical utilities are identical to physical in LTR).
27
+
3
28
  ## 0.76.3
4
29
 
5
30
  ### Patch Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/core",
3
- "version": "0.76.3",
3
+ "version": "0.76.5",
4
4
  "type": "module",
5
5
  "engines": {
6
6
  "node": ">=22"
@@ -109,6 +109,7 @@ import {
109
109
  updateRunHeartbeat,
110
110
  updateRunStatusIfRunning,
111
111
  claimBackgroundRun,
112
+ readBackgroundRunClaim,
112
113
  recordRunDiagnostic,
113
114
  RUN_DIAG_STAGE,
114
115
  } from "./run-store.js";
@@ -149,6 +150,96 @@ registerBuiltinEngines();
149
150
 
150
151
  export { PROVIDER_TO_ENV };
151
152
 
153
+ /**
154
+ * Grace window + poll interval for the foreground circuit-breaker that confirms
155
+ * a background worker actually CLAIMED a 202-dispatched run before recovering
156
+ * inline. The grace is long enough for a cold-start worker to win the claim
157
+ * (~1-2s typical) and short enough to recover quickly within the foreground's
158
+ * ~40s soft-timeout.
159
+ */
160
+ export const BACKGROUND_CLAIM_GRACE_MS = 8_000;
161
+ export const BACKGROUND_CLAIM_POLL_MS = 400;
162
+
163
+ export type BackgroundDispatchOutcome =
164
+ | { action: "stream" }
165
+ | { action: "subscribe" }
166
+ | {
167
+ action: "inline";
168
+ reason: "dispatch-failed" | "worker-never-claimed" | "no-row";
169
+ };
170
+
171
+ /**
172
+ * Decide what the foreground should do after attempting a durable background
173
+ * dispatch. A Netlify async background function returns 202 the instant it
174
+ * ENQUEUES the invocation — that is NOT proof the worker executed. If the
175
+ * generated wrapper fails to import/hand off to the route, the worker never
176
+ * reaches `claimBackgroundRun` and the run is reaped as "worker never claimed".
177
+ *
178
+ * So after a successful dispatch we poll briefly for the worker to CLAIM the run:
179
+ * - claimed within grace → "stream" (subscribe to the worker)
180
+ * - dispatch failed OR no claim → recover inline by atomically claiming the
181
+ * run ourselves: if we win → "inline"; if a (delayed) worker already won
182
+ * it → "subscribe" (never double-run).
183
+ *
184
+ * Pure except for the injected `readClaim`/`claim`/`now`/`sleep` deps, so each
185
+ * branch is unit-testable.
186
+ */
187
+ export async function resolveBackgroundDispatchOutcome(opts: {
188
+ dispatched: boolean;
189
+ backgroundRowInserted: boolean;
190
+ runId: string;
191
+ graceMs: number;
192
+ pollIntervalMs: number;
193
+ readClaim: (
194
+ runId: string,
195
+ ) => Promise<{ dispatchMode: string | null; status: string | null } | null>;
196
+ claim: (runId: string) => Promise<boolean>;
197
+ now?: () => number;
198
+ sleep?: (ms: number) => Promise<void>;
199
+ }): Promise<BackgroundDispatchOutcome> {
200
+ const now = opts.now ?? (() => Date.now());
201
+ const sleep =
202
+ opts.sleep ?? ((ms: number) => new Promise<void>((r) => setTimeout(r, ms)));
203
+
204
+ if (opts.dispatched) {
205
+ const deadline = now() + opts.graceMs;
206
+ for (;;) {
207
+ const claim = await opts.readClaim(opts.runId).catch(() => null);
208
+ if (
209
+ claim &&
210
+ ((claim.dispatchMode && claim.dispatchMode !== "background") ||
211
+ (claim.status && claim.status !== "running"))
212
+ ) {
213
+ return { action: "stream" };
214
+ }
215
+ if (now() >= deadline) break;
216
+ await sleep(opts.pollIntervalMs);
217
+ }
218
+ }
219
+
220
+ // Dispatch fast-failed OR no worker claimed within grace → recover inline.
221
+ if (!opts.backgroundRowInserted) {
222
+ // No row to reconcile (insert failed / non-duplicate) — run a fresh inline
223
+ // turn; `startRun` inserts the row.
224
+ return { action: "inline", reason: "no-row" };
225
+ }
226
+ let claimedInline = false;
227
+ try {
228
+ claimedInline = await opts.claim(opts.runId);
229
+ } catch {
230
+ claimedInline = false;
231
+ }
232
+ if (claimedInline) {
233
+ return {
234
+ action: "inline",
235
+ reason: opts.dispatched ? "worker-never-claimed" : "dispatch-failed",
236
+ };
237
+ }
238
+ // The atomic claim was lost: a (delayed) background worker already owns the
239
+ // run — subscribe to it, never run a second copy.
240
+ return { action: "subscribe" };
241
+ }
242
+
152
243
  const SAFE_BROWSER_TAB_ID_RE = /^[A-Za-z0-9_-]{1,96}$/;
153
244
 
154
245
  function normalizeBrowserTabId(value: unknown): string | undefined {
@@ -4425,7 +4516,33 @@ export function createProductionAgentHandler(
4425
4516
  );
4426
4517
  }
4427
4518
 
4428
- if (dispatched) {
4519
+ // ─── Circuit-breaker: a 202 only ENQUEUES the background invocation ─────
4520
+ // It is NOT proof the worker executed. If the generated background-function
4521
+ // wrapper fails to import `./main.mjs` or hand off to the Nitro
4522
+ // `_process-run` route, the worker never reaches `claimBackgroundRun`: the
4523
+ // row sits at `dispatch_mode='background'` until the reaper errors it
4524
+ // ("worker never claimed the run"). `resolveBackgroundDispatchOutcome`
4525
+ // polls briefly for the claim and decides:
4526
+ // - "stream": a worker claimed the run → subscribe to it.
4527
+ // - "subscribe": a (delayed) worker already owns it → subscribe, NEVER
4528
+ // run a second copy.
4529
+ // - "inline": dispatch failed OR no worker claimed within grace → we
4530
+ // atomically own the run; recover by running it inline so a
4531
+ // dead worker degrades to a working synchronous turn.
4532
+ const backgroundOutcome = await resolveBackgroundDispatchOutcome({
4533
+ dispatched,
4534
+ backgroundRowInserted,
4535
+ runId,
4536
+ graceMs: BACKGROUND_CLAIM_GRACE_MS,
4537
+ pollIntervalMs: BACKGROUND_CLAIM_POLL_MS,
4538
+ readClaim: readBackgroundRunClaim,
4539
+ claim: claimBackgroundRun,
4540
+ });
4541
+
4542
+ if (
4543
+ backgroundOutcome.action === "stream" ||
4544
+ backgroundOutcome.action === "subscribe"
4545
+ ) {
4429
4546
  const stream = subscribeToRun(runId, 0);
4430
4547
  if (stream) {
4431
4548
  setResponseHeader(event, "Content-Type", "text/event-stream");
@@ -4434,65 +4551,39 @@ export function createProductionAgentHandler(
4434
4551
  setResponseHeader(event, "X-Run-Id", runId);
4435
4552
  return stream;
4436
4553
  }
4437
- // Subscription failed even though dispatch landed — surface an error
4438
- // rather than silently running inline (the background worker is already
4439
- // processing this runId, so an inline second run would double-execute).
4554
+ // A background worker owns this run but we cannot subscribe — surface an
4555
+ // error rather than risk a double-run by falling through to inline.
4556
+ await updateRunStatusIfRunning(runId, "errored").catch(() => {});
4440
4557
  setResponseStatus(event, 500);
4441
- return { error: "Failed to subscribe to background run" };
4558
+ return {
4559
+ error:
4560
+ backgroundOutcome.action === "stream"
4561
+ ? "Failed to subscribe to background run"
4562
+ : "Failed to dispatch background run",
4563
+ };
4442
4564
  }
4443
4565
 
4444
- // ─── Dispatch failed degrade to a normal synchronous (inline) run ────
4445
- // `fireInternalDispatch` throws ONLY when the self-POST failed *fast*
4446
- // (rejected the connection, or returned a non-2xx within the ~250ms settle
4447
- // race). The `_process-run` route verifies the HMAC token and validates
4448
- // the body BEFORE it ever reaches the SQL atomic claim, so a fast throw
4449
- // means NO background worker claimed this run — there is nothing to
4450
- // double-execute. Rather than break the chat with "Failed to dispatch
4451
- // background run", we run the turn inline (the same synchronous path the
4452
- // flag-off branch below takes), reusing the already-inserted run row.
4453
- //
4454
- // Safety against a (very improbable) delayed background delivery: claim the
4455
- // run atomically here via `claimBackgroundRun`, which flips the row's
4456
- // dispatch_mode `background → background-processing` in one conditional
4457
- // UPDATE. If a delayed dispatch DID land and a worker already won the
4458
- // claim, our claim returns false and we must NOT run inline (that would
4459
- // double-execute) — fall back to subscribing to the worker's run instead.
4460
- // The SQL atomic claim is the single source of truth for ownership, so at
4461
- // most one of {inline fallback, background worker} ever executes this run.
4462
- if (backgroundRowInserted) {
4463
- let claimedInline = false;
4464
- try {
4465
- claimedInline = await claimBackgroundRun(runId);
4466
- } catch (err) {
4467
- console.error(
4468
- "[agent-chat] inline-fallback claim failed:",
4469
- err instanceof Error ? err.message : err,
4470
- );
4471
- }
4472
- if (!claimedInline) {
4473
- // A background worker already owns this run (a delayed delivery landed
4474
- // after our fast throw). Stream its events instead of running a second
4475
- // copy. If we somehow can't subscribe, surface an error rather than
4476
- // risk a double-run.
4477
- const stream = subscribeToRun(runId, 0);
4478
- if (stream) {
4479
- setResponseHeader(event, "Content-Type", "text/event-stream");
4480
- setResponseHeader(event, "Cache-Control", "no-cache");
4481
- setResponseHeader(event, "Connection", "keep-alive");
4482
- setResponseHeader(event, "X-Run-Id", runId);
4483
- return stream;
4484
- }
4485
- await updateRunStatusIfRunning(runId, "errored").catch(() => {});
4486
- setResponseStatus(event, 500);
4487
- return { error: "Failed to dispatch background run" };
4488
- }
4489
- // We own the run. `startRun` (below) calls `insertRun` again, but its
4490
- // duplicate-PK collision is swallowed (`insertRun(...).catch(() => {})`),
4491
- // so the existing `background-processing` row is reused — no double row.
4566
+ // backgroundOutcome.action === "inline": we atomically own the run (or
4567
+ // there was no row to reconcile), so falling through to the inline
4568
+ // `startRun` path below cannot double-execute. `startRun` calls `insertRun`
4569
+ // again, but its duplicate-PK collision is swallowed, so an existing
4570
+ // `background-processing` row is reused no double row.
4571
+ if (backgroundOutcome.reason === "worker-never-claimed") {
4572
+ // The async 202 landed but no worker claimed within grace — the generated
4573
+ // wrapper never reached the route. Record it so the failure is visible on
4574
+ // the run even though the user still gets a working (inline) turn.
4575
+ console.error(
4576
+ "[agent-chat] background worker did not claim the 202-dispatched run " +
4577
+ "within grace; recovering inline:",
4578
+ runId,
4579
+ );
4580
+ await recordRunDiagnostic(
4581
+ runId,
4582
+ RUN_DIAG_STAGE.foregroundInlineRecovery,
4583
+ "202 dispatched but no worker claimed within the foreground grace window",
4584
+ ).catch(() => {});
4492
4585
  }
4493
- // Fall through to the inline `startRun` path below (the same one the
4494
- // flag-off branch uses). If the row was never inserted, `startRun` inserts
4495
- // it fresh; if it was, the claim above made us the sole owner.
4586
+ // Fall through to the inline `startRun` path below.
4496
4587
  }
4497
4588
 
4498
4589
  const trackedProgressOwner =
@@ -378,6 +378,35 @@ export async function claimBackgroundRun(runId: string): Promise<boolean> {
378
378
  return (rowsAffected ?? 0) > 0;
379
379
  }
380
380
 
381
+ /**
382
+ * Read the claim/lifecycle state of a single run by id — for the foreground
383
+ * circuit-breaker that confirms a background worker actually CLAIMED a run that
384
+ * was dispatched with a Netlify async 202. A 202 only means the invocation was
385
+ * ENQUEUED; if the generated background-function wrapper fails to import/hand off
386
+ * to the route it never reaches `claimBackgroundRun`, leaving the row stuck at
387
+ * `dispatch_mode = 'background'`. `'background-processing'` means a worker won
388
+ * the claim; a terminal `status` means the run already resolved. Returns null if
389
+ * the row is missing.
390
+ */
391
+ export async function readBackgroundRunClaim(
392
+ runId: string,
393
+ ): Promise<{ dispatchMode: string | null; status: string | null } | null> {
394
+ await ensureRunTables();
395
+ const client = getDbExec();
396
+ const { rows } = await client.execute({
397
+ sql: `SELECT dispatch_mode, status FROM agent_runs WHERE id = ? LIMIT 1`,
398
+ args: [runId],
399
+ });
400
+ const row = rows?.[0] as
401
+ | { dispatch_mode?: string | null; status?: string | null }
402
+ | undefined;
403
+ if (!row) return null;
404
+ return {
405
+ dispatchMode: row.dispatch_mode ?? null,
406
+ status: row.status ?? null,
407
+ };
408
+ }
409
+
381
410
  /**
382
411
  * Atomically acquire a run lease for a thread. Succeeds (returns true) only
383
412
  * when no other run for the same thread is currently status='running' with a
@@ -481,6 +510,13 @@ export const RUN_DIAG_STAGE = {
481
510
  workerThrew: "worker_threw",
482
511
  /** The route handler caught an error from the worker invocation. */
483
512
  routeThrew: "route_threw",
513
+ /**
514
+ * The foreground circuit-breaker fired: a Netlify async 202 was returned but
515
+ * no background worker CLAIMED the run within the foreground grace window
516
+ * (the generated function wrapper never reached the route), so the foreground
517
+ * recovered by running the turn inline. The run still completes for the user.
518
+ */
519
+ foregroundInlineRecovery: "foreground_inline_recovery",
484
520
  } as const;
485
521
 
486
522
  export type RunDiagStage = (typeof RUN_DIAG_STAGE)[keyof typeof RUN_DIAG_STAGE];
@@ -1038,7 +1038,7 @@ function AgentPanelInner({
1038
1038
  type="button"
1039
1039
  tabIndex={-1}
1040
1040
  aria-hidden="true"
1041
- className="pointer-events-none absolute right-0 top-full h-px w-px opacity-0"
1041
+ className="pointer-events-none absolute end-0 top-full h-px w-px opacity-0"
1042
1042
  />
1043
1043
  }
1044
1044
  />
@@ -1344,7 +1344,7 @@ function AgentPanelInner({
1344
1344
  : "text-muted-foreground hover:bg-accent hover:text-foreground",
1345
1345
  )}
1346
1346
  >
1347
- <span className="truncate pr-1">{tab.label}</span>
1347
+ <span className="truncate pe-1">{tab.label}</span>
1348
1348
  {tab.status === "running" && (
1349
1349
  <span className="h-1.5 w-1.5 shrink-0 rounded-full bg-muted-foreground/50 animate-pulse" />
1350
1350
  )}
@@ -1458,7 +1458,7 @@ function AgentPanelInner({
1458
1458
  : "text-muted-foreground hover:bg-accent hover:text-foreground",
1459
1459
  )}
1460
1460
  >
1461
- <span className="truncate pr-1">
1461
+ <span className="truncate pe-1">
1462
1462
  {tab.subAgentName || tab.label}
1463
1463
  </span>
1464
1464
  {tab.status === "running" && (
@@ -185,7 +185,7 @@ export function AgentTaskCard({
185
185
  <button
186
186
  type="button"
187
187
  aria-expanded={expanded}
188
- className="flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-muted/45"
188
+ className="flex w-full items-center gap-2 px-3 py-2 text-start transition-colors hover:bg-muted/45"
189
189
  onClick={() => setExpanded(!expanded)}
190
190
  >
191
191
  <span className="inline-flex h-5 shrink-0 items-center gap-1 rounded-md border border-border/60 bg-background/70 px-1.5 text-[10px] font-medium text-muted-foreground">
@@ -212,6 +212,7 @@ export function AgentTaskCard({
212
212
  className={cn(
213
213
  "h-3 w-3 shrink-0 text-muted-foreground/40 transition-transform duration-150",
214
214
  expanded && "rotate-90",
215
+ "rtl:-scale-x-100",
215
216
  )}
216
217
  />
217
218
  </button>
@@ -59,7 +59,7 @@ export function AppearancePicker({
59
59
  style={{ background: preset.swatch }}
60
60
  />
61
61
  {active && (
62
- <span className="pointer-events-none absolute -right-1 -top-1 flex h-4 w-4 items-center justify-center rounded-full border border-border bg-background">
62
+ <span className="pointer-events-none absolute -end-1 -top-1 flex h-4 w-4 items-center justify-center rounded-full border border-border bg-background">
63
63
  <IconCheck
64
64
  className="h-3 w-3 text-foreground"
65
65
  stroke={3}
@@ -392,8 +392,8 @@ function ComposerAttachmentPreviewCard({
392
392
  className={cn(
393
393
  "absolute flex h-6 w-6 items-center justify-center rounded-full border border-border/60 bg-background/95 text-muted-foreground shadow-sm transition hover:text-foreground",
394
394
  isImage
395
- ? "right-1.5 top-1.5 opacity-100 md:opacity-0 md:group-hover:opacity-100"
396
- : "right-1.5 top-1.5",
395
+ ? "end-1.5 top-1.5 opacity-100 md:opacity-0 md:group-hover:opacity-100"
396
+ : "end-1.5 top-1.5",
397
397
  )}
398
398
  aria-label={`Remove ${attachment.name}`}
399
399
  >
@@ -3133,7 +3133,7 @@ const AssistantChatInner = forwardRef<
3133
3133
  content: [{ type: "text", text: suggestion }],
3134
3134
  });
3135
3135
  }}
3136
- className="w-full rounded-lg border border-border px-3 py-2 text-left text-[13px] text-muted-foreground hover:bg-accent hover:text-foreground"
3136
+ className="w-full rounded-lg border border-border px-3 py-2 text-start text-[13px] text-muted-foreground hover:bg-accent hover:text-foreground"
3137
3137
  >
3138
3138
  {suggestion}
3139
3139
  </button>
@@ -179,7 +179,7 @@ function CommandShortcut({ children, className }: CommandShortcutProps) {
179
179
  return (
180
180
  <span
181
181
  className={cn(
182
- "ml-auto text-xs tracking-widest text-muted-foreground",
182
+ "ms-auto text-xs tracking-widest text-muted-foreground",
183
183
  className,
184
184
  )}
185
185
  >
@@ -514,7 +514,7 @@ export function CommandMenu({
514
514
  >
515
515
  {/* Search input */}
516
516
  <div className="flex items-center border-b px-3">
517
- <IconSearch className="mr-2 h-4 w-4 shrink-0 opacity-50" />
517
+ <IconSearch className="me-2 h-4 w-4 shrink-0 opacity-50" />
518
518
  <input
519
519
  ref={inputRef}
520
520
  value={search}
@@ -554,7 +554,7 @@ export function CommandMenu({
554
554
  <span>{changelogLabel}</span>
555
555
  {changelogUnseen && (
556
556
  <span
557
- className="ml-auto h-2 w-2 rounded-full bg-primary"
557
+ className="ms-auto h-2 w-2 rounded-full bg-primary"
558
558
  aria-label="New updates available"
559
559
  />
560
560
  )}
@@ -600,7 +600,7 @@ export function CommandMenu({
600
600
  )}
601
601
  </span>
602
602
  {search.trim() && (
603
- <span className="ml-auto text-xs text-muted-foreground">
603
+ <span className="ms-auto text-xs text-muted-foreground">
604
604
 
605
605
  </span>
606
606
  )}
@@ -132,7 +132,7 @@ function ErrorScreen({ error }: { error: unknown }) {
132
132
  Reload
133
133
  </button>
134
134
  {stack && (
135
- <pre className="mt-6 w-full text-left text-xs overflow-auto p-4 bg-muted rounded">
135
+ <pre className="mt-6 w-full text-start text-xs overflow-auto p-4 bg-muted rounded">
136
136
  <code>{stack}</code>
137
137
  </pre>
138
138
  )}
@@ -196,7 +196,7 @@ function ChatSkeleton({
196
196
  {header ?? (
197
197
  <div className="flex items-center px-1 py-1 border-b border-border shrink-0 gap-0.5">
198
198
  <div className="h-[22px] w-20 rounded-md bg-muted animate-pulse" />
199
- <div className="ml-auto flex gap-0.5">
199
+ <div className="ms-auto flex gap-0.5">
200
200
  <div className="h-[22px] w-[22px] rounded-md bg-muted animate-pulse" />
201
201
  <div className="h-[22px] w-[22px] rounded-md bg-muted animate-pulse" />
202
202
  </div>
@@ -290,7 +290,7 @@ function ScopeBadge({
290
290
  <span className="min-w-0 truncate">{heading}</span>
291
291
  {otherCount > 0 && (
292
292
  <span
293
- className="ml-0.5 shrink-0 rounded-full bg-muted px-1.5 py-px text-[10px] leading-none text-muted-foreground"
293
+ className="ms-0.5 shrink-0 rounded-full bg-muted px-1.5 py-px text-[10px] leading-none text-muted-foreground"
294
294
  aria-label={`${otherCount} other chats for ${objectLabel}`}
295
295
  >
296
296
  +{otherCount}
@@ -373,7 +373,7 @@ function PreviousScopedChatsHint({
373
373
  key={thread.id}
374
374
  type="button"
375
375
  onClick={() => onSelectThread(thread.id)}
376
- className="flex items-baseline justify-between gap-2 rounded-md border border-border px-2.5 py-1.5 text-left hover:bg-accent cursor-pointer"
376
+ className="flex items-baseline justify-between gap-2 rounded-md border border-border px-2.5 py-1.5 text-start hover:bg-accent cursor-pointer"
377
377
  >
378
378
  <span className="truncate text-[12px] text-foreground">
379
379
  {thread.title || thread.preview || "Chat"}
@@ -443,7 +443,7 @@ function renderThreadRow(
443
443
  onClose();
444
444
  }}
445
445
  className={cn(
446
- "w-full px-3 py-2 text-left hover:bg-accent/50 cursor-pointer",
446
+ "w-full px-3 py-2 text-start hover:bg-accent/50 cursor-pointer",
447
447
  isActive && "bg-accent/30",
448
448
  )}
449
449
  >
@@ -568,7 +568,7 @@ function HistoryPopover({
568
568
  return (
569
569
  <Popover open onOpenChange={(open) => !open && onClose()}>
570
570
  <PopoverAnchor asChild>
571
- <span aria-hidden className="absolute right-2 top-0 h-px w-px" />
571
+ <span aria-hidden className="absolute end-2 top-0 h-px w-px" />
572
572
  </PopoverAnchor>
573
573
  <PopoverContent
574
574
  align="end"
@@ -682,7 +682,7 @@ function HelpPopover({ onClose }: { onClose: () => void }) {
682
682
  return (
683
683
  <>
684
684
  <div className="fixed inset-0 z-40" onClick={onClose} />
685
- <div className="absolute right-2 top-0 z-50 w-72 rounded-lg border border-border bg-popover shadow-lg">
685
+ <div className="absolute end-2 top-0 z-50 w-72 rounded-lg border border-border bg-popover shadow-lg">
686
686
  <div className="flex items-center justify-between px-3 py-2 border-b border-border">
687
687
  <span className="text-xs font-medium text-foreground">
688
688
  Available Commands
@@ -2548,9 +2548,9 @@ export function MultiTabAssistantChat({
2548
2548
  <button
2549
2549
  type="button"
2550
2550
  onClick={() => switchThread(tab.id)}
2551
- className="flex items-center gap-1 px-2.5 py-1.5 min-w-0 flex-1 text-left"
2551
+ className="flex items-center gap-1 px-2.5 py-1.5 min-w-0 flex-1 text-start"
2552
2552
  >
2553
- <span className="truncate pr-1">{tab.label}</span>
2553
+ <span className="truncate pe-1">{tab.label}</span>
2554
2554
  {tab.status === "running" && (
2555
2555
  <span className="w-1.5 h-1.5 rounded-full bg-muted-foreground/50 shrink-0 animate-pulse" />
2556
2556
  )}
@@ -2583,7 +2583,7 @@ export function MultiTabAssistantChat({
2583
2583
  })}
2584
2584
  </div>
2585
2585
  <TooltipProvider delayDuration={200}>
2586
- <div className="flex items-center gap-px shrink-0 ml-auto">
2586
+ <div className="flex items-center gap-px shrink-0 ms-auto">
2587
2587
  <Tooltip>
2588
2588
  <TooltipTrigger asChild>
2589
2589
  <button
@@ -2646,9 +2646,9 @@ export function MultiTabAssistantChat({
2646
2646
  <button
2647
2647
  type="button"
2648
2648
  onClick={() => switchThread(tab.id)}
2649
- className="flex items-center gap-1 px-2 py-1 min-w-0 flex-1 text-left"
2649
+ className="flex items-center gap-1 px-2 py-1 min-w-0 flex-1 text-start"
2650
2650
  >
2651
- <span className="truncate pr-1">
2651
+ <span className="truncate pe-1">
2652
2652
  {tab.subAgentName || tab.label}
2653
2653
  </span>
2654
2654
  {tab.status === "running" && (
@@ -344,7 +344,7 @@ export function NewWorkspaceAppFlow({
344
344
  href={branchUrl}
345
345
  target="_blank"
346
346
  rel="noreferrer"
347
- className="ml-2 inline-flex items-center gap-1 font-medium text-foreground underline"
347
+ className="ms-2 inline-flex items-center gap-1 font-medium text-foreground underline"
348
348
  >
349
349
  Open branch <IconArrowUpRight className="h-3 w-3" />
350
350
  </a>
@@ -394,7 +394,7 @@ export function NewWorkspaceAppFlow({
394
394
  type="button"
395
395
  aria-pressed={selected}
396
396
  onClick={() => toggleSecret(secret.id)}
397
- className="flex w-full cursor-pointer items-start gap-3 rounded-md px-3 py-2 text-left focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/30"
397
+ className="flex w-full cursor-pointer items-start gap-3 rounded-md px-3 py-2 text-start focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/30"
398
398
  >
399
399
  <span
400
400
  className={`mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded border transition ${
@@ -421,7 +421,7 @@ export function NewWorkspaceAppFlow({
421
421
  <IconChevronDown className="h-3 w-3 transition-transform group-open/details:rotate-180" />
422
422
  Details
423
423
  </summary>
424
- <div className="mt-1.5 space-y-1 pb-0.5 pl-4">
424
+ <div className="mt-1.5 space-y-1 pb-0.5 ps-4">
425
425
  <div className="truncate">
426
426
  Provider: {secret.provider || "Not specified"}
427
427
  </div>
@@ -470,7 +470,7 @@ export function NewWorkspaceAppFlow({
470
470
  type="button"
471
471
  aria-pressed={selected}
472
472
  onClick={() => toggleResource(resource.id)}
473
- className="flex w-full cursor-pointer items-start gap-3 rounded-md px-3 py-2 text-left focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/30"
473
+ className="flex w-full cursor-pointer items-start gap-3 rounded-md px-3 py-2 text-start focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/30"
474
474
  >
475
475
  <span
476
476
  className={`mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded border transition ${
@@ -498,7 +498,7 @@ export function NewWorkspaceAppFlow({
498
498
  <IconChevronDown className="h-3 w-3 transition-transform group-open/details:rotate-180" />
499
499
  Details
500
500
  </summary>
501
- <div className="mt-1.5 space-y-1 pb-0.5 pl-4">
501
+ <div className="mt-1.5 space-y-1 pb-0.5 ps-4">
502
502
  <div className="truncate">
503
503
  Scope:{" "}
504
504
  {resource.scope === "all"