@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.
- package/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +198 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/a2a/correlation.ts +11 -1
- package/corpus/core/src/a2a/types.ts +11 -3
- package/corpus/core/src/agent/engine/ai-sdk-engine.ts +33 -46
- package/corpus/core/src/agent/engine/builder-engine.ts +22 -10
- package/corpus/core/src/agent/engine/error-detail.ts +184 -3
- package/corpus/core/src/agent/engine/failure-taxonomy.ts +123 -0
- package/corpus/core/src/agent/engine/index.ts +8 -0
- package/corpus/core/src/agent/engine/registry.ts +92 -8
- package/corpus/core/src/agent/engine/translate-ai-sdk.ts +17 -2
- package/corpus/core/src/agent/production-agent.ts +13 -33
- package/corpus/core/src/agent/run-loop-with-resume.ts +1 -1
- package/corpus/core/src/agent/run-manager.ts +43 -14
- package/corpus/core/src/agent/run-store.ts +30 -3
- package/corpus/core/src/agent/thread-data-builder.ts +36 -4
- package/corpus/core/src/chat-threads/store.ts +42 -0
- package/corpus/core/src/cli/templates-meta.ts +13 -0
- package/corpus/core/src/cli/workspace-dev.ts +1 -0
- package/corpus/core/src/client/error-format.ts +12 -0
- package/corpus/core/src/client/use-chat-threads.ts +76 -16
- package/corpus/core/src/credentials/index.ts +51 -12
- package/corpus/core/src/extensions/url-safety.ts +46 -12
- package/corpus/core/src/integrations/adapters/slack.ts +32 -10
- package/corpus/core/src/integrations/google-docs-poller.ts +12 -1
- package/corpus/core/src/integrations/installations-store.ts +30 -0
- package/corpus/core/src/integrations/plugin.ts +5 -5
- package/corpus/core/src/integrations/types.ts +7 -0
- package/corpus/core/src/integrations/webhook-handler.ts +24 -1
- package/corpus/core/src/jobs/background-automation-runner.ts +38 -1
- package/corpus/core/src/provider-api/index.ts +8 -2
- package/corpus/core/src/scripts/call-agent.ts +6 -0
- package/corpus/core/src/server/agent-chat-plugin.ts +46 -10
- package/corpus/core/src/server/agent-discovery.ts +2 -0
- package/corpus/core/src/server/builder-design-systems.ts +21 -0
- package/corpus/core/src/server/credential-provider.ts +51 -12
- package/corpus/core/src/server/index.ts +1 -0
- package/corpus/core/src/server/onboarding-html.ts +37 -2
- package/corpus/core/src/shared/reasoning-effort.ts +1 -1
- package/corpus/core/src/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +11 -0
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +6 -2
- package/corpus/templates/assets/app/components/layout/Sidebar.tsx +39 -19
- package/corpus/templates/assets/changelog/2026-07-31-the-agent-native-logo-stays-visible-when-the-sidebar-is-coll.md +6 -0
- package/corpus/templates/brain/app/components/layout/Sidebar.tsx +30 -3
- package/corpus/templates/brain/changelog/2026-07-31-clicking-the-agent-native-logo-now-toggles-the-app-sidebar.md +6 -0
- package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +1 -1
- package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +54 -25
- package/corpus/templates/calendar/changelog/2026-07-31-the-agent-native-logo-stays-visible-when-the-sidebar-is-coll.md +6 -0
- package/corpus/templates/chat/app/components/layout/Sidebar.tsx +30 -3
- package/corpus/templates/chat/changelog/2026-07-31-clicking-the-agent-native-logo-now-toggles-the-app-sidebar.md +6 -0
- package/corpus/templates/clips/app/components/library/library-layout.tsx +37 -21
- package/corpus/templates/clips/changelog/2026-07-30-meeting-microphone-transcription-works-reliably-from-the-fir.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-31-the-agent-native-logo-stays-visible-when-the-sidebar-is-coll.md +6 -0
- package/corpus/templates/clips/desktop/src/hooks/useMediaDevices.ts +1 -1
- package/corpus/templates/clips/desktop/src/lib/media-capture-constraints.ts +1 -1
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen/custom_capture.rs +13 -0
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +2 -0
- package/corpus/templates/clips/desktop/src-tauri/src/system_audio.rs +25 -132
- package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +34 -17
- package/corpus/templates/content/changelog/2026-07-31-the-agent-native-logo-stays-visible-when-the-sidebar-is-coll.md +6 -0
- package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +6 -2
- package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +5 -0
- package/corpus/templates/design/actions/create-design-system.ts +1 -0
- package/corpus/templates/design/actions/set-default-design-system.ts +34 -26
- package/corpus/templates/design/app/components/design/KeyboardShortcutsPanel.tsx +5 -3
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +23 -0
- package/corpus/templates/design/app/components/design/keyboard-shortcuts.ts +3 -0
- package/corpus/templates/design/app/components/layout/Sidebar.tsx +21 -4
- package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +11 -7
- package/corpus/templates/design/app/i18n-data.ts +39 -0
- package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +229 -12
- package/corpus/templates/design/app/pages/DesignSystems.tsx +10 -4
- package/corpus/templates/design/changelog/2026-07-30-fixed-the-keyboard-shortcuts-panel-not-opening-with-ctrl-shi.md +6 -0
- package/corpus/templates/design/changelog/2026-07-31-clicking-the-agent-native-logo-now-toggles-the-app-sidebar.md +6 -0
- package/corpus/templates/design/changelog/2026-07-31-design-system-indexing-keeps-your-chosen-name-when-you-uploa.md +6 -0
- package/corpus/templates/design/server/lib/builder-design-system-proxy.ts +19 -4
- package/corpus/templates/dispatch/AGENTS.md +4 -0
- package/corpus/templates/factory/.agents/skills/actions/SKILL.md +562 -0
- package/corpus/templates/factory/.agents/skills/adding-a-feature/SKILL.md +198 -0
- package/corpus/templates/factory/.agents/skills/agent-native-docs/SKILL.md +115 -0
- package/corpus/templates/factory/.agents/skills/agent-native-toolkit/SKILL.md +182 -0
- package/corpus/templates/factory/.agents/skills/capture-learnings/SKILL.md +89 -0
- package/corpus/templates/factory/.agents/skills/create-skill/SKILL.md +221 -0
- package/corpus/templates/factory/.agents/skills/customizing-agent-native/SKILL.md +220 -0
- package/corpus/templates/factory/.agents/skills/delegate-to-agent/SKILL.md +263 -0
- package/corpus/templates/factory/.agents/skills/factory-graphs/SKILL.md +52 -0
- package/corpus/templates/factory/.agents/skills/feature-flags/SKILL.md +169 -0
- package/corpus/templates/factory/.agents/skills/frontend-design/SKILL.md +174 -0
- package/corpus/templates/factory/.agents/skills/real-time-sync/SKILL.md +232 -0
- package/corpus/templates/factory/.agents/skills/security/SKILL.md +324 -0
- package/corpus/templates/factory/.agents/skills/self-modifying-code/SKILL.md +119 -0
- package/corpus/templates/factory/.agents/skills/shadcn-ui/SKILL.md +123 -0
- package/corpus/templates/factory/.agents/skills/sharing/SKILL.md +232 -0
- package/corpus/templates/factory/.agents/skills/storing-data/SKILL.md +178 -0
- package/corpus/templates/factory/.agents/skills/upgrade-agent-native/SKILL.md +122 -0
- package/corpus/templates/factory/.env.example +24 -0
- package/corpus/templates/factory/.ignore +0 -0
- package/corpus/templates/factory/.oxfmtrc.json +8 -0
- package/corpus/templates/factory/AGENTS.md +90 -0
- package/corpus/templates/factory/CHANGELOG.md +10 -0
- package/corpus/templates/factory/DEVELOPING.md +185 -0
- package/corpus/templates/factory/README.md +64 -0
- package/corpus/templates/factory/_gitignore +42 -0
- package/corpus/templates/factory/actions/add-factory-comment.ts +55 -0
- package/corpus/templates/factory/actions/approve-factory-item.ts +214 -0
- package/corpus/templates/factory/actions/babysit-pull-request.ts +126 -0
- package/corpus/templates/factory/actions/evaluate-triage-item.ts +172 -0
- package/corpus/templates/factory/actions/get-factory-graph.ts +62 -0
- package/corpus/templates/factory/actions/get-triage-config.ts +42 -0
- package/corpus/templates/factory/actions/get-triage-item.ts +74 -0
- package/corpus/templates/factory/actions/hello.ts +13 -0
- package/corpus/templates/factory/actions/ingest-github-observation.ts +100 -0
- package/corpus/templates/factory/actions/list-factories.ts +40 -0
- package/corpus/templates/factory/actions/list-factory-comments.ts +40 -0
- package/corpus/templates/factory/actions/list-triage-items.ts +85 -0
- package/corpus/templates/factory/actions/list-triage-rules.ts +44 -0
- package/corpus/templates/factory/actions/navigate.ts +41 -0
- package/corpus/templates/factory/actions/poll-slack-channel.ts +118 -0
- package/corpus/templates/factory/actions/reconcile-triage-run.ts +179 -0
- package/corpus/templates/factory/actions/record-triage-feedback.ts +58 -0
- package/corpus/templates/factory/actions/run.ts +2 -0
- package/corpus/templates/factory/actions/save-factory-graph.ts +129 -0
- package/corpus/templates/factory/actions/save-triage-config.ts +67 -0
- package/corpus/templates/factory/actions/save-triage-rule.ts +89 -0
- package/corpus/templates/factory/actions/suggest-factory-rules.ts +70 -0
- package/corpus/templates/factory/actions/view-screen.ts +73 -0
- package/corpus/templates/factory/app/components/factory/FactoryCanvas.tsx +441 -0
- package/corpus/templates/factory/app/components/factory/FactoryInspector.tsx +388 -0
- package/corpus/templates/factory/app/components/layout/Header.tsx +60 -0
- package/corpus/templates/factory/app/components/layout/Layout.tsx +190 -0
- package/corpus/templates/factory/app/components/layout/Sidebar.tsx +538 -0
- package/corpus/templates/factory/app/components/triage/triage-status-pill.tsx +28 -0
- package/corpus/templates/factory/app/components/ui/button.tsx +1 -0
- package/corpus/templates/factory/app/components/ui/card.tsx +1 -0
- package/corpus/templates/factory/app/components/ui/dropdown-menu.tsx +1 -0
- package/corpus/templates/factory/app/components/ui/input.tsx +1 -0
- package/corpus/templates/factory/app/components/ui/label.tsx +1 -0
- package/corpus/templates/factory/app/components/ui/sheet.tsx +1 -0
- package/corpus/templates/factory/app/components/ui/textarea.tsx +1 -0
- package/corpus/templates/factory/app/components/ui/toolkit-provider.tsx +17 -0
- package/corpus/templates/factory/app/components/ui/tooltip.tsx +1 -0
- package/corpus/templates/factory/app/design-system.ts +3 -0
- package/corpus/templates/factory/app/entry.client.tsx +22 -0
- package/corpus/templates/factory/app/entry.server.tsx +10 -0
- package/corpus/templates/factory/app/global.css +93 -0
- package/corpus/templates/factory/app/hooks/use-navigation-state.ts +113 -0
- package/corpus/templates/factory/app/i18n/en-US.ts +211 -0
- package/corpus/templates/factory/app/i18n/index.ts +34 -0
- package/corpus/templates/factory/app/i18n-data.ts +556 -0
- package/corpus/templates/factory/app/lib/agent-page.tsx +49 -0
- package/corpus/templates/factory/app/lib/app-config.ts +11 -0
- package/corpus/templates/factory/app/lib/tab-id.ts +1 -0
- package/corpus/templates/factory/app/lib/utils.ts +1 -0
- package/corpus/templates/factory/app/root.tsx +175 -0
- package/corpus/templates/factory/app/routes/_index.tsx +94 -0
- package/corpus/templates/factory/app/routes/agent.tsx +24 -0
- package/corpus/templates/factory/app/routes/chat.$threadId.tsx +1 -0
- package/corpus/templates/factory/app/routes/database.tsx +17 -0
- package/corpus/templates/factory/app/routes/extensions.$id.$slug.tsx +2 -0
- package/corpus/templates/factory/app/routes/extensions.$id.tsx +11 -0
- package/corpus/templates/factory/app/routes/extensions._index.tsx +11 -0
- package/corpus/templates/factory/app/routes/extensions.tsx +5 -0
- package/corpus/templates/factory/app/routes/factory.tsx +1003 -0
- package/corpus/templates/factory/app/routes/observability.tsx +19 -0
- package/corpus/templates/factory/app/routes/settings.tsx +89 -0
- package/corpus/templates/factory/app/routes/team.tsx +11 -0
- package/corpus/templates/factory/app/routes.ts +4 -0
- package/corpus/templates/factory/app/vite-env.d.ts +6 -0
- package/corpus/templates/factory/changelog/2026-06-24-a-new-settings-page-gives-quick-access-to-language-workspace.md +6 -0
- package/corpus/templates/factory/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
- package/corpus/templates/factory/changelog/2026-06-27-traditional-chinese-copy-uses-taiwan-terminology.md +6 -0
- package/corpus/templates/factory/changelog/2026-06-28-left-sidebar-collapse-motion-and-footer-chrome-are-quieter.md +6 -0
- package/corpus/templates/factory/changelog/2026-06-29-chat-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
- package/corpus/templates/factory/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
- package/corpus/templates/factory/changelog/2026-07-10-chat-now-makes-ai-connection-setup-clear-without-shifting-th.md +6 -0
- package/corpus/templates/factory/changelog/2026-07-13-a-full-agent-page-now-brings-context-files-connections-jobs-.md +6 -0
- package/corpus/templates/factory/changelog/2026-07-14-chat-opens-reliably-on-hosted-deployments-instead-of-failing.md +6 -0
- package/corpus/templates/factory/changelog/2026-07-14-fixed-chat-template-startup-with-older-core-versions.md +6 -0
- package/corpus/templates/factory/changelog/2026-07-15-chat-navigation-focuses-on-chat-and-agent.md +6 -0
- package/corpus/templates/factory/changelog/2026-07-17-the-agent-chat-sidebar-stays-closed-until-you-open-it-or-sta.md +6 -0
- package/corpus/templates/factory/changelog/2026-07-22-compact-sidebar-footer.md +6 -0
- package/corpus/templates/factory/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +6 -0
- package/corpus/templates/factory/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
- package/corpus/templates/factory/changelog/2026-07-22-recent-chats-are-easier-to-scan-and-expand.md +6 -0
- package/corpus/templates/factory/changelog/2026-07-23-full-page-chat-is-better-centered-with-quieter-chat-history-.md +6 -0
- package/corpus/templates/factory/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
- package/corpus/templates/factory/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
- package/corpus/templates/factory/changelog/2026-07-25-settings-navigation-now-keeps-manage-agent-as-a-dedicated-li.md +6 -0
- package/corpus/templates/factory/changelog/2026-07-29-sidebar-footers-now-keep-feedback-search-and-collapse-togeth.md +6 -0
- package/corpus/templates/factory/changelog/2026-07-31-added-an-inspectable-observe-only-factory-queue-for-slack-.md +6 -0
- package/corpus/templates/factory/changelog/2026-07-31-clicking-the-agent-native-logo-now-toggles-the-app-sidebar.md +6 -0
- package/corpus/templates/factory/components.json +20 -0
- package/corpus/templates/factory/data/sync-config.json +1 -0
- package/corpus/templates/factory/learnings.defaults.md +5 -0
- package/corpus/templates/factory/netlify.toml +10 -0
- package/corpus/templates/factory/package.json +105 -0
- package/corpus/templates/factory/public/agent-native-icon-dark.svg +10 -0
- package/corpus/templates/factory/public/agent-native-icon-light.svg +10 -0
- package/corpus/templates/factory/public/agent-native-logo-dark.svg +21 -0
- package/corpus/templates/factory/public/agent-native-logo-light.svg +21 -0
- package/corpus/templates/factory/public/favicon.svg +1 -0
- package/corpus/templates/factory/public/icon-180.svg +1 -0
- package/corpus/templates/factory/public/icon-192.svg +1 -0
- package/corpus/templates/factory/public/icon-512.svg +1 -0
- package/corpus/templates/factory/public/manifest.json +21 -0
- package/corpus/templates/factory/react-router.config.ts +7 -0
- package/corpus/templates/factory/server/connectors/credentials.ts +129 -0
- package/corpus/templates/factory/server/connectors/slack.ts +129 -0
- package/corpus/templates/factory/server/db/index.ts +6 -0
- package/corpus/templates/factory/server/db/schema.ts +193 -0
- package/corpus/templates/factory/server/factory-graph/contracts.ts +212 -0
- package/corpus/templates/factory/server/factory-graph/store.ts +121 -0
- package/corpus/templates/factory/server/lib/require-workspace-member.ts +55 -0
- package/corpus/templates/factory/server/middleware/auth.ts +15 -0
- package/corpus/templates/factory/server/plugins/agent-chat.ts +58 -0
- package/corpus/templates/factory/server/plugins/auth.ts +14 -0
- package/corpus/templates/factory/server/plugins/factory-migrations.ts +247 -0
- package/corpus/templates/factory/server/plugins/factory-scheduler-job.ts +116 -0
- package/corpus/templates/factory/server/plugins/integrations.ts +46 -0
- package/corpus/templates/factory/server/routes/[...page].get.ts +5 -0
- package/corpus/templates/factory/server/routes/_agent-native/factory/builder-callback.post.ts +116 -0
- package/corpus/templates/factory/server/triage/ai-services-git.ts +197 -0
- package/corpus/templates/factory/server/triage/builder-executor.ts +118 -0
- package/corpus/templates/factory/server/triage/contracts.ts +164 -0
- package/corpus/templates/factory/server/triage/github-ingestion.ts +35 -0
- package/corpus/templates/factory/server/triage/guards.ts +121 -0
- package/corpus/templates/factory/server/triage/ids.ts +27 -0
- package/corpus/templates/factory/server/triage/pr-babysit.ts +100 -0
- package/corpus/templates/factory/server/triage/pr-monitor.ts +220 -0
- package/corpus/templates/factory/server/triage/slack-client.ts +55 -0
- package/corpus/templates/factory/server/triage/slack-poller.ts +152 -0
- package/corpus/templates/factory/ssr-entry.ts +15 -0
- package/corpus/templates/factory/tsconfig.json +21 -0
- package/corpus/templates/factory/vite.config.ts +19 -0
- package/corpus/templates/forms/app/components/layout/Sidebar.tsx +55 -5
- package/corpus/templates/forms/changelog/2026-07-31-the-agent-native-logo-stays-visible-when-the-sidebar-is-coll.md +6 -0
- package/corpus/templates/macros/app/components/layout/AppLayout.tsx +6 -2
- package/corpus/templates/plan/app/components/layout/Sidebar.tsx +21 -6
- package/corpus/templates/plan/changelog/2026-07-31-clicking-the-agent-native-logo-now-toggles-the-app-sidebar.md +6 -0
- package/corpus/templates/slides/.agents/skills/create-deck/SKILL.md +12 -0
- package/corpus/templates/slides/.agents/skills/design-systems/SKILL.md +9 -0
- package/corpus/templates/slides/.agents/skills/slide-editing/SKILL.md +11 -0
- package/corpus/templates/slides/AGENTS.md +5 -6
- package/corpus/templates/slides/actions/_await-fit-check.ts +20 -10
- package/corpus/templates/slides/actions/add-slide.ts +17 -4
- package/corpus/templates/slides/actions/create-design-system.ts +16 -4
- package/corpus/templates/slides/actions/delete-design-system.ts +18 -2
- package/corpus/templates/slides/actions/get-layout-overflows.ts +88 -0
- package/corpus/templates/slides/actions/import-file.ts +1 -0
- package/corpus/templates/slides/actions/index-design-system-with-builder.ts +8 -0
- package/corpus/templates/slides/actions/patch-deck.ts +48 -16
- package/corpus/templates/slides/actions/set-default-design-system.ts +49 -19
- package/corpus/templates/slides/actions/update-slide.ts +13 -3
- package/corpus/templates/slides/actions/view-screen.ts +87 -10
- package/corpus/templates/slides/app/components/deck/SlideRenderer.tsx +155 -28
- package/corpus/templates/slides/app/components/design-system/DesignSystemCard.tsx +21 -17
- package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +849 -341
- package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +102 -2
- package/corpus/templates/slides/app/components/editor/PromptDialog.tsx +13 -16
- package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +60 -12
- package/corpus/templates/slides/app/components/editor/SlideOverflowWarning.tsx +11 -1
- package/corpus/templates/slides/app/components/layout/Sidebar.tsx +66 -19
- package/corpus/templates/slides/app/i18n/en-US.ts +23 -0
- package/corpus/templates/slides/app/lib/normalize-slide-padding.ts +8 -15
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +4 -3
- package/corpus/templates/slides/app/pages/DesignSystems.tsx +4 -3
- package/corpus/templates/slides/app/pages/Index.tsx +1 -1
- package/corpus/templates/slides/changelog/2026-07-31-design-system-details-now-show-their-source-and-indexing-sta.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-31-design-system-indexing-keeps-your-chosen-name-when-you-uploa.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-31-design-system-setup-keeps-focus-rings-visible-and-uses-a-sim.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-31-skip-prompt-is-now-available-in-the-new-deck-prompt-header.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-31-slides-now-detect-real-text-and-box-overflow-across-the-deck.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-31-the-agent-native-logo-stays-visible-when-the-sidebar-is-coll.md +6 -0
- package/corpus/templates/slides/server/handlers/design-systems.ts +1 -0
- package/corpus/templates/slides/server/handlers/index-design-system-sources.ts +1 -0
- package/corpus/templates/slides/server/lib/builder-design-system-proxy.ts +23 -4
- package/corpus/templates/slides/server/plugins/agent-chat.ts +5 -0
- package/corpus/templates/slides/server/plugins/creative-context.ts +16 -3
- package/corpus/templates/slides/server/workspace-defaults.ts +5 -1
- package/corpus/templates/slides/shared/slide-fit.ts +26 -0
- package/corpus/templates/tasks/app/components/layout/Sidebar.tsx +30 -3
- package/corpus/templates/tasks/changelog/2026-07-31-clicking-the-agent-native-logo-now-toggles-the-app-sidebar.md +6 -0
- package/dist/a2a/correlation.d.ts +4 -1
- package/dist/a2a/correlation.d.ts.map +1 -1
- package/dist/a2a/correlation.js +8 -1
- package/dist/a2a/correlation.js.map +1 -1
- package/dist/a2a/types.d.ts +11 -3
- package/dist/a2a/types.d.ts.map +1 -1
- package/dist/a2a/types.js.map +1 -1
- package/dist/agent/engine/ai-sdk-engine.d.ts.map +1 -1
- package/dist/agent/engine/ai-sdk-engine.js +27 -41
- package/dist/agent/engine/ai-sdk-engine.js.map +1 -1
- package/dist/agent/engine/builder-engine.d.ts.map +1 -1
- package/dist/agent/engine/builder-engine.js +18 -8
- package/dist/agent/engine/builder-engine.js.map +1 -1
- package/dist/agent/engine/error-detail.d.ts +61 -0
- package/dist/agent/engine/error-detail.d.ts.map +1 -1
- package/dist/agent/engine/error-detail.js +145 -3
- package/dist/agent/engine/error-detail.js.map +1 -1
- package/dist/agent/engine/failure-taxonomy.d.ts +24 -0
- package/dist/agent/engine/failure-taxonomy.d.ts.map +1 -0
- package/dist/agent/engine/failure-taxonomy.js +88 -0
- package/dist/agent/engine/failure-taxonomy.js.map +1 -0
- package/dist/agent/engine/index.d.ts +2 -1
- package/dist/agent/engine/index.d.ts.map +1 -1
- package/dist/agent/engine/index.js +2 -1
- package/dist/agent/engine/index.js.map +1 -1
- package/dist/agent/engine/registry.d.ts +16 -0
- package/dist/agent/engine/registry.d.ts.map +1 -1
- package/dist/agent/engine/registry.js +71 -6
- package/dist/agent/engine/registry.js.map +1 -1
- package/dist/agent/engine/translate-ai-sdk.d.ts.map +1 -1
- package/dist/agent/engine/translate-ai-sdk.js +14 -2
- package/dist/agent/engine/translate-ai-sdk.js.map +1 -1
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +13 -24
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/run-loop-with-resume.js +1 -1
- package/dist/agent/run-loop-with-resume.js.map +1 -1
- package/dist/agent/run-manager.d.ts.map +1 -1
- package/dist/agent/run-manager.js +39 -10
- package/dist/agent/run-manager.js.map +1 -1
- package/dist/agent/run-store.d.ts +10 -0
- package/dist/agent/run-store.d.ts.map +1 -1
- package/dist/agent/run-store.js +20 -3
- package/dist/agent/run-store.js.map +1 -1
- package/dist/agent/thread-data-builder.d.ts.map +1 -1
- package/dist/agent/thread-data-builder.js +28 -4
- package/dist/agent/thread-data-builder.js.map +1 -1
- package/dist/chat-threads/store.d.ts +13 -0
- package/dist/chat-threads/store.d.ts.map +1 -1
- package/dist/chat-threads/store.js +35 -0
- package/dist/chat-threads/store.js.map +1 -1
- package/dist/cli/templates-meta.d.ts.map +1 -1
- package/dist/cli/templates-meta.js +13 -0
- package/dist/cli/templates-meta.js.map +1 -1
- package/dist/cli/workspace-dev.d.ts.map +1 -1
- package/dist/cli/workspace-dev.js +1 -0
- package/dist/cli/workspace-dev.js.map +1 -1
- package/dist/client/error-format.d.ts.map +1 -1
- package/dist/client/error-format.js +10 -0
- package/dist/client/error-format.js.map +1 -1
- package/dist/client/use-chat-threads.d.ts.map +1 -1
- package/dist/client/use-chat-threads.js +66 -16
- package/dist/client/use-chat-threads.js.map +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/credentials/index.d.ts +9 -2
- package/dist/credentials/index.d.ts.map +1 -1
- package/dist/credentials/index.js +50 -8
- package/dist/credentials/index.js.map +1 -1
- package/dist/extensions/url-safety.d.ts.map +1 -1
- package/dist/extensions/url-safety.js +38 -12
- package/dist/extensions/url-safety.js.map +1 -1
- package/dist/integrations/adapters/slack.d.ts.map +1 -1
- package/dist/integrations/adapters/slack.js +25 -8
- package/dist/integrations/adapters/slack.js.map +1 -1
- package/dist/integrations/google-docs-poller.d.ts.map +1 -1
- package/dist/integrations/google-docs-poller.js +13 -1
- package/dist/integrations/google-docs-poller.js.map +1 -1
- package/dist/integrations/installations-store.d.ts +10 -0
- package/dist/integrations/installations-store.d.ts.map +1 -1
- package/dist/integrations/installations-store.js +24 -0
- package/dist/integrations/installations-store.js.map +1 -1
- package/dist/integrations/plugin.d.ts.map +1 -1
- package/dist/integrations/plugin.js +6 -5
- package/dist/integrations/plugin.js.map +1 -1
- package/dist/integrations/types.d.ts +7 -0
- package/dist/integrations/types.d.ts.map +1 -1
- package/dist/integrations/types.js.map +1 -1
- package/dist/integrations/webhook-handler.d.ts.map +1 -1
- package/dist/integrations/webhook-handler.js +16 -1
- package/dist/integrations/webhook-handler.js.map +1 -1
- package/dist/jobs/background-automation-runner.d.ts.map +1 -1
- package/dist/jobs/background-automation-runner.js +35 -2
- package/dist/jobs/background-automation-runner.js.map +1 -1
- package/dist/notifications/routes.d.ts +6 -6
- package/dist/observability/routes.d.ts +3 -3
- package/dist/provider-api/actions/custom-provider-registration.d.ts +14 -14
- package/dist/provider-api/actions/provider-api.d.ts +8 -8
- package/dist/provider-api/index.js +7 -3
- package/dist/provider-api/index.js.map +1 -1
- package/dist/scripts/call-agent.d.ts.map +1 -1
- package/dist/scripts/call-agent.js +6 -1
- package/dist/scripts/call-agent.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +38 -9
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-discovery.d.ts +2 -0
- package/dist/server/agent-discovery.d.ts.map +1 -1
- package/dist/server/agent-discovery.js.map +1 -1
- package/dist/server/builder-design-systems.d.ts +4 -1
- package/dist/server/builder-design-systems.d.ts.map +1 -1
- package/dist/server/builder-design-systems.js +11 -1
- package/dist/server/builder-design-systems.js.map +1 -1
- package/dist/server/credential-provider.d.ts.map +1 -1
- package/dist/server/credential-provider.js +49 -12
- package/dist/server/credential-provider.js.map +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/onboarding-html.d.ts.map +1 -1
- package/dist/server/onboarding-html.js +37 -2
- package/dist/server/onboarding-html.js.map +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/shared/reasoning-effort.d.ts +1 -0
- package/dist/shared/reasoning-effort.d.ts.map +1 -1
- package/dist/shared/reasoning-effort.js +1 -1
- package/dist/shared/reasoning-effort.js.map +1 -1
- package/dist/templates/chat/app/components/layout/Sidebar.tsx +30 -3
- package/dist/templates/chat/changelog/2026-07-31-clicking-the-agent-native-logo-now-toggles-the-app-sidebar.md +6 -0
- package/dist/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +11 -0
- package/package.json +1 -1
- package/src/a2a/correlation.ts +11 -1
- package/src/a2a/types.ts +11 -3
- package/src/agent/engine/ai-sdk-engine.ts +33 -46
- package/src/agent/engine/builder-engine.ts +22 -10
- package/src/agent/engine/error-detail.ts +184 -3
- package/src/agent/engine/failure-taxonomy.ts +123 -0
- package/src/agent/engine/index.ts +8 -0
- package/src/agent/engine/registry.ts +92 -8
- package/src/agent/engine/translate-ai-sdk.ts +17 -2
- package/src/agent/production-agent.ts +13 -33
- package/src/agent/run-loop-with-resume.ts +1 -1
- package/src/agent/run-manager.ts +43 -14
- package/src/agent/run-store.ts +30 -3
- package/src/agent/thread-data-builder.ts +36 -4
- package/src/chat-threads/store.ts +42 -0
- package/src/cli/templates-meta.ts +13 -0
- package/src/cli/workspace-dev.ts +1 -0
- package/src/client/error-format.ts +12 -0
- package/src/client/use-chat-threads.ts +76 -16
- package/src/credentials/index.ts +51 -12
- package/src/extensions/url-safety.ts +46 -12
- package/src/integrations/adapters/slack.ts +32 -10
- package/src/integrations/google-docs-poller.ts +12 -1
- package/src/integrations/installations-store.ts +30 -0
- package/src/integrations/plugin.ts +5 -5
- package/src/integrations/types.ts +7 -0
- package/src/integrations/webhook-handler.ts +24 -1
- package/src/jobs/background-automation-runner.ts +38 -1
- package/src/provider-api/index.ts +8 -2
- package/src/scripts/call-agent.ts +6 -0
- package/src/server/agent-chat-plugin.ts +46 -10
- package/src/server/agent-discovery.ts +2 -0
- package/src/server/builder-design-systems.ts +21 -0
- package/src/server/credential-provider.ts +51 -12
- package/src/server/index.ts +1 -0
- package/src/server/onboarding-html.ts +37 -2
- package/src/shared/reasoning-effort.ts +1 -1
- package/src/templates/chat/app/components/layout/Sidebar.tsx +30 -3
- package/src/templates/chat/changelog/2026-07-31-clicking-the-agent-native-logo-now-toggles-the-app-sidebar.md +6 -0
- package/src/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +11 -0
- 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(
|
|
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
|
|
301
|
+
? describeErrorWithCauses(part.error)
|
|
298
302
|
: typeof part.error === "string"
|
|
299
303
|
? part.error
|
|
300
304
|
: JSON.stringify(part.error);
|
|
301
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
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
|
|
6665
|
-
//
|
|
6666
|
-
if (await turnAborted(threadId, turnId)
|
|
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)
|
|
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)
|
|
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)
|
|
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:
|
|
608
|
+
recoverable: false,
|
|
609
609
|
});
|
|
610
610
|
reportFinalOutcome({
|
|
611
611
|
state: "failed",
|