@agent-native/core 0.92.12 → 0.93.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 (772) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +39 -0
  3. package/corpus/core/docs/content/automation-connectors.mdx +80 -0
  4. package/corpus/core/docs/content/extensions.mdx +8 -0
  5. package/corpus/core/docs/content/locales/ar-SA/extensions.mdx +8 -0
  6. package/corpus/core/docs/content/locales/ar-SA/messaging.mdx +84 -15
  7. package/corpus/core/docs/content/locales/ar-SA/template-clips.mdx +1 -0
  8. package/corpus/core/docs/content/locales/ar-SA/template-design.mdx +1 -0
  9. package/corpus/core/docs/content/locales/de-DE/extensions.mdx +10 -0
  10. package/corpus/core/docs/content/locales/de-DE/messaging.mdx +92 -15
  11. package/corpus/core/docs/content/locales/de-DE/template-clips.mdx +1 -0
  12. package/corpus/core/docs/content/locales/de-DE/template-design.mdx +1 -0
  13. package/corpus/core/docs/content/locales/es-ES/extensions.mdx +10 -0
  14. package/corpus/core/docs/content/locales/es-ES/messaging.mdx +91 -15
  15. package/corpus/core/docs/content/locales/es-ES/template-clips.mdx +1 -0
  16. package/corpus/core/docs/content/locales/es-ES/template-design.mdx +1 -0
  17. package/corpus/core/docs/content/locales/fr-FR/extensions.mdx +10 -0
  18. package/corpus/core/docs/content/locales/fr-FR/messaging.mdx +91 -15
  19. package/corpus/core/docs/content/locales/fr-FR/template-clips.mdx +1 -0
  20. package/corpus/core/docs/content/locales/fr-FR/template-design.mdx +1 -0
  21. package/corpus/core/docs/content/locales/hi-IN/extensions.mdx +8 -0
  22. package/corpus/core/docs/content/locales/hi-IN/messaging.mdx +81 -15
  23. package/corpus/core/docs/content/locales/hi-IN/template-clips.mdx +1 -0
  24. package/corpus/core/docs/content/locales/hi-IN/template-design.mdx +1 -0
  25. package/corpus/core/docs/content/locales/ja-JP/extensions.mdx +9 -0
  26. package/corpus/core/docs/content/locales/ja-JP/messaging.mdx +81 -15
  27. package/corpus/core/docs/content/locales/ja-JP/template-clips.mdx +1 -0
  28. package/corpus/core/docs/content/locales/ja-JP/template-design.mdx +1 -0
  29. package/corpus/core/docs/content/locales/ko-KR/extensions.mdx +8 -0
  30. package/corpus/core/docs/content/locales/ko-KR/messaging.mdx +80 -15
  31. package/corpus/core/docs/content/locales/ko-KR/template-clips.mdx +1 -0
  32. package/corpus/core/docs/content/locales/ko-KR/template-design.mdx +1 -0
  33. package/corpus/core/docs/content/locales/pt-BR/extensions.mdx +9 -0
  34. package/corpus/core/docs/content/locales/pt-BR/messaging.mdx +88 -15
  35. package/corpus/core/docs/content/locales/pt-BR/template-clips.mdx +1 -0
  36. package/corpus/core/docs/content/locales/pt-BR/template-design.mdx +1 -0
  37. package/corpus/core/docs/content/locales/zh-CN/extensions.mdx +6 -0
  38. package/corpus/core/docs/content/locales/zh-CN/messaging.mdx +78 -15
  39. package/corpus/core/docs/content/locales/zh-CN/template-clips.mdx +1 -0
  40. package/corpus/core/docs/content/locales/zh-CN/template-design.mdx +1 -0
  41. package/corpus/core/docs/content/locales/zh-TW/extensions.mdx +6 -0
  42. package/corpus/core/docs/content/locales/zh-TW/messaging.mdx +78 -15
  43. package/corpus/core/docs/content/locales/zh-TW/template-clips.mdx +1 -0
  44. package/corpus/core/docs/content/locales/zh-TW/template-design.mdx +1 -0
  45. package/corpus/core/docs/content/messaging.mdx +227 -45
  46. package/corpus/core/docs/content/template-clips.mdx +3 -0
  47. package/corpus/core/docs/content/template-design.mdx +4 -0
  48. package/corpus/core/package.json +5 -1
  49. package/corpus/core/src/a2a/artifact-response.ts +131 -2
  50. package/corpus/core/src/a2a/client.ts +10 -0
  51. package/corpus/core/src/a2a/handlers.ts +40 -76
  52. package/corpus/core/src/a2a/types.ts +2 -0
  53. package/corpus/core/src/agent/durable-background.ts +24 -0
  54. package/corpus/core/src/agent/production-agent.ts +15 -3
  55. package/corpus/core/src/agent/run-manager.ts +130 -10
  56. package/corpus/core/src/agent/run-store.ts +225 -15
  57. package/corpus/core/src/agent/types.ts +23 -0
  58. package/corpus/core/src/audit/record.ts +31 -0
  59. package/corpus/core/src/audit/store.ts +69 -3
  60. package/corpus/core/src/audit/types.ts +13 -0
  61. package/corpus/core/src/automation/index.ts +802 -0
  62. package/corpus/core/src/cli/create.ts +12 -5
  63. package/corpus/core/src/cli/design-connect.ts +596 -36
  64. package/corpus/core/src/client/AgentPanel.tsx +51 -6
  65. package/corpus/core/src/client/AssistantChat.tsx +274 -147
  66. package/corpus/core/src/client/MultiTabAssistantChat.tsx +3 -0
  67. package/corpus/core/src/client/RunStuckBanner.tsx +69 -20
  68. package/corpus/core/src/client/agent-chat-adapter.ts +54 -5
  69. package/corpus/core/src/client/automation.ts +22 -0
  70. package/corpus/core/src/client/chat/run-recovery.tsx +67 -50
  71. package/corpus/core/src/client/composer/TiptapComposer.tsx +8 -0
  72. package/corpus/core/src/client/index.ts +30 -0
  73. package/corpus/core/src/client/integrations/api.ts +295 -0
  74. package/corpus/core/src/client/integrations/index.ts +26 -0
  75. package/corpus/core/src/client/transcription/use-live-transcription.ts +68 -5
  76. package/corpus/core/src/client/use-run-stuck-detection.ts +41 -3
  77. package/corpus/core/src/deploy/build.ts +59 -3
  78. package/corpus/core/src/deploy/workspace-deploy.ts +37 -2
  79. package/corpus/core/src/file-upload/types.ts +2 -0
  80. package/corpus/core/src/index.ts +37 -0
  81. package/corpus/core/src/integrations/a2a-continuations-store.ts +6 -4
  82. package/corpus/core/src/integrations/adapters/discord.ts +362 -0
  83. package/corpus/core/src/integrations/adapters/index.ts +29 -0
  84. package/corpus/core/src/integrations/adapters/microsoft-teams.ts +411 -0
  85. package/corpus/core/src/integrations/adapters/slack.ts +861 -27
  86. package/corpus/core/src/integrations/adapters/telegram.ts +54 -15
  87. package/corpus/core/src/integrations/adapters/whatsapp.ts +41 -17
  88. package/corpus/core/src/integrations/catalog.ts +571 -0
  89. package/corpus/core/src/integrations/controls-store.ts +187 -0
  90. package/corpus/core/src/integrations/index.ts +100 -0
  91. package/corpus/core/src/integrations/installations-store.ts +677 -0
  92. package/corpus/core/src/integrations/integration-memory.ts +187 -0
  93. package/corpus/core/src/integrations/pending-tasks-retry-job.ts +6 -6
  94. package/corpus/core/src/integrations/pending-tasks-store.ts +83 -5
  95. package/corpus/core/src/integrations/plugin.ts +685 -47
  96. package/corpus/core/src/integrations/scope-store.ts +498 -0
  97. package/corpus/core/src/integrations/slack-manifest.ts +78 -0
  98. package/corpus/core/src/integrations/slack-oauth.ts +343 -0
  99. package/corpus/core/src/integrations/types.ts +179 -0
  100. package/corpus/core/src/integrations/usage-budget-store.ts +906 -0
  101. package/corpus/core/src/integrations/webhook-handler.ts +562 -51
  102. package/corpus/core/src/jobs/scheduler.ts +100 -2
  103. package/corpus/core/src/jobs/tools.ts +45 -9
  104. package/corpus/core/src/provider-api/index.ts +72 -1
  105. package/corpus/core/src/resources/handlers.ts +88 -14
  106. package/corpus/core/src/resources/script-helpers.ts +36 -7
  107. package/corpus/core/src/resources/store.ts +59 -52
  108. package/corpus/core/src/scripts/call-agent.ts +107 -1
  109. package/corpus/core/src/server/agent-chat-plugin.ts +294 -119
  110. package/corpus/core/src/server/auth.ts +10 -14
  111. package/corpus/core/src/server/builder-design-systems.ts +16 -1
  112. package/corpus/core/src/server/edge.ts +18 -0
  113. package/corpus/core/src/server/index.ts +26 -0
  114. package/corpus/core/src/server/request-context.ts +18 -0
  115. package/corpus/core/src/server/social-og-image.ts +3 -2
  116. package/corpus/core/src/styles/agent-native.css +62 -44
  117. package/corpus/core/src/templates/default/.agents/skills/capture-learnings/SKILL.md +22 -9
  118. package/corpus/core/src/templates/default/AGENTS.md +7 -3
  119. package/corpus/core/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +1 -1
  120. package/corpus/core/src/templates/workspace-core/.agents/skills/capture-learnings/SKILL.md +22 -9
  121. package/corpus/core/src/templates/workspace-core/.agents/skills/extension-points/SKILL.md +6 -3
  122. package/corpus/core/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +25 -0
  123. package/corpus/core/src/templates/workspace-core/.agents/skills/integration-webhooks/SKILL.md +15 -0
  124. package/corpus/core/src/templates/workspace-core/AGENTS.md +3 -2
  125. package/corpus/core/src/usage/store.ts +37 -2
  126. package/corpus/templates/analytics/.agents/skills/capture-learnings/SKILL.md +22 -9
  127. package/corpus/templates/analytics/.agents/skills/provider-api/SKILL.md +23 -0
  128. package/corpus/templates/analytics/.builder/skills/provider-api/SKILL.md +15 -0
  129. package/corpus/templates/analytics/actions/save-monitor.ts +25 -2
  130. package/corpus/templates/analytics/app/lib/data-sources.ts +28 -0
  131. package/corpus/templates/analytics/changelog/2026-07-10-agent-created-uptime-monitors-now-return-a-direct-link-to-th.md +6 -0
  132. package/corpus/templates/analytics/changelog/2026-07-10-dashboard-email-reports-still-arrive-when-screenshot-capture-temporarily-fails.md +6 -0
  133. package/corpus/templates/analytics/server/jobs/dashboard-report.ts +3 -7
  134. package/corpus/templates/analytics/server/lib/credential-keys.ts +12 -0
  135. package/corpus/templates/analytics/server/lib/dashboard-report.ts +5 -1
  136. package/corpus/templates/analytics/server/lib/provider-credentials.ts +2 -0
  137. package/corpus/templates/analytics/server/routes/api/test-connection.post.ts +16 -0
  138. package/corpus/templates/assets/.agents/skills/capture-learnings/SKILL.md +22 -9
  139. package/corpus/templates/brain/.agents/skills/capture-learnings/SKILL.md +22 -9
  140. package/corpus/templates/calendar/.agents/skills/capture-learnings/SKILL.md +22 -9
  141. package/corpus/templates/calendar/app/components/calendar/CommandPalette.tsx +98 -108
  142. package/corpus/templates/calendar/app/components/calendar/EventAttendeesSection.tsx +97 -90
  143. package/corpus/templates/calendar/changelog/2026-07-10-event-guest-details-and-option-menus-now-use-valid-accessibl.md +6 -0
  144. package/corpus/templates/calendar/changelog/2026-07-10-natural-language-event-phrases-stay-available-as-quick-creat.md +6 -0
  145. package/corpus/templates/chat/.agents/skills/capture-learnings/SKILL.md +22 -9
  146. package/corpus/templates/chat/changelog/2026-07-10-chat-now-makes-ai-connection-setup-clear-without-shifting-th.md +6 -0
  147. package/corpus/templates/clips/.agents/skills/capture-learnings/SKILL.md +22 -9
  148. package/corpus/templates/clips/.agents/skills/recording/SKILL.md +17 -1
  149. package/corpus/templates/clips/.agents/skills/video-sharing/SKILL.md +8 -0
  150. package/corpus/templates/clips/AGENTS.md +8 -3
  151. package/corpus/templates/clips/actions/finalize-recording.ts +63 -23
  152. package/corpus/templates/clips/actions/get-recording-player-data.ts +6 -2
  153. package/corpus/templates/clips/actions/lib/ensure-seekable-video.ts +72 -9
  154. package/corpus/templates/clips/actions/list-recordings.ts +19 -3
  155. package/corpus/templates/clips/actions/navigate.ts +2 -0
  156. package/corpus/templates/clips/actions/reprocess-recording.ts +20 -6
  157. package/corpus/templates/clips/actions/request-transcript.ts +16 -31
  158. package/corpus/templates/clips/actions/view-screen.ts +57 -5
  159. package/corpus/templates/clips/app/components/layout/Header.tsx +1 -0
  160. package/corpus/templates/clips/app/components/library/empty-state.tsx +2 -0
  161. package/corpus/templates/clips/app/components/library/library-grid.tsx +69 -42
  162. package/corpus/templates/clips/app/components/library/library-layout.tsx +15 -1
  163. package/corpus/templates/clips/app/components/library/recording-card.tsx +81 -68
  164. package/corpus/templates/clips/app/components/library/search-bar.tsx +4 -3
  165. package/corpus/templates/clips/app/components/player/delete-recording-menu.tsx +9 -3
  166. package/corpus/templates/clips/app/components/player/share-dialog.tsx +1 -1
  167. package/corpus/templates/clips/app/hooks/use-library.ts +1 -1
  168. package/corpus/templates/clips/app/hooks/use-navigation-state.ts +10 -2
  169. package/corpus/templates/clips/app/i18n/ar-SA.ts +7 -1
  170. package/corpus/templates/clips/app/i18n/de-DE.ts +7 -1
  171. package/corpus/templates/clips/app/i18n/en-US.ts +7 -1
  172. package/corpus/templates/clips/app/i18n/es-ES.ts +7 -1
  173. package/corpus/templates/clips/app/i18n/fr-FR.ts +7 -1
  174. package/corpus/templates/clips/app/i18n/hi-IN.ts +7 -1
  175. package/corpus/templates/clips/app/i18n/ja-JP.ts +7 -1
  176. package/corpus/templates/clips/app/i18n/ko-KR.ts +7 -1
  177. package/corpus/templates/clips/app/i18n/pt-BR.ts +7 -1
  178. package/corpus/templates/clips/app/i18n/zh-CN.ts +8 -1
  179. package/corpus/templates/clips/app/i18n/zh-TW.ts +8 -1
  180. package/corpus/templates/clips/app/lib/recording-visibility.ts +70 -0
  181. package/corpus/templates/clips/app/routes/_app.shared.tsx +20 -0
  182. package/corpus/templates/clips/app/routes/download.tsx +24 -8
  183. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +115 -2
  184. package/corpus/templates/clips/app/routes/record.tsx +62 -0
  185. package/corpus/templates/clips/app/routes/share.$shareId.tsx +25 -16
  186. package/corpus/templates/clips/changelog/2026-07-10-clips-desktop-is-now-available-for-linux-with-appimage-debia.md +6 -0
  187. package/corpus/templates/clips/changelog/2026-07-10-clips-downloads-updates-sooner-in-the-background-and-offers-.md +6 -0
  188. package/corpus/templates/clips/changelog/2026-07-10-clips-shared-with-you-now-appear-in-a-searchable-shared-with.md +6 -0
  189. package/corpus/templates/clips/changelog/2026-07-10-clips-with-missing-mobile-video-frames-can-be-repaired-witho.md +6 -0
  190. package/corpus/templates/clips/changelog/2026-07-10-mobile-camera-recordings-pause-while-backgrounded.md +6 -0
  191. package/corpus/templates/clips/changelog/2026-07-10-mp4-downloads-now-show-progress-immediately-after-the-option.md +6 -0
  192. package/corpus/templates/clips/changelog/2026-07-10-recording-pages-now-open-as-soon-as-you-stop-with-a-share-li.md +6 -0
  193. package/corpus/templates/clips/changelog/2026-07-10-recordings-now-seek-smoothly-downloads-use-the-correct-file-.md +6 -0
  194. package/corpus/templates/clips/changelog/2026-07-10-s3-compatible-storage-now-saves-hosted-recordings-without-re.md +6 -0
  195. package/corpus/templates/clips/desktop/README.md +22 -6
  196. package/corpus/templates/clips/desktop/package.json +1 -1
  197. package/corpus/templates/clips/desktop/src/app.tsx +32 -19
  198. package/corpus/templates/clips/desktop/src/components/ReadinessPanel.tsx +15 -9
  199. package/corpus/templates/clips/desktop/src/lib/finalization-guard.ts +22 -0
  200. package/corpus/templates/clips/desktop/src/lib/permissions.ts +3 -1
  201. package/corpus/templates/clips/desktop/src/lib/recorder.ts +97 -120
  202. package/corpus/templates/clips/desktop/src/lib/updater.ts +26 -4
  203. package/corpus/templates/clips/desktop/src/overlays/finalizing.tsx +4 -8
  204. package/corpus/templates/clips/desktop/src-tauri/Cargo.toml +1 -1
  205. package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +2 -2
  206. package/corpus/templates/clips/desktop/src-tauri/src/permission_status.rs +11 -7
  207. package/corpus/templates/clips/desktop/src-tauri/tauri.linux.conf.json +11 -0
  208. package/corpus/templates/clips/netlify.toml +3 -0
  209. package/corpus/templates/clips/server/lib/post-finalize-dispatch.ts +106 -0
  210. package/corpus/templates/clips/server/lib/public-agent-context.ts +9 -1
  211. package/corpus/templates/clips/server/lib/resumable-upload-provider.ts +52 -0
  212. package/corpus/templates/clips/server/lib/s3-upload-provider.ts +433 -85
  213. package/corpus/templates/clips/server/lib/video-remux.ts +114 -0
  214. package/corpus/templates/clips/server/routes/api/_agent-native-background/post-finalize-worker.post.ts +109 -0
  215. package/corpus/templates/clips/server/routes/api/clips-updater.json.get.ts +22 -11
  216. package/corpus/templates/clips/server/routes/api/public-recording.get.ts +4 -2
  217. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/abort.post.ts +47 -5
  218. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +10 -2
  219. package/corpus/templates/clips/shared/share-loader-response.ts +12 -0
  220. package/corpus/templates/clips/shared/transcript-status.ts +40 -0
  221. package/corpus/templates/content/.agents/skills/capture-learnings/SKILL.md +22 -9
  222. package/corpus/templates/content/.agents/skills/content/SKILL.md +57 -5
  223. package/corpus/templates/content/AGENTS.md +65 -55
  224. package/corpus/templates/content/actions/_builder-cms-read-client.ts +10 -16
  225. package/corpus/templates/content/actions/_database-source-utils.ts +58 -11
  226. package/corpus/templates/content/actions/_property-utils.ts +30 -2
  227. package/corpus/templates/content/actions/add-content-database-source-field-property.ts +312 -114
  228. package/corpus/templates/content/actions/submit-content-database-form.ts +497 -0
  229. package/corpus/templates/content/actions/update-content-database-view.ts +8 -1
  230. package/corpus/templates/content/actions/view-screen.ts +4 -1
  231. package/corpus/templates/content/agent-native.app-skill.json +1 -1
  232. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +250 -64
  233. package/corpus/templates/content/app/components/editor/database/FormView.tsx +460 -0
  234. package/corpus/templates/content/app/components/editor/database/navigation-state.ts +3 -0
  235. package/corpus/templates/content/app/components/editor/database/settings.tsx +30 -37
  236. package/corpus/templates/content/app/components/editor/database/shared.tsx +2 -0
  237. package/corpus/templates/content/app/components/editor/database/view-config.ts +29 -1
  238. package/corpus/templates/content/app/components/ui/textarea.tsx +1 -0
  239. package/corpus/templates/content/app/hooks/use-content-database.ts +22 -0
  240. package/corpus/templates/content/app/i18n/zh-TW.ts +21 -0
  241. package/corpus/templates/content/app/i18n-data.ts +225 -0
  242. package/corpus/templates/content/changelog/2026-07-10-builder-backed-properties-now-load-current-source-values-as-.md +6 -0
  243. package/corpus/templates/content/changelog/2026-07-10-builder-database-refreshes-now-stay-explicit-and-accurate.md +6 -0
  244. package/corpus/templates/content/changelog/2026-07-10-database-form-views-now-collect-ordered-required-answers-and.md +6 -0
  245. package/corpus/templates/content/changelog/2026-07-10-database-tables-now-use-a-quieter-more-compact-layout-with-c.md +6 -0
  246. package/corpus/templates/content/changelog/2026-07-10-slack-intake-routes-to-content-database-forms.md +6 -0
  247. package/corpus/templates/content/parity/matrix.md +1 -0
  248. package/corpus/templates/content/parity/matrix.ts +18 -0
  249. package/corpus/templates/content/shared/api.ts +27 -1
  250. package/corpus/templates/content/shared/database-form.ts +53 -0
  251. package/corpus/templates/design/.agents/skills/capture-learnings/SKILL.md +22 -9
  252. package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +26 -0
  253. package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +85 -12
  254. package/corpus/templates/design/AGENTS.md +72 -18
  255. package/corpus/templates/design/DESIGN.md +1 -1
  256. package/corpus/templates/design/DEVELOPING.md +1 -1
  257. package/corpus/templates/design/FIGMA_INTEROPERABILITY.md +116 -0
  258. package/corpus/templates/design/actions/create-design-from-template.ts +220 -0
  259. package/corpus/templates/design/actions/create-design-system.ts +92 -16
  260. package/corpus/templates/design/actions/delete-design-template.ts +28 -0
  261. package/corpus/templates/design/actions/delete-file.ts +7 -0
  262. package/corpus/templates/design/actions/edit-design.ts +3 -0
  263. package/corpus/templates/design/actions/export-design-as-figma-svg.ts +137 -5
  264. package/corpus/templates/design/actions/export-pdf.ts +1 -1
  265. package/corpus/templates/design/actions/generate-design.ts +3 -0
  266. package/corpus/templates/design/actions/get-design-snapshot.ts +9 -0
  267. package/corpus/templates/design/actions/get-figma-connection-status.ts +26 -0
  268. package/corpus/templates/design/actions/get-figma-design-context.ts +138 -0
  269. package/corpus/templates/design/actions/get-figma-styles.ts +2 -2
  270. package/corpus/templates/design/actions/import-figma-clipboard.ts +112 -16
  271. package/corpus/templates/design/actions/import-figma-frame.ts +15 -4
  272. package/corpus/templates/design/actions/index-design-system-with-builder.ts +4 -0
  273. package/corpus/templates/design/actions/list-design-templates.ts +118 -0
  274. package/corpus/templates/design/actions/navigate.ts +16 -2
  275. package/corpus/templates/design/actions/provider-api-request.ts +11 -1
  276. package/corpus/templates/design/actions/save-design-as-template.ts +156 -0
  277. package/corpus/templates/design/actions/set-active-breakpoint.ts +13 -4
  278. package/corpus/templates/design/actions/take-design-screenshot.ts +73 -3
  279. package/corpus/templates/design/actions/update-file.ts +39 -22
  280. package/corpus/templates/design/actions/view-screen.ts +36 -1
  281. package/corpus/templates/design/actions/write-local-file.ts +50 -38
  282. package/corpus/templates/design/app/components/design/AutoLayoutSuggestionDialog.tsx +151 -0
  283. package/corpus/templates/design/app/components/design/CanvasContextMenu.tsx +20 -0
  284. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +251 -22
  285. package/corpus/templates/design/app/components/design/DesignEditorSkeleton.tsx +3 -3
  286. package/corpus/templates/design/app/components/design/DesignImportPanel.tsx +384 -9
  287. package/corpus/templates/design/app/components/design/EditPanel.tsx +105 -32
  288. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +58 -28
  289. package/corpus/templates/design/app/components/design/TweaksPanel.tsx +6 -0
  290. package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +539 -53
  291. package/corpus/templates/design/app/components/design/bridge/embedded-wheel.bridge.ts +40 -0
  292. package/corpus/templates/design/app/components/design/code-workbench/CodeWorkbench.tsx +1 -0
  293. package/corpus/templates/design/app/components/design/code-workbench/explorer/ExplorerView.tsx +1 -0
  294. package/corpus/templates/design/app/components/design/code-workbench/explorer/FileTree.tsx +5 -1
  295. package/corpus/templates/design/app/components/design/code-workbench/workspace/create-providers.ts +2 -0
  296. package/corpus/templates/design/app/components/design/code-workbench/workspace/localhost-provider.ts +3 -1
  297. package/corpus/templates/design/app/components/design/code-workbench/workspace/types.ts +2 -0
  298. package/corpus/templates/design/app/components/design/edit-panel/element-identity.ts +19 -0
  299. package/corpus/templates/design/app/components/design/edit-panel/frame-presets-panel.tsx +1 -0
  300. package/corpus/templates/design/app/components/design/edit-panel/interaction-state-helpers.ts +27 -0
  301. package/corpus/templates/design/app/components/design/inspector/InteractionStatePanel.tsx +137 -81
  302. package/corpus/templates/design/app/components/design/inspector/frame-size-presets.ts +25 -5
  303. package/corpus/templates/design/app/components/design/multi-screen/chrome-transitions.ts +1 -1
  304. package/corpus/templates/design/app/components/design/multi-screen/frame-geometry.ts +220 -3
  305. package/corpus/templates/design/app/components/design/multi-screen/overview-layout.ts +13 -0
  306. package/corpus/templates/design/app/components/design/multi-screen/types.ts +22 -1
  307. package/corpus/templates/design/app/components/design/types.ts +4 -0
  308. package/corpus/templates/design/app/components/design-system/ProductionDesignSystemShowcase.tsx +208 -0
  309. package/corpus/templates/design/app/components/editor/FigmaLinkComposerBubble.tsx +321 -0
  310. package/corpus/templates/design/app/components/editor/PromptDialog.tsx +24 -4
  311. package/corpus/templates/design/app/components/layout/Layout.tsx +16 -2
  312. package/corpus/templates/design/app/components/layout/Sidebar.tsx +2 -0
  313. package/corpus/templates/design/app/components/templates/TemplatePreview.tsx +72 -0
  314. package/corpus/templates/design/app/global.css +2 -35
  315. package/corpus/templates/design/app/hooks/use-navigation-state.ts +10 -0
  316. package/corpus/templates/design/app/i18n/zh-TW.ts +127 -5
  317. package/corpus/templates/design/app/i18n-breakpoints.ts +209 -0
  318. package/corpus/templates/design/app/i18n-data.ts +1317 -59
  319. package/corpus/templates/design/app/i18n-template-feature.ts +458 -0
  320. package/corpus/templates/design/app/lib/design-clipboard.ts +202 -0
  321. package/corpus/templates/design/app/lib/design-file-upload.ts +87 -0
  322. package/corpus/templates/design/app/lib/design-import.ts +168 -11
  323. package/corpus/templates/design/app/lib/desktop-design-preview.ts +423 -0
  324. package/corpus/templates/design/app/lib/figma-clipboard.ts +74 -8
  325. package/corpus/templates/design/app/lib/figma-connection.ts +161 -0
  326. package/corpus/templates/design/app/lib/figma-svg-copy.ts +814 -22
  327. package/corpus/templates/design/app/lib/figma-url.ts +77 -0
  328. package/corpus/templates/design/app/lib/pending-generation.ts +35 -0
  329. package/corpus/templates/design/app/pages/DesignSystems.tsx +236 -177
  330. package/corpus/templates/design/app/pages/Index.tsx +38 -0
  331. package/corpus/templates/design/app/pages/Templates.tsx +498 -0
  332. package/corpus/templates/design/app/pages/design-editor/auto-layout-suggestion.ts +328 -0
  333. package/corpus/templates/design/app/pages/design-editor/clone-idrefs.ts +113 -0
  334. package/corpus/templates/design/app/pages/design-editor/created-screen-navigation.ts +55 -0
  335. package/corpus/templates/design/app/pages/design-editor/editor-session.ts +32 -0
  336. package/corpus/templates/design/app/pages/design-editor/editor-state.ts +49 -2
  337. package/corpus/templates/design/app/pages/design-editor/export-capture.ts +296 -0
  338. package/corpus/templates/design/app/pages/design-editor/history.ts +101 -2
  339. package/corpus/templates/design/app/pages/design-editor/layout-operations.ts +28 -1
  340. package/corpus/templates/design/app/pages/design-editor/overview-camera.ts +34 -0
  341. package/corpus/templates/design/app/pages/design-editor/pending-edits.ts +202 -6
  342. package/corpus/templates/design/app/pages/design-editor/pending-structure-verification.ts +92 -0
  343. package/corpus/templates/design/app/pages/design-editor/save-failure.ts +58 -0
  344. package/corpus/templates/design/app/routes/templates.tsx +4 -6
  345. package/corpus/templates/design/changelog/2026-07-10-app-workspaces-now-use-clean-borderless-main-surfaces-throug.md +6 -0
  346. package/corpus/templates/design/changelog/2026-07-10-ask-chat-what-s-in-a-figma-file-or-frame-structure-screensho.md +6 -0
  347. package/corpus/templates/design/changelog/2026-07-10-canvas-edits-now-reject-malformed-html-before-it-can-corrupt.md +6 -0
  348. package/corpus/templates/design/changelog/2026-07-10-complex-designs-now-export-as-valid-secure-svgs-and-crisp-ra.md +6 -0
  349. package/corpus/templates/design/changelog/2026-07-10-complex-figma-masks-arcs-rich-text-transformed-images-and-ad.md +6 -0
  350. package/corpus/templates/design/changelog/2026-07-10-copied-layers-paste-across-designs-and-browser-tabs.md +6 -0
  351. package/corpus/templates/design/changelog/2026-07-10-copy-and-download-editable-figma-svg.md +6 -0
  352. package/corpus/templates/design/changelog/2026-07-10-copying-design-text-now-pastes-readable-text-into-other-apps.md +6 -0
  353. package/corpus/templates/design/changelog/2026-07-10-deleted-screens-can-be-restored-with-undo-and-removed-again-.md +6 -0
  354. package/corpus/templates/design/changelog/2026-07-10-design-changes-now-save-before-switching-apps-and-retry-when.md +6 -0
  355. package/corpus/templates/design/changelog/2026-07-10-design-stays-usable-on-phones-by-keeping-editor-panels-and-f.md +6 -0
  356. package/corpus/templates/design/changelog/2026-07-10-download-all-screens-as-one-multi-page-pdf-from-the-overview.md +6 -0
  357. package/corpus/templates/design/changelog/2026-07-10-duplicated-layers-now-keep-labels-aria-relationships-fragmen.md +6 -0
  358. package/corpus/templates/design/changelog/2026-07-10-fig-import-results-stay-compact.md +6 -0
  359. package/corpus/templates/design/changelog/2026-07-10-figma-imports-now-load-real-fonts-fix-rotated-gradient-dashe.md +6 -0
  360. package/corpus/templates/design/changelog/2026-07-10-figma-links-in-chat-and-the-import-tab-now-offer-secure-one-.md +6 -0
  361. package/corpus/templates/design/changelog/2026-07-10-fixed-cmd-z-not-restoring-content-after-an-agent-driven-desi.md +6 -0
  362. package/corpus/templates/design/changelog/2026-07-10-fixed-download-pdf-being-unreachable-from-the-export-panel-e.md +6 -0
  363. package/corpus/templates/design/changelog/2026-07-10-fixed-dragging-a-layer-out-of-an-auto-layout-row-column-no-l.md +6 -0
  364. package/corpus/templates/design/changelog/2026-07-10-fixed-figma-svg-export-text-wrapping-sizing-and-inner-layer.md +6 -0
  365. package/corpus/templates/design/changelog/2026-07-10-fixed-hiding-or-locking-one-layer-no-longer-hides-or-blocks-.md +6 -0
  366. package/corpus/templates/design/changelog/2026-07-10-fixed-png-screenshots-of-tall-screens-being-cropped-to-one-v.md +6 -0
  367. package/corpus/templates/design/changelog/2026-07-10-fixed-png-svg-exports-capturing-broken-layout-when-webfonts-.md +6 -0
  368. package/corpus/templates/design/changelog/2026-07-10-frame-tool-now-offers-standard-ad-unit-size-presets-medium-r.md +6 -0
  369. package/corpus/templates/design/changelog/2026-07-10-full-view-controls-stay-within-their-frame-instead-of-coveri.md +6 -0
  370. package/corpus/templates/design/changelog/2026-07-10-hover-focus-focus-visible-pressed-and-disabled-states-now-pr.md +6 -0
  371. package/corpus/templates/design/changelog/2026-07-10-layer-drops-now-land-in-the-intended-grid-row-stay-visually-.md +6 -0
  372. package/corpus/templates/design/changelog/2026-07-10-local-code-workspaces-now-keep-unsaved-edits-across-panel-sw.md +6 -0
  373. package/corpus/templates/design/changelog/2026-07-10-local-visual-editing-now-keeps-authenticated-sessions-shared.md +6 -0
  374. package/corpus/templates/design/changelog/2026-07-10-long-running-agent-work-no-longer-shows-a-premature-stuck-wa.md +6 -0
  375. package/corpus/templates/design/changelog/2026-07-10-managed-figma-connections-are-recognized-automatically.md +6 -0
  376. package/corpus/templates/design/changelog/2026-07-10-new-designs-can-open-directly-in-the-editor-without-a-pr.md +6 -0
  377. package/corpus/templates/design/changelog/2026-07-10-new-screens-are-selected-and-revealed-immediately.md +6 -0
  378. package/corpus/templates/design/changelog/2026-07-10-new-text-layers-undo-as-one-safe-creation.md +6 -0
  379. package/corpus/templates/design/changelog/2026-07-10-preview-and-apply-inferred-auto-layout-without-changing-yo.md +5 -0
  380. package/corpus/templates/design/changelog/2026-07-10-print-pdf-exports-and-paper-size-presets-letter-a4-now-match.md +6 -0
  381. package/corpus/templates/design/changelog/2026-07-10-responsive-frame-editing.md +6 -0
  382. package/corpus/templates/design/changelog/2026-07-10-reusable-design-templates.md +6 -0
  383. package/corpus/templates/design/changelog/2026-07-10-screen-overview-frames-now-use-a-clearer-interact-action-wit.md +6 -0
  384. package/corpus/templates/design/changelog/2026-07-10-start-designs-from-source-linked-material-3-carbon-or-primer.md +6 -0
  385. package/corpus/templates/design/changelog/2026-07-10-tweaks-guidance.md +6 -0
  386. package/corpus/templates/design/changelog/2026-07-10-uploaded-fig-files-can-now-become-editable-design-screens-wi.md +6 -0
  387. package/corpus/templates/design/e2e/helpers.ts +3 -3
  388. package/corpus/templates/design/package.json +2 -0
  389. package/corpus/templates/design/scripts/qa-figma-stress-import.ts +96 -0
  390. package/corpus/templates/design/server/db/index.ts +10 -0
  391. package/corpus/templates/design/server/db/schema.ts +44 -0
  392. package/corpus/templates/design/server/handlers/import-design-file.ts +114 -80
  393. package/corpus/templates/design/server/handlers/index-design-system-with-builder.ts +19 -6
  394. package/corpus/templates/design/server/lib/design-export.ts +240 -3
  395. package/corpus/templates/design/server/lib/design-template-data.ts +89 -0
  396. package/corpus/templates/design/server/lib/design-to-figma-svg.ts +250 -26
  397. package/corpus/templates/design/server/lib/fig-file-decoder.ts +839 -0
  398. package/corpus/templates/design/server/lib/fig-file-import.ts +287 -0
  399. package/corpus/templates/design/server/lib/fig-file-limits.ts +3 -0
  400. package/corpus/templates/design/server/lib/fig-file-to-html.ts +2568 -0
  401. package/corpus/templates/design/server/lib/figma-design-context.ts +359 -0
  402. package/corpus/templates/design/server/lib/figma-node-import.ts +478 -22
  403. package/corpus/templates/design/server/lib/figma-node-to-html.ts +554 -29
  404. package/corpus/templates/design/server/lib/local-figma-qa-upload.ts +112 -0
  405. package/corpus/templates/design/server/lib/verify-write-grant.ts +16 -2
  406. package/corpus/templates/design/server/lib/visible-clipboard-html.ts +13 -3
  407. package/corpus/templates/design/server/plugins/agent-chat.ts +7 -0
  408. package/corpus/templates/design/server/plugins/db.ts +42 -0
  409. package/corpus/templates/design/server/plugins/local-figma-qa-upload.ts +7 -0
  410. package/corpus/templates/design/server/register-secrets.ts +8 -8
  411. package/corpus/templates/design/server/routes/api/qa-figma-import-assets/[assetId].get.ts +46 -0
  412. package/corpus/templates/design/server/source-workspace.ts +104 -12
  413. package/corpus/templates/design/shared/code-layer.ts +105 -28
  414. package/corpus/templates/design/shared/design-system-templates.ts +301 -0
  415. package/corpus/templates/design/shared/design-template-presets.ts +195 -0
  416. package/corpus/templates/design/shared/figma-url.ts +8 -0
  417. package/corpus/templates/design/shared/html-integrity.ts +306 -0
  418. package/corpus/templates/design/shared/interaction-states.ts +318 -23
  419. package/corpus/templates/design/shared/locked-layers.ts +151 -0
  420. package/corpus/templates/dispatch/.agents/skills/capture-learnings/SKILL.md +22 -9
  421. package/corpus/templates/dispatch/app/i18n/zh-TW.ts +48 -0
  422. package/corpus/templates/dispatch/app/i18n-data.ts +536 -1
  423. package/corpus/templates/dispatch/changelog/2026-07-10-connect-slack-workspaces-with-oauth-and-manage-channel-ident.md +6 -0
  424. package/corpus/templates/dispatch/changelog/2026-07-10-microsoft-teams-bots-and-discord-slash-commands-can-now-conn.md +6 -0
  425. package/corpus/templates/dispatch/changelog/2026-07-10-slack-and-telegram-now-route-uptime-monitor-requests-to-anal.md +6 -0
  426. package/corpus/templates/forms/.agents/skills/capture-learnings/SKILL.md +22 -9
  427. package/corpus/templates/forms/.agents/skills/form-publishing/SKILL.md +7 -0
  428. package/corpus/templates/forms/AGENTS.md +4 -0
  429. package/corpus/templates/forms/actions/create-form.ts +44 -7
  430. package/corpus/templates/forms/actions/lib/assert-publishable-form.ts +38 -0
  431. package/corpus/templates/forms/actions/patch-form-fields.ts +4 -0
  432. package/corpus/templates/forms/actions/update-form.ts +2 -36
  433. package/corpus/templates/forms/app/i18n/ar-SA.ts +3 -0
  434. package/corpus/templates/forms/app/i18n/de-DE.ts +3 -0
  435. package/corpus/templates/forms/app/i18n/en-US.ts +3 -0
  436. package/corpus/templates/forms/app/i18n/es-ES.ts +3 -0
  437. package/corpus/templates/forms/app/i18n/fr-FR.ts +3 -0
  438. package/corpus/templates/forms/app/i18n/hi-IN.ts +3 -0
  439. package/corpus/templates/forms/app/i18n/ja-JP.ts +3 -0
  440. package/corpus/templates/forms/app/i18n/ko-KR.ts +3 -0
  441. package/corpus/templates/forms/app/i18n/pt-BR.ts +3 -0
  442. package/corpus/templates/forms/app/i18n/zh-CN.ts +2 -0
  443. package/corpus/templates/forms/app/i18n/zh-TW.ts +3 -0
  444. package/corpus/templates/forms/app/pages/FormBuilderPage.tsx +17 -0
  445. package/corpus/templates/forms/changelog/2026-07-10-agent-created-published-forms-now-return-the-anonymous-publi.md +6 -0
  446. package/corpus/templates/forms/changelog/2026-07-10-published-forms-can-no-longer-be-edited-into-an-unusable-emp.md +6 -0
  447. package/corpus/templates/forms/server/handlers/submissions.ts +4 -3
  448. package/corpus/templates/forms/server/plugins/agent-chat.ts +1 -0
  449. package/corpus/templates/forms/shared/types.ts +5 -0
  450. package/corpus/templates/mail/.agents/skills/capture-learnings/SKILL.md +22 -9
  451. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +2 -2
  452. package/corpus/templates/mail/changelog/2026-07-10-mail-navigation-now-uses-a-clean-borderless-drawer.md +6 -0
  453. package/corpus/templates/plan/.agents/skills/capture-learnings/SKILL.md +22 -9
  454. package/corpus/templates/plan/app/lib/plan-local-bridge.ts +4 -1
  455. package/corpus/templates/plan/changelog/2026-07-10-local-plans-now-keep-valid-content-visible-when-one-generate.md +6 -0
  456. package/corpus/templates/plan/server/lib/local-plan-files.ts +4 -1
  457. package/corpus/templates/slides/.agents/skills/capture-learnings/SKILL.md +22 -9
  458. package/dist/a2a/artifact-response.d.ts.map +1 -1
  459. package/dist/a2a/artifact-response.js +88 -2
  460. package/dist/a2a/artifact-response.js.map +1 -1
  461. package/dist/a2a/client.d.ts +9 -0
  462. package/dist/a2a/client.d.ts.map +1 -1
  463. package/dist/a2a/client.js +1 -0
  464. package/dist/a2a/client.js.map +1 -1
  465. package/dist/a2a/handlers.d.ts.map +1 -1
  466. package/dist/a2a/handlers.js +24 -69
  467. package/dist/a2a/handlers.js.map +1 -1
  468. package/dist/a2a/types.d.ts +2 -0
  469. package/dist/a2a/types.d.ts.map +1 -1
  470. package/dist/a2a/types.js.map +1 -1
  471. package/dist/agent/durable-background.d.ts +11 -0
  472. package/dist/agent/durable-background.d.ts.map +1 -1
  473. package/dist/agent/durable-background.js +17 -0
  474. package/dist/agent/durable-background.js.map +1 -1
  475. package/dist/agent/production-agent.d.ts +2 -2
  476. package/dist/agent/production-agent.d.ts.map +1 -1
  477. package/dist/agent/production-agent.js +15 -5
  478. package/dist/agent/production-agent.js.map +1 -1
  479. package/dist/agent/run-manager.d.ts +44 -2
  480. package/dist/agent/run-manager.d.ts.map +1 -1
  481. package/dist/agent/run-manager.js +90 -9
  482. package/dist/agent/run-manager.js.map +1 -1
  483. package/dist/agent/run-store.d.ts +109 -0
  484. package/dist/agent/run-store.d.ts.map +1 -1
  485. package/dist/agent/run-store.js +206 -15
  486. package/dist/agent/run-store.js.map +1 -1
  487. package/dist/agent/types.d.ts +22 -0
  488. package/dist/agent/types.d.ts.map +1 -1
  489. package/dist/agent/types.js.map +1 -1
  490. package/dist/audit/record.d.ts.map +1 -1
  491. package/dist/audit/record.js +29 -0
  492. package/dist/audit/record.js.map +1 -1
  493. package/dist/audit/store.d.ts.map +1 -1
  494. package/dist/audit/store.js +62 -3
  495. package/dist/audit/store.js.map +1 -1
  496. package/dist/audit/types.d.ts +13 -0
  497. package/dist/audit/types.d.ts.map +1 -1
  498. package/dist/audit/types.js.map +1 -1
  499. package/dist/automation/index.d.ts +193 -0
  500. package/dist/automation/index.d.ts.map +1 -0
  501. package/dist/automation/index.js +464 -0
  502. package/dist/automation/index.js.map +1 -0
  503. package/dist/cli/create.d.ts.map +1 -1
  504. package/dist/cli/create.js +10 -3
  505. package/dist/cli/create.js.map +1 -1
  506. package/dist/cli/design-connect.d.ts.map +1 -1
  507. package/dist/cli/design-connect.js +492 -35
  508. package/dist/cli/design-connect.js.map +1 -1
  509. package/dist/client/AgentPanel.d.ts +7 -1
  510. package/dist/client/AgentPanel.d.ts.map +1 -1
  511. package/dist/client/AgentPanel.js +32 -8
  512. package/dist/client/AgentPanel.js.map +1 -1
  513. package/dist/client/AssistantChat.d.ts +15 -0
  514. package/dist/client/AssistantChat.d.ts.map +1 -1
  515. package/dist/client/AssistantChat.js +115 -47
  516. package/dist/client/AssistantChat.js.map +1 -1
  517. package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
  518. package/dist/client/MultiTabAssistantChat.js +1 -1
  519. package/dist/client/MultiTabAssistantChat.js.map +1 -1
  520. package/dist/client/RunStuckBanner.d.ts +14 -1
  521. package/dist/client/RunStuckBanner.d.ts.map +1 -1
  522. package/dist/client/RunStuckBanner.js +35 -7
  523. package/dist/client/RunStuckBanner.js.map +1 -1
  524. package/dist/client/agent-chat-adapter.d.ts +4 -1
  525. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  526. package/dist/client/agent-chat-adapter.js +49 -4
  527. package/dist/client/agent-chat-adapter.js.map +1 -1
  528. package/dist/client/automation.d.ts +14 -0
  529. package/dist/client/automation.d.ts.map +1 -0
  530. package/dist/client/automation.js +9 -0
  531. package/dist/client/automation.js.map +1 -0
  532. package/dist/client/chat/run-recovery.d.ts +4 -0
  533. package/dist/client/chat/run-recovery.d.ts.map +1 -1
  534. package/dist/client/chat/run-recovery.js +12 -10
  535. package/dist/client/chat/run-recovery.js.map +1 -1
  536. package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
  537. package/dist/client/composer/TiptapComposer.js +8 -0
  538. package/dist/client/composer/TiptapComposer.js.map +1 -1
  539. package/dist/client/index.d.ts +2 -0
  540. package/dist/client/index.d.ts.map +1 -1
  541. package/dist/client/index.js +2 -0
  542. package/dist/client/index.js.map +1 -1
  543. package/dist/client/integrations/api.d.ts +115 -0
  544. package/dist/client/integrations/api.d.ts.map +1 -0
  545. package/dist/client/integrations/api.js +123 -0
  546. package/dist/client/integrations/api.js.map +1 -0
  547. package/dist/client/integrations/index.d.ts +1 -0
  548. package/dist/client/integrations/index.d.ts.map +1 -1
  549. package/dist/client/integrations/index.js +1 -0
  550. package/dist/client/integrations/index.js.map +1 -1
  551. package/dist/client/transcription/use-live-transcription.d.ts.map +1 -1
  552. package/dist/client/transcription/use-live-transcription.js +59 -5
  553. package/dist/client/transcription/use-live-transcription.js.map +1 -1
  554. package/dist/client/use-run-stuck-detection.d.ts +16 -1
  555. package/dist/client/use-run-stuck-detection.d.ts.map +1 -1
  556. package/dist/client/use-run-stuck-detection.js +23 -4
  557. package/dist/client/use-run-stuck-detection.js.map +1 -1
  558. package/dist/collab/struct-routes.d.ts +1 -1
  559. package/dist/deploy/build.d.ts.map +1 -1
  560. package/dist/deploy/build.js +49 -4
  561. package/dist/deploy/build.js.map +1 -1
  562. package/dist/deploy/workspace-deploy.d.ts.map +1 -1
  563. package/dist/deploy/workspace-deploy.js +31 -2
  564. package/dist/deploy/workspace-deploy.js.map +1 -1
  565. package/dist/file-upload/types.d.ts +2 -0
  566. package/dist/file-upload/types.d.ts.map +1 -1
  567. package/dist/file-upload/types.js.map +1 -1
  568. package/dist/index.d.ts +2 -0
  569. package/dist/index.d.ts.map +1 -1
  570. package/dist/index.js +2 -0
  571. package/dist/index.js.map +1 -1
  572. package/dist/integrations/a2a-continuations-store.d.ts.map +1 -1
  573. package/dist/integrations/a2a-continuations-store.js +6 -4
  574. package/dist/integrations/a2a-continuations-store.js.map +1 -1
  575. package/dist/integrations/adapters/discord.d.ts +3 -0
  576. package/dist/integrations/adapters/discord.d.ts.map +1 -0
  577. package/dist/integrations/adapters/discord.js +261 -0
  578. package/dist/integrations/adapters/discord.js.map +1 -0
  579. package/dist/integrations/adapters/index.d.ts +4 -0
  580. package/dist/integrations/adapters/index.d.ts.map +1 -0
  581. package/dist/integrations/adapters/index.js +26 -0
  582. package/dist/integrations/adapters/index.js.map +1 -0
  583. package/dist/integrations/adapters/microsoft-teams.d.ts +5 -0
  584. package/dist/integrations/adapters/microsoft-teams.d.ts.map +1 -0
  585. package/dist/integrations/adapters/microsoft-teams.js +295 -0
  586. package/dist/integrations/adapters/microsoft-teams.js.map +1 -0
  587. package/dist/integrations/adapters/slack.d.ts +8 -2
  588. package/dist/integrations/adapters/slack.d.ts.map +1 -1
  589. package/dist/integrations/adapters/slack.js +736 -27
  590. package/dist/integrations/adapters/slack.js.map +1 -1
  591. package/dist/integrations/adapters/telegram.d.ts +0 -2
  592. package/dist/integrations/adapters/telegram.d.ts.map +1 -1
  593. package/dist/integrations/adapters/telegram.js +49 -15
  594. package/dist/integrations/adapters/telegram.js.map +1 -1
  595. package/dist/integrations/adapters/whatsapp.d.ts +0 -2
  596. package/dist/integrations/adapters/whatsapp.d.ts.map +1 -1
  597. package/dist/integrations/adapters/whatsapp.js +40 -17
  598. package/dist/integrations/adapters/whatsapp.js.map +1 -1
  599. package/dist/integrations/catalog.d.ts +75 -0
  600. package/dist/integrations/catalog.d.ts.map +1 -0
  601. package/dist/integrations/catalog.js +451 -0
  602. package/dist/integrations/catalog.js.map +1 -0
  603. package/dist/integrations/controls-store.d.ts +44 -0
  604. package/dist/integrations/controls-store.d.ts.map +1 -0
  605. package/dist/integrations/controls-store.js +129 -0
  606. package/dist/integrations/controls-store.js.map +1 -0
  607. package/dist/integrations/index.d.ts +13 -1
  608. package/dist/integrations/index.d.ts.map +1 -1
  609. package/dist/integrations/index.js +9 -0
  610. package/dist/integrations/index.js.map +1 -1
  611. package/dist/integrations/installations-store.d.ts +112 -0
  612. package/dist/integrations/installations-store.d.ts.map +1 -0
  613. package/dist/integrations/installations-store.js +493 -0
  614. package/dist/integrations/installations-store.js.map +1 -0
  615. package/dist/integrations/integration-memory.d.ts +24 -0
  616. package/dist/integrations/integration-memory.d.ts.map +1 -0
  617. package/dist/integrations/integration-memory.js +136 -0
  618. package/dist/integrations/integration-memory.js.map +1 -0
  619. package/dist/integrations/pending-tasks-retry-job.d.ts.map +1 -1
  620. package/dist/integrations/pending-tasks-retry-job.js +6 -5
  621. package/dist/integrations/pending-tasks-retry-job.js.map +1 -1
  622. package/dist/integrations/pending-tasks-store.d.ts +17 -0
  623. package/dist/integrations/pending-tasks-store.d.ts.map +1 -1
  624. package/dist/integrations/pending-tasks-store.js +71 -5
  625. package/dist/integrations/pending-tasks-store.js.map +1 -1
  626. package/dist/integrations/plugin.d.ts.map +1 -1
  627. package/dist/integrations/plugin.js +520 -35
  628. package/dist/integrations/plugin.js.map +1 -1
  629. package/dist/integrations/scope-store.d.ts +65 -0
  630. package/dist/integrations/scope-store.d.ts.map +1 -0
  631. package/dist/integrations/scope-store.js +361 -0
  632. package/dist/integrations/scope-store.js.map +1 -0
  633. package/dist/integrations/slack-manifest.d.ts +66 -0
  634. package/dist/integrations/slack-manifest.d.ts.map +1 -0
  635. package/dist/integrations/slack-manifest.js +70 -0
  636. package/dist/integrations/slack-manifest.js.map +1 -0
  637. package/dist/integrations/slack-oauth.d.ts +99 -0
  638. package/dist/integrations/slack-oauth.d.ts.map +1 -0
  639. package/dist/integrations/slack-oauth.js +226 -0
  640. package/dist/integrations/slack-oauth.js.map +1 -0
  641. package/dist/integrations/types.d.ts +144 -0
  642. package/dist/integrations/types.d.ts.map +1 -1
  643. package/dist/integrations/types.js +16 -1
  644. package/dist/integrations/types.js.map +1 -1
  645. package/dist/integrations/usage-budget-store.d.ts +84 -0
  646. package/dist/integrations/usage-budget-store.d.ts.map +1 -0
  647. package/dist/integrations/usage-budget-store.js +650 -0
  648. package/dist/integrations/usage-budget-store.js.map +1 -0
  649. package/dist/integrations/webhook-handler.d.ts +4 -0
  650. package/dist/integrations/webhook-handler.d.ts.map +1 -1
  651. package/dist/integrations/webhook-handler.js +415 -47
  652. package/dist/integrations/webhook-handler.js.map +1 -1
  653. package/dist/jobs/scheduler.d.ts +6 -0
  654. package/dist/jobs/scheduler.d.ts.map +1 -1
  655. package/dist/jobs/scheduler.js +83 -4
  656. package/dist/jobs/scheduler.js.map +1 -1
  657. package/dist/jobs/tools.d.ts.map +1 -1
  658. package/dist/jobs/tools.js +43 -11
  659. package/dist/jobs/tools.js.map +1 -1
  660. package/dist/observability/routes.d.ts +5 -5
  661. package/dist/progress/routes.d.ts +1 -1
  662. package/dist/provider-api/index.d.ts +4 -4
  663. package/dist/provider-api/index.d.ts.map +1 -1
  664. package/dist/provider-api/index.js +72 -1
  665. package/dist/provider-api/index.js.map +1 -1
  666. package/dist/resources/handlers.d.ts +3 -3
  667. package/dist/resources/handlers.d.ts.map +1 -1
  668. package/dist/resources/handlers.js +57 -15
  669. package/dist/resources/handlers.js.map +1 -1
  670. package/dist/resources/script-helpers.d.ts.map +1 -1
  671. package/dist/resources/script-helpers.js +34 -8
  672. package/dist/resources/script-helpers.js.map +1 -1
  673. package/dist/resources/store.d.ts +10 -0
  674. package/dist/resources/store.d.ts.map +1 -1
  675. package/dist/resources/store.js +54 -47
  676. package/dist/resources/store.js.map +1 -1
  677. package/dist/scripts/call-agent.d.ts.map +1 -1
  678. package/dist/scripts/call-agent.js +106 -1
  679. package/dist/scripts/call-agent.js.map +1 -1
  680. package/dist/server/agent-chat-plugin.d.ts +15 -4
  681. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  682. package/dist/server/agent-chat-plugin.js +248 -113
  683. package/dist/server/agent-chat-plugin.js.map +1 -1
  684. package/dist/server/auth.d.ts.map +1 -1
  685. package/dist/server/auth.js +10 -14
  686. package/dist/server/auth.js.map +1 -1
  687. package/dist/server/builder-design-systems.d.ts +3 -1
  688. package/dist/server/builder-design-systems.d.ts.map +1 -1
  689. package/dist/server/builder-design-systems.js +9 -2
  690. package/dist/server/builder-design-systems.js.map +1 -1
  691. package/dist/server/edge.d.ts +1 -1
  692. package/dist/server/edge.d.ts.map +1 -1
  693. package/dist/server/edge.js +1 -1
  694. package/dist/server/edge.js.map +1 -1
  695. package/dist/server/index.d.ts +2 -1
  696. package/dist/server/index.d.ts.map +1 -1
  697. package/dist/server/index.js +2 -1
  698. package/dist/server/index.js.map +1 -1
  699. package/dist/server/request-context.d.ts +18 -0
  700. package/dist/server/request-context.d.ts.map +1 -1
  701. package/dist/server/request-context.js.map +1 -1
  702. package/dist/server/social-og-image.d.ts.map +1 -1
  703. package/dist/server/social-og-image.js +3 -2
  704. package/dist/server/social-og-image.js.map +1 -1
  705. package/dist/server/transcribe-voice.d.ts +1 -1
  706. package/dist/styles/agent-native.css +62 -44
  707. package/dist/templates/default/.agents/skills/capture-learnings/SKILL.md +22 -9
  708. package/dist/templates/default/AGENTS.md +7 -3
  709. package/dist/templates/workspace-core/.agents/skills/authentication/SKILL.md +1 -1
  710. package/dist/templates/workspace-core/.agents/skills/capture-learnings/SKILL.md +22 -9
  711. package/dist/templates/workspace-core/.agents/skills/extension-points/SKILL.md +6 -3
  712. package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +25 -0
  713. package/dist/templates/workspace-core/.agents/skills/integration-webhooks/SKILL.md +15 -0
  714. package/dist/templates/workspace-core/AGENTS.md +3 -2
  715. package/dist/usage/store.d.ts +7 -0
  716. package/dist/usage/store.d.ts.map +1 -1
  717. package/dist/usage/store.js +24 -3
  718. package/dist/usage/store.js.map +1 -1
  719. package/docs/content/automation-connectors.mdx +80 -0
  720. package/docs/content/extensions.mdx +8 -0
  721. package/docs/content/locales/ar-SA/extensions.mdx +8 -0
  722. package/docs/content/locales/ar-SA/messaging.mdx +84 -15
  723. package/docs/content/locales/ar-SA/template-clips.mdx +1 -0
  724. package/docs/content/locales/ar-SA/template-design.mdx +1 -0
  725. package/docs/content/locales/de-DE/extensions.mdx +10 -0
  726. package/docs/content/locales/de-DE/messaging.mdx +92 -15
  727. package/docs/content/locales/de-DE/template-clips.mdx +1 -0
  728. package/docs/content/locales/de-DE/template-design.mdx +1 -0
  729. package/docs/content/locales/es-ES/extensions.mdx +10 -0
  730. package/docs/content/locales/es-ES/messaging.mdx +91 -15
  731. package/docs/content/locales/es-ES/template-clips.mdx +1 -0
  732. package/docs/content/locales/es-ES/template-design.mdx +1 -0
  733. package/docs/content/locales/fr-FR/extensions.mdx +10 -0
  734. package/docs/content/locales/fr-FR/messaging.mdx +91 -15
  735. package/docs/content/locales/fr-FR/template-clips.mdx +1 -0
  736. package/docs/content/locales/fr-FR/template-design.mdx +1 -0
  737. package/docs/content/locales/hi-IN/extensions.mdx +8 -0
  738. package/docs/content/locales/hi-IN/messaging.mdx +81 -15
  739. package/docs/content/locales/hi-IN/template-clips.mdx +1 -0
  740. package/docs/content/locales/hi-IN/template-design.mdx +1 -0
  741. package/docs/content/locales/ja-JP/extensions.mdx +9 -0
  742. package/docs/content/locales/ja-JP/messaging.mdx +81 -15
  743. package/docs/content/locales/ja-JP/template-clips.mdx +1 -0
  744. package/docs/content/locales/ja-JP/template-design.mdx +1 -0
  745. package/docs/content/locales/ko-KR/extensions.mdx +8 -0
  746. package/docs/content/locales/ko-KR/messaging.mdx +80 -15
  747. package/docs/content/locales/ko-KR/template-clips.mdx +1 -0
  748. package/docs/content/locales/ko-KR/template-design.mdx +1 -0
  749. package/docs/content/locales/pt-BR/extensions.mdx +9 -0
  750. package/docs/content/locales/pt-BR/messaging.mdx +88 -15
  751. package/docs/content/locales/pt-BR/template-clips.mdx +1 -0
  752. package/docs/content/locales/pt-BR/template-design.mdx +1 -0
  753. package/docs/content/locales/zh-CN/extensions.mdx +6 -0
  754. package/docs/content/locales/zh-CN/messaging.mdx +78 -15
  755. package/docs/content/locales/zh-CN/template-clips.mdx +1 -0
  756. package/docs/content/locales/zh-CN/template-design.mdx +1 -0
  757. package/docs/content/locales/zh-TW/extensions.mdx +6 -0
  758. package/docs/content/locales/zh-TW/messaging.mdx +78 -15
  759. package/docs/content/locales/zh-TW/template-clips.mdx +1 -0
  760. package/docs/content/locales/zh-TW/template-design.mdx +1 -0
  761. package/docs/content/messaging.mdx +227 -45
  762. package/docs/content/template-clips.mdx +3 -0
  763. package/docs/content/template-design.mdx +4 -0
  764. package/package.json +5 -1
  765. package/src/templates/default/.agents/skills/capture-learnings/SKILL.md +22 -9
  766. package/src/templates/default/AGENTS.md +7 -3
  767. package/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +1 -1
  768. package/src/templates/workspace-core/.agents/skills/capture-learnings/SKILL.md +22 -9
  769. package/src/templates/workspace-core/.agents/skills/extension-points/SKILL.md +6 -3
  770. package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +25 -0
  771. package/src/templates/workspace-core/.agents/skills/integration-webhooks/SKILL.md +15 -0
  772. package/src/templates/workspace-core/AGENTS.md +3 -2
