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