@agent-native/core 0.132.1 → 0.133.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 (456) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +198 -0
  3. package/corpus/core/package.json +1 -1
  4. package/corpus/core/src/a2a/correlation.ts +11 -1
  5. package/corpus/core/src/a2a/types.ts +11 -3
  6. package/corpus/core/src/agent/engine/ai-sdk-engine.ts +33 -46
  7. package/corpus/core/src/agent/engine/builder-engine.ts +22 -10
  8. package/corpus/core/src/agent/engine/error-detail.ts +184 -3
  9. package/corpus/core/src/agent/engine/failure-taxonomy.ts +123 -0
  10. package/corpus/core/src/agent/engine/index.ts +8 -0
  11. package/corpus/core/src/agent/engine/registry.ts +92 -8
  12. package/corpus/core/src/agent/engine/translate-ai-sdk.ts +17 -2
  13. package/corpus/core/src/agent/production-agent.ts +13 -33
  14. package/corpus/core/src/agent/run-loop-with-resume.ts +1 -1
  15. package/corpus/core/src/agent/run-manager.ts +43 -14
  16. package/corpus/core/src/agent/run-store.ts +30 -3
  17. package/corpus/core/src/agent/thread-data-builder.ts +36 -4
  18. package/corpus/core/src/chat-threads/store.ts +42 -0
  19. package/corpus/core/src/cli/templates-meta.ts +13 -0
  20. package/corpus/core/src/cli/workspace-dev.ts +1 -0
  21. package/corpus/core/src/client/error-format.ts +12 -0
  22. package/corpus/core/src/client/use-chat-threads.ts +76 -16
  23. package/corpus/core/src/credentials/index.ts +51 -12
  24. package/corpus/core/src/extensions/url-safety.ts +46 -12
  25. package/corpus/core/src/integrations/adapters/slack.ts +32 -10
  26. package/corpus/core/src/integrations/google-docs-poller.ts +12 -1
  27. package/corpus/core/src/integrations/installations-store.ts +30 -0
  28. package/corpus/core/src/integrations/plugin.ts +5 -5
  29. package/corpus/core/src/integrations/types.ts +7 -0
  30. package/corpus/core/src/integrations/webhook-handler.ts +24 -1
  31. package/corpus/core/src/jobs/background-automation-runner.ts +38 -1
  32. package/corpus/core/src/provider-api/index.ts +8 -2
  33. package/corpus/core/src/scripts/call-agent.ts +6 -0
  34. package/corpus/core/src/server/agent-chat-plugin.ts +46 -10
  35. package/corpus/core/src/server/agent-discovery.ts +2 -0
  36. package/corpus/core/src/server/builder-design-systems.ts +21 -0
  37. package/corpus/core/src/server/credential-provider.ts +51 -12
  38. package/corpus/core/src/server/index.ts +1 -0
  39. package/corpus/core/src/server/onboarding-html.ts +37 -2
  40. package/corpus/core/src/shared/reasoning-effort.ts +1 -1
  41. package/corpus/core/src/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +11 -0
  42. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +6 -2
  43. package/corpus/templates/assets/app/components/layout/Sidebar.tsx +39 -19
  44. package/corpus/templates/assets/changelog/2026-07-31-the-agent-native-logo-stays-visible-when-the-sidebar-is-coll.md +6 -0
  45. package/corpus/templates/brain/app/components/layout/Sidebar.tsx +30 -3
  46. package/corpus/templates/brain/changelog/2026-07-31-clicking-the-agent-native-logo-now-toggles-the-app-sidebar.md +6 -0
  47. package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +1 -1
  48. package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +54 -25
  49. package/corpus/templates/calendar/changelog/2026-07-31-the-agent-native-logo-stays-visible-when-the-sidebar-is-coll.md +6 -0
  50. package/corpus/templates/chat/app/components/layout/Sidebar.tsx +30 -3
  51. package/corpus/templates/chat/changelog/2026-07-31-clicking-the-agent-native-logo-now-toggles-the-app-sidebar.md +6 -0
  52. package/corpus/templates/clips/app/components/library/library-layout.tsx +37 -21
  53. package/corpus/templates/clips/changelog/2026-07-30-meeting-microphone-transcription-works-reliably-from-the-fir.md +6 -0
  54. package/corpus/templates/clips/changelog/2026-07-31-the-agent-native-logo-stays-visible-when-the-sidebar-is-coll.md +6 -0
  55. package/corpus/templates/clips/desktop/src/hooks/useMediaDevices.ts +1 -1
  56. package/corpus/templates/clips/desktop/src/lib/media-capture-constraints.ts +1 -1
  57. package/corpus/templates/clips/desktop/src-tauri/src/native_screen/custom_capture.rs +13 -0
  58. package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +2 -0
  59. package/corpus/templates/clips/desktop/src-tauri/src/system_audio.rs +25 -132
  60. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +34 -17
  61. package/corpus/templates/content/changelog/2026-07-31-the-agent-native-logo-stays-visible-when-the-sidebar-is-coll.md +6 -0
  62. package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +6 -2
  63. package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +5 -0
  64. package/corpus/templates/design/actions/create-design-system.ts +1 -0
  65. package/corpus/templates/design/actions/set-default-design-system.ts +34 -26
  66. package/corpus/templates/design/app/components/design/KeyboardShortcutsPanel.tsx +5 -3
  67. package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +23 -0
  68. package/corpus/templates/design/app/components/design/keyboard-shortcuts.ts +3 -0
  69. package/corpus/templates/design/app/components/layout/Sidebar.tsx +21 -4
  70. package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +11 -7
  71. package/corpus/templates/design/app/i18n-data.ts +39 -0
  72. package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +229 -12
  73. package/corpus/templates/design/app/pages/DesignSystems.tsx +10 -4
  74. package/corpus/templates/design/changelog/2026-07-30-fixed-the-keyboard-shortcuts-panel-not-opening-with-ctrl-shi.md +6 -0
  75. package/corpus/templates/design/changelog/2026-07-31-clicking-the-agent-native-logo-now-toggles-the-app-sidebar.md +6 -0
  76. package/corpus/templates/design/changelog/2026-07-31-design-system-indexing-keeps-your-chosen-name-when-you-uploa.md +6 -0
  77. package/corpus/templates/design/server/lib/builder-design-system-proxy.ts +19 -4
  78. package/corpus/templates/dispatch/AGENTS.md +4 -0
  79. package/corpus/templates/factory/.agents/skills/actions/SKILL.md +562 -0
  80. package/corpus/templates/factory/.agents/skills/adding-a-feature/SKILL.md +198 -0
  81. package/corpus/templates/factory/.agents/skills/agent-native-docs/SKILL.md +115 -0
  82. package/corpus/templates/factory/.agents/skills/agent-native-toolkit/SKILL.md +182 -0
  83. package/corpus/templates/factory/.agents/skills/capture-learnings/SKILL.md +89 -0
  84. package/corpus/templates/factory/.agents/skills/create-skill/SKILL.md +221 -0
  85. package/corpus/templates/factory/.agents/skills/customizing-agent-native/SKILL.md +220 -0
  86. package/corpus/templates/factory/.agents/skills/delegate-to-agent/SKILL.md +263 -0
  87. package/corpus/templates/factory/.agents/skills/factory-graphs/SKILL.md +52 -0
  88. package/corpus/templates/factory/.agents/skills/feature-flags/SKILL.md +169 -0
  89. package/corpus/templates/factory/.agents/skills/frontend-design/SKILL.md +174 -0
  90. package/corpus/templates/factory/.agents/skills/real-time-sync/SKILL.md +232 -0
  91. package/corpus/templates/factory/.agents/skills/security/SKILL.md +324 -0
  92. package/corpus/templates/factory/.agents/skills/self-modifying-code/SKILL.md +119 -0
  93. package/corpus/templates/factory/.agents/skills/shadcn-ui/SKILL.md +123 -0
  94. package/corpus/templates/factory/.agents/skills/sharing/SKILL.md +232 -0
  95. package/corpus/templates/factory/.agents/skills/storing-data/SKILL.md +178 -0
  96. package/corpus/templates/factory/.agents/skills/upgrade-agent-native/SKILL.md +122 -0
  97. package/corpus/templates/factory/.env.example +24 -0
  98. package/corpus/templates/factory/.ignore +0 -0
  99. package/corpus/templates/factory/.oxfmtrc.json +8 -0
  100. package/corpus/templates/factory/AGENTS.md +90 -0
  101. package/corpus/templates/factory/CHANGELOG.md +10 -0
  102. package/corpus/templates/factory/DEVELOPING.md +185 -0
  103. package/corpus/templates/factory/README.md +64 -0
  104. package/corpus/templates/factory/_gitignore +42 -0
  105. package/corpus/templates/factory/actions/add-factory-comment.ts +55 -0
  106. package/corpus/templates/factory/actions/approve-factory-item.ts +214 -0
  107. package/corpus/templates/factory/actions/babysit-pull-request.ts +126 -0
  108. package/corpus/templates/factory/actions/evaluate-triage-item.ts +172 -0
  109. package/corpus/templates/factory/actions/get-factory-graph.ts +62 -0
  110. package/corpus/templates/factory/actions/get-triage-config.ts +42 -0
  111. package/corpus/templates/factory/actions/get-triage-item.ts +74 -0
  112. package/corpus/templates/factory/actions/hello.ts +13 -0
  113. package/corpus/templates/factory/actions/ingest-github-observation.ts +100 -0
  114. package/corpus/templates/factory/actions/list-factories.ts +40 -0
  115. package/corpus/templates/factory/actions/list-factory-comments.ts +40 -0
  116. package/corpus/templates/factory/actions/list-triage-items.ts +85 -0
  117. package/corpus/templates/factory/actions/list-triage-rules.ts +44 -0
  118. package/corpus/templates/factory/actions/navigate.ts +41 -0
  119. package/corpus/templates/factory/actions/poll-slack-channel.ts +118 -0
  120. package/corpus/templates/factory/actions/reconcile-triage-run.ts +179 -0
  121. package/corpus/templates/factory/actions/record-triage-feedback.ts +58 -0
  122. package/corpus/templates/factory/actions/run.ts +2 -0
  123. package/corpus/templates/factory/actions/save-factory-graph.ts +129 -0
  124. package/corpus/templates/factory/actions/save-triage-config.ts +67 -0
  125. package/corpus/templates/factory/actions/save-triage-rule.ts +89 -0
  126. package/corpus/templates/factory/actions/suggest-factory-rules.ts +70 -0
  127. package/corpus/templates/factory/actions/view-screen.ts +73 -0
  128. package/corpus/templates/factory/app/components/factory/FactoryCanvas.tsx +441 -0
  129. package/corpus/templates/factory/app/components/factory/FactoryInspector.tsx +388 -0
  130. package/corpus/templates/factory/app/components/layout/Header.tsx +60 -0
  131. package/corpus/templates/factory/app/components/layout/Layout.tsx +190 -0
  132. package/corpus/templates/factory/app/components/layout/Sidebar.tsx +538 -0
  133. package/corpus/templates/factory/app/components/triage/triage-status-pill.tsx +28 -0
  134. package/corpus/templates/factory/app/components/ui/button.tsx +1 -0
  135. package/corpus/templates/factory/app/components/ui/card.tsx +1 -0
  136. package/corpus/templates/factory/app/components/ui/dropdown-menu.tsx +1 -0
  137. package/corpus/templates/factory/app/components/ui/input.tsx +1 -0
  138. package/corpus/templates/factory/app/components/ui/label.tsx +1 -0
  139. package/corpus/templates/factory/app/components/ui/sheet.tsx +1 -0
  140. package/corpus/templates/factory/app/components/ui/textarea.tsx +1 -0
  141. package/corpus/templates/factory/app/components/ui/toolkit-provider.tsx +17 -0
  142. package/corpus/templates/factory/app/components/ui/tooltip.tsx +1 -0
  143. package/corpus/templates/factory/app/design-system.ts +3 -0
  144. package/corpus/templates/factory/app/entry.client.tsx +22 -0
  145. package/corpus/templates/factory/app/entry.server.tsx +10 -0
  146. package/corpus/templates/factory/app/global.css +93 -0
  147. package/corpus/templates/factory/app/hooks/use-navigation-state.ts +113 -0
  148. package/corpus/templates/factory/app/i18n/en-US.ts +211 -0
  149. package/corpus/templates/factory/app/i18n/index.ts +34 -0
  150. package/corpus/templates/factory/app/i18n-data.ts +556 -0
  151. package/corpus/templates/factory/app/lib/agent-page.tsx +49 -0
  152. package/corpus/templates/factory/app/lib/app-config.ts +11 -0
  153. package/corpus/templates/factory/app/lib/tab-id.ts +1 -0
  154. package/corpus/templates/factory/app/lib/utils.ts +1 -0
  155. package/corpus/templates/factory/app/root.tsx +175 -0
  156. package/corpus/templates/factory/app/routes/_index.tsx +94 -0
  157. package/corpus/templates/factory/app/routes/agent.tsx +24 -0
  158. package/corpus/templates/factory/app/routes/chat.$threadId.tsx +1 -0
  159. package/corpus/templates/factory/app/routes/database.tsx +17 -0
  160. package/corpus/templates/factory/app/routes/extensions.$id.$slug.tsx +2 -0
  161. package/corpus/templates/factory/app/routes/extensions.$id.tsx +11 -0
  162. package/corpus/templates/factory/app/routes/extensions._index.tsx +11 -0
  163. package/corpus/templates/factory/app/routes/extensions.tsx +5 -0
  164. package/corpus/templates/factory/app/routes/factory.tsx +1003 -0
  165. package/corpus/templates/factory/app/routes/observability.tsx +19 -0
  166. package/corpus/templates/factory/app/routes/settings.tsx +89 -0
  167. package/corpus/templates/factory/app/routes/team.tsx +11 -0
  168. package/corpus/templates/factory/app/routes.ts +4 -0
  169. package/corpus/templates/factory/app/vite-env.d.ts +6 -0
  170. package/corpus/templates/factory/changelog/2026-06-24-a-new-settings-page-gives-quick-access-to-language-workspace.md +6 -0
  171. package/corpus/templates/factory/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
  172. package/corpus/templates/factory/changelog/2026-06-27-traditional-chinese-copy-uses-taiwan-terminology.md +6 -0
  173. package/corpus/templates/factory/changelog/2026-06-28-left-sidebar-collapse-motion-and-footer-chrome-are-quieter.md +6 -0
  174. package/corpus/templates/factory/changelog/2026-06-29-chat-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
  175. package/corpus/templates/factory/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  176. package/corpus/templates/factory/changelog/2026-07-10-chat-now-makes-ai-connection-setup-clear-without-shifting-th.md +6 -0
  177. package/corpus/templates/factory/changelog/2026-07-13-a-full-agent-page-now-brings-context-files-connections-jobs-.md +6 -0
  178. package/corpus/templates/factory/changelog/2026-07-14-chat-opens-reliably-on-hosted-deployments-instead-of-failing.md +6 -0
  179. package/corpus/templates/factory/changelog/2026-07-14-fixed-chat-template-startup-with-older-core-versions.md +6 -0
  180. package/corpus/templates/factory/changelog/2026-07-15-chat-navigation-focuses-on-chat-and-agent.md +6 -0
  181. package/corpus/templates/factory/changelog/2026-07-17-the-agent-chat-sidebar-stays-closed-until-you-open-it-or-sta.md +6 -0
  182. package/corpus/templates/factory/changelog/2026-07-22-compact-sidebar-footer.md +6 -0
  183. package/corpus/templates/factory/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +6 -0
  184. package/corpus/templates/factory/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
  185. package/corpus/templates/factory/changelog/2026-07-22-recent-chats-are-easier-to-scan-and-expand.md +6 -0
  186. package/corpus/templates/factory/changelog/2026-07-23-full-page-chat-is-better-centered-with-quieter-chat-history-.md +6 -0
  187. package/corpus/templates/factory/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
  188. package/corpus/templates/factory/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
  189. package/corpus/templates/factory/changelog/2026-07-25-settings-navigation-now-keeps-manage-agent-as-a-dedicated-li.md +6 -0
  190. package/corpus/templates/factory/changelog/2026-07-29-sidebar-footers-now-keep-feedback-search-and-collapse-togeth.md +6 -0
  191. package/corpus/templates/factory/changelog/2026-07-31-added-an-inspectable-observe-only-factory-queue-for-slack-.md +6 -0
  192. package/corpus/templates/factory/changelog/2026-07-31-clicking-the-agent-native-logo-now-toggles-the-app-sidebar.md +6 -0
  193. package/corpus/templates/factory/components.json +20 -0
  194. package/corpus/templates/factory/data/sync-config.json +1 -0
  195. package/corpus/templates/factory/learnings.defaults.md +5 -0
  196. package/corpus/templates/factory/netlify.toml +10 -0
  197. package/corpus/templates/factory/package.json +105 -0
  198. package/corpus/templates/factory/public/agent-native-icon-dark.svg +10 -0
  199. package/corpus/templates/factory/public/agent-native-icon-light.svg +10 -0
  200. package/corpus/templates/factory/public/agent-native-logo-dark.svg +21 -0
  201. package/corpus/templates/factory/public/agent-native-logo-light.svg +21 -0
  202. package/corpus/templates/factory/public/favicon.svg +1 -0
  203. package/corpus/templates/factory/public/icon-180.svg +1 -0
  204. package/corpus/templates/factory/public/icon-192.svg +1 -0
  205. package/corpus/templates/factory/public/icon-512.svg +1 -0
  206. package/corpus/templates/factory/public/manifest.json +21 -0
  207. package/corpus/templates/factory/react-router.config.ts +7 -0
  208. package/corpus/templates/factory/server/connectors/credentials.ts +129 -0
  209. package/corpus/templates/factory/server/connectors/slack.ts +129 -0
  210. package/corpus/templates/factory/server/db/index.ts +6 -0
  211. package/corpus/templates/factory/server/db/schema.ts +193 -0
  212. package/corpus/templates/factory/server/factory-graph/contracts.ts +212 -0
  213. package/corpus/templates/factory/server/factory-graph/store.ts +121 -0
  214. package/corpus/templates/factory/server/lib/require-workspace-member.ts +55 -0
  215. package/corpus/templates/factory/server/middleware/auth.ts +15 -0
  216. package/corpus/templates/factory/server/plugins/agent-chat.ts +58 -0
  217. package/corpus/templates/factory/server/plugins/auth.ts +14 -0
  218. package/corpus/templates/factory/server/plugins/factory-migrations.ts +247 -0
  219. package/corpus/templates/factory/server/plugins/factory-scheduler-job.ts +116 -0
  220. package/corpus/templates/factory/server/plugins/integrations.ts +46 -0
  221. package/corpus/templates/factory/server/routes/[...page].get.ts +5 -0
  222. package/corpus/templates/factory/server/routes/_agent-native/factory/builder-callback.post.ts +116 -0
  223. package/corpus/templates/factory/server/triage/ai-services-git.ts +197 -0
  224. package/corpus/templates/factory/server/triage/builder-executor.ts +118 -0
  225. package/corpus/templates/factory/server/triage/contracts.ts +164 -0
  226. package/corpus/templates/factory/server/triage/github-ingestion.ts +35 -0
  227. package/corpus/templates/factory/server/triage/guards.ts +121 -0
  228. package/corpus/templates/factory/server/triage/ids.ts +27 -0
  229. package/corpus/templates/factory/server/triage/pr-babysit.ts +100 -0
  230. package/corpus/templates/factory/server/triage/pr-monitor.ts +220 -0
  231. package/corpus/templates/factory/server/triage/slack-client.ts +55 -0
  232. package/corpus/templates/factory/server/triage/slack-poller.ts +152 -0
  233. package/corpus/templates/factory/ssr-entry.ts +15 -0
  234. package/corpus/templates/factory/tsconfig.json +21 -0
  235. package/corpus/templates/factory/vite.config.ts +19 -0
  236. package/corpus/templates/forms/app/components/layout/Sidebar.tsx +55 -5
  237. package/corpus/templates/forms/changelog/2026-07-31-the-agent-native-logo-stays-visible-when-the-sidebar-is-coll.md +6 -0
  238. package/corpus/templates/macros/app/components/layout/AppLayout.tsx +6 -2
  239. package/corpus/templates/plan/app/components/layout/Sidebar.tsx +21 -6
  240. package/corpus/templates/plan/changelog/2026-07-31-clicking-the-agent-native-logo-now-toggles-the-app-sidebar.md +6 -0
  241. package/corpus/templates/slides/.agents/skills/create-deck/SKILL.md +12 -0
  242. package/corpus/templates/slides/.agents/skills/design-systems/SKILL.md +9 -0
  243. package/corpus/templates/slides/.agents/skills/slide-editing/SKILL.md +11 -0
  244. package/corpus/templates/slides/AGENTS.md +5 -6
  245. package/corpus/templates/slides/actions/_await-fit-check.ts +20 -10
  246. package/corpus/templates/slides/actions/add-slide.ts +17 -4
  247. package/corpus/templates/slides/actions/create-design-system.ts +16 -4
  248. package/corpus/templates/slides/actions/delete-design-system.ts +18 -2
  249. package/corpus/templates/slides/actions/get-layout-overflows.ts +88 -0
  250. package/corpus/templates/slides/actions/import-file.ts +1 -0
  251. package/corpus/templates/slides/actions/index-design-system-with-builder.ts +8 -0
  252. package/corpus/templates/slides/actions/patch-deck.ts +48 -16
  253. package/corpus/templates/slides/actions/set-default-design-system.ts +49 -19
  254. package/corpus/templates/slides/actions/update-slide.ts +13 -3
  255. package/corpus/templates/slides/actions/view-screen.ts +87 -10
  256. package/corpus/templates/slides/app/components/deck/SlideRenderer.tsx +155 -28
  257. package/corpus/templates/slides/app/components/design-system/DesignSystemCard.tsx +21 -17
  258. package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +849 -341
  259. package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +102 -2
  260. package/corpus/templates/slides/app/components/editor/PromptDialog.tsx +13 -16
  261. package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +60 -12
  262. package/corpus/templates/slides/app/components/editor/SlideOverflowWarning.tsx +11 -1
  263. package/corpus/templates/slides/app/components/layout/Sidebar.tsx +66 -19
  264. package/corpus/templates/slides/app/i18n/en-US.ts +23 -0
  265. package/corpus/templates/slides/app/lib/normalize-slide-padding.ts +8 -15
  266. package/corpus/templates/slides/app/pages/DeckEditor.tsx +4 -3
  267. package/corpus/templates/slides/app/pages/DesignSystems.tsx +4 -3
  268. package/corpus/templates/slides/app/pages/Index.tsx +1 -1
  269. package/corpus/templates/slides/changelog/2026-07-31-design-system-details-now-show-their-source-and-indexing-sta.md +6 -0
  270. package/corpus/templates/slides/changelog/2026-07-31-design-system-indexing-keeps-your-chosen-name-when-you-uploa.md +6 -0
  271. package/corpus/templates/slides/changelog/2026-07-31-design-system-setup-keeps-focus-rings-visible-and-uses-a-sim.md +6 -0
  272. package/corpus/templates/slides/changelog/2026-07-31-skip-prompt-is-now-available-in-the-new-deck-prompt-header.md +6 -0
  273. package/corpus/templates/slides/changelog/2026-07-31-slides-now-detect-real-text-and-box-overflow-across-the-deck.md +6 -0
  274. package/corpus/templates/slides/changelog/2026-07-31-the-agent-native-logo-stays-visible-when-the-sidebar-is-coll.md +6 -0
  275. package/corpus/templates/slides/server/handlers/design-systems.ts +1 -0
  276. package/corpus/templates/slides/server/handlers/index-design-system-sources.ts +1 -0
  277. package/corpus/templates/slides/server/lib/builder-design-system-proxy.ts +23 -4
  278. package/corpus/templates/slides/server/plugins/agent-chat.ts +5 -0
  279. package/corpus/templates/slides/server/plugins/creative-context.ts +16 -3
  280. package/corpus/templates/slides/server/workspace-defaults.ts +5 -1
  281. package/corpus/templates/slides/shared/slide-fit.ts +26 -0
  282. package/corpus/templates/tasks/app/components/layout/Sidebar.tsx +30 -3
  283. package/corpus/templates/tasks/changelog/2026-07-31-clicking-the-agent-native-logo-now-toggles-the-app-sidebar.md +6 -0
  284. package/dist/a2a/correlation.d.ts +4 -1
  285. package/dist/a2a/correlation.d.ts.map +1 -1
  286. package/dist/a2a/correlation.js +8 -1
  287. package/dist/a2a/correlation.js.map +1 -1
  288. package/dist/a2a/types.d.ts +11 -3
  289. package/dist/a2a/types.d.ts.map +1 -1
  290. package/dist/a2a/types.js.map +1 -1
  291. package/dist/agent/engine/ai-sdk-engine.d.ts.map +1 -1
  292. package/dist/agent/engine/ai-sdk-engine.js +27 -41
  293. package/dist/agent/engine/ai-sdk-engine.js.map +1 -1
  294. package/dist/agent/engine/builder-engine.d.ts.map +1 -1
  295. package/dist/agent/engine/builder-engine.js +18 -8
  296. package/dist/agent/engine/builder-engine.js.map +1 -1
  297. package/dist/agent/engine/error-detail.d.ts +61 -0
  298. package/dist/agent/engine/error-detail.d.ts.map +1 -1
  299. package/dist/agent/engine/error-detail.js +145 -3
  300. package/dist/agent/engine/error-detail.js.map +1 -1
  301. package/dist/agent/engine/failure-taxonomy.d.ts +24 -0
  302. package/dist/agent/engine/failure-taxonomy.d.ts.map +1 -0
  303. package/dist/agent/engine/failure-taxonomy.js +88 -0
  304. package/dist/agent/engine/failure-taxonomy.js.map +1 -0
  305. package/dist/agent/engine/index.d.ts +2 -1
  306. package/dist/agent/engine/index.d.ts.map +1 -1
  307. package/dist/agent/engine/index.js +2 -1
  308. package/dist/agent/engine/index.js.map +1 -1
  309. package/dist/agent/engine/registry.d.ts +16 -0
  310. package/dist/agent/engine/registry.d.ts.map +1 -1
  311. package/dist/agent/engine/registry.js +71 -6
  312. package/dist/agent/engine/registry.js.map +1 -1
  313. package/dist/agent/engine/translate-ai-sdk.d.ts.map +1 -1
  314. package/dist/agent/engine/translate-ai-sdk.js +14 -2
  315. package/dist/agent/engine/translate-ai-sdk.js.map +1 -1
  316. package/dist/agent/production-agent.d.ts.map +1 -1
  317. package/dist/agent/production-agent.js +13 -24
  318. package/dist/agent/production-agent.js.map +1 -1
  319. package/dist/agent/run-loop-with-resume.js +1 -1
  320. package/dist/agent/run-loop-with-resume.js.map +1 -1
  321. package/dist/agent/run-manager.d.ts.map +1 -1
  322. package/dist/agent/run-manager.js +39 -10
  323. package/dist/agent/run-manager.js.map +1 -1
  324. package/dist/agent/run-store.d.ts +10 -0
  325. package/dist/agent/run-store.d.ts.map +1 -1
  326. package/dist/agent/run-store.js +20 -3
  327. package/dist/agent/run-store.js.map +1 -1
  328. package/dist/agent/thread-data-builder.d.ts.map +1 -1
  329. package/dist/agent/thread-data-builder.js +28 -4
  330. package/dist/agent/thread-data-builder.js.map +1 -1
  331. package/dist/chat-threads/store.d.ts +13 -0
  332. package/dist/chat-threads/store.d.ts.map +1 -1
  333. package/dist/chat-threads/store.js +35 -0
  334. package/dist/chat-threads/store.js.map +1 -1
  335. package/dist/cli/templates-meta.d.ts.map +1 -1
  336. package/dist/cli/templates-meta.js +13 -0
  337. package/dist/cli/templates-meta.js.map +1 -1
  338. package/dist/cli/workspace-dev.d.ts.map +1 -1
  339. package/dist/cli/workspace-dev.js +1 -0
  340. package/dist/cli/workspace-dev.js.map +1 -1
  341. package/dist/client/error-format.d.ts.map +1 -1
  342. package/dist/client/error-format.js +10 -0
  343. package/dist/client/error-format.js.map +1 -1
  344. package/dist/client/use-chat-threads.d.ts.map +1 -1
  345. package/dist/client/use-chat-threads.js +66 -16
  346. package/dist/client/use-chat-threads.js.map +1 -1
  347. package/dist/collab/awareness.d.ts +2 -2
  348. package/dist/collab/awareness.d.ts.map +1 -1
  349. package/dist/collab/struct-routes.d.ts +1 -1
  350. package/dist/credentials/index.d.ts +9 -2
  351. package/dist/credentials/index.d.ts.map +1 -1
  352. package/dist/credentials/index.js +50 -8
  353. package/dist/credentials/index.js.map +1 -1
  354. package/dist/extensions/url-safety.d.ts.map +1 -1
  355. package/dist/extensions/url-safety.js +38 -12
  356. package/dist/extensions/url-safety.js.map +1 -1
  357. package/dist/integrations/adapters/slack.d.ts.map +1 -1
  358. package/dist/integrations/adapters/slack.js +25 -8
  359. package/dist/integrations/adapters/slack.js.map +1 -1
  360. package/dist/integrations/google-docs-poller.d.ts.map +1 -1
  361. package/dist/integrations/google-docs-poller.js +13 -1
  362. package/dist/integrations/google-docs-poller.js.map +1 -1
  363. package/dist/integrations/installations-store.d.ts +10 -0
  364. package/dist/integrations/installations-store.d.ts.map +1 -1
  365. package/dist/integrations/installations-store.js +24 -0
  366. package/dist/integrations/installations-store.js.map +1 -1
  367. package/dist/integrations/plugin.d.ts.map +1 -1
  368. package/dist/integrations/plugin.js +6 -5
  369. package/dist/integrations/plugin.js.map +1 -1
  370. package/dist/integrations/types.d.ts +7 -0
  371. package/dist/integrations/types.d.ts.map +1 -1
  372. package/dist/integrations/types.js.map +1 -1
  373. package/dist/integrations/webhook-handler.d.ts.map +1 -1
  374. package/dist/integrations/webhook-handler.js +16 -1
  375. package/dist/integrations/webhook-handler.js.map +1 -1
  376. package/dist/jobs/background-automation-runner.d.ts.map +1 -1
  377. package/dist/jobs/background-automation-runner.js +35 -2
  378. package/dist/jobs/background-automation-runner.js.map +1 -1
  379. package/dist/notifications/routes.d.ts +6 -6
  380. package/dist/observability/routes.d.ts +3 -3
  381. package/dist/provider-api/actions/custom-provider-registration.d.ts +14 -14
  382. package/dist/provider-api/actions/provider-api.d.ts +8 -8
  383. package/dist/provider-api/index.js +7 -3
  384. package/dist/provider-api/index.js.map +1 -1
  385. package/dist/scripts/call-agent.d.ts.map +1 -1
  386. package/dist/scripts/call-agent.js +6 -1
  387. package/dist/scripts/call-agent.js.map +1 -1
  388. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  389. package/dist/server/agent-chat-plugin.js +38 -9
  390. package/dist/server/agent-chat-plugin.js.map +1 -1
  391. package/dist/server/agent-discovery.d.ts +2 -0
  392. package/dist/server/agent-discovery.d.ts.map +1 -1
  393. package/dist/server/agent-discovery.js.map +1 -1
  394. package/dist/server/builder-design-systems.d.ts +4 -1
  395. package/dist/server/builder-design-systems.d.ts.map +1 -1
  396. package/dist/server/builder-design-systems.js +11 -1
  397. package/dist/server/builder-design-systems.js.map +1 -1
  398. package/dist/server/credential-provider.d.ts.map +1 -1
  399. package/dist/server/credential-provider.js +49 -12
  400. package/dist/server/credential-provider.js.map +1 -1
  401. package/dist/server/index.d.ts +1 -1
  402. package/dist/server/index.d.ts.map +1 -1
  403. package/dist/server/index.js.map +1 -1
  404. package/dist/server/onboarding-html.d.ts.map +1 -1
  405. package/dist/server/onboarding-html.js +37 -2
  406. package/dist/server/onboarding-html.js.map +1 -1
  407. package/dist/server/transcribe-voice.d.ts +1 -1
  408. package/dist/shared/reasoning-effort.d.ts +1 -0
  409. package/dist/shared/reasoning-effort.d.ts.map +1 -1
  410. package/dist/shared/reasoning-effort.js +1 -1
  411. package/dist/shared/reasoning-effort.js.map +1 -1
  412. package/dist/templates/chat/app/components/layout/Sidebar.tsx +30 -3
  413. package/dist/templates/chat/changelog/2026-07-31-clicking-the-agent-native-logo-now-toggles-the-app-sidebar.md +6 -0
  414. package/dist/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +11 -0
  415. package/package.json +1 -1
  416. package/src/a2a/correlation.ts +11 -1
  417. package/src/a2a/types.ts +11 -3
  418. package/src/agent/engine/ai-sdk-engine.ts +33 -46
  419. package/src/agent/engine/builder-engine.ts +22 -10
  420. package/src/agent/engine/error-detail.ts +184 -3
  421. package/src/agent/engine/failure-taxonomy.ts +123 -0
  422. package/src/agent/engine/index.ts +8 -0
  423. package/src/agent/engine/registry.ts +92 -8
  424. package/src/agent/engine/translate-ai-sdk.ts +17 -2
  425. package/src/agent/production-agent.ts +13 -33
  426. package/src/agent/run-loop-with-resume.ts +1 -1
  427. package/src/agent/run-manager.ts +43 -14
  428. package/src/agent/run-store.ts +30 -3
  429. package/src/agent/thread-data-builder.ts +36 -4
  430. package/src/chat-threads/store.ts +42 -0
  431. package/src/cli/templates-meta.ts +13 -0
  432. package/src/cli/workspace-dev.ts +1 -0
  433. package/src/client/error-format.ts +12 -0
  434. package/src/client/use-chat-threads.ts +76 -16
  435. package/src/credentials/index.ts +51 -12
  436. package/src/extensions/url-safety.ts +46 -12
  437. package/src/integrations/adapters/slack.ts +32 -10
  438. package/src/integrations/google-docs-poller.ts +12 -1
  439. package/src/integrations/installations-store.ts +30 -0
  440. package/src/integrations/plugin.ts +5 -5
  441. package/src/integrations/types.ts +7 -0
  442. package/src/integrations/webhook-handler.ts +24 -1
  443. package/src/jobs/background-automation-runner.ts +38 -1
  444. package/src/provider-api/index.ts +8 -2
  445. package/src/scripts/call-agent.ts +6 -0
  446. package/src/server/agent-chat-plugin.ts +46 -10
  447. package/src/server/agent-discovery.ts +2 -0
  448. package/src/server/builder-design-systems.ts +21 -0
  449. package/src/server/credential-provider.ts +51 -12
  450. package/src/server/index.ts +1 -0
  451. package/src/server/onboarding-html.ts +37 -2
  452. package/src/shared/reasoning-effort.ts +1 -1
  453. package/src/templates/chat/app/components/layout/Sidebar.tsx +30 -3
  454. package/src/templates/chat/changelog/2026-07-31-clicking-the-agent-native-logo-now-toggles-the-app-sidebar.md +6 -0
  455. package/src/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +11 -0
  456. package/corpus/templates/clips/desktop/src/lib/media-device-selection.ts +0 -157
