@vellumai/assistant 0.8.2 → 0.8.4
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/ARCHITECTURE.md +11 -12
- package/docker-entrypoint.sh +13 -2
- package/docker-init-apt-root.sh +79 -6
- package/node_modules/@vellumai/gateway-client/src/types.ts +2 -0
- package/openapi.yaml +945 -36
- package/package.json +1 -1
- package/src/__tests__/agent-loop-exit-reason.test.ts +271 -0
- package/src/__tests__/agent-loop-override-profile.test.ts +1 -1
- package/src/__tests__/agent-loop-provider-error-recording.test.ts +195 -0
- package/src/__tests__/agent-loop.test.ts +88 -3
- package/src/__tests__/anthropic-provider.test.ts +272 -0
- package/src/__tests__/approval-cascade.test.ts +1 -1
- package/src/__tests__/background-workers-disk-pressure.test.ts +2 -1
- package/src/__tests__/channel-delivery-store.test.ts +193 -0
- package/src/__tests__/channel-reply-delivery.test.ts +284 -5
- package/src/__tests__/channel-retry-sweep.test.ts +274 -1
- package/src/__tests__/compaction-events.test.ts +1 -1
- package/src/__tests__/compactor-preserved-tail-count.test.ts +110 -0
- package/src/__tests__/compactor-tail-resolution.test.ts +107 -1
- package/src/__tests__/config-get-vision-flag.test.ts +136 -0
- package/src/__tests__/config-loader-backfill.test.ts +115 -18
- package/src/__tests__/config-watcher.test.ts +1 -1
- package/src/__tests__/context-token-estimator.test.ts +112 -57
- package/src/__tests__/conversation-abort-tool-results.test.ts +1 -1
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +54 -3
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +31 -6
- package/src/__tests__/conversation-agent-loop.test.ts +77 -3
- package/src/__tests__/conversation-app-control-lifecycle.test.ts +1 -1
- package/src/__tests__/conversation-clean-command.test.ts +137 -0
- package/src/__tests__/conversation-confirmation-signals.test.ts +1 -1
- package/src/__tests__/conversation-fork-crud.test.ts +161 -0
- package/src/__tests__/conversation-lifecycle.test.ts +1 -1
- package/src/__tests__/conversation-load-cleaned-at.test.ts +279 -0
- package/src/__tests__/conversation-load-history-repair.test.ts +1 -1
- package/src/__tests__/conversation-media-retry.test.ts +19 -8
- package/src/__tests__/conversation-pairing.test.ts +2 -2
- package/src/__tests__/conversation-process-callsite.test.ts +1 -1
- package/src/__tests__/conversation-provider-retry-repair.test.ts +1 -1
- package/src/__tests__/conversation-queue.test.ts +1 -1
- package/src/__tests__/conversation-runtime-assembly.test.ts +290 -85
- package/src/__tests__/conversation-seed-composer.test.ts +66 -4
- package/src/__tests__/conversation-slash-commands.test.ts +36 -8
- package/src/__tests__/conversation-slash-queue.test.ts +1 -1
- package/src/__tests__/conversation-slash-unknown.test.ts +1 -1
- package/src/__tests__/conversation-speed-override.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +220 -0
- package/src/__tests__/conversation-workspace-cache-state.test.ts +1 -1
- package/src/__tests__/conversation-workspace-injection.test.ts +5 -1
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +5 -1
- package/src/__tests__/credential-security-invariants.test.ts +6 -0
- package/src/__tests__/cu-unified-flow.test.ts +10 -1
- package/src/__tests__/date-context.test.ts +45 -0
- package/src/__tests__/dm-backfill.test.ts +64 -0
- package/src/__tests__/dm-persistence.test.ts +33 -0
- package/src/__tests__/document-find-replace.test.ts +501 -0
- package/src/__tests__/external-plugin-loader.test.ts +91 -19
- package/src/__tests__/first-greeting.test.ts +23 -2
- package/src/__tests__/guardian-action-no-hardcoded-copy.test.ts +0 -1
- package/src/__tests__/guardian-dispatch.test.ts +1 -0
- package/src/__tests__/headless-browser-navigate.test.ts +172 -0
- package/src/__tests__/heartbeat-service.test.ts +24 -164
- package/src/__tests__/helpers/channel-test-adapter.ts +0 -2
- package/src/__tests__/host-app-control-proxy.test.ts +241 -0
- package/src/__tests__/host-bash-proxy.test.ts +6 -0
- package/src/__tests__/host-browser-proxy.test.ts +10 -0
- package/src/__tests__/host-cu-proxy.test.ts +8 -1
- package/src/__tests__/host-file-proxy.test.ts +8 -1
- package/src/__tests__/host-proxy-preactivation.test.ts +200 -13
- package/src/__tests__/host-transfer-proxy.test.ts +8 -1
- package/src/__tests__/identity-routes.test.ts +57 -0
- package/src/__tests__/inbound-slack-persistence.test.ts +3 -0
- package/src/__tests__/injector-background-turn.test.ts +153 -0
- package/src/__tests__/injector-chain.test.ts +7 -0
- package/src/__tests__/injector-document-comments.test.ts +378 -0
- package/src/__tests__/injector-pkb-v2-silenced.test.ts +4 -25
- package/src/__tests__/lifecycle-memory-v2-seed.test.ts +9 -2
- package/src/__tests__/list-messages-attachments.test.ts +21 -17
- package/src/__tests__/list-messages-hidden-metadata.test.ts +217 -0
- package/src/__tests__/list-messages-page-latest.test.ts +130 -14
- package/src/__tests__/list-messages-tool-merge.test.ts +17 -16
- package/src/__tests__/llm-callsite-catalog.test.ts +25 -0
- package/src/__tests__/llm-catalog-parity.test.ts +3 -0
- package/src/__tests__/llm-context-normalization.test.ts +0 -2
- package/src/__tests__/llm-request-log-agent-loop-exit-reason.test.ts +116 -0
- package/src/__tests__/llm-request-log-error-payload.test.ts +138 -0
- package/src/__tests__/llm-request-log-source-clickhouse.test.ts +2 -0
- package/src/__tests__/llm-resolver.test.ts +340 -3
- package/src/__tests__/log-export-routes.test.ts +99 -2
- package/src/__tests__/managed-profile-guard.test.ts +10 -0
- package/src/__tests__/message-queue-steer.test.ts +114 -0
- package/src/__tests__/notification-decision-fallback.test.ts +0 -91
- package/src/__tests__/notification-decision-strategy.test.ts +14 -31
- package/src/__tests__/notification-deep-link.test.ts +15 -0
- package/src/__tests__/notification-guardian-path.test.ts +1 -2
- package/src/__tests__/notification-platform-adapter.test.ts +5 -4
- package/src/__tests__/notification-telegram-adapter.test.ts +1 -0
- package/src/__tests__/notification-vellum-adapter.test.ts +113 -0
- package/src/__tests__/openai-provider.test.ts +323 -3
- package/src/__tests__/openai-responses-cutover-guard.test.ts +3 -3
- package/src/__tests__/openai-responses-provider.test.ts +4 -4
- package/src/__tests__/openrouter-provider-only.test.ts +51 -3
- package/src/__tests__/openrouter-token-estimation.test.ts +34 -25
- package/src/__tests__/outbound-slack-persistence.test.ts +187 -20
- package/src/__tests__/pending-interactions-resolved-event.test.ts +190 -0
- package/src/__tests__/platform-proxy-context.test.ts +6 -1
- package/src/__tests__/platform.test.ts +0 -3
- package/src/__tests__/plugin-source-watcher.test.ts +302 -0
- package/src/__tests__/plugin-tool-contribution.test.ts +3 -3
- package/src/__tests__/plugin-types.test.ts +2 -2
- package/src/__tests__/process-message-background-slack.test.ts +1 -51
- package/src/__tests__/process-message-display-content.test.ts +21 -16
- package/src/__tests__/provider-catalog-visibility.test.ts +16 -0
- package/src/__tests__/provider-platform-proxy-integration.test.ts +27 -25
- package/src/__tests__/secret-routes-platform-proxy.test.ts +1 -1
- package/src/__tests__/server-history-render.test.ts +83 -4
- package/src/__tests__/steer-tool-repair.test.ts +249 -0
- package/src/__tests__/system-prompt.test.ts +57 -101
- package/src/__tests__/terminal-tools.test.ts +11 -1
- package/src/__tests__/thinking-block-replay.test.ts +113 -0
- package/src/__tests__/thread-backfill.test.ts +370 -22
- package/src/__tests__/tool-executor.test.ts +90 -1
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +167 -0
- package/src/__tests__/twilio-routes.test.ts +1 -1
- package/src/__tests__/web-fetch.test.ts +2 -2
- package/src/__tests__/workspace-git-service.test.ts +88 -5
- package/src/__tests__/workspace-migration-087-memory-router-balanced-profile.test.ts +228 -0
- package/src/__tests__/workspace-migration-088-deprecate-background-conversation-override.test.ts +158 -0
- package/src/a2a/__tests__/agent-card.test.ts +98 -0
- package/src/a2a/__tests__/e2e-a2a-channel.test.ts +597 -0
- package/src/a2a/__tests__/protocol-helpers.test.ts +113 -0
- package/src/a2a/__tests__/task-store.test.ts +246 -0
- package/src/a2a/agent-card.ts +58 -0
- package/src/a2a/feature-gate.ts +8 -0
- package/src/a2a/protocol-constants.ts +21 -0
- package/src/a2a/protocol-errors.ts +50 -0
- package/src/a2a/protocol-types.ts +162 -0
- package/src/a2a/task-store.ts +168 -0
- package/src/agent/attachments.ts +1 -0
- package/src/agent/loop.ts +208 -22
- package/src/background-wake/next-wake.test.ts +289 -0
- package/src/background-wake/next-wake.ts +172 -0
- package/src/browser/operations.ts +15 -0
- package/src/channels/config.ts +9 -0
- package/src/channels/types.ts +14 -0
- package/src/cli/commands/__tests__/conversations-slack.test.ts +572 -0
- package/src/cli/commands/__tests__/memory-v2.test.ts +9 -12
- package/src/cli/{__tests__ → commands/__tests__}/notifications.test.ts +201 -28
- package/src/cli/commands/__tests__/schedules.test.ts +469 -0
- package/src/cli/commands/conversations.ts +128 -1
- package/src/cli/commands/inference-providers.ts +147 -1
- package/src/cli/commands/memory-v2.ts +308 -0
- package/src/cli/commands/notifications.ts +89 -37
- package/src/cli/commands/plugins.ts +67 -0
- package/src/cli/commands/schedules.ts +297 -5
- package/src/cli/lib/__tests__/search-plugins.test.ts +261 -0
- package/src/cli/lib/install-from-github.ts +8 -9
- package/src/cli/lib/search-plugins.ts +163 -0
- package/src/cli/program.ts +14 -0
- package/src/cli/utils/conversation-id.ts +17 -5
- package/src/config/assistant-feature-flags.ts +24 -54
- package/src/config/bundled-skills/app-builder/SKILL.md +117 -1
- package/src/config/bundled-skills/document-editor/SKILL.md +115 -0
- package/src/config/bundled-skills/document-editor/TOOLS.json +240 -0
- package/src/config/bundled-skills/document-editor/tools/comment-list.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/comment-reply.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/comment-resolve.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/document-find.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/document-replace-text.ts +12 -0
- package/src/config/bundled-skills/media-processing/SKILL.md +8 -0
- package/src/config/bundled-skills/phone-calls/SKILL.md +1 -1
- package/src/config/bundled-skills/schedule/SKILL.md +8 -0
- package/src/config/bundled-tool-registry.ts +22 -12
- package/src/config/call-site-defaults.ts +124 -0
- package/src/config/feature-flag-registry.json +111 -23
- package/src/config/llm-resolver.ts +66 -1
- package/src/config/schema.ts +2 -0
- package/src/config/schemas/__tests__/memory-v2.test.ts +7 -3
- package/src/config/schemas/call-site-catalog.ts +21 -0
- package/src/config/schemas/channels.ts +9 -0
- package/src/config/schemas/conversations.ts +10 -0
- package/src/config/schemas/heartbeat.ts +14 -0
- package/src/config/schemas/llm.ts +4 -3
- package/src/config/schemas/memory-retrospective.ts +1 -1
- package/src/config/schemas/memory-v2.ts +51 -4
- package/src/config/schemas/memory.ts +3 -1
- package/src/config/seed-inference-profiles.ts +99 -29
- package/src/context/compactor.ts +80 -13
- package/src/context/token-estimator.ts +72 -31
- package/src/context/window-manager.ts +25 -0
- package/src/credential-health/credential-health-service.ts +34 -19
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +3 -22
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +66 -6
- package/src/daemon/__tests__/native-web-search-metadata.test.ts +357 -0
- package/src/daemon/__tests__/web-search-status-text.test.ts +287 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +231 -23
- package/src/daemon/conversation-agent-loop.ts +252 -56
- package/src/daemon/conversation-lifecycle.ts +142 -116
- package/src/daemon/conversation-messaging.ts +3 -0
- package/src/daemon/conversation-process.ts +273 -0
- package/src/daemon/conversation-queue-manager.ts +14 -0
- package/src/daemon/conversation-runtime-assembly.ts +144 -75
- package/src/daemon/conversation-slash.ts +37 -5
- package/src/daemon/conversation-surfaces.ts +45 -2
- package/src/daemon/conversation-tool-setup.ts +7 -0
- package/src/daemon/conversation.ts +42 -12
- package/src/daemon/date-context.ts +40 -0
- package/src/daemon/first-greeting.ts +10 -0
- package/src/daemon/guardian-action-generators.ts +1 -125
- package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +498 -0
- package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +248 -0
- package/src/daemon/handlers/__tests__/config-a2a-invite.test.ts +154 -0
- package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +133 -0
- package/src/daemon/handlers/__tests__/config-a2a.test.ts +95 -0
- package/src/daemon/handlers/config-a2a.ts +449 -0
- package/src/daemon/handlers/config-model.test.ts +1 -0
- package/src/daemon/handlers/conversations.ts +80 -0
- package/src/daemon/handlers/shared.ts +92 -29
- package/src/daemon/host-app-control-proxy.ts +69 -18
- package/src/daemon/host-bash-proxy.ts +1 -1
- package/src/daemon/host-cu-proxy.ts +1 -1
- package/src/daemon/host-file-proxy.ts +1 -1
- package/src/daemon/host-proxy-preactivation.ts +85 -18
- package/src/daemon/host-transfer-proxy.ts +1 -1
- package/src/daemon/lifecycle.ts +67 -65
- package/src/daemon/memory-v2-startup.ts +49 -13
- package/src/daemon/message-protocol.ts +4 -0
- package/src/daemon/message-types/conversations.ts +8 -0
- package/src/daemon/message-types/document-comments.ts +50 -0
- package/src/daemon/message-types/messages.ts +68 -1
- package/src/daemon/message-types/notifications.ts +21 -0
- package/src/daemon/message-types/surfaces.ts +3 -1
- package/src/daemon/message-types/web-activity.ts +57 -0
- package/src/daemon/pkb-reminder-builder.test.ts +10 -53
- package/src/daemon/pkb-reminder-builder.ts +4 -19
- package/src/daemon/plugin-source-watcher.ts +135 -3
- package/src/daemon/process-message.ts +72 -12
- package/src/daemon/query-complexity-router.ts +75 -0
- package/src/daemon/skill-memory-refresh.ts +5 -1
- package/src/daemon/trust-context.ts +6 -0
- package/src/daemon/wake-target-adapter.ts +2 -0
- package/src/documents/document-comments-store.test.ts +338 -0
- package/src/documents/document-comments-store.ts +237 -0
- package/src/documents/document-store.ts +202 -0
- package/src/export/__tests__/transcript-formatter.test.ts +121 -0
- package/src/export/transcript-formatter.ts +54 -20
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +44 -1
- package/src/heartbeat/heartbeat-service.ts +35 -191
- package/src/home/__tests__/feed-types.test.ts +40 -0
- package/src/home/__tests__/suggested-prompts.test.ts +33 -2
- package/src/home/feed-types.ts +20 -3
- package/src/home/home-content-refresh.ts +52 -0
- package/src/home/home-greeting-cache.ts +69 -0
- package/src/home/home-greeting.ts +94 -0
- package/src/home/suggested-prompts.ts +177 -9
- package/src/ipc/cli-client.ts +147 -45
- package/src/memory/__tests__/conversation-queries.test.ts +220 -0
- package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +135 -2
- package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +2 -50
- package/src/memory/__tests__/memory-retrospective-job.test.ts +407 -10
- package/src/memory/conversation-crud.ts +133 -43
- package/src/memory/conversation-queries.ts +87 -1
- package/src/memory/conversation-title-service.ts +26 -4
- package/src/memory/db-init.ts +22 -0
- package/src/memory/delivery-crud.ts +41 -0
- package/src/memory/delivery-status.ts +141 -15
- package/src/memory/external-conversation-store.ts +32 -1
- package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +84 -3
- package/src/memory/graph/conversation-graph-memory.ts +18 -6
- package/src/memory/graph/tools.ts +6 -37
- package/src/memory/invite-store.ts +53 -0
- package/src/memory/jobs-worker.ts +21 -1
- package/src/memory/llm-request-log-source-clickhouse.ts +7 -2
- package/src/memory/llm-request-log-store.ts +92 -1
- package/src/memory/memory-retrospective-constants.ts +28 -0
- package/src/memory/memory-retrospective-enqueue.ts +4 -22
- package/src/memory/memory-retrospective-job.ts +438 -21
- package/src/memory/memory-retrospective-startup-cleanup.ts +3 -3
- package/src/memory/memory-v2-activation-log-store.ts +26 -8
- package/src/memory/migrations/100-core-tables.ts +1 -0
- package/src/memory/migrations/109-external-conversation-bindings.ts +1 -0
- package/src/memory/migrations/250-provider-connection-base-url-and-models.ts +28 -0
- package/src/memory/migrations/251-a2a-tasks.ts +49 -0
- package/src/memory/migrations/252-llm-request-log-agent-loop-exit-reason.ts +32 -0
- package/src/memory/migrations/253-conversation-last-notified-profile.ts +15 -0
- package/src/memory/migrations/253-document-comments.ts +47 -0
- package/src/memory/migrations/254-external-conversation-binding-chat-name.ts +43 -0
- package/src/memory/migrations/255-channel-inbound-delivery-attempts.ts +24 -0
- package/src/memory/migrations/256-memory-v2-injection-events.ts +113 -0
- package/src/memory/migrations/257-strip-base-url-non-openai-compatible.ts +22 -0
- package/src/memory/migrations/258-onboarding-events-prior-assistants.ts +13 -0
- package/src/memory/migrations/259-conversation-cleaned-at.ts +33 -0
- package/src/memory/migrations/index.ts +20 -0
- package/src/memory/migrations/registry.ts +33 -0
- package/src/memory/onboarding-events-store.ts +7 -0
- package/src/memory/schema/a2a.ts +15 -0
- package/src/memory/schema/calls.ts +1 -0
- package/src/memory/schema/conversations.ts +3 -0
- package/src/memory/schema/index.ts +1 -0
- package/src/memory/schema/inference.ts +2 -0
- package/src/memory/schema/infrastructure.ts +2 -0
- package/src/memory/v2/__tests__/activation-store.test.ts +25 -23
- package/src/memory/v2/__tests__/cli-command-store.test.ts +404 -0
- package/src/memory/v2/__tests__/frontmatter-sweep.test.ts +25 -4
- package/src/memory/v2/__tests__/injection-events.test.ts +318 -0
- package/src/memory/v2/__tests__/injection.test.ts +221 -17
- package/src/memory/v2/__tests__/page-index.test.ts +365 -1
- package/src/memory/v2/__tests__/router.test.ts +489 -1
- package/src/memory/v2/__tests__/static-context.test.ts +12 -1
- package/src/memory/v2/activation-store.ts +14 -16
- package/src/memory/v2/cli-command-content.ts +19 -0
- package/src/memory/v2/cli-command-store.ts +304 -0
- package/src/memory/v2/consolidation-job.ts +14 -0
- package/src/memory/v2/frontmatter-sweep.ts +7 -1
- package/src/memory/v2/injection-events.ts +101 -0
- package/src/memory/v2/injection.ts +69 -29
- package/src/memory/v2/page-index.ts +246 -19
- package/src/memory/v2/page-store.ts +18 -0
- package/src/memory/v2/router.ts +209 -55
- package/src/memory/v2/static-context.ts +4 -4
- package/src/memory/v2/types.ts +23 -0
- package/src/messaging/providers/a2a/__tests__/deliver.test.ts +274 -0
- package/src/messaging/providers/a2a/deliver.ts +156 -0
- package/src/messaging/providers/gmail/client.ts +9 -2
- package/src/messaging/providers/index.ts +18 -3
- package/src/messaging/providers/slack/__tests__/adapter-mention-rendering.test.ts +329 -3
- package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +34 -1
- package/src/messaging/providers/slack/adapter.ts +178 -25
- package/src/messaging/providers/slack/api.test.ts +54 -0
- package/src/messaging/providers/slack/api.ts +119 -3
- package/src/messaging/providers/slack/client.ts +12 -0
- package/src/messaging/providers/slack/deep-link.ts +20 -1
- package/src/messaging/providers/slack/message-metadata.test.ts +48 -0
- package/src/messaging/providers/slack/message-metadata.ts +156 -0
- package/src/messaging/providers/slack/render-transcript.test.ts +107 -75
- package/src/messaging/providers/slack/render-transcript.ts +176 -49
- package/src/messaging/providers/slack/send.test.ts +77 -0
- package/src/messaging/providers/slack/send.ts +8 -2
- package/src/messaging/providers/slack/types.ts +14 -0
- package/src/notifications/__tests__/broadcaster.test.ts +203 -0
- package/src/notifications/__tests__/decision-engine.test.ts +283 -0
- package/src/notifications/__tests__/deterministic-checks.test.ts +286 -0
- package/src/notifications/__tests__/emit-signal-home-feed.test.ts +5 -1
- package/src/notifications/__tests__/home-feed-side-effect.test.ts +521 -36
- package/src/notifications/adapters/macos.ts +12 -2
- package/src/notifications/broadcaster.ts +29 -4
- package/src/notifications/conversation-seed-composer.ts +14 -2
- package/src/notifications/copy-composer.ts +17 -64
- package/src/notifications/decision-engine.ts +111 -44
- package/src/notifications/deferred-emit.ts +135 -0
- package/src/notifications/deterministic-checks.ts +96 -0
- package/src/notifications/emit-signal.ts +10 -1
- package/src/notifications/home-feed-side-effect.ts +136 -27
- package/src/notifications/signal.ts +0 -4
- package/src/notifications/types.ts +8 -0
- package/src/oauth/connect-orchestrator.ts +3 -0
- package/src/oauth/credential-token-resolver.ts +2 -0
- package/src/oauth/manual-token-connection.ts +19 -0
- package/src/oauth/oauth-store.ts +12 -0
- package/src/oauth/platform-connection.test.ts +43 -3
- package/src/oauth/platform-connection.ts +13 -4
- package/src/oauth/seed-providers.ts +22 -0
- package/src/permissions/prompter.ts +5 -2
- package/src/permissions/secret-prompter.ts +4 -1
- package/src/plugins/defaults/injectors.ts +118 -26
- package/src/plugins/external-plugin-loader.ts +82 -10
- package/src/plugins/types.ts +16 -7
- package/src/prompts/__tests__/system-prompt.test.ts +44 -45
- package/src/prompts/__tests__/task-progress-hint-section.test.ts +4 -8
- package/src/prompts/normalize-onboarding.ts +40 -0
- package/src/prompts/sections.ts +32 -14
- package/src/prompts/system-prompt.ts +105 -76
- package/src/prompts/template-detection.ts +37 -0
- package/src/prompts/templates/BOOTSTRAP-CONTENT-AUTOMATION.md +141 -0
- package/src/prompts/templates/BOOTSTRAP.md +13 -5
- package/src/prompts/templates/VOICE.md +3 -0
- package/src/prompts/templates/system-sections.ts +51 -10
- package/src/providers/__tests__/inference.test.ts +2 -0
- package/src/providers/anthropic/client.ts +132 -5
- package/src/providers/call-site-routing.ts +24 -6
- package/src/providers/connection-resolution.ts +63 -13
- package/src/providers/fireworks/client.ts +20 -2
- package/src/providers/inference/__tests__/adapter-factory-openai-compatible.test.ts +74 -0
- package/src/providers/inference/__tests__/base-url-route-validation.test.ts +342 -0
- package/src/providers/inference/__tests__/base-url-security.test.ts +189 -0
- package/src/providers/inference/__tests__/codex-token-refresh.test.ts +254 -0
- package/src/providers/inference/__tests__/connections-openai-compatible.test.ts +175 -0
- package/src/providers/inference/__tests__/connections-status-label.test.ts +15 -0
- package/src/providers/inference/adapter-factory.ts +24 -21
- package/src/providers/inference/auth.ts +15 -3
- package/src/providers/inference/backfill.ts +14 -1
- package/src/providers/inference/codex-token-refresh.ts +128 -0
- package/src/providers/inference/connections.ts +85 -5
- package/src/providers/inference/resolve-auth.ts +50 -5
- package/src/providers/model-catalog.ts +244 -242
- package/src/providers/model-intents.ts +3 -3
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +235 -0
- package/src/providers/openai/chat-completions-provider.ts +215 -25
- package/src/providers/openai/responses-provider.ts +9 -3
- package/src/providers/openrouter/client.ts +46 -4
- package/src/providers/platform-proxy/constants.ts +3 -4
- package/src/providers/provider-catalog-visibility.ts +3 -1
- package/src/providers/provider-send-message.ts +27 -12
- package/src/providers/registry.ts +30 -1
- package/src/providers/types.ts +25 -0
- package/src/runtime/__tests__/agent-wake.test.ts +214 -0
- package/src/runtime/__tests__/background-job-runner.test.ts +128 -0
- package/src/runtime/agent-wake.ts +212 -57
- package/src/runtime/auth/route-policy.ts +20 -3
- package/src/runtime/background-job-runner.ts +26 -0
- package/src/runtime/channel-reply-delivery.ts +182 -47
- package/src/runtime/channel-retry-sweep.ts +141 -16
- package/src/runtime/http-server.ts +7 -16
- package/src/runtime/http-types.ts +7 -51
- package/src/runtime/pending-interactions.ts +51 -8
- package/src/runtime/routes/__tests__/consolidation-routes.test.ts +258 -0
- package/src/runtime/routes/__tests__/content-source-routes.test.ts +162 -0
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +121 -5
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +275 -44
- package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +12 -0
- package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +14 -0
- package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +271 -0
- package/src/runtime/routes/__tests__/sanity-routes.test.ts +280 -0
- package/src/runtime/routes/__tests__/slack-channel-routes.test.ts +266 -0
- package/src/runtime/routes/approval-routes.ts +4 -1
- package/src/runtime/routes/channel-availability-routes.ts +5 -0
- package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +246 -0
- package/src/runtime/routes/consolidation-routes.ts +100 -0
- package/src/runtime/routes/content-source-routes.ts +78 -0
- package/src/runtime/routes/conversation-cli-routes.ts +146 -1
- package/src/runtime/routes/conversation-query-routes.ts +130 -12
- package/src/runtime/routes/conversation-routes.ts +288 -76
- package/src/runtime/routes/document-comments-routes.ts +287 -0
- package/src/runtime/routes/documents-routes.ts +33 -0
- package/src/runtime/routes/home-feed-routes.ts +6 -3
- package/src/runtime/routes/host-app-control-routes.ts +1 -1
- package/src/runtime/routes/host-browser-routes.ts +8 -1
- package/src/runtime/routes/identity-routes.ts +21 -0
- package/src/runtime/routes/inbound-message-handler.ts +288 -58
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +365 -6
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +283 -82
- package/src/runtime/routes/index.ts +14 -4
- package/src/runtime/routes/inference-provider-connection-routes.ts +192 -3
- package/src/runtime/routes/integrations/a2a.ts +294 -0
- package/src/runtime/routes/llm-call-sites-routes.ts +11 -1
- package/src/runtime/routes/log-export-routes.ts +39 -0
- package/src/runtime/routes/memory-v2-routes.ts +217 -0
- package/src/runtime/routes/notification-routes.ts +19 -2
- package/src/runtime/routes/question-routes.ts +4 -1
- package/src/runtime/routes/sanity-routes.ts +159 -0
- package/src/runtime/routes/slack-channel-routes.ts +187 -0
- package/src/runtime/routes/subagents-routes.ts +41 -0
- package/src/runtime/services/conversation-serializer.ts +30 -4
- package/src/schedule/integration-status.ts +3 -1
- package/src/security/__tests__/oauth2-device-code.test.ts +479 -0
- package/src/security/oauth2-device-code.ts +307 -0
- package/src/security/oauth2.ts +26 -9
- package/src/security/secure-keys.ts +5 -0
- package/src/skills/catalog-install.ts +6 -2
- package/src/subagent/manager.ts +2 -0
- package/src/tools/browser/__tests__/pinned-tabs.test.ts +80 -0
- package/src/tools/browser/browser-execution.ts +93 -0
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +28 -0
- package/src/tools/browser/cdp-client/__tests__/types.test.ts +1 -0
- package/src/tools/browser/cdp-client/cdp-inspect-client.ts +10 -0
- package/src/tools/browser/cdp-client/extension-cdp-client.ts +15 -1
- package/src/tools/browser/cdp-client/factory.ts +87 -3
- package/src/tools/browser/cdp-client/local-cdp-client.ts +9 -0
- package/src/tools/browser/cdp-client/types.ts +36 -0
- package/src/tools/browser/pinned-tabs.ts +90 -0
- package/src/tools/document/document-comment-tool.test.ts +379 -0
- package/src/tools/document/document-comment-tool.ts +156 -0
- package/src/tools/document/document-tool.ts +128 -2
- package/src/tools/memory/register.ts +1 -9
- package/src/tools/network/__tests__/web-fetch-metadata.test.ts +229 -0
- package/src/tools/network/__tests__/web-search-metadata.test.ts +346 -0
- package/src/tools/network/domain-normalize.ts +17 -0
- package/src/tools/network/web-fetch.ts +213 -64
- package/src/tools/network/web-search.ts +191 -66
- package/src/tools/registry.ts +2 -2
- package/src/tools/terminal/safe-env.ts +3 -2
- package/src/tools/tool-approval-handler.ts +19 -12
- package/src/tools/types.ts +41 -2
- package/src/tools/ui-surface/definitions.ts +3 -1
- package/src/types/onboarding-context.ts +4 -0
- package/src/util/__tests__/favicon.test.ts +84 -0
- package/src/util/favicon.ts +40 -0
- package/src/util/platform.ts +0 -5
- package/src/workspace/git-service.ts +75 -4
- package/src/workspace/migrations/087-memory-router-balanced-profile.ts +91 -0
- package/src/workspace/migrations/088-deprecate-background-conversation-override.ts +103 -0
- package/src/workspace/migrations/registry.ts +4 -0
- package/src/__tests__/guardian-action-conversation-turn.test.ts +0 -441
- package/src/config/bundled-skills/document/SKILL.md +0 -54
- package/src/config/bundled-skills/document/TOOLS.json +0 -106
- package/src/daemon/seed-files.ts +0 -18
- package/src/memory/graph/__tests__/remember-description.test.ts +0 -55
- package/src/runtime/guardian-action-conversation-turn.ts +0 -99
- package/src/runtime/routes/interface-routes.ts +0 -43
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-create.ts +0 -0
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-delete.ts +0 -0
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-list.ts +0 -0
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-read.ts +0 -0
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-update.ts +0 -0
|
@@ -15,6 +15,7 @@ import { optimizeImageForTransport } from "../agent/image-optimize.js";
|
|
|
15
15
|
import type {
|
|
16
16
|
AgentEvent,
|
|
17
17
|
AgentLoop,
|
|
18
|
+
AgentLoopExitReason,
|
|
18
19
|
CheckpointDecision,
|
|
19
20
|
CheckpointInfo,
|
|
20
21
|
} from "../agent/loop.js";
|
|
@@ -25,11 +26,16 @@ import type {
|
|
|
25
26
|
TurnChannelContext,
|
|
26
27
|
TurnInterfaceContext,
|
|
27
28
|
} from "../channels/types.js";
|
|
29
|
+
import { isAssistantFeatureFlagEnabled } from "../config/assistant-feature-flags.js";
|
|
28
30
|
import {
|
|
29
31
|
contextWindowConfigFromEffective,
|
|
32
|
+
type EffectiveContextWindow,
|
|
30
33
|
resolveEffectiveContextWindow,
|
|
31
34
|
} from "../config/llm-context-resolution.js";
|
|
32
|
-
import {
|
|
35
|
+
import {
|
|
36
|
+
resolveCallSiteConfig,
|
|
37
|
+
resolveDefaultProfileKey,
|
|
38
|
+
} from "../config/llm-resolver.js";
|
|
33
39
|
import { getConfig } from "../config/loader.js";
|
|
34
40
|
import type { LLMCallSite } from "../config/schemas/llm.js";
|
|
35
41
|
import type { ContextWindowConfig } from "../config/types.js";
|
|
@@ -62,6 +68,7 @@ import {
|
|
|
62
68
|
getLastUserTimestampBefore,
|
|
63
69
|
getMessageById,
|
|
64
70
|
provenanceFromTrustContext,
|
|
71
|
+
setLastNotifiedInferenceProfile,
|
|
65
72
|
updateConversationContextWindow,
|
|
66
73
|
updateConversationSlackContextWatermark,
|
|
67
74
|
} from "../memory/conversation-crud.js";
|
|
@@ -71,7 +78,9 @@ import {
|
|
|
71
78
|
isReplaceableTitle,
|
|
72
79
|
queueRegenerateConversationTitle,
|
|
73
80
|
} from "../memory/conversation-title-service.js";
|
|
81
|
+
import { isBackgroundConversationType } from "../memory/conversation-types.js";
|
|
74
82
|
import type { ConversationGraphMemory } from "../memory/graph/conversation-graph-memory.js";
|
|
83
|
+
import { backfillMessageIdOnLogs } from "../memory/llm-request-log-store.js";
|
|
75
84
|
import { recordMemoryRecallLog } from "../memory/memory-recall-log-store.js";
|
|
76
85
|
import { enqueueMemoryRetrospectiveOnCompaction } from "../memory/memory-retrospective-enqueue.js";
|
|
77
86
|
import { PKB_WORKSPACE_SCOPE } from "../memory/pkb/types.js";
|
|
@@ -109,6 +118,7 @@ import type {
|
|
|
109
118
|
MemoryResult,
|
|
110
119
|
OverflowReduceArgs,
|
|
111
120
|
OverflowReduceResult,
|
|
121
|
+
PersistAddResult,
|
|
112
122
|
PersistArgs,
|
|
113
123
|
PersistResult,
|
|
114
124
|
TurnContext as PluginTurnContext,
|
|
@@ -212,6 +222,10 @@ import {
|
|
|
212
222
|
SYNC_TAGS,
|
|
213
223
|
} from "./message-types/sync.js";
|
|
214
224
|
import { parseActualTokensFromError } from "./parse-actual-tokens-from-error.js";
|
|
225
|
+
import {
|
|
226
|
+
classifyQueryComplexity,
|
|
227
|
+
complexityTierToProfileKey,
|
|
228
|
+
} from "./query-complexity-router.js";
|
|
215
229
|
import type { TraceEmitter } from "./trace-emitter.js";
|
|
216
230
|
import type { TrustContext } from "./trust-context.js";
|
|
217
231
|
import { stripHistoricalWebSearchResults } from "./web-search-history.js";
|
|
@@ -518,12 +532,11 @@ export interface AgentLoopConversationContext {
|
|
|
518
532
|
/** Per-turn snapshot of channelCapabilities, frozen at message-processing start. */
|
|
519
533
|
currentTurnChannelCapabilities?: ChannelCapabilities;
|
|
520
534
|
/**
|
|
521
|
-
*
|
|
535
|
+
* Current inference-profile override for this turn. Read by
|
|
522
536
|
* `createToolExecutor` so `ToolContext.overrideProfile` carries the same
|
|
523
|
-
* profile the agent loop is sending to the provider.
|
|
524
|
-
*
|
|
525
|
-
*
|
|
526
|
-
* had `inferenceProfile` set.
|
|
537
|
+
* profile the agent loop is sending to the provider. Refreshed between
|
|
538
|
+
* model calls so an explicitly confirmed profile session opened mid-turn
|
|
539
|
+
* is inherited by later tool executions and nested subagents.
|
|
527
540
|
*/
|
|
528
541
|
currentTurnOverrideProfile?: string;
|
|
529
542
|
commandIntent?: { type: string; payload?: string; languageCode?: string };
|
|
@@ -533,7 +546,6 @@ export interface AgentLoopConversationContext {
|
|
|
533
546
|
assistantId?: string;
|
|
534
547
|
voiceCallControlPrompt?: string;
|
|
535
548
|
transportHints?: string[];
|
|
536
|
-
slackRuntimeContextNotice?: string;
|
|
537
549
|
clientTimezone?: string;
|
|
538
550
|
|
|
539
551
|
readonly coreToolNames: Set<string>;
|
|
@@ -667,6 +679,11 @@ export async function runAgentLoopImpl(
|
|
|
667
679
|
requestId: reqId,
|
|
668
680
|
});
|
|
669
681
|
let yieldedForHandoff = false;
|
|
682
|
+
let yieldedForBudget = false;
|
|
683
|
+
let pendingCheckpointYield: "budget" | "handoff" | null = null;
|
|
684
|
+
let emitTerminalExit:
|
|
685
|
+
| ((reason: AgentLoopExitReason) => Promise<void>)
|
|
686
|
+
| null = null;
|
|
670
687
|
|
|
671
688
|
// Default user-initiated turns to the `mainAgent` call site. Other
|
|
672
689
|
// invocation contexts (heartbeat, filing, analyze, etc.) pass their own
|
|
@@ -688,31 +705,134 @@ export async function runAgentLoopImpl(
|
|
|
688
705
|
// spawned subagent's background conversation) wins over the row read
|
|
689
706
|
// so the agent loop's own background-skip rule doesn't zero out an
|
|
690
707
|
// explicitly inherited override.
|
|
691
|
-
const
|
|
708
|
+
const userExplicitOverride =
|
|
692
709
|
options?.overrideProfile ??
|
|
693
710
|
getConversationOverrideProfileFromRow(turnStartConversation);
|
|
694
711
|
|
|
695
712
|
const config = getConfig();
|
|
713
|
+
|
|
714
|
+
// Query complexity routing: when no explicit user override is set and the
|
|
715
|
+
// feature flag is enabled, classify the query and route to the appropriate
|
|
716
|
+
// profile for this turn. The override is ephemeral (not persisted).
|
|
717
|
+
let turnOverrideProfile = userExplicitOverride;
|
|
718
|
+
if (
|
|
719
|
+
!userExplicitOverride &&
|
|
720
|
+
turnCallSite === "mainAgent" &&
|
|
721
|
+
isAssistantFeatureFlagEnabled("query-complexity-routing", config)
|
|
722
|
+
) {
|
|
723
|
+
const tier = await classifyQueryComplexity(content);
|
|
724
|
+
if (tier && tier !== "balanced") {
|
|
725
|
+
const routedProfile = complexityTierToProfileKey(tier);
|
|
726
|
+
if (config.llm.profiles?.[routedProfile]) {
|
|
727
|
+
turnOverrideProfile = routedProfile;
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
// Notify clients when the auto-router selected a non-default profile.
|
|
733
|
+
if (turnOverrideProfile && turnOverrideProfile !== userExplicitOverride) {
|
|
734
|
+
const profileEntry = config.llm.profiles?.[turnOverrideProfile];
|
|
735
|
+
const label = profileEntry?.label ?? turnOverrideProfile;
|
|
736
|
+
broadcastMessage({
|
|
737
|
+
type: "turn_profile_auto_routed",
|
|
738
|
+
conversationId: ctx.conversationId,
|
|
739
|
+
profile: turnOverrideProfile,
|
|
740
|
+
profileLabel: label,
|
|
741
|
+
});
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
// Only use the complexity-routed profile as a fallback — not the initial
|
|
745
|
+
// explicit override. If a mid-turn session expiry clears the conversation
|
|
746
|
+
// override, the old behavior (return undefined → revert to workspace
|
|
747
|
+
// defaults) must be preserved for non-routed turns.
|
|
748
|
+
const complexityRoutedProfile =
|
|
749
|
+
turnOverrideProfile !== userExplicitOverride
|
|
750
|
+
? turnOverrideProfile
|
|
751
|
+
: undefined;
|
|
752
|
+
const readCurrentOverrideProfile = (): string | undefined =>
|
|
753
|
+
options?.overrideProfile ??
|
|
754
|
+
getConversationOverrideProfileFromRow(
|
|
755
|
+
getConversation(ctx.conversationId),
|
|
756
|
+
) ??
|
|
757
|
+
complexityRoutedProfile;
|
|
758
|
+
|
|
696
759
|
const effectiveContextWindow = resolveEffectiveContextWindow({
|
|
697
760
|
llm: config.llm,
|
|
698
761
|
callSite: turnCallSite,
|
|
699
762
|
overrideProfile: turnOverrideProfile ?? undefined,
|
|
700
763
|
});
|
|
701
|
-
|
|
764
|
+
let currentEffectiveContextWindow: EffectiveContextWindow =
|
|
765
|
+
effectiveContextWindow;
|
|
766
|
+
let currentContextWindowConfig = contextWindowConfigFromEffective(
|
|
702
767
|
resolveCallSiteConfig(turnCallSite, config.llm, {
|
|
703
768
|
overrideProfile: turnOverrideProfile ?? undefined,
|
|
704
769
|
}).contextWindow,
|
|
705
|
-
|
|
770
|
+
currentEffectiveContextWindow,
|
|
706
771
|
);
|
|
707
|
-
|
|
772
|
+
const contextWindowManager =
|
|
708
773
|
ctx.contextWindowManager as ContextWindowManager & {
|
|
709
774
|
updateConfig?: (config: ContextWindowConfig) => void;
|
|
775
|
+
};
|
|
776
|
+
contextWindowManager.updateConfig?.(currentContextWindowConfig);
|
|
777
|
+
|
|
778
|
+
let appliedOverrideProfile = turnOverrideProfile;
|
|
779
|
+
const refreshCurrentProfileState = (): string | undefined => {
|
|
780
|
+
const currentOverrideProfile = readCurrentOverrideProfile();
|
|
781
|
+
if (currentOverrideProfile !== appliedOverrideProfile) {
|
|
782
|
+
currentEffectiveContextWindow = resolveEffectiveContextWindow({
|
|
783
|
+
llm: config.llm,
|
|
784
|
+
callSite: turnCallSite,
|
|
785
|
+
overrideProfile: currentOverrideProfile,
|
|
786
|
+
});
|
|
787
|
+
currentContextWindowConfig = contextWindowConfigFromEffective(
|
|
788
|
+
resolveCallSiteConfig(turnCallSite, config.llm, {
|
|
789
|
+
overrideProfile: currentOverrideProfile,
|
|
790
|
+
}).contextWindow,
|
|
791
|
+
currentEffectiveContextWindow,
|
|
792
|
+
);
|
|
793
|
+
contextWindowManager.updateConfig?.(currentContextWindowConfig);
|
|
794
|
+
appliedOverrideProfile = currentOverrideProfile;
|
|
795
|
+
rlog.info(
|
|
796
|
+
{ overrideProfile: currentOverrideProfile ?? null },
|
|
797
|
+
"Turn inference profile changed mid-loop",
|
|
798
|
+
);
|
|
710
799
|
}
|
|
711
|
-
|
|
800
|
+
ctx.currentTurnOverrideProfile = currentOverrideProfile;
|
|
801
|
+
return currentOverrideProfile;
|
|
802
|
+
};
|
|
803
|
+
const resolveCurrentOverrideProfile = (): string | undefined =>
|
|
804
|
+
refreshCurrentProfileState();
|
|
805
|
+
const resolveCurrentMaxInputTokens = (): number => {
|
|
806
|
+
refreshCurrentProfileState();
|
|
807
|
+
return currentEffectiveContextWindow.maxInputTokens;
|
|
808
|
+
};
|
|
809
|
+
const resolveCurrentContextWindowConfig = (): ContextWindowConfig => {
|
|
810
|
+
refreshCurrentProfileState();
|
|
811
|
+
return currentContextWindowConfig;
|
|
812
|
+
};
|
|
813
|
+
const resolveCurrentContextBudget = (): {
|
|
814
|
+
overflowRecovery: EffectiveContextWindow["overflowRecovery"];
|
|
815
|
+
providerMaxTokens: number;
|
|
816
|
+
preflightBudget: number;
|
|
817
|
+
} => {
|
|
818
|
+
refreshCurrentProfileState();
|
|
819
|
+
const overflowRecovery = currentEffectiveContextWindow.overflowRecovery;
|
|
820
|
+
const providerMaxTokens = currentEffectiveContextWindow.maxInputTokens;
|
|
821
|
+
const baseSafetyMargin = overflowRecovery.safetyMarginRatio;
|
|
822
|
+
const messageCount = ctx.messages.length;
|
|
823
|
+
const safetyMargin =
|
|
824
|
+
messageCount > 50 ? Math.max(baseSafetyMargin, 0.15) : baseSafetyMargin;
|
|
825
|
+
return {
|
|
826
|
+
overflowRecovery,
|
|
827
|
+
providerMaxTokens,
|
|
828
|
+
preflightBudget: Math.floor(providerMaxTokens * (1 - safetyMargin)),
|
|
829
|
+
};
|
|
830
|
+
};
|
|
712
831
|
|
|
713
|
-
//
|
|
714
|
-
//
|
|
715
|
-
//
|
|
832
|
+
// Initial value for `createToolExecutor` to read into
|
|
833
|
+
// `ToolContext.overrideProfile`. `resolveCurrentOverrideProfile` refreshes
|
|
834
|
+
// this between model calls so a confirmed profile session opened by a tool
|
|
835
|
+
// applies to later tool executions and nested subagents in the same turn.
|
|
716
836
|
ctx.currentTurnOverrideProfile = turnOverrideProfile;
|
|
717
837
|
|
|
718
838
|
// Capture the turn channel context *before* any awaits so a second
|
|
@@ -1026,6 +1146,7 @@ export async function runAgentLoopImpl(
|
|
|
1026
1146
|
{
|
|
1027
1147
|
message: result.messages[0]!,
|
|
1028
1148
|
sourceChannelTs: null,
|
|
1149
|
+
tagLineProvenance: "none",
|
|
1029
1150
|
},
|
|
1030
1151
|
...retainedRenderedMessages,
|
|
1031
1152
|
],
|
|
@@ -1085,7 +1206,7 @@ export async function runAgentLoopImpl(
|
|
|
1085
1206
|
precomputedEstimate: compactCheck.estimatedTokens,
|
|
1086
1207
|
conversationOriginChannel:
|
|
1087
1208
|
getConversationOriginChannel(ctx.conversationId) ?? undefined,
|
|
1088
|
-
overrideProfile:
|
|
1209
|
+
overrideProfile: resolveCurrentOverrideProfile() ?? null,
|
|
1089
1210
|
};
|
|
1090
1211
|
let compacted: Awaited<
|
|
1091
1212
|
ReturnType<typeof ctx.contextWindowManager.maybeCompact>
|
|
@@ -1450,6 +1571,26 @@ export async function runAgentLoopImpl(
|
|
|
1450
1571
|
}
|
|
1451
1572
|
}
|
|
1452
1573
|
|
|
1574
|
+
// Resolve the effective profile key for this turn and detect changes.
|
|
1575
|
+
// Only inject model_profile into the turn context when the profile
|
|
1576
|
+
// changed since the last turn (or on the first turn of a conversation)
|
|
1577
|
+
// to avoid per-turn token cost.
|
|
1578
|
+
const effectiveProfileKey =
|
|
1579
|
+
turnOverrideProfile ??
|
|
1580
|
+
config.llm.activeProfile ??
|
|
1581
|
+
resolveDefaultProfileKey("mainAgent", config.llm);
|
|
1582
|
+
const lastNotified = turnStartConversation?.lastNotifiedInferenceProfile;
|
|
1583
|
+
let modelProfileStr: string | null = null;
|
|
1584
|
+
if (effectiveProfileKey != null && effectiveProfileKey !== lastNotified) {
|
|
1585
|
+
const profileEntry = config.llm.profiles?.[effectiveProfileKey];
|
|
1586
|
+
const resolved = resolveCallSiteConfig(turnCallSite, config.llm, {
|
|
1587
|
+
overrideProfile: turnOverrideProfile ?? undefined,
|
|
1588
|
+
});
|
|
1589
|
+
const label = profileEntry?.label ?? effectiveProfileKey;
|
|
1590
|
+
modelProfileStr = resolved.model ? `${label} (${resolved.model})` : label;
|
|
1591
|
+
setLastNotifiedInferenceProfile(ctx.conversationId, effectiveProfileKey);
|
|
1592
|
+
}
|
|
1593
|
+
|
|
1453
1594
|
const baseTurnContext = {
|
|
1454
1595
|
timestamp,
|
|
1455
1596
|
interfaceName,
|
|
@@ -1458,6 +1599,7 @@ export async function runAgentLoopImpl(
|
|
|
1458
1599
|
clientTimezone: timezoneContext.clientTimezone,
|
|
1459
1600
|
detectedTimezone: timezoneContext.detectedTimezone,
|
|
1460
1601
|
timeSinceLastMessage,
|
|
1602
|
+
modelProfile: modelProfileStr,
|
|
1461
1603
|
};
|
|
1462
1604
|
const unifiedTurnContextStr = buildUnifiedTurnContextBlock(
|
|
1463
1605
|
isGuardian
|
|
@@ -1614,8 +1756,10 @@ export async function runAgentLoopImpl(
|
|
|
1614
1756
|
nowScratchpad,
|
|
1615
1757
|
voiceCallControlPrompt: ctx.voiceCallControlPrompt ?? null,
|
|
1616
1758
|
transportHints: ctx.transportHints ?? null,
|
|
1617
|
-
slackRuntimeContextNotice: ctx.slackRuntimeContextNotice ?? null,
|
|
1618
1759
|
isNonInteractive: !isInteractiveResolved,
|
|
1760
|
+
isBackgroundConversation: isBackgroundConversationType(
|
|
1761
|
+
turnStartConversation?.conversationType,
|
|
1762
|
+
),
|
|
1619
1763
|
subagentStatusBlock,
|
|
1620
1764
|
slackChronologicalMessages,
|
|
1621
1765
|
slackActiveThreadFocusBlock,
|
|
@@ -1698,15 +1842,9 @@ export async function runAgentLoopImpl(
|
|
|
1698
1842
|
// After runtime injections are applied, estimate the prompt token count
|
|
1699
1843
|
// and proactively invoke the reducer if already above budget. This avoids
|
|
1700
1844
|
// a wasted provider round-trip that would just fail with context_too_large.
|
|
1701
|
-
const
|
|
1702
|
-
const
|
|
1703
|
-
|
|
1704
|
-
// compounds across many messages with tool results.
|
|
1705
|
-
const baseSafetyMargin = overflowRecovery.safetyMarginRatio;
|
|
1706
|
-
const messageCount = ctx.messages.length;
|
|
1707
|
-
const safetyMargin =
|
|
1708
|
-
messageCount > 50 ? Math.max(baseSafetyMargin, 0.15) : baseSafetyMargin;
|
|
1709
|
-
const preflightBudget = Math.floor(providerMaxTokens * (1 - safetyMargin));
|
|
1845
|
+
const initialContextBudget = resolveCurrentContextBudget();
|
|
1846
|
+
const overflowRecovery = initialContextBudget.overflowRecovery;
|
|
1847
|
+
const preflightBudget = initialContextBudget.preflightBudget;
|
|
1710
1848
|
let reducerState: ReducerState | undefined;
|
|
1711
1849
|
|
|
1712
1850
|
const toolTokenBudget = ctx.agentLoop.getToolTokenBudget(runMessages);
|
|
@@ -1783,10 +1921,10 @@ export async function runAgentLoopImpl(
|
|
|
1783
1921
|
runMessages,
|
|
1784
1922
|
systemPrompt: ctx.systemPrompt,
|
|
1785
1923
|
providerName: estimationProviderName,
|
|
1786
|
-
contextWindow:
|
|
1924
|
+
contextWindow: resolveCurrentContextWindowConfig(),
|
|
1787
1925
|
preflightBudget,
|
|
1788
1926
|
toolTokenBudget,
|
|
1789
|
-
maxAttempts: overflowRecovery.maxAttempts,
|
|
1927
|
+
maxAttempts: resolveCurrentContextBudget().overflowRecovery.maxAttempts,
|
|
1790
1928
|
abortSignal: abortController.signal,
|
|
1791
1929
|
compactFn: async (msgs, signal, opts) => {
|
|
1792
1930
|
// Route the reducer's forced-compaction tier through the
|
|
@@ -1816,7 +1954,7 @@ export async function runAgentLoopImpl(
|
|
|
1816
1954
|
signal,
|
|
1817
1955
|
options: {
|
|
1818
1956
|
...(opts ?? {}),
|
|
1819
|
-
overrideProfile:
|
|
1957
|
+
overrideProfile: resolveCurrentOverrideProfile() ?? null,
|
|
1820
1958
|
},
|
|
1821
1959
|
},
|
|
1822
1960
|
buildPluginTurnContext(ctx, reqId),
|
|
@@ -2070,8 +2208,9 @@ export async function runAgentLoopImpl(
|
|
|
2070
2208
|
};
|
|
2071
2209
|
const eventHandler = (event: AgentEvent) =>
|
|
2072
2210
|
dispatchAgentEvent(state, deps, event);
|
|
2073
|
-
|
|
2074
|
-
|
|
2211
|
+
emitTerminalExit = async (reason: AgentLoopExitReason): Promise<void> => {
|
|
2212
|
+
await eventHandler({ type: "agent_loop_exit", reason });
|
|
2213
|
+
};
|
|
2075
2214
|
|
|
2076
2215
|
const onCheckpoint = async (
|
|
2077
2216
|
checkpoint: CheckpointInfo,
|
|
@@ -2080,6 +2219,7 @@ export async function runAgentLoopImpl(
|
|
|
2080
2219
|
|
|
2081
2220
|
if (ctx.canHandoffAtCheckpoint()) {
|
|
2082
2221
|
yieldedForHandoff = true;
|
|
2222
|
+
pendingCheckpointYield = "handoff";
|
|
2083
2223
|
return "yield";
|
|
2084
2224
|
}
|
|
2085
2225
|
|
|
@@ -2087,7 +2227,8 @@ export async function runAgentLoopImpl(
|
|
|
2087
2227
|
// yield if we're approaching the preflight budget. This lets the
|
|
2088
2228
|
// conversation-agent-loop run compaction before the provider rejects.
|
|
2089
2229
|
if (overflowRecovery.enabled) {
|
|
2090
|
-
const midLoopThreshold =
|
|
2230
|
+
const midLoopThreshold =
|
|
2231
|
+
resolveCurrentContextBudget().preflightBudget * 0.85;
|
|
2091
2232
|
const estimated = await runTokenEstimatePipeline(checkpoint.history);
|
|
2092
2233
|
if (estimated > midLoopThreshold) {
|
|
2093
2234
|
rlog.warn(
|
|
@@ -2095,6 +2236,7 @@ export async function runAgentLoopImpl(
|
|
|
2095
2236
|
"Token estimate approaching budget — yielding for compaction",
|
|
2096
2237
|
);
|
|
2097
2238
|
yieldedForBudget = true;
|
|
2239
|
+
pendingCheckpointYield = "budget";
|
|
2098
2240
|
return "yield";
|
|
2099
2241
|
}
|
|
2100
2242
|
}
|
|
@@ -2123,7 +2265,9 @@ export async function runAgentLoopImpl(
|
|
|
2123
2265
|
turnCallSite,
|
|
2124
2266
|
loopTurnCtx,
|
|
2125
2267
|
turnOverrideProfile,
|
|
2126
|
-
|
|
2268
|
+
resolveCurrentMaxInputTokens(),
|
|
2269
|
+
resolveCurrentOverrideProfile,
|
|
2270
|
+
resolveCurrentMaxInputTokens,
|
|
2127
2271
|
);
|
|
2128
2272
|
|
|
2129
2273
|
rlog.info(
|
|
@@ -2131,6 +2275,11 @@ export async function runAgentLoopImpl(
|
|
|
2131
2275
|
"Agent loop run completed",
|
|
2132
2276
|
);
|
|
2133
2277
|
|
|
2278
|
+
if (yieldedForHandoff) {
|
|
2279
|
+
await emitTerminalExit?.("checkpoint_handoff");
|
|
2280
|
+
pendingCheckpointYield = null;
|
|
2281
|
+
}
|
|
2282
|
+
|
|
2134
2283
|
// ── Proactive mid-loop compaction ───────────────────────────────
|
|
2135
2284
|
// When the agent loop yielded because the token budget check in
|
|
2136
2285
|
// onCheckpoint detected approaching limits, run compaction on the
|
|
@@ -2140,12 +2289,14 @@ export async function runAgentLoopImpl(
|
|
|
2140
2289
|
let midLoopCompactAttempts = 0;
|
|
2141
2290
|
while (
|
|
2142
2291
|
yieldedForBudget &&
|
|
2143
|
-
midLoopCompactAttempts <
|
|
2292
|
+
midLoopCompactAttempts <
|
|
2293
|
+
resolveCurrentContextBudget().overflowRecovery.maxAttempts &&
|
|
2144
2294
|
!state.contextTooLargeDetected &&
|
|
2145
2295
|
!abortController.signal.aborted
|
|
2146
2296
|
) {
|
|
2147
2297
|
midLoopCompactAttempts++;
|
|
2148
2298
|
yieldedForBudget = false;
|
|
2299
|
+
pendingCheckpointYield = null;
|
|
2149
2300
|
|
|
2150
2301
|
rlog.info(
|
|
2151
2302
|
{ phase: "mid-loop-compact" },
|
|
@@ -2187,10 +2338,11 @@ export async function runAgentLoopImpl(
|
|
|
2187
2338
|
options: {
|
|
2188
2339
|
lastCompactedAt: ctx.contextCompactedAt ?? undefined,
|
|
2189
2340
|
force: true,
|
|
2190
|
-
targetInputTokensOverride:
|
|
2341
|
+
targetInputTokensOverride:
|
|
2342
|
+
resolveCurrentContextBudget().preflightBudget,
|
|
2191
2343
|
conversationOriginChannel:
|
|
2192
2344
|
getConversationOriginChannel(ctx.conversationId) ?? undefined,
|
|
2193
|
-
overrideProfile:
|
|
2345
|
+
overrideProfile: resolveCurrentOverrideProfile() ?? null,
|
|
2194
2346
|
},
|
|
2195
2347
|
},
|
|
2196
2348
|
buildPluginTurnContext(ctx, reqId),
|
|
@@ -2276,7 +2428,9 @@ export async function runAgentLoopImpl(
|
|
|
2276
2428
|
turnCallSite,
|
|
2277
2429
|
loopTurnCtx,
|
|
2278
2430
|
turnOverrideProfile,
|
|
2279
|
-
|
|
2431
|
+
resolveCurrentMaxInputTokens(),
|
|
2432
|
+
resolveCurrentOverrideProfile,
|
|
2433
|
+
resolveCurrentMaxInputTokens,
|
|
2280
2434
|
);
|
|
2281
2435
|
}
|
|
2282
2436
|
|
|
@@ -2290,7 +2444,8 @@ export async function runAgentLoopImpl(
|
|
|
2290
2444
|
{
|
|
2291
2445
|
phase: "mid-loop-compact",
|
|
2292
2446
|
midLoopCompactAttempts,
|
|
2293
|
-
maxAttempts:
|
|
2447
|
+
maxAttempts:
|
|
2448
|
+
resolveCurrentContextBudget().overflowRecovery.maxAttempts,
|
|
2294
2449
|
},
|
|
2295
2450
|
"Mid-loop compaction exhausted all attempts — escalating to convergence loop",
|
|
2296
2451
|
);
|
|
@@ -2333,7 +2488,9 @@ export async function runAgentLoopImpl(
|
|
|
2333
2488
|
turnCallSite,
|
|
2334
2489
|
loopTurnCtx,
|
|
2335
2490
|
turnOverrideProfile,
|
|
2336
|
-
|
|
2491
|
+
resolveCurrentMaxInputTokens(),
|
|
2492
|
+
resolveCurrentOverrideProfile,
|
|
2493
|
+
resolveCurrentMaxInputTokens,
|
|
2337
2494
|
);
|
|
2338
2495
|
|
|
2339
2496
|
if (state.orderingErrorDetected) {
|
|
@@ -2402,7 +2559,9 @@ export async function runAgentLoopImpl(
|
|
|
2402
2559
|
turnCallSite,
|
|
2403
2560
|
loopTurnCtx,
|
|
2404
2561
|
turnOverrideProfile,
|
|
2405
|
-
|
|
2562
|
+
resolveCurrentMaxInputTokens(),
|
|
2563
|
+
resolveCurrentOverrideProfile,
|
|
2564
|
+
resolveCurrentMaxInputTokens,
|
|
2406
2565
|
);
|
|
2407
2566
|
if (state.imageTooLargeDetected) {
|
|
2408
2567
|
rlog.error(
|
|
@@ -2473,18 +2632,21 @@ export async function runAgentLoopImpl(
|
|
|
2473
2632
|
toolTokenBudget,
|
|
2474
2633
|
},
|
|
2475
2634
|
);
|
|
2476
|
-
|
|
2635
|
+
const convergenceBudget = resolveCurrentContextBudget();
|
|
2636
|
+
let correctedTarget = convergenceBudget.preflightBudget;
|
|
2477
2637
|
if (actualTokens && estimatedTokensAtOverflow > 0) {
|
|
2478
2638
|
const estimationErrorRatio = actualTokens / estimatedTokensAtOverflow;
|
|
2479
2639
|
if (estimationErrorRatio > 1.0) {
|
|
2480
|
-
correctedTarget = Math.floor(
|
|
2640
|
+
correctedTarget = Math.floor(
|
|
2641
|
+
convergenceBudget.preflightBudget / estimationErrorRatio,
|
|
2642
|
+
);
|
|
2481
2643
|
rlog.warn(
|
|
2482
2644
|
{
|
|
2483
2645
|
phase: "convergence",
|
|
2484
2646
|
actualTokens,
|
|
2485
2647
|
estimatedTokens: estimatedTokensAtOverflow,
|
|
2486
2648
|
estimationErrorRatio: estimationErrorRatio.toFixed(2),
|
|
2487
|
-
preflightBudget,
|
|
2649
|
+
preflightBudget: convergenceBudget.preflightBudget,
|
|
2488
2650
|
correctedTarget,
|
|
2489
2651
|
},
|
|
2490
2652
|
"Adjusting compaction target based on observed estimation error",
|
|
@@ -2509,11 +2671,11 @@ export async function runAgentLoopImpl(
|
|
|
2509
2671
|
systemPrompt: ctx.systemPrompt,
|
|
2510
2672
|
tools: undefined,
|
|
2511
2673
|
compaction: emergencyConfig,
|
|
2512
|
-
maxInputTokens:
|
|
2674
|
+
maxInputTokens: resolveCurrentMaxInputTokens(),
|
|
2513
2675
|
previousEstimatedInputTokens: estimatedTokensAtOverflow,
|
|
2514
2676
|
force: true,
|
|
2515
2677
|
signal: abortController.signal,
|
|
2516
|
-
overrideProfile:
|
|
2678
|
+
overrideProfile: resolveCurrentOverrideProfile() ?? null,
|
|
2517
2679
|
nonPersistedPrefixCount:
|
|
2518
2680
|
ctx.contextWindowManager.nonPersistedPrefixCount,
|
|
2519
2681
|
});
|
|
@@ -2551,7 +2713,7 @@ export async function runAgentLoopImpl(
|
|
|
2551
2713
|
}
|
|
2552
2714
|
|
|
2553
2715
|
let convergenceAttempts = 0;
|
|
2554
|
-
const maxAttempts = overflowRecovery.maxAttempts;
|
|
2716
|
+
const maxAttempts = convergenceBudget.overflowRecovery.maxAttempts;
|
|
2555
2717
|
|
|
2556
2718
|
while (
|
|
2557
2719
|
state.contextTooLargeDetected &&
|
|
@@ -2580,7 +2742,7 @@ export async function runAgentLoopImpl(
|
|
|
2580
2742
|
{
|
|
2581
2743
|
providerName: estimationProviderName,
|
|
2582
2744
|
systemPrompt: ctx.systemPrompt,
|
|
2583
|
-
contextWindow:
|
|
2745
|
+
contextWindow: resolveCurrentContextWindowConfig(),
|
|
2584
2746
|
targetTokens: correctedTarget,
|
|
2585
2747
|
toolTokenBudget,
|
|
2586
2748
|
},
|
|
@@ -2588,7 +2750,7 @@ export async function runAgentLoopImpl(
|
|
|
2588
2750
|
(msgs, signal, opts) =>
|
|
2589
2751
|
ctx.contextWindowManager.maybeCompact(msgs, signal!, {
|
|
2590
2752
|
...(opts ?? {}),
|
|
2591
|
-
overrideProfile:
|
|
2753
|
+
overrideProfile: resolveCurrentOverrideProfile() ?? null,
|
|
2592
2754
|
}),
|
|
2593
2755
|
abortController.signal,
|
|
2594
2756
|
);
|
|
@@ -2664,7 +2826,9 @@ export async function runAgentLoopImpl(
|
|
|
2664
2826
|
turnCallSite,
|
|
2665
2827
|
loopTurnCtx,
|
|
2666
2828
|
turnOverrideProfile,
|
|
2667
|
-
|
|
2829
|
+
resolveCurrentMaxInputTokens(),
|
|
2830
|
+
resolveCurrentOverrideProfile,
|
|
2831
|
+
resolveCurrentMaxInputTokens,
|
|
2668
2832
|
);
|
|
2669
2833
|
|
|
2670
2834
|
// If the rerun still yields at checkpoint, the turn is still
|
|
@@ -2742,7 +2906,7 @@ export async function runAgentLoopImpl(
|
|
|
2742
2906
|
force: true,
|
|
2743
2907
|
minKeepRecentUserTurns: 0,
|
|
2744
2908
|
targetInputTokensOverride: correctedTarget,
|
|
2745
|
-
overrideProfile:
|
|
2909
|
+
overrideProfile: resolveCurrentOverrideProfile() ?? null,
|
|
2746
2910
|
},
|
|
2747
2911
|
},
|
|
2748
2912
|
buildPluginTurnContext(ctx, reqId),
|
|
@@ -2825,7 +2989,9 @@ export async function runAgentLoopImpl(
|
|
|
2825
2989
|
turnCallSite,
|
|
2826
2990
|
loopTurnCtx,
|
|
2827
2991
|
turnOverrideProfile,
|
|
2828
|
-
|
|
2992
|
+
resolveCurrentMaxInputTokens(),
|
|
2993
|
+
resolveCurrentOverrideProfile,
|
|
2994
|
+
resolveCurrentMaxInputTokens,
|
|
2829
2995
|
);
|
|
2830
2996
|
}
|
|
2831
2997
|
// action === "fail_gracefully" falls through to the final error below
|
|
@@ -2837,6 +3003,8 @@ export async function runAgentLoopImpl(
|
|
|
2837
3003
|
new Error("context_length_exceeded"),
|
|
2838
3004
|
{ phase: "agent_loop" },
|
|
2839
3005
|
);
|
|
3006
|
+
await emitTerminalExit?.("context_too_large");
|
|
3007
|
+
pendingCheckpointYield = null;
|
|
2840
3008
|
onEvent(buildConversationErrorMessage(ctx.conversationId, classified));
|
|
2841
3009
|
}
|
|
2842
3010
|
}
|
|
@@ -2942,7 +3110,7 @@ export async function runAgentLoopImpl(
|
|
|
2942
3110
|
const errorAssistantMessage = createAssistantMessage(
|
|
2943
3111
|
state.providerErrorUserMessage,
|
|
2944
3112
|
);
|
|
2945
|
-
await runPipeline<PersistArgs, PersistResult>(
|
|
3113
|
+
const errorPersistResult = (await runPipeline<PersistArgs, PersistResult>(
|
|
2946
3114
|
"persistence",
|
|
2947
3115
|
getMiddlewaresFor("persistence"),
|
|
2948
3116
|
defaultPersistenceTerminal,
|
|
@@ -2955,9 +3123,30 @@ export async function runAgentLoopImpl(
|
|
|
2955
3123
|
},
|
|
2956
3124
|
buildPluginTurnContext(ctx, reqId),
|
|
2957
3125
|
DEFAULT_TIMEOUTS.persistence,
|
|
2958
|
-
);
|
|
3126
|
+
)) as PersistAddResult;
|
|
2959
3127
|
persistedErrorAssistantMessage = true;
|
|
2960
3128
|
newMessages.push(errorAssistantMessage);
|
|
3129
|
+
// Pipe the just-assigned message id into any orphaned LLM request log
|
|
3130
|
+
// row(s) for this turn. The success path links rows via
|
|
3131
|
+
// `handleMessageComplete` -> `backfillMessageIdOnLogs`, but provider-
|
|
3132
|
+
// failure turns never fire `message_complete` (the synthetic assistant
|
|
3133
|
+
// message is persisted directly above), so without this call the rows
|
|
3134
|
+
// from `handleProviderError` stay with `message_id IS NULL` and a
|
|
3135
|
+
// later turn's backfill sweep would wrong-attach them to that turn's
|
|
3136
|
+
// assistant message. Scope is per-conversation, so concurrent runs on
|
|
3137
|
+
// other conversations cannot collide. Non-fatal — a DB hiccup must
|
|
3138
|
+
// not escalate a provider rejection into a turn-level throw.
|
|
3139
|
+
try {
|
|
3140
|
+
backfillMessageIdOnLogs(
|
|
3141
|
+
ctx.conversationId,
|
|
3142
|
+
errorPersistResult.message.id,
|
|
3143
|
+
);
|
|
3144
|
+
} catch (err) {
|
|
3145
|
+
rlog.warn(
|
|
3146
|
+
{ err },
|
|
3147
|
+
"Failed to backfill message_id on provider-error LLM request logs (non-fatal)",
|
|
3148
|
+
);
|
|
3149
|
+
}
|
|
2961
3150
|
// Do NOT send assistant_text_delta here — handleProviderError already
|
|
2962
3151
|
// emitted a conversation_error event for this same error text, and the
|
|
2963
3152
|
// client renders it as an InlineChatErrorAlert. Sending a text delta
|
|
@@ -3014,11 +3203,11 @@ export async function runAgentLoopImpl(
|
|
|
3014
3203
|
state.exchangeLlmCallCount,
|
|
3015
3204
|
{
|
|
3016
3205
|
tokens: state.lastCallInputTokens,
|
|
3017
|
-
maxTokens:
|
|
3206
|
+
maxTokens: resolveCurrentMaxInputTokens(),
|
|
3018
3207
|
},
|
|
3019
3208
|
{
|
|
3020
3209
|
callSite: turnCallSite,
|
|
3021
|
-
overrideProfile:
|
|
3210
|
+
overrideProfile: resolveCurrentOverrideProfile() ?? null,
|
|
3022
3211
|
},
|
|
3023
3212
|
);
|
|
3024
3213
|
|
|
@@ -3078,6 +3267,10 @@ export async function runAgentLoopImpl(
|
|
|
3078
3267
|
|
|
3079
3268
|
// Re-check: the user may have cancelled during attachment resolution
|
|
3080
3269
|
if (abortController.signal.aborted) {
|
|
3270
|
+
if (pendingCheckpointYield === "budget") {
|
|
3271
|
+
await emitTerminalExit?.("aborted_after_checkpoint");
|
|
3272
|
+
pendingCheckpointYield = null;
|
|
3273
|
+
}
|
|
3081
3274
|
ctx.emitActivityState("idle", "generation_cancelled", "global", reqId);
|
|
3082
3275
|
ctx.traceEmitter.emit(
|
|
3083
3276
|
"generation_cancelled",
|
|
@@ -3219,6 +3412,10 @@ export async function runAgentLoopImpl(
|
|
|
3219
3412
|
aborted: abortController.signal.aborted,
|
|
3220
3413
|
};
|
|
3221
3414
|
if (isUserCancellation(err, errorCtx)) {
|
|
3415
|
+
if (pendingCheckpointYield === "budget") {
|
|
3416
|
+
await emitTerminalExit?.("aborted_after_checkpoint");
|
|
3417
|
+
pendingCheckpointYield = null;
|
|
3418
|
+
}
|
|
3222
3419
|
ctx.emitActivityState("idle", "generation_cancelled", "global", reqId);
|
|
3223
3420
|
rlog.info("Generation cancelled by user");
|
|
3224
3421
|
ctx.traceEmitter.emit(
|
|
@@ -3311,7 +3508,6 @@ export async function runAgentLoopImpl(
|
|
|
3311
3508
|
ctx.diskPressureCleanupModeActive = false;
|
|
3312
3509
|
ctx.preactivatedSkillIds = undefined;
|
|
3313
3510
|
ctx.currentTurnOverrideProfile = undefined;
|
|
3314
|
-
ctx.slackRuntimeContextNotice = undefined;
|
|
3315
3511
|
// Channel command intents (e.g. Telegram /start) are single-turn metadata.
|
|
3316
3512
|
// Clear at turn end so they never leak into subsequent unrelated messages.
|
|
3317
3513
|
ctx.commandIntent = undefined;
|