@agent-native/core 0.131.5 → 0.131.7

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 (350) hide show
  1. package/corpus/README.md +3 -3
  2. package/corpus/core/CHANGELOG.md +70 -0
  3. package/corpus/core/docs/content/agent-native-toolkit.mdx +13 -6
  4. package/corpus/core/docs/content/cloneable-saas.mdx +5 -5
  5. package/corpus/core/docs/content/creating-templates.mdx +9 -0
  6. package/corpus/core/docs/content/deployment.mdx +18 -12
  7. package/corpus/core/docs/content/doctor.mdx +8 -1
  8. package/corpus/core/docs/content/drop-in-agent.mdx +1 -1
  9. package/corpus/core/docs/content/extensions.mdx +18 -18
  10. package/corpus/core/docs/content/faq.mdx +4 -4
  11. package/corpus/core/docs/content/key-concepts.mdx +30 -21
  12. package/corpus/core/docs/content/security.mdx +2 -2
  13. package/corpus/core/docs/content/template-brain-developers.mdx +4 -1
  14. package/corpus/core/docs/content/template-mail-developers.mdx +4 -1
  15. package/corpus/core/docs/content/what-is-agent-native.mdx +6 -6
  16. package/corpus/core/package.json +1 -1
  17. package/corpus/core/src/a2a/client.ts +449 -66
  18. package/corpus/core/src/a2a/correlation.ts +31 -0
  19. package/corpus/core/src/a2a/invoke.ts +4 -2
  20. package/corpus/core/src/a2a/types.ts +4 -0
  21. package/corpus/core/src/action.ts +3 -0
  22. package/corpus/core/src/agent/action-continuation-guidance.ts +2 -1
  23. package/corpus/core/src/agent/engine/registry.ts +98 -6
  24. package/corpus/core/src/agent/production-agent.ts +151 -18
  25. package/corpus/core/src/agent/run-loop-with-resume.ts +190 -3
  26. package/corpus/core/src/agent/run-manager.ts +117 -41
  27. package/corpus/core/src/agent/thread-debug-history.ts +86 -0
  28. package/corpus/core/src/agent/types.ts +3 -1
  29. package/corpus/core/src/cli/create.ts +11 -1
  30. package/corpus/core/src/cli/templates-meta.ts +2 -2
  31. package/corpus/core/src/client/agent-chat-adapter.ts +91 -13
  32. package/corpus/core/src/client/resources/McpIntegrationDialog.tsx +11 -9
  33. package/corpus/core/src/client/sse-event-processor.ts +17 -3
  34. package/corpus/core/src/db/client.ts +57 -17
  35. package/corpus/core/src/guards/no-env-credentials.ts +2 -0
  36. package/corpus/core/src/integrations/adapters/slack.ts +8 -3
  37. package/corpus/core/src/localization/default-messages.ts +44 -0
  38. package/corpus/core/src/observability/traces.ts +78 -5
  39. package/corpus/core/src/scripts/call-agent.ts +294 -11
  40. package/corpus/core/src/scripts/describe-workspace-apps.ts +2 -2
  41. package/corpus/core/src/secrets/crypto.ts +156 -35
  42. package/corpus/core/src/secrets/storage.ts +64 -26
  43. package/corpus/core/src/server/agent-capabilities.ts +1 -1
  44. package/corpus/core/src/server/agent-chat/action-filters-a2a.ts +113 -7
  45. package/corpus/core/src/server/agent-chat/context-tools.ts +2 -0
  46. package/corpus/core/src/server/agent-chat/plugin-options.ts +34 -1
  47. package/corpus/core/src/server/agent-chat/prompt-resources.ts +1 -1
  48. package/corpus/core/src/server/agent-chat-plugin.ts +91 -59
  49. package/corpus/core/src/templates/default/.agents/skills/secrets/SKILL.md +19 -7
  50. package/corpus/core/src/templates/headless/.agents/skills/secrets/SKILL.md +19 -7
  51. package/corpus/core/src/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +18 -7
  52. package/corpus/core/src/templates/workspace-core/.agents/skills/composable-mini-apps/SKILL.md +15 -14
  53. package/corpus/core/src/templates/workspace-core/.agents/skills/secrets/SKILL.md +19 -7
  54. package/corpus/core/src/vite/client.ts +1 -0
  55. package/corpus/templates/analytics/.agents/skills/dashboard-ops/SKILL.md +5 -4
  56. package/corpus/templates/analytics/.agents/skills/gong/SKILL.md +6 -4
  57. package/corpus/templates/analytics/AGENTS.md +7 -4
  58. package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +4 -3
  59. package/corpus/templates/analytics/changelog/2026-07-30-delegated-analytics-questions-now-return-a-useful-current-me.md +6 -0
  60. package/corpus/templates/analytics/changelog/2026-07-30-scheduled-dashboard-emails-complete-every-panel-without-pool.md +6 -0
  61. package/corpus/templates/analytics/scripts/emit-netlify-dashboard-report-cron.ts +28 -1
  62. package/corpus/templates/analytics/server/jobs/dashboard-report.ts +18 -11
  63. package/corpus/templates/analytics/server/lib/analytics-connector-catalog.ts +4 -4
  64. package/corpus/templates/analytics/server/lib/canonical-first-party-dashboard-repair.ts +9 -5
  65. package/corpus/templates/analytics/server/lib/dashboard-panel-query.ts +6 -2
  66. package/corpus/templates/analytics/server/lib/dashboard-panel-source-resolver.ts +11 -4
  67. package/corpus/templates/analytics/server/lib/dashboard-report-render.ts +49 -31
  68. package/corpus/templates/analytics/server/lib/first-party-analytics.ts +16 -8
  69. package/corpus/templates/analytics/server/lib/first-party-metric-catalog.ts +9 -3
  70. package/corpus/templates/analytics/server/lib/production-serverless-runtime.ts +11 -0
  71. package/corpus/templates/analytics/server/lib/real-data-actions.ts +10 -0
  72. package/corpus/templates/analytics/server/plugins/agent-chat.ts +3 -2
  73. package/corpus/templates/analytics/server/plugins/analytics-alert-jobs.ts +2 -1
  74. package/corpus/templates/analytics/server/plugins/dashboard-report-jobs.ts +2 -1
  75. package/corpus/templates/analytics/server/plugins/uptime-monitor-jobs.ts +1 -12
  76. package/corpus/templates/brain/.agents/skills/brain/RUNBOOK.md +54 -6
  77. package/corpus/templates/brain/.agents/skills/brain/SKILL.md +20 -9
  78. package/corpus/templates/brain/.agents/skills/ingestion-and-connectors/SKILL.md +33 -1
  79. package/corpus/templates/brain/AGENTS.md +3 -1
  80. package/corpus/templates/brain/README.md +4 -1
  81. package/corpus/templates/brain/actions/_schemas.ts +30 -8
  82. package/corpus/templates/brain/actions/ask-brain.ts +124 -14
  83. package/corpus/templates/brain/actions/create-source.ts +18 -2
  84. package/corpus/templates/brain/actions/enqueue-captures-distillation.ts +8 -123
  85. package/corpus/templates/brain/actions/enqueue-distillation.ts +6 -127
  86. package/corpus/templates/brain/actions/import-capture.ts +17 -5
  87. package/corpus/templates/brain/actions/import-transcript.ts +17 -5
  88. package/corpus/templates/brain/actions/update-source.ts +25 -5
  89. package/corpus/templates/brain/app/components/layout/Sidebar.tsx +1 -1
  90. package/corpus/templates/brain/changelog/2026-07-30-blessed-resources-can-feed-cited-company-answers.md +6 -0
  91. package/corpus/templates/brain/changelog/2026-07-30-the-left-sidebar-no-longer-shows-a-blank-organization-placeh.md +6 -0
  92. package/corpus/templates/brain/server/lib/brain.ts +49 -19
  93. package/corpus/templates/brain/server/lib/distillation-queue.ts +147 -0
  94. package/corpus/templates/brain/server/lib/source-policy.ts +264 -0
  95. package/corpus/templates/brain/server/plugins/agent-chat.ts +3 -2
  96. package/corpus/templates/brain/server/routes/api/_agent-native/brain/ingest.post.ts +116 -19
  97. package/corpus/templates/clips/app/components/meetings/google-oauth-identity-notice.tsx +51 -0
  98. package/corpus/templates/clips/app/i18n/en-US.ts +4 -0
  99. package/corpus/templates/clips/app/routes/_app.meetings._index.tsx +3 -1
  100. package/corpus/templates/clips/changelog/2026-07-30-google-calendar-warning.md +6 -0
  101. package/corpus/templates/content/app/components/editor/VisualEditor.tsx +72 -8
  102. package/corpus/templates/content/changelog/2026-07-30-the-slash-command-hint-now-stays-on-only-the-active-empty-li.md +6 -0
  103. package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +506 -11
  104. package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +148 -17
  105. package/corpus/templates/design/app/components/design/canvas-interactions/design-canvas-interactions.ts +357 -0
  106. package/corpus/templates/design/app/components/design/inspector/ScrubInput.tsx +7 -466
  107. package/corpus/templates/design/app/components/design/inspector/scrub-input-utils.ts +15 -311
  108. package/corpus/templates/design/app/components/visual-editor/CanvasCommentPins.tsx +19 -997
  109. package/corpus/templates/design/app/components/visual-editor/DrawOverlay.tsx +8 -1216
  110. package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +31 -38
  111. package/corpus/templates/design/package.json +0 -1
  112. package/corpus/templates/dispatch/AGENTS.md +8 -0
  113. package/corpus/templates/dispatch/DEVELOPING.md +29 -0
  114. package/corpus/templates/dispatch/actions/view-screen.ts +34 -2
  115. package/corpus/templates/dispatch/app/i18n-data.ts +457 -0
  116. package/corpus/templates/dispatch/changelog/2026-07-30-delegated-dispatch-work-continues-reliably-in-the-background.md +6 -0
  117. package/corpus/templates/dispatch/changelog/2026-07-30-find-failed-runs-across-apps.md +6 -0
  118. package/corpus/templates/dispatch/netlify.toml +3 -0
  119. package/corpus/templates/plan/actions/get-visual-plan.ts +10 -6
  120. package/corpus/templates/plan/actions/patch-visual-plan-source.ts +117 -1
  121. package/corpus/templates/plan/actions/update-visual-plan.ts +56 -14
  122. package/corpus/templates/plan/app/pages/PlansPage.tsx +1 -1
  123. package/corpus/templates/plan/changelog/2026-07-30-plan-agents-recover-with-targeted-writes.md +6 -0
  124. package/corpus/templates/plan/shared/plan-content.ts +35 -0
  125. package/corpus/templates/slides/.agents/skills/analytics-data-for-decks/SKILL.md +8 -12
  126. package/corpus/templates/slides/AGENTS.md +4 -4
  127. package/corpus/templates/slides/actions/create-deck.ts +1 -1
  128. package/corpus/templates/slides/actions/duplicate-deck.ts +19 -4
  129. package/corpus/templates/slides/app/components/deck/DeckCard.tsx +2 -10
  130. package/corpus/templates/slides/app/components/deck/MermaidRenderer.tsx +12 -1
  131. package/corpus/templates/slides/app/components/deck/SlideRenderer.tsx +30 -13
  132. package/corpus/templates/slides/app/components/editor/DeckEditorSkeleton.tsx +35 -0
  133. package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +63 -56
  134. package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +21 -76
  135. package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +1110 -292
  136. package/corpus/templates/slides/app/components/editor/SlideOverflowWarning.tsx +53 -0
  137. package/corpus/templates/slides/app/components/editor/SlideStyleInspector.tsx +235 -18
  138. package/corpus/templates/slides/app/components/editor/SpeakerNotesPanel.tsx +4 -1
  139. package/corpus/templates/slides/app/components/editor/canvas-interactions/index.ts +11 -0
  140. package/corpus/templates/slides/app/components/editor/canvas-interactions/slides-canvas-adapter.ts +129 -0
  141. package/corpus/templates/slides/app/components/editor/selection-overlay-measurement.ts +70 -0
  142. package/corpus/templates/slides/app/components/editor/slide-object-interactions.ts +519 -65
  143. package/corpus/templates/slides/app/components/visual-editor/CanvasCommentPins.tsx +36 -426
  144. package/corpus/templates/slides/app/components/visual-editor/DrawOverlay.tsx +19 -458
  145. package/corpus/templates/slides/app/context/DeckContext.tsx +179 -72
  146. package/corpus/templates/slides/app/global.css +105 -0
  147. package/corpus/templates/slides/app/i18n/en-US.ts +8 -0
  148. package/corpus/templates/slides/app/lib/deck-editor-loading.ts +26 -0
  149. package/corpus/templates/slides/app/lib/mermaid-blocks.ts +27 -0
  150. package/corpus/templates/slides/app/pages/DeckEditor.tsx +71 -38
  151. package/corpus/templates/slides/app/pages/Index.tsx +98 -41
  152. package/corpus/templates/slides/changelog/2026-07-30-deck-loading-no-longer-flashes-an-unavailable-message.md +6 -0
  153. package/corpus/templates/slides/changelog/2026-07-30-duplicating-a-deck-from-the-deck-list-now-opens-the-copy-imm.md +6 -0
  154. package/corpus/templates/slides/changelog/2026-07-30-layout-overflow-warning-is-readable-and-dismissible.md +6 -0
  155. package/corpus/templates/slides/changelog/2026-07-30-new-decks-now-start-with-an-empty-slide-list-when-no-slides-.md +6 -0
  156. package/corpus/templates/slides/changelog/2026-07-30-shared-canvas-annotations.md +6 -0
  157. package/corpus/templates/slides/changelog/2026-07-30-slide-objects-can-be-moved-as-a-group-copied-and-pasted-with.md +6 -0
  158. package/corpus/templates/slides/changelog/2026-07-30-slide-text-editing-and-object-controls-now-match-google-slides.md +6 -0
  159. package/corpus/templates/slides/changelog/2026-07-30-style-panel-now-scrolls-with-speaker-notes-open-shows-the-sl.md +6 -0
  160. package/corpus/templates/slides/changelog/2026-07-30-top-toolbar-controls-now-use-consistent-sizing-with-undo-and.md +6 -0
  161. package/corpus/templates/slides/netlify.toml +3 -1
  162. package/corpus/templates/slides/package.json +0 -1
  163. package/corpus/templates/slides/server/lib/chat-attachments.ts +18 -0
  164. package/corpus/templates/slides/server/plugins/agent-chat.ts +5 -0
  165. package/corpus/templates/slides/vite.config.ts +0 -1
  166. package/corpus/toolkit/CHANGELOG.md +13 -0
  167. package/corpus/toolkit/README.md +19 -0
  168. package/corpus/toolkit/agent-native.eject.json +38 -0
  169. package/corpus/toolkit/package.json +29 -1
  170. package/corpus/toolkit/src/canvas-annotations/CanvasCommentPins.tsx +861 -0
  171. package/corpus/toolkit/src/canvas-annotations/DrawOverlay.tsx +1233 -0
  172. package/corpus/toolkit/src/canvas-annotations/index.ts +15 -0
  173. package/corpus/toolkit/src/canvas-annotations/types.ts +14 -0
  174. package/corpus/toolkit/src/canvas-interactions/canvas-interactions.ts +933 -0
  175. package/corpus/toolkit/src/canvas-interactions/index.ts +67 -0
  176. package/corpus/toolkit/src/design-tweaks/scrub-input-utils.ts +311 -0
  177. package/corpus/toolkit/src/design-tweaks/scrub-input.tsx +491 -0
  178. package/corpus/toolkit/src/design-tweaks/visual-style-controls.tsx +26 -171
  179. package/corpus/toolkit/src/index.ts +1 -0
  180. package/dist/a2a/client.d.ts +23 -0
  181. package/dist/a2a/client.d.ts.map +1 -1
  182. package/dist/a2a/client.js +309 -44
  183. package/dist/a2a/client.js.map +1 -1
  184. package/dist/a2a/correlation.d.ts +1 -0
  185. package/dist/a2a/correlation.d.ts.map +1 -1
  186. package/dist/a2a/correlation.js +27 -0
  187. package/dist/a2a/correlation.js.map +1 -1
  188. package/dist/a2a/invoke.d.ts.map +1 -1
  189. package/dist/a2a/invoke.js +4 -2
  190. package/dist/a2a/invoke.js.map +1 -1
  191. package/dist/a2a/types.d.ts +4 -0
  192. package/dist/a2a/types.d.ts.map +1 -1
  193. package/dist/a2a/types.js.map +1 -1
  194. package/dist/action.d.ts +3 -0
  195. package/dist/action.d.ts.map +1 -1
  196. package/dist/action.js.map +1 -1
  197. package/dist/agent/action-continuation-guidance.d.ts.map +1 -1
  198. package/dist/agent/action-continuation-guidance.js +2 -1
  199. package/dist/agent/action-continuation-guidance.js.map +1 -1
  200. package/dist/agent/engine/registry.d.ts.map +1 -1
  201. package/dist/agent/engine/registry.js +82 -8
  202. package/dist/agent/engine/registry.js.map +1 -1
  203. package/dist/agent/production-agent.d.ts +40 -1
  204. package/dist/agent/production-agent.d.ts.map +1 -1
  205. package/dist/agent/production-agent.js +113 -15
  206. package/dist/agent/production-agent.js.map +1 -1
  207. package/dist/agent/run-loop-with-resume.d.ts +21 -0
  208. package/dist/agent/run-loop-with-resume.d.ts.map +1 -1
  209. package/dist/agent/run-loop-with-resume.js +163 -4
  210. package/dist/agent/run-loop-with-resume.js.map +1 -1
  211. package/dist/agent/run-manager.d.ts +16 -9
  212. package/dist/agent/run-manager.d.ts.map +1 -1
  213. package/dist/agent/run-manager.js +93 -42
  214. package/dist/agent/run-manager.js.map +1 -1
  215. package/dist/agent/thread-debug-history.d.ts +10 -0
  216. package/dist/agent/thread-debug-history.d.ts.map +1 -0
  217. package/dist/agent/thread-debug-history.js +68 -0
  218. package/dist/agent/thread-debug-history.js.map +1 -0
  219. package/dist/agent/types.d.ts +3 -1
  220. package/dist/agent/types.d.ts.map +1 -1
  221. package/dist/agent/types.js.map +1 -1
  222. package/dist/cli/create.d.ts.map +1 -1
  223. package/dist/cli/create.js +6 -1
  224. package/dist/cli/create.js.map +1 -1
  225. package/dist/cli/templates-meta.js +2 -2
  226. package/dist/cli/templates-meta.js.map +1 -1
  227. package/dist/client/agent-chat-adapter.d.ts +1 -1
  228. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  229. package/dist/client/agent-chat-adapter.js +76 -13
  230. package/dist/client/agent-chat-adapter.js.map +1 -1
  231. package/dist/client/resources/McpIntegrationDialog.d.ts.map +1 -1
  232. package/dist/client/resources/McpIntegrationDialog.js +1 -1
  233. package/dist/client/resources/McpIntegrationDialog.js.map +1 -1
  234. package/dist/client/sse-event-processor.d.ts.map +1 -1
  235. package/dist/client/sse-event-processor.js +12 -3
  236. package/dist/client/sse-event-processor.js.map +1 -1
  237. package/dist/collab/routes.d.ts +1 -1
  238. package/dist/db/client.d.ts.map +1 -1
  239. package/dist/db/client.js +48 -17
  240. package/dist/db/client.js.map +1 -1
  241. package/dist/guards/no-env-credentials.d.ts.map +1 -1
  242. package/dist/guards/no-env-credentials.js +2 -0
  243. package/dist/guards/no-env-credentials.js.map +1 -1
  244. package/dist/integrations/adapters/slack.js +7 -3
  245. package/dist/integrations/adapters/slack.js.map +1 -1
  246. package/dist/localization/default-messages.d.ts +43 -0
  247. package/dist/localization/default-messages.d.ts.map +1 -1
  248. package/dist/localization/default-messages.js +43 -0
  249. package/dist/localization/default-messages.js.map +1 -1
  250. package/dist/observability/traces.d.ts +3 -1
  251. package/dist/observability/traces.d.ts.map +1 -1
  252. package/dist/observability/traces.js +73 -4
  253. package/dist/observability/traces.js.map +1 -1
  254. package/dist/progress/routes.d.ts +1 -1
  255. package/dist/provider-api/actions/custom-provider-registration.d.ts +12 -12
  256. package/dist/provider-api/actions/provider-api.d.ts +13 -13
  257. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  258. package/dist/scripts/call-agent.d.ts.map +1 -1
  259. package/dist/scripts/call-agent.js +237 -12
  260. package/dist/scripts/call-agent.js.map +1 -1
  261. package/dist/scripts/describe-workspace-apps.js +2 -2
  262. package/dist/scripts/describe-workspace-apps.js.map +1 -1
  263. package/dist/secrets/crypto.d.ts +36 -21
  264. package/dist/secrets/crypto.d.ts.map +1 -1
  265. package/dist/secrets/crypto.js +134 -33
  266. package/dist/secrets/crypto.js.map +1 -1
  267. package/dist/secrets/storage.d.ts +6 -6
  268. package/dist/secrets/storage.d.ts.map +1 -1
  269. package/dist/secrets/storage.js +43 -26
  270. package/dist/secrets/storage.js.map +1 -1
  271. package/dist/server/agent-capabilities.js +1 -1
  272. package/dist/server/agent-capabilities.js.map +1 -1
  273. package/dist/server/agent-chat/action-filters-a2a.d.ts +17 -3
  274. package/dist/server/agent-chat/action-filters-a2a.d.ts.map +1 -1
  275. package/dist/server/agent-chat/action-filters-a2a.js +94 -3
  276. package/dist/server/agent-chat/action-filters-a2a.js.map +1 -1
  277. package/dist/server/agent-chat/context-tools.d.ts.map +1 -1
  278. package/dist/server/agent-chat/context-tools.js +2 -0
  279. package/dist/server/agent-chat/context-tools.js.map +1 -1
  280. package/dist/server/agent-chat/plugin-options.d.ts +23 -0
  281. package/dist/server/agent-chat/plugin-options.d.ts.map +1 -1
  282. package/dist/server/agent-chat/plugin-options.js +4 -1
  283. package/dist/server/agent-chat/plugin-options.js.map +1 -1
  284. package/dist/server/agent-chat/prompt-resources.js +1 -1
  285. package/dist/server/agent-chat/prompt-resources.js.map +1 -1
  286. package/dist/server/agent-chat-plugin.d.ts +2 -1
  287. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  288. package/dist/server/agent-chat-plugin.js +79 -56
  289. package/dist/server/agent-chat-plugin.js.map +1 -1
  290. package/dist/server/realtime-token.d.ts +1 -1
  291. package/dist/templates/default/.agents/skills/secrets/SKILL.md +19 -7
  292. package/dist/templates/headless/.agents/skills/secrets/SKILL.md +19 -7
  293. package/dist/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +18 -7
  294. package/dist/templates/workspace-core/.agents/skills/composable-mini-apps/SKILL.md +15 -14
  295. package/dist/templates/workspace-core/.agents/skills/secrets/SKILL.md +19 -7
  296. package/dist/vite/client.d.ts.map +1 -1
  297. package/dist/vite/client.js +1 -0
  298. package/dist/vite/client.js.map +1 -1
  299. package/docs/content/agent-native-toolkit.mdx +13 -6
  300. package/docs/content/cloneable-saas.mdx +5 -5
  301. package/docs/content/creating-templates.mdx +9 -0
  302. package/docs/content/deployment.mdx +18 -12
  303. package/docs/content/doctor.mdx +8 -1
  304. package/docs/content/drop-in-agent.mdx +1 -1
  305. package/docs/content/extensions.mdx +18 -18
  306. package/docs/content/faq.mdx +4 -4
  307. package/docs/content/key-concepts.mdx +30 -21
  308. package/docs/content/security.mdx +2 -2
  309. package/docs/content/template-brain-developers.mdx +4 -1
  310. package/docs/content/template-mail-developers.mdx +4 -1
  311. package/docs/content/what-is-agent-native.mdx +6 -6
  312. package/package.json +3 -3
  313. package/src/a2a/client.ts +449 -66
  314. package/src/a2a/correlation.ts +31 -0
  315. package/src/a2a/invoke.ts +4 -2
  316. package/src/a2a/types.ts +4 -0
  317. package/src/action.ts +3 -0
  318. package/src/agent/action-continuation-guidance.ts +2 -1
  319. package/src/agent/engine/registry.ts +98 -6
  320. package/src/agent/production-agent.ts +151 -18
  321. package/src/agent/run-loop-with-resume.ts +190 -3
  322. package/src/agent/run-manager.ts +117 -41
  323. package/src/agent/thread-debug-history.ts +86 -0
  324. package/src/agent/types.ts +3 -1
  325. package/src/cli/create.ts +11 -1
  326. package/src/cli/templates-meta.ts +2 -2
  327. package/src/client/agent-chat-adapter.ts +91 -13
  328. package/src/client/resources/McpIntegrationDialog.tsx +11 -9
  329. package/src/client/sse-event-processor.ts +17 -3
  330. package/src/db/client.ts +57 -17
  331. package/src/guards/no-env-credentials.ts +2 -0
  332. package/src/integrations/adapters/slack.ts +8 -3
  333. package/src/localization/default-messages.ts +44 -0
  334. package/src/observability/traces.ts +78 -5
  335. package/src/scripts/call-agent.ts +294 -11
  336. package/src/scripts/describe-workspace-apps.ts +2 -2
  337. package/src/secrets/crypto.ts +156 -35
  338. package/src/secrets/storage.ts +64 -26
  339. package/src/server/agent-capabilities.ts +1 -1
  340. package/src/server/agent-chat/action-filters-a2a.ts +113 -7
  341. package/src/server/agent-chat/context-tools.ts +2 -0
  342. package/src/server/agent-chat/plugin-options.ts +34 -1
  343. package/src/server/agent-chat/prompt-resources.ts +1 -1
  344. package/src/server/agent-chat-plugin.ts +91 -59
  345. package/src/templates/default/.agents/skills/secrets/SKILL.md +19 -7
  346. package/src/templates/headless/.agents/skills/secrets/SKILL.md +19 -7
  347. package/src/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +18 -7
  348. package/src/templates/workspace-core/.agents/skills/composable-mini-apps/SKILL.md +15 -14
  349. package/src/templates/workspace-core/.agents/skills/secrets/SKILL.md +19 -7
  350. package/src/vite/client.ts +1 -0