@@ -18,6 +18,7 @@ import {
18
18
  cleanupOldRuns,
19
19
  updateRunHeartbeat,
20
20
  bumpRunProgress,
21
+ setRunInFlightMarker,
21
22
  reapIfStale,
22
23
  reapUnclaimedBackgroundRun,
23
24
  shouldRedispatchUnclaimedBackgroundRun,
@@ -627,6 +628,7 @@ export function startRun(
627
628
  let lastRealProgressAt = Date.now();
628
629
  let inFlightWorkCount = 0;
629
630
  const trackInFlightWork = (event: AgentChatEvent) => {
631
+ const wasIdle = inFlightWorkCount === 0;
630
632
  if (event.type === "tool_start") {
631
633
  inFlightWorkCount += 1;
632
634
  } else if (event.type === "tool_done") {
@@ -637,6 +639,23 @@ export function startRun(
637
639
  } else {
638
640
  inFlightWorkCount = Math.max(0, inFlightWorkCount - 1);
639
641
  }
642
+ } else {
643
+ return; // Not a work-tracking event — no transition possible.
644
+ }
645
+ // Mirror the 0<->N transition into SQL so a stale reaper running in a
646
+ // DIFFERENT isolate (a client's SQL-subscription poll, a sibling
647
+ // isolate's opportunistic cleanup, a fresh boot's startup sweep) can
648
+ // grant this demonstrably-alive run a bounded grace even when THIS
649
+ // isolate's own heartbeat write is failing (e.g. Neon pooler saturation)
650
+ // — `inFlightWorkCount` itself is in-memory and invisible to those other
651
+ // isolates. Fire-and-forget: never block event emission on this write,
652
+ // and a write failure here is no worse than today's behavior (the row
653
+ // just gets no grace). See `setRunInFlightMarker` / `IN_FLIGHT_RUN_STALE_GRACE_MS`
654
+ // in run-store.ts for the full reasoning and the bounded-grace derivation.
655
+ if (wasIdle && inFlightWorkCount > 0) {
656
+ setRunInFlightMarker(runId, true).catch(() => {});
657
+ } else if (!wasIdle && inFlightWorkCount === 0) {
658
+ setRunInFlightMarker(runId, false).catch(() => {});
640
659
  }
641
660
  };
642
661
  const checkNoProgressBackstop = () => {
@@ -1432,7 +1451,11 @@ export function getActiveRunForThread(threadId: string): ActiveRun | null {
1432
1451
  * dead even before the server-side stale reap has fired. Returns
1433
1452
  * `lastProgressAt` so the client-side stuck-detector can show a
1434
1453
  * user-visible "this chat looks stuck" affordance when a run is alive
1435
- * (heartbeating) but not actually emitting events.
1454
+ * (heartbeating) but not actually emitting events. Returns
1455
+ * `awaitingRedispatch` so the client's background follow loop can tell a
1456
+ * legitimately-deferred `chainServerDrivenContinuation` successor (recovery
1457
+ * in progress server-side) apart from a genuinely dead run — see this
1458
+ * field's own doc comment below.
1436
1459
  */
1437
1460
  export async function getActiveRunForThreadAsync(threadId: string): Promise<{
1438
1461
  runId: string;
@@ -1451,6 +1474,37 @@ export async function getActiveRunForThreadAsync(threadId: string): Promise<{
1451
1474
  * diagnosable from the client WITHOUT the unreadable bg-fn logs.
1452
1475
  */
1453
1476
  diagStage?: string | null;
1477
+ /**
1478
+ * True exactly when this run is a `chainServerDrivenContinuation` deferral
1479
+ * (dispatch_mode === 'background', never claimed) still inside
1480
+ * `UNCLAIMED_BACKGROUND_RUN_REDISPATCH_BOUND_MS` — the same condition this
1481
+ * function already uses below to skip its own `reapUnclaimedBackgroundRun`.
1482
+ * Surfaced on `/runs/active` (agent-chat-plugin.ts) so
1483
+ * `agent-chat-adapter.ts`'s follow loop can tell "silently deferred,
1484
+ * server-side recovery in progress" apart from "dead" and stop counting the
1485
+ * quiet gap against its idle timeout — see the THREE-SITE INVARIANT comment
1486
+ * below and in agent-chat-plugin.ts / production-agent.ts. Always false for
1487
+ * an in-memory run (that isolate IS the live producer) and for any run that
1488
+ * isn't an unclaimed background dispatch.
1489
+ */
1490
+ awaitingRedispatch: boolean;
1491
+ /**
1492
+ * True exactly when this run's `in_flight_since` marker is set — a tool
1493
+ * call or A2A `agent_call` delegation is open and has not yet resolved
1494
+ * (see `setRunInFlightMarker` / `IN_FLIGHT_RUN_STALE_GRACE_MS` in
1495
+ * run-store.ts). This is the SAME signal `reapIfStale` reads to grant its
1496
+ * bounded stale-reap grace — computed here from the identical
1497
+ * `in_flight_since` column via `getRunByThread`, never re-derived, so the
1498
+ * client and the reaper cannot disagree about what "in flight" means.
1499
+ *
1500
+ * Surfaced on `/runs/active` (agent-chat-plugin.ts) as the
1501
+ * server-authoritative alternative to the client-side proxy
1502
+ * `RunStuckBanner` currently infers from unresolved `tool-call` content
1503
+ * parts in the local message list — that proxy can go stale after a
1504
+ * reconnect or reader-mode replay; this cannot, because it is read fresh
1505
+ * from SQL on every poll.
1506
+ */
1507
+ hasInFlightWork: boolean;
1454
1508
  } | null> {
1455
1509
  // Check memory first — return both running AND recently-completed runs
1456
1510
  // that still have events in memory. This allows sub-agent tabs to replay
@@ -1483,6 +1537,18 @@ export async function getActiveRunForThreadAsync(threadId: string): Promise<{
1483
1537
  dispatchMode: sqlSnapshot?.dispatchMode ?? null,
1484
1538
  terminalReason: sqlSnapshot?.terminalReason ?? null,
1485
1539
  diagStage: sqlSnapshot?.diagStage ?? null,
1540
+ // In-memory means this isolate is the live producer — never the
1541
+ // "deferred, nobody producing" state this flag identifies.
1542
+ awaitingRedispatch: false,
1543
+ // Read from the SAME SQL snapshot the other fields above already read
1544
+ // (`fetchRunThreadSnapshot` -> `getRunByThread`) rather than the
1545
+ // producer's own in-memory `inFlightWorkCount` — this isolate IS the
1546
+ // live producer, but there is no separate in-memory channel wired for
1547
+ // that counter today, and the SQL marker is written on every 0<->N
1548
+ // transition (see run-manager's `trackInFlightWork`), so it is at most
1549
+ // one event behind here — the same tolerance `lastProgressAt` above
1550
+ // already accepts.
1551
+ hasInFlightWork: sqlSnapshot?.inFlightSince != null,
1486
1552
  };
1487
1553
  }
1488
1554
  // Fall back to SQL — also surface recently terminated runs so the client
@@ -1525,12 +1591,17 @@ export async function getActiveRunForThreadAsync(threadId: string): Promise<{
1525
1591
  // follow loop AUTO-continues — and once the redispatch bound is exceeded
1526
1592
  // this reap fires loudly as before. So recovery stays automatic in the
1527
1593
  // common case and loud failure is only moved later, never removed.
1528
- if (
1529
- sqlRun.dispatchMode === "background" &&
1530
- !shouldRedispatchUnclaimedBackgroundRun({
1531
- startedAt: sqlRun.startedAt,
1532
- })
1533
- ) {
1594
+ //
1595
+ // `isUnclaimedBackgroundDispatch` also becomes the `awaitingRedispatch`
1596
+ // wire field below once the still-inside-the-bound check passes — see
1597
+ // this function's doc comment and the THREE-SITE INVARIANT comment in
1598
+ // agent-chat-plugin.ts / production-agent.ts.
1599
+ const isUnclaimedBackgroundDispatch =
1600
+ sqlRun.dispatchMode === "background";
1601
+ const stillInsideRedispatchBound = shouldRedispatchUnclaimedBackgroundRun(
1602
+ { startedAt: sqlRun.startedAt },
1603
+ );
1604
+ if (isUnclaimedBackgroundDispatch && !stillInsideRedispatchBound) {
1534
1605
  const recovered = await reapUnclaimedBackgroundRun(sqlRun.id).catch(
1535
1606
  () => false,
1536
1607
  );
@@ -1551,6 +1622,12 @@ export async function getActiveRunForThreadAsync(threadId: string): Promise<{
1551
1622
  dispatchMode: sqlRun.dispatchMode,
1552
1623
  terminalReason: sqlRun.terminalReason,
1553
1624
  diagStage: sqlRun.diagStage,
1625
+ awaitingRedispatch:
1626
+ isUnclaimedBackgroundDispatch && stillInsideRedispatchBound,
1627
+ // Same `in_flight_since` column `reapIfStale` (just called above,
1628
+ // and it did NOT reap this row) reads for its own grace decision —
1629
+ // one source of truth, not a second re-derived notion of "in flight".
1630
+ hasInFlightWork: sqlRun.inFlightSince != null,
1554
1631
  };
1555
1632
  }
1556
1633
  if (sqlRun.status === "completed" || sqlRun.status === "errored") {
@@ -1579,6 +1656,10 @@ export async function getActiveRunForThreadAsync(threadId: string): Promise<{
1579
1656
  dispatchMode: sqlRun.dispatchMode,
1580
1657
  terminalReason: sqlRun.terminalReason,
1581
1658
  diagStage: sqlRun.diagStage,
1659
+ // Terminal already — never the "still deferred, running" state.
1660
+ awaitingRedispatch: false,
1661
+ // Terminal already — no live work can still be in flight.
1662
+ hasInFlightWork: false,
1582
1663
  };
1583
1664
  }
1584
1665
  } catch {
@@ -1606,15 +1687,54 @@ export function getRun(runId: string): ActiveRun | null {
1606
1687
  return activeRuns.get(runId) ?? null;
1607
1688
  }
1608
1689
 
1609
- /** Explicitly abort a run (e.g. Stop button) */
1610
- export function abortRun(runId: string, reason: string = "user"): boolean {
1690
+ function abortRunInMemory(runId: string, reason: string): boolean {
1611
1691
  const run = activeRuns.get(runId);
1612
1692
  if (run) {
1613
1693
  abortInMemoryRun(run, reason);
1614
1694
  }
1695
+ return !!run;
1696
+ }
1697
+
1698
+ /** Explicitly abort a run (e.g. Stop button). */
1699
+ export function abortRun(runId: string, reason: string = "user"): boolean {
1700
+ const abortedInMemory = abortRunInMemory(runId, reason);
1615
1701
  // Also mark as aborted in SQL (for cross-isolate abort on Workers)
1616
1702
  markRunAborted(runId, reason).catch(() => {});
1617
- return !!run;
1703
+ return abortedInMemory;
1704
+ }
1705
+
1706
+ /**
1707
+ * Abort a run and wait until the cross-isolate SQL state and terminal event
1708
+ * are durable. Request handlers that start recovery immediately after aborting
1709
+ * must use this path; otherwise the recovery POST can race the old row while
1710
+ * it is still marked running.
1711
+ */
1712
+ export async function abortRunDurably(
1713
+ runId: string,
1714
+ reason: string = "user",
1715
+ ): Promise<boolean> {
1716
+ const abortedInMemory = abortRunInMemory(runId, reason);
1717
+ try {
1718
+ await markRunAborted(runId, reason);
1719
+ } catch (error) {
1720
+ // The local run is already stopped. A transient durable cleanup failure
1721
+ // must not turn the user's Stop/Retry request into a 500 after that
1722
+ // irreversible in-memory outcome. Capture it for repair/reaping and let
1723
+ // the request report the abort it did complete.
1724
+ captureError(error, {
1725
+ route: "/_agent-native/agent-chat/runs/:id/abort",
1726
+ tags: {
1727
+ source: "agent-run-manager",
1728
+ phase: "abort-run",
1729
+ },
1730
+ extra: { runId, reason, abortedInMemory },
1731
+ });
1732
+ console.error(
1733
+ "[run-manager] durable abort persistence failed:",
1734
+ error instanceof Error ? error.message : error,
1735
+ );
1736
+ }
1737
+ return abortedInMemory;
1618
1738
  }
1619
1739
 
1620
1740
  // Re-export so callers can avoid importing from run-store directly.
@@ -118,6 +118,84 @@ export const UNCLAIMED_BACKGROUND_RUN_GRACE_MS = 25_000;
118
118
  */
119
119
  export const UNCLAIMED_BACKGROUND_RUN_REDISPATCH_BOUND_MS = 5 * 60_000;
120
120
 
121
+ /**
122
+ * Tick interval for the DEDICATED fast redispatch sweep in
123
+ * agent-chat-plugin.ts (distinct from that file's general-purpose 2-minute
124
+ * orphan/reap sweep). Only attempts redispatch for rows still inside
125
+ * `UNCLAIMED_BACKGROUND_RUN_REDISPATCH_BOUND_MS` — it never reaps, so it
126
+ * cannot race the loud-failure fallback onto an earlier trigger.
127
+ *
128
+ * This constant exists because the general sweep's 2-minute cadence puts the
129
+ * FIRST redispatch attempt uncomfortably close to (and on a slow tick, past)
130
+ * `BACKGROUND_FOLLOW_IDLE_TIMEOUT_MS` (150s, agent-chat-adapter.ts) — the
131
+ * client following a deferred successor would give up and report a fatal
132
+ * error for a turn the server was silently about to recover. The whole
133
+ * budget is a derived chain, each bound following from the one before it:
134
+ *
135
+ * UNCLAIMED_BACKGROUND_RUN_GRACE_MS (25s) row must look abandoned
136
+ * + UNCLAIMED_BACKGROUND_RUN_FAST_SWEEP_MS (20s) worst-case tick latency
137
+ * = ~45s worst-case time-to-first-redispatch-attempt, ~65s to a second
138
+ * attempt if the first fails — both comfortably under the client's 150s
139
+ * idle timeout, which additionally no longer counts a known-deferred row
140
+ * against its idle window at all (see `awaitingRedispatch` surfaced by
141
+ * `/runs/active` and consumed by the client follow loop).
142
+ * < BACKGROUND_FOLLOW_IDLE_TIMEOUT_MS (150s) client's own backstop
143
+ * < UNCLAIMED_BACKGROUND_RUN_REDISPATCH_BOUND_MS (300s) hard, unresettable
144
+ * ceiling — untouched by this constant — past which the slow sweep's
145
+ * existing loud reap (`background_worker_never_started`) still fires.
146
+ */
147
+ export const UNCLAIMED_BACKGROUND_RUN_FAST_SWEEP_MS = 20_000;
148
+
149
+ /**
150
+ * Maximum time the stale reapers (`reapIfStale`, `reapAllStaleRuns`,
151
+ * `cleanupOldRuns`'s heartbeat-stale pass) will suspend reaping a "running"
152
+ * row that is marked in-flight (`in_flight_since`, see `setRunInFlightMarker`)
153
+ * even though its heartbeat/progress liveness basis
154
+ * (`livenessBasisSql`/`backgroundAwareStaleCutoffSql`) has gone stale.
155
+ *
156
+ * WHY a marker column at all: `inFlightWorkCount` in run-manager.ts (the
157
+ * no-progress backstop's guard) is in-memory, per-isolate — but all three
158
+ * reapers above can run in a DIFFERENT isolate than the one holding the
159
+ * producing run (a client's SQL-subscription poll, a sibling isolate's
160
+ * opportunistic `cleanupOldRuns` after ITS OWN run completes, or a fresh
161
+ * boot's `reapAllStaleRuns`). None of them can read another isolate's
162
+ * in-memory counter, so the counter's 0->1 / 1->0 transitions are mirrored
163
+ * into this column (`setRunInFlightMarker`, called from
164
+ * run-manager.ts's `trackInFlightWork`) so it is observable from SQL. This is
165
+ * exactly the gap that let a demonstrably-alive run holding a long tool call
166
+ * or A2A `call-agent` delegation get reaped: the heartbeat WRITE can fail
167
+ * silently (Neon pooler saturation) for the whole `BACKGROUND_RUN_STALE_MS`
168
+ * window while the run is provably still doing work.
169
+ *
170
+ * BOUNDED, not a silent hang — derived from two independent ceilings already
171
+ * in the codebase, not picked by feel:
172
+ * - `DEFAULT_TOOL_TIMEOUT_MS` (12 min, production-agent.ts) is the longest
173
+ * any SINGLE tool call or `agent_call` (A2A delegation) may legitimately
174
+ * stay in flight — past that its own `AbortSignal.timeout` forces a
175
+ * tool_done/error and clears the marker.
176
+ * - `BACKGROUND_SOFT_TIMEOUT_CEILING_MS` (13 min, run-manager.ts) is the
177
+ * background chunk's OWN soft-timeout ceiling. Unlike the no-progress
178
+ * backstop, this timer is NOT gated on in-flight work (see the "secondary"
179
+ * hazard documented next to the soft-timeout timer in run-manager.ts) —
180
+ * it fires unconditionally and checkpoints/continues the run, so by 13
181
+ * minutes the row leaves status='running' via that path regardless of
182
+ * what the marker says.
183
+ * This grace is the LARGER of the two (13 min) plus one `BACKGROUND_RUN_STALE_MS`
184
+ * (90s) buffer for that checkpoint's own completion write to land under the
185
+ * same DB pressure that could have caused the heartbeat to lapse in the first
186
+ * place: 780_000 + 90_000 = 870_000ms (14.5 min). Past that, a "running" row
187
+ * that still shows in-flight work AND a stale liveness basis is not a slow
188
+ * producer anymore — every backstop that should have ended it has ALSO failed
189
+ * to write, and it is reaped loud like any other stale run.
190
+ *
191
+ * Never applied when a caller passes an explicit `maxStaleMs` override to
192
+ * `reapIfStale` — that escape hatch is an exact, caller-chosen window and
193
+ * stays exact. Never weakens the no-in-flight case: a row with no marker set
194
+ * evaluates this grace clause to a no-op and is reaped at the original
195
+ * `BACKGROUND_RUN_STALE_MS` / `RUN_STALE_MS` exactly as before.
196
+ */
197
+ export const IN_FLIGHT_RUN_STALE_GRACE_MS = 14.5 * 60_000; // 870_000
198
+
121
199
  async function ensureRunTables(): Promise<void> {
122
200
  if (!_initPromise) {
123
201
  _initPromise = (async () => {
@@ -225,6 +303,14 @@ async function ensureRunTables(): Promise<void> {
225
303
  // rehydrates the body from this column via the marker's payloadRef.
226
304
  // Cleared on terminal status writes.
227
305
  ["dispatch_payload", "TEXT"],
306
+ // in_flight_since = ms epoch when run-manager's in-memory
307
+ // `inFlightWorkCount` last transitioned 0->1 (a tool call or nested
308
+ // `agent_call`/A2A delegation started), NULL once it drops back to 0.
309
+ // Lets the cross-isolate stale reapers grant a bounded grace to a
310
+ // demonstrably-alive run even when the SAME-isolate heartbeat write
311
+ // has failed. See `IN_FLIGHT_RUN_STALE_GRACE_MS` and
312
+ // `setRunInFlightMarker`.
313
+ ["in_flight_since", intType()],
228
314
  ] as const) {
229
315
  await ensureColumnExists(
230
316
  "agent_runs",
@@ -250,6 +336,7 @@ async function ensureRunTables(): Promise<void> {
250
336
  "completed_at",
251
337
  "heartbeat_at",
252
338
  "last_progress_at",
339
+ "in_flight_since",
253
340
  ]);
254
341
  await widenIntColumnsToBigInt("agent_run_events", ["event_at"]);
255
342
  await widenIntColumnsToBigInt("agent_tool_ledger", ["completed_at"]);
@@ -286,6 +373,18 @@ async function ensureRunTables(): Promise<void> {
286
373
  } catch {
287
374
  // Column already exists — ignore
288
375
  }
376
+ // Backfill in_flight_since — ms epoch when run-manager's in-memory
377
+ // `inFlightWorkCount` last transitioned 0->1, NULL once back to 0. Lets
378
+ // the cross-isolate stale reapers grant a bounded grace to a
379
+ // demonstrably-alive run even when the heartbeat write itself has
380
+ // failed. See `IN_FLIGHT_RUN_STALE_GRACE_MS` and `setRunInFlightMarker`.
381
+ try {
382
+ await client.execute(
383
+ `ALTER TABLE agent_runs ADD COLUMN in_flight_since ${intType()}`,
384
+ );
385
+ } catch {
386
+ // Column already exists — ignore
387
+ }
289
388
  // Backfill turn_id / error_code / error_detail.
290
389
  // turn_id = stable identity for one logical assistant turn that may
291
390
  // span several continuation runs, so the durable record
@@ -339,6 +438,7 @@ async function ensureRunTables(): Promise<void> {
339
438
  "completed_at",
340
439
  "heartbeat_at",
341
440
  "last_progress_at",
441
+ "in_flight_since",
342
442
  ]);
343
443
  await widenIntColumnsToBigInt("agent_run_events", ["event_at"]);
344
444
  await widenIntColumnsToBigInt("agent_tool_ledger", ["completed_at"]);
@@ -529,6 +629,23 @@ function livenessBasisSql(): string {
529
629
  return `(CASE WHEN COALESCE(last_progress_at, started_at) > COALESCE(heartbeat_at, started_at) THEN COALESCE(last_progress_at, started_at) ELSE COALESCE(heartbeat_at, started_at) END)`;
530
630
  }
531
631
 
632
+ /**
633
+ * Additive grace clause for the default (no explicit `maxStaleMs` override)
634
+ * heartbeat/liveness-based stale reap conditions — TRUE (row remains eligible
635
+ * for the surrounding staleness check) unless `in_flight_since` is set AND
636
+ * still inside `IN_FLIGHT_RUN_STALE_GRACE_MS`. A row with no marker set
637
+ * (`in_flight_since IS NULL`, the common case and every pre-existing row
638
+ * before this migration) always evaluates TRUE here, so this can only make
639
+ * reaping MORE conservative — the no-in-flight `BACKGROUND_RUN_STALE_MS` /
640
+ * `RUN_STALE_MS` behavior is unchanged. See `IN_FLIGHT_RUN_STALE_GRACE_MS`'s
641
+ * doc comment for why this is sound and bounded.
642
+ *
643
+ * Binds one param: the same `now` value the surrounding cutoff clause binds.
644
+ */
645
+ function inFlightGraceSql(): string {
646
+ return `(in_flight_since IS NULL OR in_flight_since <= (CAST(? AS BIGINT) - ${IN_FLIGHT_RUN_STALE_GRACE_MS}))`;
647
+ }
648
+
532
649
  /**
533
650
  * Atomically claim a background-dispatched run for processing. The foreground
534
651
  * POST inserts the run row with `dispatch_mode = 'background'`; the FIRST
@@ -1139,12 +1256,57 @@ export async function updateRunHeartbeat(runId: string): Promise<void> {
1139
1256
  export async function bumpRunProgress(runId: string): Promise<void> {
1140
1257
  await ensureRunTables();
1141
1258
  const client = getDbExec();
1259
+ const now = Date.now();
1142
1260
  await client.execute({
1143
- sql: `UPDATE agent_runs SET last_progress_at = ? WHERE id = ?`,
1144
- args: [Date.now(), runId],
1261
+ // Multiple event-persistence paths and serverless isolates can bump the
1262
+ // same run concurrently. A slower, older write must never land after a
1263
+ // newer one and move the user-visible no-progress clock backwards.
1264
+ // CASE keeps this portable across SQLite and Postgres.
1265
+ sql: `UPDATE agent_runs SET last_progress_at = CASE WHEN last_progress_at IS NULL OR last_progress_at < ? THEN ? ELSE last_progress_at END WHERE id = ? AND status = 'running'`,
1266
+ args: [now, now, runId],
1145
1267
  });
1146
1268
  }
1147
1269
 
1270
+ /**
1271
+ * Mirror run-manager's in-memory `inFlightWorkCount` 0<->N transitions into
1272
+ * SQL so a stale reaper running in a DIFFERENT isolate can tell a
1273
+ * demonstrably-alive run (holding a tool call or A2A `agent_call` delegation)
1274
+ * apart from a genuinely dead one — see `IN_FLIGHT_RUN_STALE_GRACE_MS`'s doc
1275
+ * comment for the full reasoning.
1276
+ *
1277
+ * `inFlight: true` only writes when the row is still `NULL` — a defense-in-
1278
+ * depth belt-and-suspenders against a nested 1->2 transition clobbering the
1279
+ * ORIGINAL start time with a later one (the caller's own counter already
1280
+ * dedupes 0->1 transitions; this WHERE just makes the write itself
1281
+ * idempotent/order-independent too). `inFlight: false` always clears
1282
+ * unconditionally — if it races a fresh 0->1 write from a *different* tool
1283
+ * finishing/starting back to back, worst case is losing a few seconds of
1284
+ * grace, never gaining an incorrect one.
1285
+ *
1286
+ * Best-effort: callers fire-and-forget (`.catch(() => {})`) so a write
1287
+ * failure here never blocks event emission or aborts the run. If this write
1288
+ * itself fails (the same DB pressure that could be starving the heartbeat),
1289
+ * the row simply gets no grace — never worse than today's behavior.
1290
+ */
1291
+ export async function setRunInFlightMarker(
1292
+ runId: string,
1293
+ inFlight: boolean,
1294
+ ): Promise<void> {
1295
+ await ensureRunTables();
1296
+ const client = getDbExec();
1297
+ if (inFlight) {
1298
+ await client.execute({
1299
+ sql: `UPDATE agent_runs SET in_flight_since = ? WHERE id = ? AND status = 'running' AND in_flight_since IS NULL`,
1300
+ args: [Date.now(), runId],
1301
+ });
1302
+ } else {
1303
+ await client.execute({
1304
+ sql: `UPDATE agent_runs SET in_flight_since = NULL WHERE id = ?`,
1305
+ args: [runId],
1306
+ });
1307
+ }
1308
+ }
1309
+
1148
1310
  /**
1149
1311
  * If the given run is marked "running" in SQL but its heartbeat is stale
1150
1312
  * (producer likely crashed), flip it to "errored" so watchers stop waiting.
@@ -1160,13 +1322,20 @@ export async function reapIfStale(
1160
1322
  const completedAt = Date.now();
1161
1323
  // Background-dispatched runs get the wider stale window so a slow cold-start
1162
1324
  // isn't reaped; foreground runs keep the tight 15s window. An explicit
1163
- // override forces a flat window for callers that want one.
1325
+ // override forces a flat window for callers that want one — and, like that
1326
+ // override already bypasses the background-aware widening, it also bypasses
1327
+ // the in-flight grace below: an explicit `maxStaleMs` is an exact,
1328
+ // caller-chosen window and stays exact.
1164
1329
  const staleClause =
1165
1330
  typeof maxStaleMs === "number"
1166
1331
  ? `${livenessBasisSql()} < ?`
1167
- : `${livenessBasisSql()} < ${backgroundAwareStaleCutoffSql()}`;
1332
+ : `${livenessBasisSql()} < ${backgroundAwareStaleCutoffSql()} AND ${inFlightGraceSql()}`;
1168
1333
  const staleArgs =
1169
- typeof maxStaleMs === "number" ? [completedAt - maxStaleMs] : [completedAt];
1334
+ typeof maxStaleMs === "number"
1335
+ ? [completedAt - maxStaleMs]
1336
+ : // First `?` is backgroundAwareStaleCutoffSql's CAST param, second is
1337
+ // inFlightGraceSql's — both bound to the same "now".
1338
+ [completedAt, completedAt];
1170
1339
  const { rowsAffected } = await client.execute({
1171
1340
  sql: `UPDATE agent_runs
1172
1341
  SET status = 'errored',
@@ -1500,12 +1669,23 @@ export async function getRunByThread(
1500
1669
  dispatchMode: string | null;
1501
1670
  terminalReason: string | null;
1502
1671
  diagStage: string | null;
1672
+ /**
1673
+ * Raw `in_flight_since` marker (see `setRunInFlightMarker`) — non-null
1674
+ * exactly when run-manager's in-memory `inFlightWorkCount` was last known
1675
+ * (from THIS row's own producer) to be > 0: a tool call or A2A `agent_call`
1676
+ * delegation is open and has not yet resolved. Callers that want the
1677
+ * authoritative "does this run currently hold live work" signal (e.g. the
1678
+ * `hasInFlightWork` wire field on `/runs/active`) should test this for
1679
+ * non-null, not re-derive their own notion of in-flight — see
1680
+ * `getActiveRunForThreadAsync` in run-manager.ts.
1681
+ */
1682
+ inFlightSince: number | null;
1503
1683
  } | null> {
1504
1684
  await ensureRunTables();
1505
1685
  const client = getDbExec();
1506
1686
  const sql = options?.includeTerminal
1507
- ? `SELECT id, thread_id, turn_id, status, started_at, heartbeat_at, completed_at, last_progress_at, dispatch_mode, terminal_reason, diag_stage, error_code FROM agent_runs WHERE thread_id = ? ORDER BY started_at DESC LIMIT 1`
1508
- : `SELECT id, thread_id, turn_id, status, started_at, heartbeat_at, completed_at, last_progress_at, dispatch_mode, terminal_reason, diag_stage, error_code FROM agent_runs WHERE thread_id = ? AND status = 'running' ORDER BY started_at DESC LIMIT 1`;
1687
+ ? `SELECT id, thread_id, turn_id, status, started_at, heartbeat_at, completed_at, last_progress_at, dispatch_mode, terminal_reason, diag_stage, error_code, in_flight_since FROM agent_runs WHERE thread_id = ? ORDER BY started_at DESC LIMIT 1`
1688
+ : `SELECT id, thread_id, turn_id, status, started_at, heartbeat_at, completed_at, last_progress_at, dispatch_mode, terminal_reason, diag_stage, error_code, in_flight_since FROM agent_runs WHERE thread_id = ? AND status = 'running' ORDER BY started_at DESC LIMIT 1`;
1509
1689
  const { rows } = await client.execute({ sql, args: [threadId] });
1510
1690
  if (rows.length === 0) return null;
1511
1691
  const r = rows[0] as {
@@ -1521,6 +1701,7 @@ export async function getRunByThread(
1521
1701
  terminal_reason?: string | null;
1522
1702
  diag_stage?: string | null;
1523
1703
  error_code?: string | null;
1704
+ in_flight_since?: number | string | null;
1524
1705
  };
1525
1706
  const canReconcileFromEvents =
1526
1707
  r.status === "running" ||
@@ -1542,6 +1723,7 @@ export async function getRunByThread(
1542
1723
  dispatchMode: r.dispatch_mode ?? null,
1543
1724
  terminalReason: r.terminal_reason ?? null,
1544
1725
  diagStage: r.diag_stage ?? null,
1726
+ inFlightSince: r.in_flight_since == null ? null : Number(r.in_flight_since),
1545
1727
  };
1546
1728
  }
1547
1729
 
@@ -1706,12 +1888,21 @@ export async function reapAllStaleRuns(): Promise<number> {
1706
1888
  await ensureRunTables();
1707
1889
  const client = getDbExec();
1708
1890
  const now = Date.now();
1709
- // Background-dispatched runs use the wider window; everything else 15s.
1891
+ // Background-dispatched runs use the wider window; everything else 15s. The
1892
+ // in-flight grace clause is applied identically to this SELECT and the
1893
+ // UPDATE below (both derive `stale.rows`/the terminal-event-append loop
1894
+ // from the SAME predicate) so a row the grace clause protects from the
1895
+ // UPDATE is never mistakenly given a terminal event anyway — see
1896
+ // `inFlightGraceSql` and `IN_FLIGHT_RUN_STALE_GRACE_MS`. This runs at
1897
+ // server startup across possibly-multiple isolates, so a sibling isolate's
1898
+ // still-alive, in-flight run must not be reaped just because THIS isolate
1899
+ // just booted and has no heartbeat history for it.
1710
1900
  const stale = await client.execute({
1711
1901
  sql: `SELECT id FROM agent_runs
1712
1902
  WHERE status = 'running'
1713
- AND ${livenessBasisSql()} < ${backgroundAwareStaleCutoffSql()}`,
1714
- args: [now],
1903
+ AND ${livenessBasisSql()} < ${backgroundAwareStaleCutoffSql()}
1904
+ AND ${inFlightGraceSql()}`,
1905
+ args: [now, now],
1715
1906
  });
1716
1907
  for (const row of stale.rows) {
1717
1908
  const id = (row as { id?: unknown }).id;
@@ -1729,13 +1920,15 @@ export async function reapAllStaleRuns(): Promise<number> {
1729
1920
  terminal_reason = ?
1730
1921
  WHERE status = 'running'
1731
1922
  AND ${terminalRunEventExclusionSql()}
1732
- AND ${livenessBasisSql()} < ${backgroundAwareStaleCutoffSql()}`,
1923
+ AND ${livenessBasisSql()} < ${backgroundAwareStaleCutoffSql()}
1924
+ AND ${inFlightGraceSql()}`,
1733
1925
  args: [
1734
1926
  completedAt,
1735
1927
  STALE_RUN_ERROR_EVENT.errorCode,
1736
1928
  STALE_RUN_ERROR_EVENT.details,
1737
1929
  STALE_RUN_ERROR_EVENT.errorCode,
1738
1930
  completedAt,
1931
+ completedAt,
1739
1932
  ],
1740
1933
  });
1741
1934
  for (const row of stale.rows) {
@@ -1770,15 +1963,24 @@ export async function cleanupOldRuns(
1770
1963
  // SELECT covers BOTH UPDATE conditions so the terminal-event-append loop
1771
1964
  // below catches every row we're about to flip — a 24h-old row with a
1772
1965
  // somehow-fresh heartbeat would slip past a heartbeat-only SELECT.
1966
+ //
1967
+ // The in-flight grace clause is applied ONLY to the heartbeat-based branch
1968
+ // (mirroring the second UPDATE below), never the absolute-age branch:
1969
+ // nothing can legitimately hold in-flight work anywhere near `olderThanMs`
1970
+ // (default on the order of a day) — `IN_FLIGHT_RUN_STALE_GRACE_MS` bounds
1971
+ // any real grace at ~14.5 minutes — so a row that old is dead regardless of
1972
+ // its in-flight marker. This runs opportunistically after EVERY run
1973
+ // completes in ANY isolate, so a different thread's still-in-flight A2A
1974
+ // call must not be reaped as a side effect of an unrelated run finishing.
1773
1975
  const now = Date.now();
1774
1976
  const stale = await client.execute({
1775
1977
  sql: `SELECT id FROM agent_runs
1776
1978
  WHERE status = 'running'
1777
1979
  AND (
1778
- ${livenessBasisSql()} < ${backgroundAwareStaleCutoffSql()}
1980
+ (${livenessBasisSql()} < ${backgroundAwareStaleCutoffSql()} AND ${inFlightGraceSql()})
1779
1981
  OR started_at < ?
1780
1982
  )`,
1781
- args: [now, cutoff],
1983
+ args: [now, now, cutoff],
1782
1984
  });
1783
1985
  for (const row of stale.rows) {
1784
1986
  const id = (row as { id?: unknown }).id;
@@ -1806,7 +2008,13 @@ export async function cleanupOldRuns(
1806
2008
  ],
1807
2009
  });
1808
2010
  // Also expire runs whose heartbeat is stale — producer has died. Uses the
1809
- // background-aware window so a slow background cold-start isn't reaped early.
2011
+ // background-aware window so a slow background cold-start isn't reaped
2012
+ // early, and the in-flight grace so a demonstrably-alive run holding a tool
2013
+ // call / A2A delegation survives a heartbeat write failure. Must match the
2014
+ // SELECT's heartbeat branch above exactly — the terminal-event-append loop
2015
+ // below fires for every row the SELECT returned, so a mismatch would
2016
+ // silently inject a terminal error event onto a row this UPDATE left
2017
+ // status='running'.
1810
2018
  await client.execute({
1811
2019
  sql: `UPDATE agent_runs
1812
2020
  SET status = 'errored',
@@ -1816,13 +2024,15 @@ export async function cleanupOldRuns(
1816
2024
  terminal_reason = ?
1817
2025
  WHERE status = 'running'
1818
2026
  AND ${terminalRunEventExclusionSql()}
1819
- AND ${livenessBasisSql()} < ${backgroundAwareStaleCutoffSql()}`,
2027
+ AND ${livenessBasisSql()} < ${backgroundAwareStaleCutoffSql()}
2028
+ AND ${inFlightGraceSql()}`,
1820
2029
  args: [
1821
2030
  completedAt,
1822
2031
  STALE_RUN_ERROR_EVENT.errorCode,
1823
2032
  STALE_RUN_ERROR_EVENT.details,
1824
2033
  STALE_RUN_ERROR_EVENT.errorCode,
1825
2034
  completedAt,
2035
+ completedAt,
1826
2036
  ],
1827
2037
  });
1828
2038
  for (const row of stale.rows) {
@@ -274,6 +274,29 @@ export type AgentChatEvent =
274
274
  agent: string;
275
275
  status: "start" | "done" | "error";
276
276
  }
277
+ | {
278
+ /**
279
+ * Periodic liveness for an in-flight cross-app A2A call. Emitted by the
280
+ * `call-agent` action once per throttle window ONLY when a real poll
281
+ * round-trip to the remote agent succeeds and reports a non-terminal
282
+ * state — never on a timer, so a hung/dead remote emits nothing and the
283
+ * stuck-detector can still fire. Counts as real progress in
284
+ * `run-manager`'s `shouldBumpProgressForEvent` (any non-special event
285
+ * type does), which keeps `last_progress_at` fresh so a slow-but-healthy
286
+ * sub-agent call doesn't trip the client's stuck banner. A distinct
287
+ * event type (not an `agent_call` status) so existing `agent_call`
288
+ * consumers that treat "not start/done" as a failure don't render an
289
+ * in-flight tick as an error.
290
+ */
291
+ type: "agent_call_progress";
292
+ agent: string;
293
+ /** Remote A2A task state for this poll, e.g. "working" | "submitted". */
294
+ state: string;
295
+ /** Elapsed wall-clock seconds since the cross-app call began. */
296
+ elapsedSeconds: number;
297
+ /** Optional short text surfaced from the remote poll, when present. */
298
+ detail?: string;
299
+ }
277
300
  | { type: "agent_call_text"; agent: string; text: string }
278
301
  | {
279
302
  type: "agent_task";