@@ -8,9 +8,6 @@
8
8
  * `.cause`. Recording `err.message` alone makes every one of them
9
9
  * indistinguishable after the fact, which is how a whole class of production
10
10
  * failures becomes undiagnosable.
11
- *
12
- * Classification (`isConnectionError`, `isRetryableError`) must keep matching
13
- * on the bare `err.message` — this is for the RECORDED detail only.
14
11
  */
15
12
  const DEFAULT_MAX_CAUSE_LINKS = 4;
16
13
  const MAX_CAUSE_LINK_CHARS = 200;
@@ -37,3 +34,187 @@ export function describeErrorWithCauses(
37
34
  }
38
35
  return links.length > 0 ? `${head} (cause: ${links.join(" <- ")})` : head;
39
36
  }
37
+
38
+ /**
39
+ * The single provider-transport-failure classifier. Every layer that decides
40
+ * "is this a network blip?" — engine error codes, run-level retry, Sentry
41
+ * suppression — must call THIS, on `describeErrorWithCauses(err)` rather than
42
+ * on a bare `err.message`.
43
+ *
44
+ * Four divergent copies of this predicate existed, and they disagreed on
45
+ * exactly the string production actually throws. The AI SDK's `RetryError`
46
+ * reports `"Failed after 2 attempts. Last error: Cannot connect to API: …"`,
47
+ * so a copy anchored with `startsWith` scored it as unclassified while a copy
48
+ * using `includes` scored it as retryable. The result was a split brain: the
49
+ * agent loop retried the turn, but the run persisted `error_code = 'unknown'`,
50
+ * which the client does not list as auto-recoverable — so a transient TLS
51
+ * reset ended the user's chat with a dead error instead of resuming. That one
52
+ * mismatch accounted for ~150 failed production runs in a week.
53
+ *
54
+ * Substring matching is deliberate: the real message is always a provider SDK
55
+ * wrapper around the transport error, never bare, and the wrapper prefix
56
+ * differs per SDK and per version.
57
+ */
58
+ export function isProviderConnectionErrorMessage(message: string): boolean {
59
+ const normalized = message.toLowerCase();
60
+ return (
61
+ normalized.includes("connection error") ||
62
+ normalized.includes("cannot connect to api")
63
+ );
64
+ }
65
+
66
+ /** `isProviderConnectionErrorMessage` over an error's full cause chain. */
67
+ export function isProviderConnectionError(err: unknown): boolean {
68
+ return isProviderConnectionErrorMessage(describeErrorWithCauses(err));
69
+ }
70
+
71
+ /** Classification fields an AI SDK provider failure carries. */
72
+ export interface ProviderErrorClassification {
73
+ errorCode?: string;
74
+ statusCode?: number;
75
+ providerRetryable?: boolean;
76
+ }
77
+
78
+ /**
79
+ * Classify a provider error from the AI SDK, whichever way it surfaced.
80
+ *
81
+ * `streamText` does not throw for a failed provider request — it emits an
82
+ * `error` part on `fullStream` — so there are two arrival paths, and only the
83
+ * thrown one used to be classified. The stream-part path discarded
84
+ * `statusCode`, `errorCode`, and `isRetryable` entirely, which is why every
85
+ * provider HTTP failure on an ai-sdk engine landed as `unknown`: a 429 was only
86
+ * retried if its prose happened to contain "rate_limit", and a
87
+ * 100%-reproducible config 400 was indistinguishable from any other unclassified
88
+ * failure, so it had no signature to alert on. Both call sites go through here.
89
+ *
90
+ * `timedOut` is the caller's own first-event deadline, which only the streaming
91
+ * path can know.
92
+ */
93
+ export function classifyProviderError(
94
+ err: unknown,
95
+ timedOut = false,
96
+ ): ProviderErrorClassification {
97
+ // The AI SDK wraps exhausted retries in RetryError and keeps the final
98
+ // APICallError on `lastError`.
99
+ const wrapped = err as { lastError?: unknown } | null;
100
+ const providerError = (
101
+ wrapped?.lastError instanceof Error ? wrapped.lastError : err
102
+ ) as {
103
+ statusCode?: unknown;
104
+ isRetryable?: unknown;
105
+ message?: unknown;
106
+ } | null;
107
+
108
+ const statusCode =
109
+ typeof providerError?.statusCode === "number"
110
+ ? providerError.statusCode
111
+ : undefined;
112
+
113
+ // Classify on the cause chain of the ORIGINAL error, not the unwrapped one:
114
+ // when RetryError does not expose `lastError` as an Error the unwrap falls
115
+ // back to the wrapper, whose message ("Failed after 2 attempts. Last error:
116
+ // …") only *embeds* the transport failure. Matching the wrapper is the point.
117
+ const described = describeErrorWithCauses(err);
118
+ const isConnectionError =
119
+ !timedOut &&
120
+ statusCode === undefined &&
121
+ (isProviderConnectionErrorMessage(described) ||
122
+ isProviderConnectionErrorMessage(
123
+ typeof providerError?.message === "string"
124
+ ? providerError.message
125
+ : String(providerError),
126
+ ));
127
+
128
+ const providerRetryable =
129
+ typeof providerError?.isRetryable === "boolean"
130
+ ? providerError.isRetryable
131
+ : isConnectionError || timedOut
132
+ ? true
133
+ : undefined;
134
+
135
+ return {
136
+ // Tag every known status as `http_<status>` (not just 401) so a rate limit
137
+ // surfaces as `http_429`: the structured statusCode drives turn-level
138
+ // retries, but run-level continuation keys off the errorCode.
139
+ ...(statusCode !== undefined
140
+ ? { errorCode: `http_${statusCode}`, statusCode }
141
+ : isConnectionError || timedOut
142
+ ? { errorCode: "provider_network_error" }
143
+ : // Nothing structured — fall back to reading the message, so a
144
+ // stream-part 529/timeout is not silently unclassified.
145
+ (() => {
146
+ const code = classifyTerminalErrorCode(described);
147
+ return code ? { errorCode: code } : {};
148
+ })()),
149
+ ...(providerRetryable !== undefined ? { providerRetryable } : {}),
150
+ };
151
+ }
152
+
153
+ /**
154
+ * Last-resort error code for a terminal error that reached persistence with no
155
+ * structured code. Persisting `"unknown"` is not a neutral default: the client
156
+ * auto-recovers a fixed list of transport codes, so an unclassified transient
157
+ * blip ends the user's chat while the identical failure carrying its real code
158
+ * resumes. Over four days that gap was 28% of ALL production chat turns.
159
+ *
160
+ * The invariant is NOT "only transport failures may be named". It is: a code
161
+ * returned here must be absent from the client's recoverable list unless a
162
+ * fresh attempt genuinely helps. Naming a deterministic failure is what stops
163
+ * it from reaching the user as raw provider text and hiding inside `unknown`;
164
+ * naming it *recoverable* is what buys a retry spiral. Those are different
165
+ * decisions, and `error-detail.spec.ts` asserts the deterministic codes below
166
+ * stay non-recoverable.
167
+ */
168
+ export function classifyTerminalErrorCode(
169
+ message: string | undefined,
170
+ ): string | undefined {
171
+ if (!message) return undefined;
172
+ const msg = message.toLowerCase();
173
+ if (isProviderConnectionErrorMessage(msg)) return "provider_network_error";
174
+ // Word-bounded: request ids and hashes routinely contain a bare "529".
175
+ if (msg.includes("overloaded") || /\b529\b/.test(msg)) {
176
+ return "overloaded_error";
177
+ }
178
+ if (msg.includes("too many requests") || /\b429\b/.test(msg)) {
179
+ return "http_429";
180
+ }
181
+ if (
182
+ msg.includes("timed out") ||
183
+ msg.includes("timeout") ||
184
+ msg.includes("too much time has passed without sending any data")
185
+ ) {
186
+ return "timeout";
187
+ }
188
+ if (msg.includes("stream ended without a stop event")) {
189
+ return "builder_gateway_network_error";
190
+ }
191
+ // Deterministic below this line — named so they stop landing in `unknown`,
192
+ // never retried. Both were measured against the 13 prod app DBs over
193
+ // 2026-07-24..31: 27 turns/week and 14 turns/week respectively, each with
194
+ // exactly 1.00 runs/turn, i.e. the chat died on the first attempt showing
195
+ // the raw provider sentence.
196
+ //
197
+ // The request side already avoids emitting reasoning_effort alongside tools
198
+ // (see ai-sdk-engine.ts). This classifies the failure for the paths that
199
+ // still reach the provider — another gateway, a stale deploy — so it reads
200
+ // as a configuration problem rather than a mystery.
201
+ if (
202
+ msg.includes("reasoning_effort are not supported") ||
203
+ msg.includes("reasoning_effort to 'none'") ||
204
+ (msg.includes("reasoning_effort") &&
205
+ (msg.includes("tools") || msg.includes("function")))
206
+ ) {
207
+ return "provider_config_error";
208
+ }
209
+ if (msg.includes("missing authentication header") || msg === "unauthorized") {
210
+ return "authentication_error";
211
+ }
212
+ if (
213
+ /(?:err_)?ssl|tlsv?\d|tls handshake|ssl routines|econnreset|econnrefused|und_err_socket|socket hang up/i.test(
214
+ message,
215
+ )
216
+ ) {
217
+ return "provider_network_error";
218
+ }
219
+ return undefined;
220
+ }
@@ -0,0 +1,123 @@
1
+ import { classifyTerminalErrorCode } from "./error-detail.js";
2
+
3
+ export const AGENT_FAILURE_TAXONOMY_CODES = [
4
+ "provider_network_error",
5
+ "provider_config_error",
6
+ "overloaded_error",
7
+ "authentication_error",
8
+ "unknown",
9
+ ] as const;
10
+
11
+ export type AgentFailureTaxonomyCode =
12
+ (typeof AGENT_FAILURE_TAXONOMY_CODES)[number];
13
+
14
+ export type AgentFailureRegime = "interactive" | "scheduled";
15
+
16
+ export interface AgentFailureTaxonomy {
17
+ code: AgentFailureTaxonomyCode;
18
+ label: string;
19
+ regime: AgentFailureRegime;
20
+ source: "error_code" | "error_detail" | "unknown";
21
+ }
22
+
23
+ const LABELS: Record<AgentFailureTaxonomyCode, string> = {
24
+ provider_network_error: "SSL/TLS provider transport drop",
25
+ provider_config_error: "Model reasoning_effort with tools",
26
+ overloaded_error: "Provider overloaded_error",
27
+ authentication_error: "Missing provider authentication",
28
+ unknown: "Unclassified failure",
29
+ };
30
+
31
+ function knownCode(value: unknown): AgentFailureTaxonomyCode | undefined {
32
+ const normalized =
33
+ typeof value === "string" ? value.trim().toLowerCase() : "";
34
+ if (
35
+ normalized === "provider_network_error" ||
36
+ normalized === "connection_error" ||
37
+ normalized === "network_error" ||
38
+ normalized === "ssl_error" ||
39
+ normalized === "tls_error"
40
+ ) {
41
+ return "provider_network_error";
42
+ }
43
+ if (
44
+ normalized === "provider_config_error" ||
45
+ normalized === "reasoning_effort_tools"
46
+ ) {
47
+ return "provider_config_error";
48
+ }
49
+ if (
50
+ normalized === "overloaded_error" ||
51
+ normalized === "provider_overloaded"
52
+ ) {
53
+ return "overloaded_error";
54
+ }
55
+ if (
56
+ normalized === "authentication_error" ||
57
+ normalized === "missing_authentication_header" ||
58
+ normalized === "http_401" ||
59
+ normalized === "unauthorized"
60
+ ) {
61
+ return "authentication_error";
62
+ }
63
+ return undefined;
64
+ }
65
+
66
+ /**
67
+ * Classify the production failure families used by the Factory triage queue.
68
+ * The regime is deliberately derived from the durable run id, not inferred
69
+ * from prose: scheduled runs use the `job-` namespace and interactive runs do
70
+ * not. This keeps a healthy chat sample from hiding a scheduled outage.
71
+ */
72
+ export function classifyAgentFailure(input: {
73
+ runId?: unknown;
74
+ errorCode?: unknown;
75
+ errorDetail?: unknown;
76
+ terminalReason?: unknown;
77
+ terminalEvent?: unknown;
78
+ regime?: AgentFailureRegime;
79
+ }): AgentFailureTaxonomy {
80
+ const regime =
81
+ input.regime ??
82
+ (typeof input.runId === "string" && input.runId.startsWith("job-")
83
+ ? "scheduled"
84
+ : "interactive");
85
+ const explicit = knownCode(input.errorCode);
86
+ if (explicit) {
87
+ return {
88
+ code: explicit,
89
+ label: LABELS[explicit],
90
+ regime,
91
+ source: "error_code",
92
+ };
93
+ }
94
+
95
+ const evidence = [
96
+ input.errorCode,
97
+ input.errorDetail,
98
+ input.terminalReason,
99
+ input.terminalEvent,
100
+ ].filter((value) => value !== undefined && value !== null);
101
+ for (const value of evidence) {
102
+ const text =
103
+ typeof value === "string"
104
+ ? value
105
+ : (JSON.stringify(value) ?? String(value));
106
+ const classified = knownCode(classifyTerminalErrorCode(text));
107
+ if (classified) {
108
+ return {
109
+ code: classified,
110
+ label: LABELS[classified],
111
+ regime,
112
+ source: "error_detail",
113
+ };
114
+ }
115
+ }
116
+
117
+ return {
118
+ code: "unknown",
119
+ label: LABELS.unknown,
120
+ regime,
121
+ source: "unknown",
122
+ };
123
+ }
@@ -25,6 +25,7 @@ export {
25
25
  getConfiguredEngineNameForRequest,
26
26
  getStoredModelForEngine,
27
27
  normalizeModelForEngine,
28
+ resolveDelegatedRunModel,
28
29
  resolveEnginePreservesCustomModels,
29
30
  type NormalizeModelOptions,
30
31
  detectEngineFromEnv,
@@ -54,3 +55,10 @@ export {
54
55
  } from "./anthropic-engine.js";
55
56
  export { createAISDKEngine, type AISDKProvider } from "./ai-sdk-engine.js";
56
57
  export { registerBuiltinEngines } from "./builtin.js";
58
+ export {
59
+ AGENT_FAILURE_TAXONOMY_CODES,
60
+ classifyAgentFailure,
61
+ type AgentFailureRegime,
62
+ type AgentFailureTaxonomy,
63
+ type AgentFailureTaxonomyCode,
64
+ } from "./failure-taxonomy.js";
@@ -13,6 +13,7 @@ import { createRequire } from "node:module";
13
13
  import {
14
14
  assertCredentialStoreReadable,
15
15
  canUseDeployCredentialFallbackForRequest,
16
+ getBuilderCredentialAuthFailure,
16
17
  getProviderCredentialAuthFailure,
17
18
  readDeployCredentialEnv,
18
19
  resolveBuilderCredentialsDetailed,
@@ -272,6 +273,70 @@ export function normalizeModelForEngine(
272
273
  );
273
274
  }
274
275
 
276
+ type ModelResolvableEngine = Pick<
277
+ AgentEngine,
278
+ "name" | "defaultModel" | "supportedModels" | "preserveCustomModels"
279
+ >;
280
+
281
+ /**
282
+ * Bound an untrusted, caller-supplied model preference to this engine's own
283
+ * catalog. Returns `undefined` — never a substitute — when the hint names
284
+ * anything the engine does not already offer, so a peer can never move the run
285
+ * to a different provider, an unknown id, or a capability tier this engine was
286
+ * not going to serve on its own.
287
+ */
288
+ function resolveModelHintForEngine(
289
+ engine: ModelResolvableEngine,
290
+ hint: string | null | undefined,
291
+ ): string | undefined {
292
+ const candidate = typeof hint === "string" ? hint.trim() : "";
293
+ if (!candidate || candidate === "auto") return undefined;
294
+ // An engine with no catalog, or one that passes custom ids through verbatim
295
+ // (an OpenAI-compatible gateway), cannot prove membership — so it takes no
296
+ // hint at all rather than forwarding an unverifiable id to a provider.
297
+ if (engine.preserveCustomModels || engine.supportedModels.length === 0) {
298
+ return undefined;
299
+ }
300
+ const normalized = normalizeModelForEngine(engine, candidate);
301
+ // `normalizeModelForEngine` answers `defaultModel` both for "this IS the
302
+ // default" and for "no idea what this is", so an unmatched hint is only
303
+ // distinguishable by re-checking the raw candidate. Anything else it returns
304
+ // is a real catalog hit.
305
+ const matched =
306
+ normalized === engine.defaultModel
307
+ ? engine.supportedModels.includes(candidate)
308
+ : engine.supportedModels.includes(normalized);
309
+ return matched ? normalized : undefined;
310
+ }
311
+
312
+ /**
313
+ * Model for a delegated (A2A) run, in strict precedence: the receiving app's
314
+ * explicit configuration, then its own stored setting, then the caller's hint,
315
+ * then the engine default. An app that pins a model keeps it; a hint only fills
316
+ * the gap where the receiver would otherwise take a default it never chose.
317
+ *
318
+ * A rejected hint is logged and dropped — a delegated run must never fail over
319
+ * a preference.
320
+ */
321
+ export function resolveDelegatedRunModel(
322
+ engine: ModelResolvableEngine,
323
+ options: {
324
+ explicitModel?: string | null;
325
+ storedModel?: string | null;
326
+ callerModelHint?: string | null;
327
+ },
328
+ ): string {
329
+ const own = options.explicitModel ?? options.storedModel;
330
+ if (own) return normalizeModelForEngine(engine, own);
331
+ const hinted = resolveModelHintForEngine(engine, options.callerModelHint);
332
+ if (!hinted && options.callerModelHint) {
333
+ console.log(
334
+ `[a2a] Ignoring caller model hint "${options.callerModelHint}" — not offered by engine ${engine.name}`,
335
+ );
336
+ }
337
+ return normalizeModelForEngine(engine, hinted ?? engine.defaultModel);
338
+ }
339
+
275
340
  /**
276
341
  * Whether models saved or read for this engine ENTRY should be preserved
277
342
  * verbatim instead of normalized against the built-in catalog.
@@ -360,10 +425,7 @@ export function detectEngineFromEnv(): AgentEngineEntry | null {
360
425
  return null;
361
426
  }
362
427
 
363
- async function envKeyUsableForEntry(
364
- entry: AgentEngineEntry,
365
- key: string,
366
- ): Promise<boolean> {
428
+ async function envKeyUsableForEntry(key: string): Promise<boolean> {
367
429
  if (
368
430
  !(
369
431
  canUseDeployCredentialFallbackForRequest(key) &&
@@ -372,19 +434,41 @@ async function envKeyUsableForEntry(
372
434
  ) {
373
435
  return false;
374
436
  }
375
- if (entry.name === "builder") {
376
- return true;
377
- }
378
437
  const value = readDeployCredentialEnv(key);
379
438
  if (!value) return false;
380
439
  return !(await getProviderCredentialAuthFailure({ key, value }));
381
440
  }
382
441
 
442
+ /**
443
+ * Builder's deploy-env fallback is checked as a pair, not per-key: the
444
+ * auth-failure marker is fingerprinted from privateKey+publicKey together
445
+ * (see `builderCredentialFingerprint`), so a single-key lookup can never
446
+ * match it. Without this, a rejected deploy-level Builder key would keep
447
+ * reporting "usable" through this env-only path forever — the same class of
448
+ * bug as the per-scope check in `credential-provider.ts`'s
449
+ * `isCompleteBuilderConnection`.
450
+ */
451
+ async function hasUsableBuilderEnvKeys(): Promise<boolean> {
452
+ const privateKey = canUseDeployCredentialFallbackForRequest(
453
+ "BUILDER_PRIVATE_KEY",
454
+ )
455
+ ? readDeployCredentialEnv("BUILDER_PRIVATE_KEY")
456
+ : null;
457
+ const publicKey = canUseDeployCredentialFallbackForRequest(
458
+ "BUILDER_PUBLIC_KEY",
459
+ )
460
+ ? readDeployCredentialEnv("BUILDER_PUBLIC_KEY")
461
+ : null;
462
+ if (!privateKey || !publicKey) return false;
463
+ return !(await getBuilderCredentialAuthFailure({ privateKey, publicKey }));
464
+ }
465
+
383
466
  async function hasUsableEnvKeys(entry: AgentEngineEntry): Promise<boolean> {
384
467
  if (!isAgentEnginePackageInstalled(entry)) return false;
385
468
  if (entry.requiredEnvVars.length === 0) return false;
469
+ if (entry.name === "builder") return hasUsableBuilderEnvKeys();
386
470
  for (const key of entry.requiredEnvVars) {
387
- if (!(await envKeyUsableForEntry(entry, key))) return false;
471
+ if (!(await envKeyUsableForEntry(key))) return false;
388
472
  }
389
473
  return true;
390
474
  }
@@ -7,6 +7,10 @@
7
7
  * `ModelMessage` shapes.
8
8
  */
9
9
 
10
+ import {
11
+ classifyProviderError,
12
+ describeErrorWithCauses,
13
+ } from "./error-detail.js";
10
14
  import { backfillEngineMessagesToolResults } from "./translate-anthropic.js";
11
15
  import type {
12
16
  EngineTool,
@@ -294,11 +298,22 @@ export function aiSdkPartToEngineEvents(part: any): EngineEvent[] {
294
298
  case "error": {
295
299
  const errMsg =
296
300
  part.error instanceof Error
297
- ? part.error.message
301
+ ? describeErrorWithCauses(part.error)
298
302
  : typeof part.error === "string"
299
303
  ? part.error
300
304
  : JSON.stringify(part.error);
301
- events.push({ type: "stop", reason: "error", error: errMsg });
305
+ // `streamText` reports a failed provider request as a stream part rather
306
+ // than a throw, so this is the arrival path for most provider HTTP
307
+ // failures. It used to emit the message alone, discarding the
308
+ // APICallError's statusCode/isRetryable — which is why they all landed as
309
+ // `unknown` and were retried only if their prose happened to match a
310
+ // keyword. Same classifier as the thrown path in ai-sdk-engine.ts.
311
+ events.push({
312
+ type: "stop",
313
+ reason: "error",
314
+ error: errMsg,
315
+ ...classifyProviderError(part.error),
316
+ });
302
317
  break;
303
318
  }
304
319
 
@@ -84,6 +84,7 @@ import {
84
84
  LLM_MISSING_CREDENTIALS_MESSAGE,
85
85
  userFacingLlmCredentialError,
86
86
  } from "./engine/credential-errors.js";
87
+ import { isProviderConnectionErrorMessage } from "./engine/error-detail.js";
87
88
  import {
88
89
  resolveEngine,
89
90
  registerBuiltinEngines,
@@ -1312,7 +1313,7 @@ export function isRetryableError(err: unknown): boolean {
1312
1313
  msg.includes("gateway error") ||
1313
1314
  msg.includes("socket hang up") ||
1314
1315
  msg.includes("connection reset") ||
1315
- hasProviderConnectionErrorMessage(msg) ||
1316
+ isProviderConnectionErrorMessage(msg) ||
1316
1317
  msg.includes("too many requests") ||
1317
1318
  msg.includes("timeout") ||
1318
1319
  msg.includes("gateway timeout") ||
@@ -1321,17 +1322,6 @@ export function isRetryableError(err: unknown): boolean {
1321
1322
  );
1322
1323
  }
1323
1324
 
1324
- function hasProviderConnectionErrorMessage(message: string): boolean {
1325
- const normalized = message.toLowerCase();
1326
- // Anthropic's APIConnectionError uses "Connection error."; AI SDK wraps
1327
- // OpenAI TLS failures as "Cannot connect to API". Both can cross a worker
1328
- // boundary without their structured EngineError metadata.
1329
- return (
1330
- normalized.includes("connection error") ||
1331
- normalized.includes("cannot connect to api")
1332
- );
1333
- }
1334
-
1335
1325
  // ---------------------------------------------------------------------------
1336
1326
  // Context-window overflow recovery
1337
1327
  // ---------------------------------------------------------------------------
@@ -2264,7 +2254,7 @@ export function isResumableEngineError(err: unknown): boolean {
2264
2254
  text.includes("econnaborted") ||
2265
2255
  text.includes("fetch failed") ||
2266
2256
  text.includes("network error") ||
2267
- hasProviderConnectionErrorMessage(text) ||
2257
+ isProviderConnectionErrorMessage(text) ||
2268
2258
  text.includes("connection reset") ||
2269
2259
  text.includes("connection closed") ||
2270
2260
  text.includes("stream closed") ||
@@ -6104,7 +6094,7 @@ function isRecoverableContinuationError(event: {
6104
6094
  code === "http_529" ||
6105
6095
  code === "run_timeout" ||
6106
6096
  message.includes("timeout") ||
6107
- hasProviderConnectionErrorMessage(message) ||
6097
+ isProviderConnectionErrorMessage(message) ||
6108
6098
  message.includes("temporarily unavailable")
6109
6099
  );
6110
6100
  }
@@ -6432,7 +6422,7 @@ export async function runAgentLoopWithMainChatInternalContinuations(
6432
6422
  type: "error",
6433
6423
  error: RUN_BUDGET_EXHAUSTED_MESSAGE,
6434
6424
  errorCode: RUN_BUDGET_EXHAUSTED_ERROR_CODE,
6435
- recoverable: true,
6425
+ recoverable: false,
6436
6426
  });
6437
6427
  }
6438
6428
  return usage;
@@ -6661,9 +6651,9 @@ export async function claimBackgroundWorkerRunEarly(opts: {
6661
6651
  .join(" "),
6662
6652
  ).catch(() => {});
6663
6653
 
6664
- // A failed durable abort read is fail-closed: never let a worker execute
6665
- // after cancellation just because the database was temporarily unreadable.
6666
- if (await turnAborted(threadId, turnId).catch(() => true)) {
6654
+ // A failed durable abort read must surface as infrastructure failure. It is
6655
+ // not evidence that the user stopped the turn.
6656
+ if (await turnAborted(threadId, turnId)) {
6667
6657
  await abortRun(opts.runId, "user").catch(() => {});
6668
6658
  return { claimed: false, skipped: "turn-aborted" };
6669
6659
  }
@@ -6674,7 +6664,7 @@ export async function claimBackgroundWorkerRunEarly(opts: {
6674
6664
  }).catch(() => {});
6675
6665
  }
6676
6666
 
6677
- if (await turnAborted(threadId, turnId).catch(() => true)) {
6667
+ if (await turnAborted(threadId, turnId)) {
6678
6668
  await abortRun(opts.runId, "user").catch(() => {});
6679
6669
  return { claimed: false, skipped: "turn-aborted" };
6680
6670
  }
@@ -6687,7 +6677,7 @@ export async function claimBackgroundWorkerRunEarly(opts: {
6687
6677
 
6688
6678
  await record(opts.runId, RUN_DIAG_STAGE.workerClaimed).catch(() => {});
6689
6679
  await heartbeat(opts.runId).catch(() => {});
6690
- if (await turnAborted(threadId, turnId).catch(() => true)) {
6680
+ if (await turnAborted(threadId, turnId)) {
6691
6681
  await abortRun(opts.runId, "user").catch(() => {});
6692
6682
  return { claimed: false, skipped: "turn-aborted" };
6693
6683
  }
@@ -7143,11 +7133,7 @@ export async function chainServerDrivenContinuation(opts: {
7143
7133
  };
7144
7134
  delete continuationBody[AGENT_CHAT_BACKGROUND_RUN_FIELD];
7145
7135
  try {
7146
- if (
7147
- await d
7148
- .isTurnAborted(effectiveThreadId, effectiveTurnId)
7149
- .catch(() => true)
7150
- ) {
7136
+ if (await d.isTurnAborted(effectiveThreadId, effectiveTurnId)) {
7151
7137
  await d.markRunAborted(runId, "user").catch(() => {});
7152
7138
  return;
7153
7139
  }
@@ -7196,11 +7182,7 @@ export async function chainServerDrivenContinuation(opts: {
7196
7182
  insertErr instanceof Error ? insertErr.message : insertErr,
7197
7183
  );
7198
7184
  }
7199
- if (
7200
- await d
7201
- .isTurnAborted(effectiveThreadId, effectiveTurnId)
7202
- .catch(() => true)
7203
- ) {
7185
+ if (await d.isTurnAborted(effectiveThreadId, effectiveTurnId)) {
7204
7186
  if (nextRowInserted)
7205
7187
  await d.markRunAborted(nextRunId, "user").catch(() => {});
7206
7188
  await d.markRunAborted(runId, "user").catch(() => {});
@@ -8376,9 +8358,7 @@ export function createProductionAgentHandler(
8376
8358
  : runId;
8377
8359
  if (
8378
8360
  isBackgroundWorker &&
8379
- (await isTurnAborted(effectiveThreadId, effectiveTurnId).catch(
8380
- () => true,
8381
- ))
8361
+ (await isTurnAborted(effectiveThreadId, effectiveTurnId))
8382
8362
  ) {
8383
8363
  await markRunAborted(runId, "user").catch(() => {});
8384
8364
  return { ok: true, stopped: true };
@@ -605,7 +605,7 @@ export async function runAgentLoopDirectWithSoftTimeout(
605
605
  type: "error",
606
606
  error: RUN_BUDGET_EXHAUSTED_MESSAGE,
607
607
  errorCode: RUN_BUDGET_EXHAUSTED_ERROR_CODE,
608
- recoverable: true,
608
+ recoverable: false,
609
609
  });
610
610
  reportFinalOutcome({
611
611
  state: "failed",