@@ -26,11 +26,13 @@ import {
26
26
  runAgentLoop,
27
27
  appendAgentLoopContinuation,
28
28
  isResumableEngineError,
29
+ isTransientProviderRateLimitError,
29
30
  continuationReasonForResumableError,
30
31
  lastUnfinishedPreparingActionToolFromEvents,
31
32
  resolveFinalResponseGuardRequestText,
32
33
  SELF_CHAIN_MIN_CONTINUATION_BUDGET_MS,
33
34
  type AgentLoopContinuationReason,
35
+ type AgentLoopOutcome,
34
36
  } from "./production-agent.js";
35
37
  import { resolveRunSoftTimeoutMs } from "./run-manager.js";
36
38
  import type { ResolveRunSoftTimeoutOptions } from "./run-manager.js";
@@ -112,7 +114,7 @@ function appendToolCallJournalNote(
112
114
 
113
115
  async function appendContinuationAndJournal(
114
116
  messages: EngineMessage[],
115
- reason: AgentLoopContinuationReason,
117
+ reason: AgentLoopContinuationReason | "rate_limited",
116
118
  threadId: string | undefined,
117
119
  localEvents: readonly AgentChatEvent[] = [],
118
120
  ): Promise<void> {
@@ -185,6 +187,47 @@ function internalContinuationReasonForAttempt(
185
187
  */
186
188
  export const MAX_RUN_LOOP_CONTINUATIONS = 6;
187
189
 
190
+ /**
191
+ * A delegated turn that is proven to be running inside a durable background
192
+ * function has the same 15-minute host budget as main chat, but this wrapper
193
+ * historically kept the foreground-sized six-continuation cap. A healthy
194
+ * child A2A call can consume several minutes and the receiving model may then
195
+ * need more than six recovery/model-stream boundaries to finish its own tool
196
+ * work. Keep a hard cap, but give the proven background path the same bounded
197
+ * continuation allowance as the durable main-chat runner. The cumulative
198
+ * soft-timeout below still prevents these rounds from exceeding the one real
199
+ * background-function wall-clock budget.
200
+ */
201
+ export const MAX_BACKGROUND_RUN_LOOP_CONTINUATIONS = 20;
202
+
203
+ /**
204
+ * The engine already performs its own short provider retries. After those are
205
+ * exhausted, a proven durable background A2A/MCP run gets one cooled-down
206
+ * continuation for a transient 429/529. One extra round is enough to bridge a
207
+ * short provider bucket without multiplying a sustained rate limit into a
208
+ * request storm across the larger background continuation allowance.
209
+ */
210
+ export const MAX_BACKGROUND_RATE_LIMIT_CONTINUATIONS = 1;
211
+ export const BACKGROUND_RATE_LIMIT_CONTINUATION_DELAY_MS = 20_000;
212
+
213
+ function waitForBackgroundRateLimitCooldown(
214
+ signal: AbortSignal,
215
+ ): Promise<void> {
216
+ if (signal.aborted) return Promise.resolve();
217
+ return new Promise((resolve) => {
218
+ const finish = () => {
219
+ clearTimeout(timer);
220
+ signal.removeEventListener("abort", finish);
221
+ resolve();
222
+ };
223
+ const timer = setTimeout(
224
+ finish,
225
+ BACKGROUND_RATE_LIMIT_CONTINUATION_DELAY_MS,
226
+ );
227
+ signal.addEventListener("abort", finish, { once: true });
228
+ });
229
+ }
230
+
188
231
  /** Machine-readable code carried on the give-up terminal `error` event so the
189
232
  * client renders a loud "stopped before finishing" terminal instead of an
190
233
  * ambiguous silent stall. Deliberately NOT in the client's auto-recoverable
@@ -222,7 +265,73 @@ export async function runAgentLoopDirectWithSoftTimeout(
222
265
  resolveFinalResponseGuardRequestText(opts.messages);
223
266
  const stableOpts = { ...opts, finalResponseGuardRequestText };
224
267
  const timeoutMs = resolveRunSoftTimeoutMs(softTimeoutMs, timeoutOptions);
225
- if (timeoutMs <= 0) return runAgentLoop(stableOpts);
268
+ let finalOutcomeReported = false;
269
+ const reportFinalOutcome = (outcome: AgentLoopOutcome) => {
270
+ if (finalOutcomeReported) return;
271
+ finalOutcomeReported = true;
272
+ try {
273
+ opts.onOutcome?.(outcome);
274
+ } catch {
275
+ // Outcome observers cannot alter recovery or completion.
276
+ }
277
+ };
278
+
279
+ // Disabling continuation recovery must not disable terminal classification.
280
+ // Keep the same outcome boundary around a direct loop so A2A/MCP callers
281
+ // never infer success from a rejected or canceled run.
282
+ if (timeoutMs <= 0) {
283
+ const directEvents: AgentChatEvent[] = [];
284
+ let directOutcome: AgentLoopOutcome | undefined;
285
+ try {
286
+ const result = await runAgentLoop({
287
+ ...stableOpts,
288
+ send: (event) => {
289
+ directEvents.push(event);
290
+ stableOpts.send(event);
291
+ },
292
+ onOutcome: (outcome) => {
293
+ directOutcome = outcome;
294
+ },
295
+ });
296
+ const unfinishedReason =
297
+ internalContinuationReasonForAttempt(directEvents);
298
+ if (opts.signal.aborted) {
299
+ reportFinalOutcome({
300
+ state: "canceled",
301
+ message: "Agent run was aborted.",
302
+ });
303
+ } else if (unfinishedReason) {
304
+ reportFinalOutcome({
305
+ state: "failed",
306
+ code: unfinishedReason,
307
+ retryable: false,
308
+ message: `Agent stopped before finishing (${unfinishedReason}).`,
309
+ });
310
+ } else {
311
+ reportFinalOutcome(directOutcome ?? { state: "completed" });
312
+ }
313
+ return result;
314
+ } catch (err) {
315
+ const candidate = err as { errorCode?: unknown; message?: unknown };
316
+ reportFinalOutcome(
317
+ opts.signal.aborted
318
+ ? { state: "canceled", message: "Agent run was aborted." }
319
+ : {
320
+ state: "failed",
321
+ code:
322
+ typeof candidate?.errorCode === "string" && candidate.errorCode
323
+ ? candidate.errorCode
324
+ : "internal_error",
325
+ retryable: isResumableEngineError(err),
326
+ message:
327
+ typeof candidate?.message === "string"
328
+ ? candidate.message
329
+ : String(err),
330
+ },
331
+ );
332
+ throw err;
333
+ }
334
+ }
226
335
 
227
336
  const upstreamSignal = opts.signal;
228
337
  const usage: Awaited<ReturnType<typeof runAgentLoop>> = {
@@ -260,6 +369,11 @@ export async function runAgentLoopDirectWithSoftTimeout(
260
369
  // pattern, already proven for the analogous foreground self-chain case).
261
370
  // The first round is unaffected — it always gets the full `timeoutMs`.
262
371
  const loopEntryAt = Date.now();
372
+ const maxRunLoopContinuations =
373
+ timeoutOptions?.backgroundFunction === true
374
+ ? MAX_BACKGROUND_RUN_LOOP_CONTINUATIONS
375
+ : MAX_RUN_LOOP_CONTINUATIONS;
376
+ let backgroundRateLimitContinuations = 0;
263
377
  // Tracks whether the most recent attempt ended by scheduling another
264
378
  // continuation (soft-timeout or resumable error → `continue`) rather than
265
379
  // returning a finished turn. When the loop then exits because the budget is
@@ -267,7 +381,7 @@ export async function runAgentLoopDirectWithSoftTimeout(
267
381
  // this is the silent give-up case: emit a loud terminal so the user sees an
268
382
  // unambiguous "stopped before finishing" instead of a bare done/"…".
269
383
  let lastAttemptWasUnfinishedContinuation = false;
270
- while (!upstreamSignal.aborted && attempts < MAX_RUN_LOOP_CONTINUATIONS) {
384
+ while (!upstreamSignal.aborted && attempts < maxRunLoopContinuations) {
271
385
  const roundTimeoutMs =
272
386
  attempts === 0 ? timeoutMs : timeoutMs - (Date.now() - loopEntryAt);
273
387
  if (
@@ -307,10 +421,14 @@ export async function runAgentLoopDirectWithSoftTimeout(
307
421
  };
308
422
 
309
423
  try {
424
+ let attemptOutcome: AgentLoopOutcome | undefined;
310
425
  const nextUsage = await runAgentLoop({
311
426
  ...stableOpts,
312
427
  send,
313
428
  signal: controller.signal,
429
+ onOutcome: (outcome) => {
430
+ attemptOutcome = outcome;
431
+ },
314
432
  });
315
433
  addUsage(nextUsage);
316
434
  const attemptEvents = localTurnEvents.slice(attemptStartIndex);
@@ -345,6 +463,11 @@ export async function runAgentLoopDirectWithSoftTimeout(
345
463
  );
346
464
  continue;
347
465
  }
466
+ reportFinalOutcome(
467
+ upstreamSignal.aborted
468
+ ? { state: "canceled", message: "Agent run was aborted." }
469
+ : (attemptOutcome ?? { state: "completed" }),
470
+ );
348
471
  return usage;
349
472
  } catch (err) {
350
473
  if (softTimedOut && !upstreamSignal.aborted) {
@@ -367,6 +490,39 @@ export async function runAgentLoopDirectWithSoftTimeout(
367
490
  );
368
491
  continue;
369
492
  }
493
+ const transientRateLimit = isTransientProviderRateLimitError(err);
494
+ const rateLimitRetryFitsBudget =
495
+ timeoutOptions?.backgroundFunction === true &&
496
+ backgroundRateLimitContinuations <
497
+ MAX_BACKGROUND_RATE_LIMIT_CONTINUATIONS &&
498
+ timeoutMs -
499
+ (Date.now() - loopEntryAt) -
500
+ BACKGROUND_RATE_LIMIT_CONTINUATION_DELAY_MS >=
501
+ SELF_CHAIN_MIN_CONTINUATION_BUDGET_MS;
502
+ if (
503
+ !upstreamSignal.aborted &&
504
+ transientRateLimit &&
505
+ rateLimitRetryFitsBudget
506
+ ) {
507
+ lastAttemptWasUnfinishedContinuation = true;
508
+ backgroundRateLimitContinuations++;
509
+ if (
510
+ !(await hasCompletedSideEffectToolCallInCurrentTurn(
511
+ opts.threadId,
512
+ localTurnEvents,
513
+ ))
514
+ ) {
515
+ opts.send({ type: "clear" });
516
+ }
517
+ await appendContinuationAndJournal(
518
+ opts.messages,
519
+ "rate_limited",
520
+ opts.threadId,
521
+ localTurnEvents,
522
+ );
523
+ await waitForBackgroundRateLimitCooldown(upstreamSignal);
524
+ continue;
525
+ }
370
526
  // Resumable transport / gateway interruptions: the LLM call was cut off
371
527
  // mid-stream (gateway 45s timeout, socket hang up, function-level
372
528
  // timeout that didn't trip our soft timer first). Treat it the same way
@@ -398,6 +554,26 @@ export async function runAgentLoopDirectWithSoftTimeout(
398
554
  );
399
555
  continue;
400
556
  }
557
+ if (upstreamSignal.aborted) {
558
+ reportFinalOutcome({
559
+ state: "canceled",
560
+ message: "Agent run was aborted.",
561
+ });
562
+ throw err;
563
+ }
564
+ const candidate = err as { errorCode?: unknown; message?: unknown };
565
+ reportFinalOutcome({
566
+ state: "failed",
567
+ code:
568
+ typeof candidate?.errorCode === "string" && candidate.errorCode
569
+ ? candidate.errorCode
570
+ : "internal_error",
571
+ retryable: false,
572
+ message:
573
+ typeof candidate?.message === "string"
574
+ ? candidate.message
575
+ : String(err),
576
+ });
401
577
  throw err;
402
578
  } finally {
403
579
  clearTimeout(timer);
@@ -431,6 +607,17 @@ export async function runAgentLoopDirectWithSoftTimeout(
431
607
  errorCode: RUN_BUDGET_EXHAUSTED_ERROR_CODE,
432
608
  recoverable: true,
433
609
  });
610
+ reportFinalOutcome({
611
+ state: "failed",
612
+ code: RUN_BUDGET_EXHAUSTED_ERROR_CODE,
613
+ retryable: false,
614
+ message: RUN_BUDGET_EXHAUSTED_MESSAGE,
615
+ });
616
+ } else if (upstreamSignal.aborted) {
617
+ reportFinalOutcome({
618
+ state: "canceled",
619
+ message: "Agent run was aborted.",
620
+ });
434
621
  }
435
622
 
436
623
  return usage;
@@ -136,17 +136,6 @@ export const BACKGROUND_SOFT_TIMEOUT_CEILING_MS = 13 * 60_000; // 780_000
136
136
  export const DEFAULT_BACKGROUND_RUN_SOFT_TIMEOUT_MS =
137
137
  BACKGROUND_SOFT_TIMEOUT_CEILING_MS;
138
138
 
139
- /**
140
- * Default no-progress window for a run executing inside a proven durable
141
- * background function. Keep this below the 13-minute soft timeout so a truly
142
- * wedged background turn can still checkpoint, persist, and continue before
143
- * the function budget expires, but far above the foreground 150s window so
144
- * large Design/Plan/Assets generations are not chopped up while the model is
145
- * legitimately planning a big tool payload.
146
- */
147
- export const DEFAULT_BACKGROUND_NO_PROGRESS_TIMEOUT_MS =
148
- BACKGROUND_SOFT_TIMEOUT_CEILING_MS - 60_000;
149
-
150
139
  /**
151
140
  * AUTHORITATIVE no-progress backstop for a run, enforced by the run manager
152
141
  * itself (timer-driven, independent of any layer below).
@@ -176,6 +165,17 @@ export const DEFAULT_BACKGROUND_NO_PROGRESS_TIMEOUT_MS =
176
165
  */
177
166
  export const RUN_NO_PROGRESS_HARD_TIMEOUT_MS = 150_000;
178
167
 
168
+ /**
169
+ * Default no-progress window for a run executing inside a proven durable
170
+ * background function. A background worker that is heartbeating but has no
171
+ * real progress and no tool/A2A work in flight is still wedged; letting that
172
+ * state outlive the client's follow budget only turns a recoverable stall into
173
+ * a terminal timeout. In-flight work suspends this backstop, so use the same
174
+ * server-owned 150s bound as the long foreground regime.
175
+ */
176
+ export const DEFAULT_BACKGROUND_NO_PROGRESS_TIMEOUT_MS =
177
+ RUN_NO_PROGRESS_HARD_TIMEOUT_MS;
178
+
179
179
  /**
180
180
  * Fraction of the soft timeout a foreground no-progress backstop may consume.
181
181
  * The hosted foreground path rides a synchronous serverless function whose
@@ -291,6 +291,15 @@ export const SQL_SUBSCRIPTION_ACTIVE_GRACE_MS = 2_000;
291
291
  /** Keep terminal/status probes at the historical cadence to bound DB work. */
292
292
  export const SQL_SUBSCRIPTION_STATUS_POLL_MS = 500;
293
293
 
294
+ /** Initial retry delay after a transient cross-isolate SQL polling failure. */
295
+ export const SQL_SUBSCRIPTION_RETRY_BASE_MS = 250;
296
+
297
+ /** Bound consecutive SQL polling failures so a dead subscription fails loud. */
298
+ export const SQL_SUBSCRIPTION_MAX_CONSECUTIVE_FAILURES = 4;
299
+
300
+ /** Cap retry delay even if the failure bound changes independently. */
301
+ export const SQL_SUBSCRIPTION_RETRY_MAX_MS = 2_000;
302
+
294
303
  export function resolveSqlSubscriptionPollMs(
295
304
  now: number,
296
305
  activePollUntil: number,
@@ -300,7 +309,18 @@ export function resolveSqlSubscriptionPollMs(
300
309
  : SQL_SUBSCRIPTION_IDLE_POLL_MS;
301
310
  }
302
311
 
312
+ export function resolveSqlSubscriptionRetryMs(
313
+ consecutiveFailures: number,
314
+ ): number {
315
+ const retryIndex = Math.max(0, Math.floor(consecutiveFailures) - 1);
316
+ return Math.min(
317
+ SQL_SUBSCRIPTION_RETRY_MAX_MS,
318
+ SQL_SUBSCRIPTION_RETRY_BASE_MS * 2 ** retryIndex,
319
+ );
320
+ }
321
+
303
322
  const PROVIDER_RATE_LIMITED_ERROR_CODE = "provider_rate_limited";
323
+ const PROVIDER_NETWORK_ERROR_CODE = "provider_network_error";
304
324
 
305
325
  function isPreparingActionActivityEvent(event: AgentChatEvent): boolean {
306
326
  if (event.type !== "activity") return false;
@@ -321,9 +341,22 @@ function getRunErrorMessage(err: unknown): string {
321
341
  return "Unknown error";
322
342
  }
323
343
 
324
- function getEngineRunErrorCode(err: EngineError): string | undefined {
325
- if (err.errorCode) return err.errorCode;
326
- if (err.statusCode === 429) return PROVIDER_RATE_LIMITED_ERROR_CODE;
344
+ function isProviderConnectionErrorMessage(message: string): boolean {
345
+ const normalized = message.trim().toLowerCase();
346
+ return (
347
+ normalized === "connection error." ||
348
+ normalized.includes("cannot connect to api:")
349
+ );
350
+ }
351
+
352
+ function getRunErrorCode(err: unknown): string | undefined {
353
+ if (err instanceof EngineError) {
354
+ if (err.errorCode) return err.errorCode;
355
+ if (err.statusCode === 429) return PROVIDER_RATE_LIMITED_ERROR_CODE;
356
+ }
357
+ if (err instanceof Error && isProviderConnectionErrorMessage(err.message)) {
358
+ return PROVIDER_NETWORK_ERROR_CODE;
359
+ }
327
360
  return undefined;
328
361
  }
329
362
 
@@ -333,17 +366,23 @@ function getEngineRunErrorDetails(err: EngineError): string | undefined {
333
366
  }
334
367
 
335
368
  function shouldCaptureRunError(err: unknown): boolean {
336
- if (!(err instanceof EngineError)) return true;
337
- const errorCode = getEngineRunErrorCode(err);
369
+ const errorCode = getRunErrorCode(err);
338
370
  if (isLlmCredentialError(err, errorCode)) return false;
339
- if (err.statusCode === 401 || err.statusCode === 403) return false;
371
+ if (
372
+ err instanceof EngineError &&
373
+ (err.statusCode === 401 || err.statusCode === 403)
374
+ ) {
375
+ return false;
376
+ }
377
+ if (!(err instanceof Error)) return true;
340
378
  if (/^40[13] status code\b/i.test(err.message)) return false;
341
- if (err.message.trim().toLowerCase() === "connection error.") return false;
379
+ if (isProviderConnectionErrorMessage(err.message)) return false;
342
380
  if (!errorCode) return true;
343
381
  const normalizedCode = errorCode.toLowerCase();
344
382
  return (
345
383
  !normalizedCode.startsWith("credits-limit") &&
346
384
  normalizedCode !== "builder_gateway_network_error" &&
385
+ normalizedCode !== PROVIDER_NETWORK_ERROR_CODE &&
347
386
  normalizedCode !== "provider_rate_limited" &&
348
387
  normalizedCode !== "rate_limit_exceeded"
349
388
  );
@@ -1042,8 +1081,7 @@ export function startRun(
1042
1081
  let pendingTerminalEvent: RunEvent | null = null;
1043
1082
 
1044
1083
  const captureRunError = (error: unknown, phase: "run" | "completion") => {
1045
- const errorCode =
1046
- error instanceof EngineError ? getEngineRunErrorCode(error) : undefined;
1084
+ const errorCode = getRunErrorCode(error);
1047
1085
  captureError(error, {
1048
1086
  route: "/_agent-native/agent-chat",
1049
1087
  tags: {
@@ -1162,8 +1200,7 @@ export function startRun(
1162
1200
  captureRunError(err, "run");
1163
1201
  }
1164
1202
  const errorMessage = getRunErrorMessage(err);
1165
- const errorCode =
1166
- err instanceof EngineError ? getEngineRunErrorCode(err) : undefined;
1203
+ const errorCode = getRunErrorCode(err);
1167
1204
  const details =
1168
1205
  err instanceof EngineError ? getEngineRunErrorDetails(err) : undefined;
1169
1206
  send({
@@ -1587,6 +1624,7 @@ function subscribeFromSQL(
1587
1624
  let lastSeq = fromSeq;
1588
1625
  let activePollUntil = 0;
1589
1626
  let lastStatusCheckAt = 0;
1627
+ let consecutivePollFailures = 0;
1590
1628
  const ping = () => {
1591
1629
  try {
1592
1630
  controller.enqueue(encoder.encode(`: ping ${Date.now()}\n\n`));
@@ -1598,6 +1636,49 @@ function subscribeFromSQL(
1598
1636
  ping();
1599
1637
  pingTimer = setInterval(ping, 10_000);
1600
1638
 
1639
+ const closeStream = () => {
1640
+ cancelled = true;
1641
+ if (pollTimer) clearTimeout(pollTimer);
1642
+ if (pingTimer) clearInterval(pingTimer);
1643
+ try {
1644
+ controller.close();
1645
+ } catch {}
1646
+ };
1647
+
1648
+ const failSubscription = (error: unknown) => {
1649
+ const event: AgentChatEvent = {
1650
+ type: "error",
1651
+ error:
1652
+ "The live agent connection could not load persisted run progress.",
1653
+ errorCode: "run_subscription_poll_failed",
1654
+ details:
1655
+ "The agent may still be running. Reconnect to resume from the last persisted event.",
1656
+ recoverable: true,
1657
+ };
1658
+ captureError(error, {
1659
+ route: "/_agent-native/agent-chat/runs/:id/events",
1660
+ tags: {
1661
+ source: "agent-run-manager",
1662
+ phase: "sql-subscription-poll",
1663
+ consecutiveFailures: String(consecutivePollFailures),
1664
+ },
1665
+ extra: {
1666
+ runId,
1667
+ fromSeq,
1668
+ lastSeq,
1669
+ error: getRunErrorMessage(error),
1670
+ },
1671
+ });
1672
+ try {
1673
+ controller.enqueue(
1674
+ encoder.encode(
1675
+ `data: ${JSON.stringify({ ...event, seq: lastSeq })}\n\n`,
1676
+ ),
1677
+ );
1678
+ } catch {}
1679
+ closeStream();
1680
+ };
1681
+
1601
1682
  const poll = async () => {
1602
1683
  if (cancelled) return;
1603
1684
  try {
@@ -1642,6 +1723,7 @@ function subscribeFromSQL(
1642
1723
  const now = Date.now();
1643
1724
  if (now - lastStatusCheckAt < SQL_SUBSCRIPTION_STATUS_POLL_MS) {
1644
1725
  if (!cancelled) {
1726
+ consecutivePollFailures = 0;
1645
1727
  const pollMs = resolveSqlSubscriptionPollMs(
1646
1728
  now,
1647
1729
  activePollUntil,
@@ -1786,34 +1868,28 @@ function subscribeFromSQL(
1786
1868
 
1787
1869
  // Schedule next poll
1788
1870
  if (!cancelled) {
1871
+ consecutivePollFailures = 0;
1789
1872
  const pollMs = resolveSqlSubscriptionPollMs(
1790
1873
  Date.now(),
1791
1874
  activePollUntil,
1792
1875
  );
1793
1876
  pollTimer = setTimeout(poll, pollMs);
1794
1877
  }
1795
- } catch {
1796
- // SQL error — close stream
1797
- try {
1798
- if (pingTimer) clearInterval(pingTimer);
1799
- controller.close();
1800
- } catch {}
1878
+ } catch (error) {
1879
+ consecutivePollFailures += 1;
1880
+ if (
1881
+ consecutivePollFailures >= SQL_SUBSCRIPTION_MAX_CONSECUTIVE_FAILURES
1882
+ ) {
1883
+ failSubscription(error);
1884
+ return;
1885
+ }
1886
+ pollTimer = setTimeout(
1887
+ poll,
1888
+ resolveSqlSubscriptionRetryMs(consecutivePollFailures),
1889
+ );
1801
1890
  }
1802
1891
  };
1803
1892
 
1804
- // Verify run exists before starting poll
1805
- try {
1806
- const run = await getRunById(runId);
1807
- if (!run) {
1808
- if (pingTimer) clearInterval(pingTimer);
1809
- controller.close();
1810
- return;
1811
- }
1812
- } catch {
1813
- controller.close();
1814
- return;
1815
- }
1816
-
1817
1893
  await poll();
1818
1894
  },
1819
1895
  cancel() {
@@ -0,0 +1,86 @@
1
+ import { createHash } from "node:crypto";
2
+
3
+ export const MAX_THREAD_DEBUG_RUNS = 50;
4
+
5
+ type UnknownRecord = Record<string, unknown>;
6
+
7
+ function isRecord(value: unknown): value is UnknownRecord {
8
+ return typeof value === "object" && value !== null && !Array.isArray(value);
9
+ }
10
+
11
+ export function hashThreadDebugPrompt(prompt: string): string {
12
+ return `sha256:${createHash("sha256").update(prompt).digest("hex")}`;
13
+ }
14
+
15
+ function compactDebugEntry(
16
+ value: unknown,
17
+ prompts: Map<string, string>,
18
+ ): UnknownRecord | null {
19
+ if (!isRecord(value)) return null;
20
+
21
+ const entry = { ...value };
22
+ if (typeof entry.systemPrompt === "string") {
23
+ const promptHash = hashThreadDebugPrompt(entry.systemPrompt);
24
+ prompts.set(promptHash, entry.systemPrompt);
25
+ entry.systemPromptHash = promptHash;
26
+ delete entry.systemPrompt;
27
+ }
28
+ return entry;
29
+ }
30
+
31
+ /**
32
+ * Append one run's diagnostics while keeping repeated system prompts out of
33
+ * every history entry. Existing full-prompt history is migrated on write.
34
+ */
35
+ export function appendThreadDebugHistory(
36
+ threadData: UnknownRecord,
37
+ currentDebug: UnknownRecord,
38
+ ): UnknownRecord {
39
+ const promptCandidates = new Map<string, string>();
40
+ if (isRecord(threadData._debugPrompts)) {
41
+ for (const [hash, prompt] of Object.entries(threadData._debugPrompts)) {
42
+ if (typeof prompt === "string") promptCandidates.set(hash, prompt);
43
+ }
44
+ }
45
+
46
+ const previousRuns = Array.isArray(threadData._debugRuns)
47
+ ? threadData._debugRuns
48
+ .map((entry) => compactDebugEntry(entry, promptCandidates))
49
+ .filter((entry): entry is UnknownRecord => entry !== null)
50
+ : [];
51
+ const compactCurrent = compactDebugEntry(currentDebug, promptCandidates) ?? {
52
+ ...currentDebug,
53
+ };
54
+ const debugRuns = [...previousRuns, compactCurrent].slice(
55
+ -MAX_THREAD_DEBUG_RUNS,
56
+ );
57
+
58
+ const referencedHashes = new Set<string>();
59
+ for (const entry of debugRuns) {
60
+ if (typeof entry.systemPromptHash === "string") {
61
+ referencedHashes.add(entry.systemPromptHash);
62
+ }
63
+ }
64
+ if (typeof compactCurrent.systemPromptHash === "string") {
65
+ referencedHashes.add(compactCurrent.systemPromptHash);
66
+ }
67
+
68
+ const debugPrompts = Object.fromEntries(
69
+ [...referencedHashes].sort().flatMap((hash) => {
70
+ const prompt = promptCandidates.get(hash);
71
+ return prompt === undefined ? [] : [[hash, prompt]];
72
+ }),
73
+ );
74
+
75
+ const result: UnknownRecord = {
76
+ ...threadData,
77
+ _debug: compactCurrent,
78
+ _debugRuns: debugRuns,
79
+ };
80
+ if (Object.keys(debugPrompts).length > 0) {
81
+ result._debugPrompts = debugPrompts;
82
+ } else {
83
+ delete result._debugPrompts;
84
+ }
85
+ return result;
86
+ }
@@ -276,8 +276,10 @@ export type AgentChatEvent =
276
276
  | {
277
277
  type: "agent_call";
278
278
  agent: string;
279
- status: "start" | "done" | "error";
279
+ status: "start" | "done" | "pending" | "error";
280
280
  agentCallId?: string;
281
+ /** Remote task to resume when status is pending/input-required. */
282
+ taskId?: string;
281
283
  durationMs?: number;
282
284
  }
283
285
  | {
@@ -708,6 +708,14 @@ export async function addAppToWorkspace(
708
708
  }
709
709
 
710
710
  const hasDispatch = installed.includes("dispatch");
711
+ const availableTemplates = coreTemplates().filter(
712
+ (template) => !installed.includes(template.name),
713
+ );
714
+ if (availableTemplates.length === 0) {
715
+ clack.cancel("All available apps are already installed.");
716
+ process.exit(0);
717
+ }
718
+
711
719
  const templates = await promptTemplatePicker(preselected, clack, {
712
720
  excludeNames: installed,
713
721
  message: "Which apps do you want to add?",
@@ -716,7 +724,9 @@ export async function addAppToWorkspace(
716
724
  recommendedNames: hasDispatch ? [] : ["dispatch"],
717
725
  });
718
726
  if (templates.length === 0) {
719
- clack.cancel("No apps selected. Cancelled.");
727
+ clack.cancel(
728
+ "No apps selected. Press space to select an app, then press enter to continue.",
729
+ );
720
730
  process.exit(0);
721
731
  }
722
732
 
@@ -99,7 +99,7 @@ export const TEMPLATES: TemplateMeta[] = [
99
99
  devPort: 8086,
100
100
  prodUrl: "https://slides.agent-native.com",
101
101
  defaultMode: "prod",
102
- requiredPackages: ["pinpoint", "creative-context"],
102
+ requiredPackages: ["creative-context"],
103
103
  core: true,
104
104
  },
105
105
  {
@@ -199,7 +199,7 @@ export const TEMPLATES: TemplateMeta[] = [
199
199
  devPort: 8099,
200
200
  prodUrl: "https://design.agent-native.com",
201
201
  defaultMode: "prod",
202
- requiredPackages: ["pinpoint", "embedding", "creative-context"],
202
+ requiredPackages: ["embedding", "creative-context"],
203
203
  core: true,
204
204
  },
205
205
  {