@agent-native/core 0.119.3 → 0.119.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +21 -0
- package/corpus/core/package.json +3 -3
- package/corpus/core/src/agent/engine/index.ts +2 -0
- package/corpus/core/src/agent/engine/registry.ts +95 -2
- package/corpus/core/src/agent/production-agent.ts +107 -125
- package/corpus/core/src/agent/run-manager.ts +45 -2
- package/corpus/core/src/agent/thread-data-builder.ts +85 -8
- package/corpus/core/src/client/AssistantChat.tsx +37 -9
- package/corpus/core/src/client/chat/message-components.tsx +9 -1
- package/corpus/core/src/client/chat/repo-helpers.ts +77 -0
- package/corpus/core/src/client/chat/tool-call-display.tsx +51 -15
- package/corpus/core/src/scripts/agent-engines/list-agent-engines.ts +8 -0
- package/corpus/core/src/scripts/agent-engines/manage-agent-engine.ts +5 -1
- package/corpus/core/src/scripts/agent-engines/set-agent-engine.ts +9 -1
- package/corpus/core/src/server/agent-chat/framework-prompts.ts +3 -1
- package/corpus/core/src/server/agent-chat/plugin-options.ts +9 -0
- package/corpus/core/src/server/agent-chat-plugin.ts +12 -3
- package/corpus/core/src/templates/chat/.agents/skills/actions/SKILL.md +512 -0
- package/corpus/core/src/templates/chat/.agents/skills/adding-a-feature/SKILL.md +189 -0
- package/corpus/core/src/templates/chat/.agents/skills/agent-native-docs/SKILL.md +115 -0
- package/corpus/core/src/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +177 -0
- package/corpus/core/src/templates/chat/.agents/skills/capture-learnings/SKILL.md +89 -0
- package/corpus/core/src/templates/chat/.agents/skills/create-skill/SKILL.md +221 -0
- package/corpus/core/src/templates/chat/.agents/skills/customizing-agent-native/SKILL.md +220 -0
- package/corpus/core/src/templates/chat/.agents/skills/delegate-to-agent/SKILL.md +263 -0
- package/corpus/core/src/templates/chat/.agents/skills/feature-flags/SKILL.md +169 -0
- package/corpus/core/src/templates/chat/.agents/skills/frontend-design/SKILL.md +160 -0
- package/corpus/core/src/templates/chat/.agents/skills/real-time-sync/SKILL.md +232 -0
- package/corpus/core/src/templates/chat/.agents/skills/security/SKILL.md +280 -0
- package/corpus/core/src/templates/chat/.agents/skills/self-modifying-code/SKILL.md +118 -0
- package/corpus/core/src/templates/chat/.agents/skills/shadcn-ui/SKILL.md +119 -0
- package/corpus/core/src/templates/chat/.agents/skills/upgrade-agent-native/SKILL.md +100 -0
- package/corpus/core/src/templates/chat/.env.example +5 -0
- package/corpus/core/src/templates/chat/.ignore +0 -0
- package/corpus/core/src/templates/chat/.oxfmtrc.json +8 -0
- package/corpus/core/src/templates/chat/AGENTS.md +69 -0
- package/corpus/core/src/templates/chat/CHANGELOG.md +10 -0
- package/corpus/core/src/templates/chat/DEVELOPING.md +185 -0
- package/corpus/core/src/templates/chat/README.md +32 -0
- package/corpus/core/src/templates/chat/_gitignore +43 -0
- package/corpus/core/src/templates/chat/actions/hello.ts +13 -0
- package/corpus/core/src/templates/chat/actions/navigate.ts +41 -0
- package/corpus/core/src/templates/chat/actions/run.ts +2 -0
- package/corpus/core/src/templates/chat/actions/view-screen.ts +31 -0
- package/corpus/core/src/templates/chat/app/components/layout/Header.tsx +60 -0
- package/corpus/core/src/templates/chat/app/components/layout/Layout.tsx +185 -0
- package/corpus/core/src/templates/chat/app/components/layout/Sidebar.tsx +450 -0
- package/corpus/core/src/templates/chat/app/components/ui/button.tsx +1 -0
- package/corpus/core/src/templates/chat/app/components/ui/card.tsx +1 -0
- package/corpus/core/src/templates/chat/app/components/ui/dropdown-menu.tsx +1 -0
- package/corpus/core/src/templates/chat/app/components/ui/input.tsx +1 -0
- package/corpus/core/src/templates/chat/app/components/ui/label.tsx +1 -0
- package/corpus/core/src/templates/chat/app/components/ui/sheet.tsx +1 -0
- package/corpus/core/src/templates/chat/app/components/ui/toolkit-provider.tsx +17 -0
- package/corpus/core/src/templates/chat/app/components/ui/tooltip.tsx +1 -0
- package/corpus/core/src/templates/chat/app/design-system.ts +3 -0
- package/corpus/core/src/templates/chat/app/entry.client.tsx +19 -0
- package/corpus/core/src/templates/chat/app/entry.server.tsx +10 -0
- package/corpus/core/src/templates/chat/app/global.css +93 -0
- package/corpus/core/src/templates/chat/app/hooks/use-navigation-state.ts +93 -0
- package/corpus/core/src/templates/chat/app/i18n/ar-SA.ts +68 -0
- package/corpus/core/src/templates/chat/app/i18n/de-DE.ts +71 -0
- package/corpus/core/src/templates/chat/app/i18n/en-US.ts +70 -0
- package/corpus/core/src/templates/chat/app/i18n/es-ES.ts +71 -0
- package/corpus/core/src/templates/chat/app/i18n/fr-FR.ts +71 -0
- package/corpus/core/src/templates/chat/app/i18n/hi-IN.ts +69 -0
- package/corpus/core/src/templates/chat/app/i18n/index.ts +34 -0
- package/corpus/core/src/templates/chat/app/i18n/ja-JP.ts +70 -0
- package/corpus/core/src/templates/chat/app/i18n/ko-KR.ts +70 -0
- package/corpus/core/src/templates/chat/app/i18n/pt-BR.ts +71 -0
- package/corpus/core/src/templates/chat/app/i18n/zh-CN.ts +66 -0
- package/corpus/core/src/templates/chat/app/i18n/zh-TW.ts +66 -0
- package/corpus/core/src/templates/chat/app/i18n-data.ts +556 -0
- package/corpus/core/src/templates/chat/app/lib/agent-page.tsx +49 -0
- package/corpus/core/src/templates/chat/app/lib/app-config.ts +11 -0
- package/corpus/core/src/templates/chat/app/lib/tab-id.ts +1 -0
- package/corpus/core/src/templates/chat/app/lib/utils.ts +1 -0
- package/corpus/core/src/templates/chat/app/root.tsx +173 -0
- package/corpus/core/src/templates/chat/app/routes/_index.tsx +94 -0
- package/corpus/core/src/templates/chat/app/routes/agent.tsx +24 -0
- package/corpus/core/src/templates/chat/app/routes/chat.$threadId.tsx +1 -0
- package/corpus/core/src/templates/chat/app/routes/database.tsx +17 -0
- package/corpus/core/src/templates/chat/app/routes/extensions.$id.$slug.tsx +2 -0
- package/corpus/core/src/templates/chat/app/routes/extensions.$id.tsx +11 -0
- package/corpus/core/src/templates/chat/app/routes/extensions._index.tsx +11 -0
- package/corpus/core/src/templates/chat/app/routes/extensions.tsx +5 -0
- package/corpus/core/src/templates/chat/app/routes/observability.tsx +19 -0
- package/corpus/core/src/templates/chat/app/routes/settings.tsx +89 -0
- package/corpus/core/src/templates/chat/app/routes/team.tsx +11 -0
- package/corpus/core/src/templates/chat/app/routes.ts +4 -0
- package/corpus/core/src/templates/chat/app/vite-env.d.ts +6 -0
- package/corpus/core/src/templates/chat/changelog/2026-06-24-a-new-settings-page-gives-quick-access-to-language-workspace.md +6 -0
- package/corpus/core/src/templates/chat/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
- package/corpus/core/src/templates/chat/changelog/2026-06-27-traditional-chinese-copy-uses-taiwan-terminology.md +6 -0
- package/corpus/core/src/templates/chat/changelog/2026-06-28-left-sidebar-collapse-motion-and-footer-chrome-are-quieter.md +6 -0
- package/corpus/core/src/templates/chat/changelog/2026-06-29-chat-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
- package/corpus/core/src/templates/chat/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
- package/corpus/core/src/templates/chat/changelog/2026-07-10-chat-now-makes-ai-connection-setup-clear-without-shifting-th.md +6 -0
- package/corpus/core/src/templates/chat/changelog/2026-07-13-a-full-agent-page-now-brings-context-files-connections-jobs-.md +6 -0
- package/corpus/core/src/templates/chat/changelog/2026-07-14-chat-opens-reliably-on-hosted-deployments-instead-of-failing.md +6 -0
- package/corpus/core/src/templates/chat/changelog/2026-07-14-fixed-chat-template-startup-with-older-core-versions.md +6 -0
- package/corpus/core/src/templates/chat/changelog/2026-07-15-chat-navigation-focuses-on-chat-and-agent.md +6 -0
- package/corpus/core/src/templates/chat/changelog/2026-07-17-the-agent-chat-sidebar-stays-closed-until-you-open-it-or-sta.md +6 -0
- package/corpus/core/src/templates/chat/changelog/2026-07-22-compact-sidebar-footer.md +6 -0
- package/corpus/core/src/templates/chat/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +6 -0
- package/corpus/core/src/templates/chat/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
- package/corpus/core/src/templates/chat/changelog/2026-07-22-recent-chats-are-easier-to-scan-and-expand.md +6 -0
- package/corpus/core/src/templates/chat/changelog/2026-07-23-full-page-chat-is-better-centered-with-quieter-chat-history-.md +6 -0
- package/corpus/core/src/templates/chat/components.json +20 -0
- package/corpus/core/src/templates/chat/learnings.defaults.md +5 -0
- package/corpus/core/src/templates/chat/netlify.toml +10 -0
- package/corpus/core/src/templates/chat/package.json +92 -0
- package/corpus/core/src/templates/chat/public/agent-native-icon-dark.svg +10 -0
- package/corpus/core/src/templates/chat/public/agent-native-icon-light.svg +10 -0
- package/corpus/core/src/templates/chat/public/agent-native-logo-dark.svg +21 -0
- package/corpus/core/src/templates/chat/public/agent-native-logo-light.svg +21 -0
- package/corpus/core/src/templates/chat/public/favicon.svg +1 -0
- package/corpus/core/src/templates/chat/public/icon-180.svg +1 -0
- package/corpus/core/src/templates/chat/public/icon-192.svg +1 -0
- package/corpus/core/src/templates/chat/public/icon-512.svg +1 -0
- package/corpus/core/src/templates/chat/public/manifest.json +21 -0
- package/corpus/core/src/templates/chat/react-router.config.ts +7 -0
- package/corpus/core/src/templates/chat/server/middleware/auth.ts +15 -0
- package/corpus/core/src/templates/chat/server/plugins/agent-chat.ts +21 -0
- package/corpus/core/src/templates/chat/server/plugins/auth.ts +17 -0
- package/corpus/core/src/templates/chat/server/routes/[...page].get.ts +5 -0
- package/corpus/core/src/templates/chat/ssr-entry.ts +15 -0
- package/corpus/core/src/templates/chat/tsconfig.json +21 -0
- package/corpus/core/src/templates/chat/vite.config.ts +19 -0
- package/corpus/templates/analytics/AGENTS.md +19 -11
- package/corpus/templates/analytics/actions/list-data-dictionary.ts +3 -1
- package/corpus/templates/analytics/actions/save-data-dictionary-entry.ts +14 -0
- package/corpus/templates/analytics/actions/search-analytics-query-catalog.ts +41 -0
- package/corpus/templates/analytics/app/components/dashboard/DashboardPanelSkeleton.tsx +13 -0
- package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +12 -11
- package/corpus/templates/analytics/app/pages/adhoc/DashboardSkeleton.tsx +3 -3
- package/corpus/templates/analytics/changelog/2026-07-23-dashboard-chart-loading-placeholders-are-easier-to-see-in-da.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-23-routine-analytics-lookups-reuse-existing-query-definitions.md +6 -0
- package/corpus/templates/analytics/server/lib/agent-chat-plan-mode.ts +1 -12
- package/corpus/templates/analytics/server/lib/analytics-query-catalog.ts +405 -0
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +11 -16
- package/corpus/templates/content/changelog/2026-07-23-database-toolbar-sort-and-filter-controls-open-reliably.md +6 -0
- package/corpus/templates/forms/app/lib/public-form-link.ts +14 -0
- package/corpus/templates/forms/app/pages/FormBuilderPage.tsx +6 -14
- package/corpus/templates/forms/changelog/2026-07-23-published-form-links-can-be-copied-without-being-asked-to-re.md +6 -0
- package/corpus/templates/mail/changelog/2026-07-23-scheduled-emails-now-send-only-once-when-multiple-requests-r.md +6 -0
- package/corpus/templates/mail/server/lib/jobs.ts +13 -4
- package/corpus/templates/mail/server/plugins/mail-jobs.ts +1 -1
- package/corpus/templates/slides/actions/patch-deck.ts +2 -1
- package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +7 -18
- package/corpus/templates/slides/app/lib/agent-visible-message.ts +28 -0
- package/corpus/templates/slides/app/pages/Index.tsx +6 -34
- package/corpus/templates/slides/changelog/2026-07-23-full-prompts-stay-visible-in-chat-when-creating-decks-or-add.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-23-opening-or-refining-a-deck-no-longer-crashes-with-a-blank-er.md +6 -0
- package/corpus/templates/slides/shared/aspect-ratios.ts +4 -1
- package/corpus/templates/tasks/.oxfmtrc.json +8 -0
- package/corpus/templates/tasks/AGENTS.md +34 -41
- package/corpus/templates/tasks/README.md +13 -6
- package/corpus/templates/tasks/actions/bulk-delete-inbox-items.ts +10 -8
- package/corpus/templates/tasks/actions/bulk-delete-tasks.ts +10 -8
- package/corpus/templates/tasks/actions/bulk-mark-inbox-items-ready.ts +1 -1
- package/corpus/templates/tasks/actions/bulk-update-tasks.ts +12 -10
- package/corpus/templates/tasks/actions/create-inbox-item.ts +7 -4
- package/corpus/templates/tasks/actions/create-task.ts +2 -1
- package/corpus/templates/tasks/actions/delete-inbox-item.ts +6 -4
- package/corpus/templates/tasks/actions/delete-task.ts +1 -1
- package/corpus/templates/tasks/actions/list-inbox-items.ts +4 -2
- package/corpus/templates/tasks/actions/list-visible-task-fields.ts +3 -1
- package/corpus/templates/tasks/actions/mark-inbox-item-ready.ts +6 -4
- package/corpus/templates/tasks/actions/navigate.ts +16 -14
- package/corpus/templates/tasks/actions/reorder-inbox-items.ts +9 -7
- package/corpus/templates/tasks/actions/update-inbox-item.ts +6 -4
- package/corpus/templates/tasks/actions/update-task.ts +12 -9
- package/corpus/templates/tasks/actions/update-visible-task-fields.ts +10 -8
- package/corpus/templates/tasks/actions/view-screen.ts +1 -1
- package/corpus/templates/tasks/app/components/tasks/fields/TaskFieldsSidebar.tsx +15 -0
- package/corpus/templates/tasks/changelog/2026-07-23-task-detail-extensions.md +6 -0
- package/corpus/templates/tasks/drizzle.config.ts +3 -0
- package/corpus/templates/tasks/package.json +4 -1
- package/corpus/templates/tasks/server/db/schema.ts +0 -10
- package/corpus/templates/tasks/server/db/test-tasks-table.ts +0 -5
- package/corpus/templates/tasks/server/plugins/agent-chat.ts +1 -1
- package/corpus/templates/tasks/server/plugins/db.ts +43 -10
- package/corpus/templates/tasks/server/user-config/store.ts +42 -81
- package/corpus/templates/tasks/tsconfig.json +1 -2
- package/corpus/templates/tasks/vitest.config.ts +10 -1
- package/corpus/toolkit/CHANGELOG.md +13 -0
- package/corpus/toolkit/package.json +1 -1
- package/corpus/toolkit/src/editor/SharedRichEditor.tsx +23 -2
- package/corpus/toolkit/src/editor/SlashCommandMenu.tsx +68 -2
- package/corpus/toolkit/src/editor/index.ts +1 -0
- package/corpus/toolkit/src/editor.css +75 -0
- package/corpus/toolkit/src/ui/button.tsx +3 -2
- package/dist/agent/engine/index.d.ts +1 -1
- package/dist/agent/engine/index.d.ts.map +1 -1
- package/dist/agent/engine/index.js +1 -1
- package/dist/agent/engine/index.js.map +1 -1
- package/dist/agent/engine/registry.d.ts +32 -1
- package/dist/agent/engine/registry.d.ts.map +1 -1
- package/dist/agent/engine/registry.js +75 -3
- package/dist/agent/engine/registry.js.map +1 -1
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +96 -115
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/run-manager.d.ts +9 -1
- package/dist/agent/run-manager.d.ts.map +1 -1
- package/dist/agent/run-manager.js +26 -0
- package/dist/agent/run-manager.js.map +1 -1
- package/dist/agent/thread-data-builder.d.ts +2 -0
- package/dist/agent/thread-data-builder.d.ts.map +1 -1
- package/dist/agent/thread-data-builder.js +69 -9
- package/dist/agent/thread-data-builder.js.map +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +32 -10
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/chat/message-components.d.ts +2 -1
- package/dist/client/chat/message-components.d.ts.map +1 -1
- package/dist/client/chat/message-components.js +9 -3
- package/dist/client/chat/message-components.js.map +1 -1
- package/dist/client/chat/repo-helpers.d.ts +4 -0
- package/dist/client/chat/repo-helpers.d.ts.map +1 -1
- package/dist/client/chat/repo-helpers.js +61 -0
- package/dist/client/chat/repo-helpers.js.map +1 -1
- package/dist/client/chat/tool-call-display.d.ts +2 -1
- package/dist/client/chat/tool-call-display.d.ts.map +1 -1
- package/dist/client/chat/tool-call-display.js +10 -9
- package/dist/client/chat/tool-call-display.js.map +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/observability/routes.d.ts +5 -5
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +7 -7
- package/dist/provider-api/actions/provider-api.d.ts +7 -7
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/scripts/agent-engines/list-agent-engines.d.ts.map +1 -1
- package/dist/scripts/agent-engines/list-agent-engines.js +8 -2
- package/dist/scripts/agent-engines/list-agent-engines.js.map +1 -1
- package/dist/scripts/agent-engines/manage-agent-engine.d.ts.map +1 -1
- package/dist/scripts/agent-engines/manage-agent-engine.js +5 -2
- package/dist/scripts/agent-engines/manage-agent-engine.js.map +1 -1
- package/dist/scripts/agent-engines/set-agent-engine.d.ts.map +1 -1
- package/dist/scripts/agent-engines/set-agent-engine.js +9 -2
- package/dist/scripts/agent-engines/set-agent-engine.js.map +1 -1
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/server/agent-chat/framework-prompts.d.ts.map +1 -1
- package/dist/server/agent-chat/framework-prompts.js +3 -1
- package/dist/server/agent-chat/framework-prompts.js.map +1 -1
- package/dist/server/agent-chat/plugin-options.d.ts +9 -0
- package/dist/server/agent-chat/plugin-options.d.ts.map +1 -1
- package/dist/server/agent-chat/plugin-options.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +11 -2
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/package.json +4 -4
- package/src/agent/engine/index.ts +2 -0
- package/src/agent/engine/registry.ts +95 -2
- package/src/agent/production-agent.ts +107 -125
- package/src/agent/run-manager.ts +45 -2
- package/src/agent/thread-data-builder.ts +85 -8
- package/src/client/AssistantChat.tsx +37 -9
- package/src/client/chat/message-components.tsx +9 -1
- package/src/client/chat/repo-helpers.ts +77 -0
- package/src/client/chat/tool-call-display.tsx +51 -15
- package/src/scripts/agent-engines/list-agent-engines.ts +8 -0
- package/src/scripts/agent-engines/manage-agent-engine.ts +5 -1
- package/src/scripts/agent-engines/set-agent-engine.ts +9 -1
- package/src/server/agent-chat/framework-prompts.ts +3 -1
- package/src/server/agent-chat/plugin-options.ts +9 -0
- package/src/server/agent-chat-plugin.ts +12 -3
- package/corpus/templates/tasks/.prettierrc +0 -5
- package/src/templates/chat/actions/hello.spec.ts +0 -23
- package/src/templates/chat/actions/navigate.spec.ts +0 -68
- package/src/templates/chat/actions/view-screen.spec.ts +0 -40
- package/src/templates/chat/app/lib/agent-page.spec.tsx +0 -61
|
@@ -26,9 +26,9 @@ export declare function createRealtimeTokenHandler(): import("h3").EventHandlerW
|
|
|
26
26
|
expiresAt?: undefined;
|
|
27
27
|
ttlSeconds?: undefined;
|
|
28
28
|
} | {
|
|
29
|
-
error?: undefined;
|
|
30
29
|
token: string;
|
|
31
30
|
expiresAt: string;
|
|
32
31
|
ttlSeconds: number;
|
|
32
|
+
error?: undefined;
|
|
33
33
|
}>>;
|
|
34
34
|
//# sourceMappingURL=realtime-token.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/core",
|
|
3
|
-
"version": "0.119.
|
|
3
|
+
"version": "0.119.5",
|
|
4
4
|
"description": "Framework for agent-native application development — where AI agents and UI share SQL state, actions, and context",
|
|
5
5
|
"homepage": "https://github.com/BuilderIO/agent-native#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -362,7 +362,7 @@
|
|
|
362
362
|
"highlight.js": "^11.11.1",
|
|
363
363
|
"i18next": "26.3.1",
|
|
364
364
|
"isbot": "^5",
|
|
365
|
-
"jiti": "^2.
|
|
365
|
+
"jiti": "^2.7.0",
|
|
366
366
|
"jose": "^6.2.2",
|
|
367
367
|
"linkedom": "0.18.12",
|
|
368
368
|
"lowlight": "^3.3.0",
|
|
@@ -370,7 +370,7 @@
|
|
|
370
370
|
"nanoid": "^5.1.9",
|
|
371
371
|
"next-themes": "^0.4.6",
|
|
372
372
|
"nf3": "0.3.17",
|
|
373
|
-
"nitro": "3.0.
|
|
373
|
+
"nitro": "3.0.260610-beta",
|
|
374
374
|
"p-limit": "^7.3.0",
|
|
375
375
|
"prettier": "^3.8.3",
|
|
376
376
|
"react-i18next": "17.0.8",
|
|
@@ -390,7 +390,7 @@
|
|
|
390
390
|
"yjs": "^13.6.31",
|
|
391
391
|
"zod": "^4.3.6",
|
|
392
392
|
"@agent-native/recap-cli": "0.5.1",
|
|
393
|
-
"@agent-native/toolkit": "^0.10.
|
|
393
|
+
"@agent-native/toolkit": "^0.10.4"
|
|
394
394
|
},
|
|
395
395
|
"devDependencies": {
|
|
396
396
|
"@ai-sdk/anthropic": "^3.0.71",
|
|
@@ -25,6 +25,8 @@ export {
|
|
|
25
25
|
getConfiguredEngineNameForRequest,
|
|
26
26
|
getStoredModelForEngine,
|
|
27
27
|
normalizeModelForEngine,
|
|
28
|
+
resolveEnginePreservesCustomModels,
|
|
29
|
+
type NormalizeModelOptions,
|
|
28
30
|
detectEngineFromEnv,
|
|
29
31
|
detectEngineFromEnvForRequest,
|
|
30
32
|
detectEngineFromUserSecrets,
|
|
@@ -96,6 +96,42 @@ function packageNameFromInstallSpecifier(specifier: string): string | null {
|
|
|
96
96
|
return versionIndex === -1 ? trimmed : trimmed.slice(0, versionIndex);
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
+
/**
|
|
100
|
+
* True only when there is positive evidence this module is executing from a
|
|
101
|
+
* bundled serverless function where optional dependencies were inlined into the
|
|
102
|
+
* bundle and are therefore NOT resolvable via `require.resolve` — even though
|
|
103
|
+
* the dynamic `import()` the engine uses to load them still works.
|
|
104
|
+
*
|
|
105
|
+
* Deliberately narrow. The Nitro Vercel/Netlify presets (which agent-native's
|
|
106
|
+
* own `deploy` command emits) inline optional peers and always set these env
|
|
107
|
+
* markers, so they are a reliable signal. Other serverless runtimes — a
|
|
108
|
+
* container on Cloud Run / Google Cloud Functions (`K_SERVICE` /
|
|
109
|
+
* `FUNCTION_TARGET`), or a plain AWS Lambda — commonly ship a real
|
|
110
|
+
* `node_modules` where `require.resolve` is authoritative; there a resolve miss
|
|
111
|
+
* means the package is genuinely absent and must NOT be masked. Those runtimes
|
|
112
|
+
* are still covered *when the code is actually bundled*, via the module-path
|
|
113
|
+
* check below, which stays false for a normal `node_modules` layout.
|
|
114
|
+
*/
|
|
115
|
+
function isBundledServerlessRuntime(): boolean {
|
|
116
|
+
const env = process.env;
|
|
117
|
+
// Nitro's Vercel/Netlify presets inline optional peers into the function
|
|
118
|
+
// bundle; these platforms always set these markers.
|
|
119
|
+
if (env.VERCEL || env.NETLIFY) return true;
|
|
120
|
+
// Otherwise require direct evidence that this module is running from inside a
|
|
121
|
+
// bundle output directory (Vercel's `/var/task`, Nitro's `.output/server`,
|
|
122
|
+
// inlined `_libs`). This is the real signal that `require.resolve` cannot be
|
|
123
|
+
// trusted; it stays false for normal `node_modules` layouts (dev, tests, and
|
|
124
|
+
// container/Lambda/Cloud Run deploys that ship their dependencies), so a
|
|
125
|
+
// genuine "package not installed" miss still surfaces there.
|
|
126
|
+
try {
|
|
127
|
+
return /[\\/](?:_libs|\.vercel|\.netlify|\.output)[\\/]|\/var\/task\//.test(
|
|
128
|
+
import.meta.url ?? "",
|
|
129
|
+
);
|
|
130
|
+
} catch {
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
99
135
|
function canResolvePackage(packageName: string): boolean {
|
|
100
136
|
const cached = _packageAvailabilityCache.get(packageName);
|
|
101
137
|
if (cached !== undefined) return cached;
|
|
@@ -104,7 +140,15 @@ function canResolvePackage(packageName: string): boolean {
|
|
|
104
140
|
require.resolve(packageName);
|
|
105
141
|
available = true;
|
|
106
142
|
} catch {
|
|
107
|
-
|
|
143
|
+
// Bundled serverless runtimes (e.g. Nitro on Vercel/Netlify) inline optional
|
|
144
|
+
// provider packages into the function bundle, so require.resolve cannot find
|
|
145
|
+
// them even though the dynamic `import()` the engine actually uses to load
|
|
146
|
+
// them works. Treat them as available there and let the engine's own import
|
|
147
|
+
// be the real gate — it already fails with a clear "pnpm add …" message when
|
|
148
|
+
// the package is genuinely missing. Without this, every engine-usability
|
|
149
|
+
// gate rejects the AI-SDK engines at runtime and the agent silently falls
|
|
150
|
+
// back to the native Anthropic engine.
|
|
151
|
+
available = isBundledServerlessRuntime();
|
|
108
152
|
}
|
|
109
153
|
_packageAvailabilityCache.set(packageName, available);
|
|
110
154
|
return available;
|
|
@@ -179,17 +223,41 @@ function findLatestSupportedVersionMatch(
|
|
|
179
223
|
return best?.model;
|
|
180
224
|
}
|
|
181
225
|
|
|
226
|
+
export interface NormalizeModelOptions {
|
|
227
|
+
/**
|
|
228
|
+
* Force unrecognized (custom) model IDs to be kept verbatim, as if
|
|
229
|
+
* `engine.preserveCustomModels` were set on a live engine instance.
|
|
230
|
+
*
|
|
231
|
+
* The settings actions call `normalizeModelForEngine` with a static registry
|
|
232
|
+
* ENTRY, which never carries the runtime `preserveCustomModels` flag — that
|
|
233
|
+
* is only set on the engine INSTANCE created with an OpenAI-compatible
|
|
234
|
+
* `baseUrl`. They resolve the capability with
|
|
235
|
+
* {@link resolveEnginePreservesCustomModels} and pass it here so a gateway
|
|
236
|
+
* model (e.g. an Ollama `gemma4`) is not rewritten to the OpenAI default on
|
|
237
|
+
* save/read. First-party OpenAI (no gateway) leaves this unset, so an unknown
|
|
238
|
+
* or invalid model still normalizes to a supported one.
|
|
239
|
+
*/
|
|
240
|
+
preserveCustomModels?: boolean;
|
|
241
|
+
}
|
|
242
|
+
|
|
182
243
|
export function normalizeModelForEngine(
|
|
183
244
|
engine: Pick<
|
|
184
245
|
AgentEngine,
|
|
185
246
|
"name" | "defaultModel" | "supportedModels" | "preserveCustomModels"
|
|
186
247
|
>,
|
|
187
248
|
model: string | null | undefined,
|
|
249
|
+
options: NormalizeModelOptions = {},
|
|
188
250
|
): string {
|
|
189
251
|
const candidate = typeof model === "string" ? model.trim() : "";
|
|
190
252
|
if (!candidate) return engine.defaultModel;
|
|
191
253
|
|
|
192
|
-
|
|
254
|
+
// Preserve custom IDs verbatim BEFORE any catalog/version matching, so a
|
|
255
|
+
// version-shaped gateway model that happens to share a family with a
|
|
256
|
+
// built-in model (e.g. `gpt-5.4` on an OpenAI-compatible endpoint) is not
|
|
257
|
+
// rewritten to a catalog entry.
|
|
258
|
+
if (engine.preserveCustomModels || options.preserveCustomModels) {
|
|
259
|
+
return candidate;
|
|
260
|
+
}
|
|
193
261
|
|
|
194
262
|
if (engine.supportedModels.length === 0) return candidate;
|
|
195
263
|
|
|
@@ -203,6 +271,31 @@ export function normalizeModelForEngine(
|
|
|
203
271
|
);
|
|
204
272
|
}
|
|
205
273
|
|
|
274
|
+
/**
|
|
275
|
+
* Whether models saved or read for this engine ENTRY should be preserved
|
|
276
|
+
* verbatim instead of normalized against the built-in catalog.
|
|
277
|
+
*
|
|
278
|
+
* `normalizeModelForEngine` honors a live engine's `preserveCustomModels`, but
|
|
279
|
+
* that flag is only set on an AI SDK engine INSTANCE when the OpenAI provider
|
|
280
|
+
* is pointed at an OpenAI-compatible gateway (a custom base URL — e.g. Ollama
|
|
281
|
+
* Cloud or LiteLLM), whose model IDs are not in the built-in OpenAI catalog.
|
|
282
|
+
* The static registry entry the settings actions pass to
|
|
283
|
+
* `normalizeModelForEngine` cannot carry that runtime flag, so this async
|
|
284
|
+
* helper reproduces the same decision — `ai-sdk:openai` AND a resolved base URL
|
|
285
|
+
* — from the request's stored/deploy config. First-party OpenAI (no gateway)
|
|
286
|
+
* returns false so an unknown/invalid model still normalizes to a supported one.
|
|
287
|
+
*/
|
|
288
|
+
export async function resolveEnginePreservesCustomModels(
|
|
289
|
+
entry: Pick<AgentEngineEntry, "name">,
|
|
290
|
+
): Promise<boolean> {
|
|
291
|
+
if (entry.name !== "ai-sdk:openai") return false;
|
|
292
|
+
try {
|
|
293
|
+
return Boolean(await resolveOpenAiBaseUrl());
|
|
294
|
+
} catch {
|
|
295
|
+
return false;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
206
299
|
function assertAgentEnginePackageInstalled(entry: AgentEngineEntry): void {
|
|
207
300
|
if (isAgentEnginePackageInstalled(entry)) return;
|
|
208
301
|
const installHint = entry.installPackage
|
|
@@ -7746,18 +7746,6 @@ export function createProductionAgentHandler(
|
|
|
7746
7746
|
}).catch(() => {});
|
|
7747
7747
|
}
|
|
7748
7748
|
|
|
7749
|
-
// The background worker must AWAIT the run to completion before returning,
|
|
7750
|
-
// or Netlify freezes/kills the function the instant the handler returns and
|
|
7751
|
-
// the detached run dies mid-turn (mirrors the agent-teams processor, which
|
|
7752
|
-
// wraps startRun in `await new Promise(resolve => startRun(..., onComplete:
|
|
7753
|
-
// () => resolve()))`). We resolve this when the run's onComplete fires.
|
|
7754
|
-
let resolveBackgroundRunDone: (() => void) | null = null;
|
|
7755
|
-
const backgroundRunDone = isBackgroundWorker
|
|
7756
|
-
? new Promise<void>((resolve) => {
|
|
7757
|
-
resolveBackgroundRunDone = resolve;
|
|
7758
|
-
})
|
|
7759
|
-
: null;
|
|
7760
|
-
|
|
7761
7749
|
const baseHandleRunComplete =
|
|
7762
7750
|
options.onRunComplete || trackedProgressRunId
|
|
7763
7751
|
? async (run: ActiveRun) => {
|
|
@@ -7771,119 +7759,114 @@ export function createProductionAgentHandler(
|
|
|
7771
7759
|
}
|
|
7772
7760
|
: undefined;
|
|
7773
7761
|
|
|
7774
|
-
//
|
|
7775
|
-
// onRunComplete / tracked-progress callback configured.
|
|
7776
|
-
//
|
|
7777
|
-
// wrapper to fire the continuation dispatch below.
|
|
7762
|
+
// Install the completion callback for background continuation even when
|
|
7763
|
+
// there is no app onRunComplete / tracked-progress callback configured.
|
|
7764
|
+
// The foreground self-chain path uses the same continuation dispatch.
|
|
7778
7765
|
const handleRunComplete =
|
|
7779
7766
|
isBackgroundWorker || foregroundSelfChainEligible || baseHandleRunComplete
|
|
7780
7767
|
? async (run: ActiveRun) => {
|
|
7781
|
-
|
|
7782
|
-
|
|
7783
|
-
|
|
7784
|
-
|
|
7785
|
-
|
|
7786
|
-
|
|
7787
|
-
|
|
7788
|
-
|
|
7789
|
-
|
|
7790
|
-
|
|
7791
|
-
|
|
7792
|
-
|
|
7793
|
-
|
|
7794
|
-
|
|
7795
|
-
|
|
7796
|
-
|
|
7797
|
-
|
|
7798
|
-
|
|
7799
|
-
|
|
7800
|
-
|
|
7801
|
-
errEvent
|
|
7802
|
-
|
|
7803
|
-
|
|
7804
|
-
|
|
7805
|
-
|
|
7806
|
-
|
|
7807
|
-
|
|
7808
|
-
|
|
7809
|
-
|
|
7810
|
-
|
|
7811
|
-
|
|
7812
|
-
|
|
7813
|
-
|
|
7814
|
-
|
|
7815
|
-
|
|
7816
|
-
|
|
7817
|
-
|
|
7818
|
-
|
|
7819
|
-
|
|
7820
|
-
|
|
7821
|
-
|
|
7822
|
-
|
|
7823
|
-
|
|
7824
|
-
|
|
7825
|
-
|
|
7826
|
-
|
|
7827
|
-
|
|
7828
|
-
|
|
7829
|
-
|
|
7830
|
-
|
|
7831
|
-
|
|
7832
|
-
|
|
7833
|
-
|
|
7834
|
-
|
|
7835
|
-
|
|
7836
|
-
|
|
7837
|
-
|
|
7838
|
-
|
|
7839
|
-
|
|
7840
|
-
|
|
7841
|
-
|
|
7842
|
-
|
|
7843
|
-
|
|
7844
|
-
|
|
7845
|
-
|
|
7846
|
-
|
|
7847
|
-
|
|
7848
|
-
|
|
7849
|
-
|
|
7850
|
-
|
|
7851
|
-
|
|
7852
|
-
|
|
7853
|
-
|
|
7854
|
-
|
|
7855
|
-
|
|
7856
|
-
|
|
7857
|
-
|
|
7858
|
-
|
|
7859
|
-
|
|
7860
|
-
|
|
7861
|
-
|
|
7862
|
-
|
|
7863
|
-
|
|
7864
|
-
|
|
7865
|
-
|
|
7866
|
-
|
|
7867
|
-
|
|
7868
|
-
|
|
7869
|
-
|
|
7870
|
-
|
|
7871
|
-
|
|
7872
|
-
|
|
7873
|
-
|
|
7874
|
-
|
|
7875
|
-
|
|
7876
|
-
|
|
7877
|
-
|
|
7878
|
-
|
|
7879
|
-
|
|
7880
|
-
|
|
7881
|
-
|
|
7882
|
-
|
|
7883
|
-
});
|
|
7884
|
-
}
|
|
7885
|
-
} finally {
|
|
7886
|
-
resolveBackgroundRunDone?.();
|
|
7768
|
+
// DIAGNOSTIC: a background worker that completed in an errored
|
|
7769
|
+
// state threw inside the loop. Record it (with the last error
|
|
7770
|
+
// event's message when available) so the failure cause is
|
|
7771
|
+
// readable from the client. Skipped for clean completions and for
|
|
7772
|
+
// recoverable soft-timeout boundaries (those chain a continuation
|
|
7773
|
+
// below, they did not "throw").
|
|
7774
|
+
if (
|
|
7775
|
+
isBackgroundWorker &&
|
|
7776
|
+
run.status === "errored" &&
|
|
7777
|
+
!willChainBackgroundContinuation(run)
|
|
7778
|
+
) {
|
|
7779
|
+
const errEvent = [...run.events]
|
|
7780
|
+
.reverse()
|
|
7781
|
+
.find((e) => e.event.type === "error")?.event as
|
|
7782
|
+
| { error?: string; errorCode?: string }
|
|
7783
|
+
| undefined;
|
|
7784
|
+
await recordRunDiagnostic(
|
|
7785
|
+
run.runId,
|
|
7786
|
+
RUN_DIAG_STAGE.workerThrew,
|
|
7787
|
+
errEvent?.errorCode || errEvent?.error
|
|
7788
|
+
? `${errEvent.errorCode ?? ""} ${errEvent.error ?? ""}`.trim()
|
|
7789
|
+
: "run ended in errored state",
|
|
7790
|
+
).catch(() => {});
|
|
7791
|
+
}
|
|
7792
|
+
// Persist the (partial) assistant turn to thread_data FIRST — the
|
|
7793
|
+
// server-driven continuation below rebuilds from it, so it must be
|
|
7794
|
+
// committed before we re-fire.
|
|
7795
|
+
await baseHandleRunComplete?.(run);
|
|
7796
|
+
|
|
7797
|
+
// Server-driven background→background continuation. If this chunk
|
|
7798
|
+
// hit its soft-timeout still unfinished (ended at an auto_continue
|
|
7799
|
+
// / loop_limit / recoverable boundary), chain the next chunk by
|
|
7800
|
+
// re-firing the `_process-run` self-dispatch with mode "continue"
|
|
7801
|
+
// (carried as internalContinuation + an incremented count),
|
|
7802
|
+
// instead of relying on the client to re-POST. Mirrors the
|
|
7803
|
+
// agent-teams `fireInternalDispatch({ body: { mode: "continue" }})`
|
|
7804
|
+
// chain. Bounded by MAX_BACKGROUND_RUN_CONTINUATIONS. Aborted /
|
|
7805
|
+
// user-stopped runs do NOT chain.
|
|
7806
|
+
// Self-chain server-side for EVERY durable worker, not only the
|
|
7807
|
+
// ones inside a `-background` function. Server-driven
|
|
7808
|
+
// continuation is the whole point of durable background: the run
|
|
7809
|
+
// must survive the client disconnecting (closed tab), so it
|
|
7810
|
+
// cannot depend on the browser re-POSTing `auto_continue`. A
|
|
7811
|
+
// worker on the regular ~60s function — a Netlify routing miss,
|
|
7812
|
+
// or a non-Netlify host (Vercel/Cloudflare/Render/Fly) that
|
|
7813
|
+
// never emits a `-background` function — checkpoints at the 40s
|
|
7814
|
+
// soft-timeout and self-dispatches the next 40s chunk; a worker
|
|
7815
|
+
// in a real `-background` function chains ~13-min chunks. Only
|
|
7816
|
+
// the per-chunk BUDGET differs by function type (gated by
|
|
7817
|
+
// `runsInBackgroundFunction` at the startRun call below); the
|
|
7818
|
+
// continuation itself must stay server-driven on both. (The
|
|
7819
|
+
// self-chain is only reachable when the initial dispatch already
|
|
7820
|
+
// succeeded — a dispatch fast-fail degrades to the inline
|
|
7821
|
+
// foreground fallback, which is not a worker and rides the
|
|
7822
|
+
// connected client's auto_continue instead.)
|
|
7823
|
+
if (willChainBackgroundContinuation(run)) {
|
|
7824
|
+
// Full handoff discipline lives in
|
|
7825
|
+
// `chainServerDrivenContinuation` (exported + unit-tested):
|
|
7826
|
+
// per-turn SQL run budget, successor row PRE-INSERTED before
|
|
7827
|
+
// the dispatch, fully awaited dispatch with retries, loud
|
|
7828
|
+
// diag/terminal marking on failure. Never throws.
|
|
7829
|
+
await chainServerDrivenContinuation({
|
|
7830
|
+
event,
|
|
7831
|
+
run,
|
|
7832
|
+
effectiveThreadId,
|
|
7833
|
+
effectiveTurnId,
|
|
7834
|
+
requestBody: body as unknown as Record<string, unknown>,
|
|
7835
|
+
backgroundContinuationCount,
|
|
7836
|
+
// Re-evaluate the durable gate rather than keying off
|
|
7837
|
+
// isBackgroundWorker: a successor chunk of a FOREGROUND
|
|
7838
|
+
// self-chain re-enters as a worker too, and must keep
|
|
7839
|
+
// chaining via the regular function — the Netlify
|
|
7840
|
+
// `-background` function is only emitted into the deploy
|
|
7841
|
+
// output when the durable flag is on.
|
|
7842
|
+
//
|
|
7843
|
+
// `&& !runsInBackgroundFunction`: a worker PROVEN to already
|
|
7844
|
+
// be executing inside the real `-background` function must
|
|
7845
|
+
// never dispatch back to that same function's own URL — a
|
|
7846
|
+
// background function invoking itself by URL from inside a
|
|
7847
|
+
// live invocation is a documented Netlify platform
|
|
7848
|
+
// limitation (404), unlike the initial foreground→background
|
|
7849
|
+
// dispatch or a worker that landed on the regular function
|
|
7850
|
+
// (a genuinely different function calling the background
|
|
7851
|
+
// one, which works). This only changes the dispatch TARGET
|
|
7852
|
+
// for that one proven-in-bg-function case — by this point
|
|
7853
|
+
// (with the in-process resumable-error resume above) it is
|
|
7854
|
+
// reached only when the chunk genuinely exhausted its
|
|
7855
|
+
// budget, so falling back to the regular `_process-run`
|
|
7856
|
+
// function (40s clamp) here is the correct, safe target.
|
|
7857
|
+
chainViaDurableBackground:
|
|
7858
|
+
isAgentChatDurableBackgroundEnabled({
|
|
7859
|
+
appOptIn: options.durableBackgroundRuns,
|
|
7860
|
+
}) && !runsInBackgroundFunction,
|
|
7861
|
+
// Only changes the retry BUDGET, never the dispatch target
|
|
7862
|
+
// above: a worker proven in a real background function has
|
|
7863
|
+
// minutes of remaining wall clock and no connected-client
|
|
7864
|
+
// fallback, so it must not be demoted to the foreground's
|
|
7865
|
+
// 2-attempt budget just because it was forced onto the
|
|
7866
|
+
// regular-function dispatch target. See
|
|
7867
|
+
// `resolveContinuationDispatchBudget`.
|
|
7868
|
+
workerProvenInBackgroundFunction: runsInBackgroundFunction,
|
|
7869
|
+
});
|
|
7887
7870
|
}
|
|
7888
7871
|
}
|
|
7889
7872
|
: undefined;
|
|
@@ -7970,7 +7953,7 @@ export function createProductionAgentHandler(
|
|
|
7970
7953
|
)
|
|
7971
7954
|
: null;
|
|
7972
7955
|
|
|
7973
|
-
startRun(
|
|
7956
|
+
const startedRun = startRun(
|
|
7974
7957
|
runId,
|
|
7975
7958
|
effectiveThreadId,
|
|
7976
7959
|
async (rawSend, signal) => {
|
|
@@ -8414,9 +8397,8 @@ export function createProductionAgentHandler(
|
|
|
8414
8397
|
// Background worker: await the run to completion so Netlify keeps the
|
|
8415
8398
|
// background function alive for the whole turn (the client is streaming the
|
|
8416
8399
|
// same events via the foreground POST's cross-isolate SQL subscription).
|
|
8417
|
-
// The onComplete wrapper above resolves `backgroundRunDone`.
|
|
8418
8400
|
if (isBackgroundWorker) {
|
|
8419
|
-
|
|
8401
|
+
await startedRun.finalized;
|
|
8420
8402
|
return { ok: true, runId };
|
|
8421
8403
|
}
|
|
8422
8404
|
|
package/src/agent/run-manager.ts
CHANGED
|
@@ -44,6 +44,15 @@ export interface ActiveRun {
|
|
|
44
44
|
startedAt: number;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
+
export interface StartedRun extends ActiveRun {
|
|
48
|
+
/**
|
|
49
|
+
* Resolves after the terminal event and final SQL status have been persisted.
|
|
50
|
+
* Serverless workers must await this before returning or the runtime can
|
|
51
|
+
* freeze the isolate between onComplete and terminalization.
|
|
52
|
+
*/
|
|
53
|
+
finalized: Promise<void>;
|
|
54
|
+
}
|
|
55
|
+
|
|
47
56
|
const activeRuns = new Map<string, ActiveRun>();
|
|
48
57
|
const threadToRun = new Map<string, string>();
|
|
49
58
|
|
|
@@ -447,7 +456,7 @@ export function startRun(
|
|
|
447
456
|
) => Promise<void>,
|
|
448
457
|
onComplete?: (run: ActiveRun) => void | Promise<void>,
|
|
449
458
|
options?: StartRunOptions,
|
|
450
|
-
):
|
|
459
|
+
): StartedRun {
|
|
451
460
|
// If there's already a run for this thread, abort it
|
|
452
461
|
const existingRunId = threadToRun.get(threadId);
|
|
453
462
|
if (existingRunId) {
|
|
@@ -456,7 +465,17 @@ export function startRun(
|
|
|
456
465
|
|
|
457
466
|
const abort = new AbortController();
|
|
458
467
|
let softTimedOut = false;
|
|
459
|
-
|
|
468
|
+
let resolveFinalized: () => void = () => {};
|
|
469
|
+
let rejectFinalized: (reason?: unknown) => void = () => {};
|
|
470
|
+
const finalized = new Promise<void>((resolve, reject) => {
|
|
471
|
+
resolveFinalized = resolve;
|
|
472
|
+
rejectFinalized = reject;
|
|
473
|
+
});
|
|
474
|
+
// Foreground callers do not await this promise, but terminal persistence
|
|
475
|
+
// failures must still be observable to background workers without creating
|
|
476
|
+
// an unhandled rejection in the foreground path.
|
|
477
|
+
void finalized.catch(() => {});
|
|
478
|
+
const run: StartedRun = {
|
|
460
479
|
runId,
|
|
461
480
|
threadId,
|
|
462
481
|
turnId: options?.turnId ?? runId,
|
|
@@ -465,6 +484,7 @@ export function startRun(
|
|
|
465
484
|
subscribers: new Set(),
|
|
466
485
|
abort,
|
|
467
486
|
startedAt: Date.now(),
|
|
487
|
+
finalized,
|
|
468
488
|
};
|
|
469
489
|
|
|
470
490
|
activeRuns.set(runId, run);
|
|
@@ -1039,6 +1059,21 @@ export function startRun(
|
|
|
1039
1059
|
"[run-manager] terminal event persistence error:",
|
|
1040
1060
|
err instanceof Error ? err.message : err,
|
|
1041
1061
|
);
|
|
1062
|
+
try {
|
|
1063
|
+
await insertRunEvent(
|
|
1064
|
+
runId,
|
|
1065
|
+
terminal.seq,
|
|
1066
|
+
JSON.stringify(terminal.event),
|
|
1067
|
+
);
|
|
1068
|
+
terminalPersistenceError = null;
|
|
1069
|
+
} catch (retryError) {
|
|
1070
|
+
terminalPersistenceError = retryError;
|
|
1071
|
+
captureRunError(retryError, "completion");
|
|
1072
|
+
console.error(
|
|
1073
|
+
"[run-manager] terminal event retry persistence error:",
|
|
1074
|
+
retryError instanceof Error ? retryError.message : retryError,
|
|
1075
|
+
);
|
|
1076
|
+
}
|
|
1042
1077
|
}
|
|
1043
1078
|
}
|
|
1044
1079
|
}
|
|
@@ -1112,6 +1147,13 @@ export function startRun(
|
|
|
1112
1147
|
await setRunError(runId, errorCode ?? "unknown", errorDetail);
|
|
1113
1148
|
}
|
|
1114
1149
|
|
|
1150
|
+
if (terminalPersistenceError) {
|
|
1151
|
+
const reconciled = await reconcileTerminalRunFromEvents(runId).catch(
|
|
1152
|
+
() => false,
|
|
1153
|
+
);
|
|
1154
|
+
if (!reconciled) throw terminalPersistenceError;
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1115
1157
|
// 6. Schedule in-memory cleanup + opportunistic old-run pruning.
|
|
1116
1158
|
setTimeout(() => {
|
|
1117
1159
|
activeRuns.delete(runId);
|
|
@@ -1124,6 +1166,7 @@ export function startRun(
|
|
|
1124
1166
|
resolveErroredRunRetentionMs(),
|
|
1125
1167
|
).catch(() => {});
|
|
1126
1168
|
});
|
|
1169
|
+
runPromise.then(resolveFinalized, rejectFinalized);
|
|
1127
1170
|
|
|
1128
1171
|
// On Cloudflare Workers, keep the isolate alive for this run
|
|
1129
1172
|
try {
|