@vellumai/assistant 0.8.3 → 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/docker-entrypoint.sh +0 -1
- package/node_modules/@vellumai/gateway-client/src/types.ts +2 -0
- package/openapi.yaml +610 -16
- package/package.json +1 -1
- package/src/__tests__/agent-loop-exit-reason.test.ts +4 -5
- package/src/__tests__/agent-loop-override-profile.test.ts +1 -1
- 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__/config-watcher.test.ts +1 -1
- package/src/__tests__/context-token-estimator.test.ts +91 -1
- 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 +25 -7
- 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-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 +264 -81
- 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__/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__/first-greeting.test.ts +23 -2
- package/src/__tests__/headless-browser-navigate.test.ts +172 -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-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-chain.test.ts +2 -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__/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-context-normalization.test.ts +0 -2
- package/src/__tests__/llm-resolver.test.ts +85 -1
- package/src/__tests__/log-export-routes.test.ts +99 -2
- package/src/__tests__/message-queue-steer.test.ts +114 -0
- package/src/__tests__/openai-provider.test.ts +105 -0
- package/src/__tests__/openai-responses-provider.test.ts +4 -4
- 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.test.ts +0 -3
- package/src/__tests__/plugin-source-watcher.test.ts +302 -0
- 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__/server-history-render.test.ts +83 -4
- package/src/__tests__/steer-tool-repair.test.ts +249 -0
- package/src/__tests__/system-prompt.test.ts +51 -28
- 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-088-deprecate-background-conversation-override.test.ts +158 -0
- package/src/agent/attachments.ts +1 -0
- package/src/agent/loop.ts +57 -20
- 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/cli/commands/__tests__/conversations-slack.test.ts +572 -0
- package/src/cli/commands/__tests__/memory-v2.test.ts +9 -12
- 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 +24 -2
- package/src/cli/utils/conversation-id.ts +17 -5
- package/src/config/bundled-skills/app-builder/SKILL.md +2 -2
- 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/schedule/SKILL.md +8 -0
- package/src/config/bundled-tool-registry.ts +22 -12
- package/src/config/call-site-defaults.ts +19 -0
- package/src/config/feature-flag-registry.json +99 -3
- package/src/config/llm-resolver.ts +16 -2
- package/src/config/schemas/__tests__/memory-v2.test.ts +4 -0
- package/src/config/schemas/call-site-catalog.ts +21 -0
- package/src/config/schemas/llm.ts +3 -0
- package/src/config/schemas/memory-v2.ts +48 -1
- package/src/context/compactor.ts +8 -1
- package/src/context/token-estimator.ts +47 -4
- package/src/context/window-manager.ts +25 -0
- package/src/credential-health/credential-health-service.ts +34 -19
- 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 +153 -23
- package/src/daemon/conversation-agent-loop.ts +223 -54
- 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 +135 -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 -5
- package/src/daemon/first-greeting.ts +10 -0
- package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +498 -0
- package/src/daemon/handlers/config-a2a.ts +160 -0
- package/src/daemon/handlers/config-model.test.ts +1 -0
- package/src/daemon/handlers/conversations.ts +79 -0
- package/src/daemon/handlers/shared.ts +92 -29
- 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-transfer-proxy.ts +1 -1
- package/src/daemon/lifecycle.ts +18 -4
- 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/surfaces.ts +3 -1
- package/src/daemon/message-types/web-activity.ts +57 -0
- package/src/daemon/plugin-source-watcher.ts +135 -3
- package/src/daemon/process-message.ts +69 -12
- package/src/daemon/query-complexity-router.ts +75 -0
- package/src/daemon/trust-context.ts +6 -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/heartbeat/__tests__/heartbeat-service.test.ts +0 -1
- package/src/heartbeat/heartbeat-service.ts +1 -0
- package/src/home/__tests__/suggested-prompts.test.ts +33 -2
- package/src/home/feed-types.ts +6 -1
- 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/memory/__tests__/jobs-worker-v2-schedule.test.ts +135 -2
- package/src/memory/__tests__/memory-retrospective-job.test.ts +320 -6
- package/src/memory/conversation-crud.ts +133 -43
- package/src/memory/db-init.ts +16 -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/jobs-worker.ts +21 -1
- package/src/memory/memory-retrospective-constants.ts +28 -0
- package/src/memory/memory-retrospective-enqueue.ts +3 -2
- package/src/memory/memory-retrospective-job.ts +408 -18
- 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/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 +17 -0
- package/src/memory/migrations/registry.ts +25 -0
- package/src/memory/onboarding-events-store.ts +7 -0
- package/src/memory/schema/calls.ts +1 -0
- package/src/memory/schema/conversations.ts +3 -0
- package/src/memory/schema/infrastructure.ts +1 -0
- package/src/memory/v2/__tests__/injection-events.test.ts +318 -0
- package/src/memory/v2/__tests__/injection.test.ts +31 -14
- 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/consolidation-job.ts +14 -0
- package/src/memory/v2/injection-events.ts +101 -0
- package/src/memory/v2/injection.ts +21 -10
- package/src/memory/v2/page-index.ts +209 -7
- package/src/memory/v2/page-store.ts +18 -0
- package/src/memory/v2/router.ts +209 -55
- package/src/messaging/providers/index.ts +7 -1
- 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__/emit-signal-home-feed.test.ts +4 -1
- package/src/notifications/__tests__/home-feed-side-effect.test.ts +116 -54
- package/src/notifications/conversation-seed-composer.ts +14 -2
- package/src/notifications/deferred-emit.ts +135 -0
- package/src/notifications/emit-signal.ts +9 -1
- package/src/notifications/home-feed-side-effect.ts +60 -30
- 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/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 +82 -9
- package/src/prompts/__tests__/system-prompt.test.ts +46 -2
- package/src/prompts/normalize-onboarding.ts +40 -0
- package/src/prompts/sections.ts +32 -14
- package/src/prompts/system-prompt.ts +105 -68
- package/src/prompts/template-detection.ts +37 -0
- package/src/prompts/templates/BOOTSTRAP-CONTENT-AUTOMATION.md +141 -0
- package/src/prompts/templates/BOOTSTRAP.md +8 -0
- package/src/prompts/templates/VOICE.md +3 -0
- package/src/prompts/templates/system-sections.ts +53 -3
- package/src/providers/anthropic/client.ts +132 -5
- package/src/providers/fireworks/client.ts +20 -2
- 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/adapter-factory.ts +15 -1
- package/src/providers/inference/auth.ts +3 -3
- package/src/providers/inference/codex-token-refresh.ts +128 -0
- package/src/providers/inference/resolve-auth.ts +49 -6
- package/src/providers/model-catalog.ts +48 -1
- package/src/providers/openai/chat-completions-provider.ts +57 -20
- package/src/providers/openai/responses-provider.ts +9 -3
- package/src/providers/openrouter/client.ts +5 -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 +151 -56
- package/src/runtime/auth/route-policy.ts +7 -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-types.ts +7 -4
- package/src/runtime/pending-interactions.ts +51 -8
- package/src/runtime/routes/__tests__/content-source-routes.test.ts +162 -0
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +55 -1
- 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/chatgpt-subscription-auth-routes.ts +246 -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 +60 -1
- package/src/runtime/routes/conversation-routes.ts +281 -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 +12 -4
- package/src/runtime/routes/inference-provider-connection-routes.ts +63 -7
- package/src/runtime/routes/integrations/a2a.ts +60 -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/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/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/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/terminal/safe-env.ts +3 -2
- package/src/tools/tool-approval-handler.ts +19 -12
- package/src/tools/types.ts +4 -0
- 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/088-deprecate-background-conversation-override.ts +103 -0
- package/src/workspace/migrations/registry.ts +2 -0
- 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/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";
|
|
@@ -215,6 +222,10 @@ import {
|
|
|
215
222
|
SYNC_TAGS,
|
|
216
223
|
} from "./message-types/sync.js";
|
|
217
224
|
import { parseActualTokensFromError } from "./parse-actual-tokens-from-error.js";
|
|
225
|
+
import {
|
|
226
|
+
classifyQueryComplexity,
|
|
227
|
+
complexityTierToProfileKey,
|
|
228
|
+
} from "./query-complexity-router.js";
|
|
218
229
|
import type { TraceEmitter } from "./trace-emitter.js";
|
|
219
230
|
import type { TrustContext } from "./trust-context.js";
|
|
220
231
|
import { stripHistoricalWebSearchResults } from "./web-search-history.js";
|
|
@@ -521,12 +532,11 @@ export interface AgentLoopConversationContext {
|
|
|
521
532
|
/** Per-turn snapshot of channelCapabilities, frozen at message-processing start. */
|
|
522
533
|
currentTurnChannelCapabilities?: ChannelCapabilities;
|
|
523
534
|
/**
|
|
524
|
-
*
|
|
535
|
+
* Current inference-profile override for this turn. Read by
|
|
525
536
|
* `createToolExecutor` so `ToolContext.overrideProfile` carries the same
|
|
526
|
-
* profile the agent loop is sending to the provider.
|
|
527
|
-
*
|
|
528
|
-
*
|
|
529
|
-
* 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.
|
|
530
540
|
*/
|
|
531
541
|
currentTurnOverrideProfile?: string;
|
|
532
542
|
commandIntent?: { type: string; payload?: string; languageCode?: string };
|
|
@@ -536,7 +546,6 @@ export interface AgentLoopConversationContext {
|
|
|
536
546
|
assistantId?: string;
|
|
537
547
|
voiceCallControlPrompt?: string;
|
|
538
548
|
transportHints?: string[];
|
|
539
|
-
slackRuntimeContextNotice?: string;
|
|
540
549
|
clientTimezone?: string;
|
|
541
550
|
|
|
542
551
|
readonly coreToolNames: Set<string>;
|
|
@@ -670,6 +679,11 @@ export async function runAgentLoopImpl(
|
|
|
670
679
|
requestId: reqId,
|
|
671
680
|
});
|
|
672
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;
|
|
673
687
|
|
|
674
688
|
// Default user-initiated turns to the `mainAgent` call site. Other
|
|
675
689
|
// invocation contexts (heartbeat, filing, analyze, etc.) pass their own
|
|
@@ -691,31 +705,134 @@ export async function runAgentLoopImpl(
|
|
|
691
705
|
// spawned subagent's background conversation) wins over the row read
|
|
692
706
|
// so the agent loop's own background-skip rule doesn't zero out an
|
|
693
707
|
// explicitly inherited override.
|
|
694
|
-
const
|
|
708
|
+
const userExplicitOverride =
|
|
695
709
|
options?.overrideProfile ??
|
|
696
710
|
getConversationOverrideProfileFromRow(turnStartConversation);
|
|
697
711
|
|
|
698
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
|
+
|
|
699
759
|
const effectiveContextWindow = resolveEffectiveContextWindow({
|
|
700
760
|
llm: config.llm,
|
|
701
761
|
callSite: turnCallSite,
|
|
702
762
|
overrideProfile: turnOverrideProfile ?? undefined,
|
|
703
763
|
});
|
|
704
|
-
|
|
764
|
+
let currentEffectiveContextWindow: EffectiveContextWindow =
|
|
765
|
+
effectiveContextWindow;
|
|
766
|
+
let currentContextWindowConfig = contextWindowConfigFromEffective(
|
|
705
767
|
resolveCallSiteConfig(turnCallSite, config.llm, {
|
|
706
768
|
overrideProfile: turnOverrideProfile ?? undefined,
|
|
707
769
|
}).contextWindow,
|
|
708
|
-
|
|
770
|
+
currentEffectiveContextWindow,
|
|
709
771
|
);
|
|
710
|
-
|
|
772
|
+
const contextWindowManager =
|
|
711
773
|
ctx.contextWindowManager as ContextWindowManager & {
|
|
712
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
|
+
);
|
|
713
799
|
}
|
|
714
|
-
|
|
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
|
+
};
|
|
715
831
|
|
|
716
|
-
//
|
|
717
|
-
//
|
|
718
|
-
//
|
|
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.
|
|
719
836
|
ctx.currentTurnOverrideProfile = turnOverrideProfile;
|
|
720
837
|
|
|
721
838
|
// Capture the turn channel context *before* any awaits so a second
|
|
@@ -1029,6 +1146,7 @@ export async function runAgentLoopImpl(
|
|
|
1029
1146
|
{
|
|
1030
1147
|
message: result.messages[0]!,
|
|
1031
1148
|
sourceChannelTs: null,
|
|
1149
|
+
tagLineProvenance: "none",
|
|
1032
1150
|
},
|
|
1033
1151
|
...retainedRenderedMessages,
|
|
1034
1152
|
],
|
|
@@ -1088,7 +1206,7 @@ export async function runAgentLoopImpl(
|
|
|
1088
1206
|
precomputedEstimate: compactCheck.estimatedTokens,
|
|
1089
1207
|
conversationOriginChannel:
|
|
1090
1208
|
getConversationOriginChannel(ctx.conversationId) ?? undefined,
|
|
1091
|
-
overrideProfile:
|
|
1209
|
+
overrideProfile: resolveCurrentOverrideProfile() ?? null,
|
|
1092
1210
|
};
|
|
1093
1211
|
let compacted: Awaited<
|
|
1094
1212
|
ReturnType<typeof ctx.contextWindowManager.maybeCompact>
|
|
@@ -1453,6 +1571,26 @@ export async function runAgentLoopImpl(
|
|
|
1453
1571
|
}
|
|
1454
1572
|
}
|
|
1455
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
|
+
|
|
1456
1594
|
const baseTurnContext = {
|
|
1457
1595
|
timestamp,
|
|
1458
1596
|
interfaceName,
|
|
@@ -1461,6 +1599,7 @@ export async function runAgentLoopImpl(
|
|
|
1461
1599
|
clientTimezone: timezoneContext.clientTimezone,
|
|
1462
1600
|
detectedTimezone: timezoneContext.detectedTimezone,
|
|
1463
1601
|
timeSinceLastMessage,
|
|
1602
|
+
modelProfile: modelProfileStr,
|
|
1464
1603
|
};
|
|
1465
1604
|
const unifiedTurnContextStr = buildUnifiedTurnContextBlock(
|
|
1466
1605
|
isGuardian
|
|
@@ -1617,7 +1756,6 @@ export async function runAgentLoopImpl(
|
|
|
1617
1756
|
nowScratchpad,
|
|
1618
1757
|
voiceCallControlPrompt: ctx.voiceCallControlPrompt ?? null,
|
|
1619
1758
|
transportHints: ctx.transportHints ?? null,
|
|
1620
|
-
slackRuntimeContextNotice: ctx.slackRuntimeContextNotice ?? null,
|
|
1621
1759
|
isNonInteractive: !isInteractiveResolved,
|
|
1622
1760
|
isBackgroundConversation: isBackgroundConversationType(
|
|
1623
1761
|
turnStartConversation?.conversationType,
|
|
@@ -1704,15 +1842,9 @@ export async function runAgentLoopImpl(
|
|
|
1704
1842
|
// After runtime injections are applied, estimate the prompt token count
|
|
1705
1843
|
// and proactively invoke the reducer if already above budget. This avoids
|
|
1706
1844
|
// a wasted provider round-trip that would just fail with context_too_large.
|
|
1707
|
-
const
|
|
1708
|
-
const
|
|
1709
|
-
|
|
1710
|
-
// compounds across many messages with tool results.
|
|
1711
|
-
const baseSafetyMargin = overflowRecovery.safetyMarginRatio;
|
|
1712
|
-
const messageCount = ctx.messages.length;
|
|
1713
|
-
const safetyMargin =
|
|
1714
|
-
messageCount > 50 ? Math.max(baseSafetyMargin, 0.15) : baseSafetyMargin;
|
|
1715
|
-
const preflightBudget = Math.floor(providerMaxTokens * (1 - safetyMargin));
|
|
1845
|
+
const initialContextBudget = resolveCurrentContextBudget();
|
|
1846
|
+
const overflowRecovery = initialContextBudget.overflowRecovery;
|
|
1847
|
+
const preflightBudget = initialContextBudget.preflightBudget;
|
|
1716
1848
|
let reducerState: ReducerState | undefined;
|
|
1717
1849
|
|
|
1718
1850
|
const toolTokenBudget = ctx.agentLoop.getToolTokenBudget(runMessages);
|
|
@@ -1789,10 +1921,10 @@ export async function runAgentLoopImpl(
|
|
|
1789
1921
|
runMessages,
|
|
1790
1922
|
systemPrompt: ctx.systemPrompt,
|
|
1791
1923
|
providerName: estimationProviderName,
|
|
1792
|
-
contextWindow:
|
|
1924
|
+
contextWindow: resolveCurrentContextWindowConfig(),
|
|
1793
1925
|
preflightBudget,
|
|
1794
1926
|
toolTokenBudget,
|
|
1795
|
-
maxAttempts: overflowRecovery.maxAttempts,
|
|
1927
|
+
maxAttempts: resolveCurrentContextBudget().overflowRecovery.maxAttempts,
|
|
1796
1928
|
abortSignal: abortController.signal,
|
|
1797
1929
|
compactFn: async (msgs, signal, opts) => {
|
|
1798
1930
|
// Route the reducer's forced-compaction tier through the
|
|
@@ -1822,7 +1954,7 @@ export async function runAgentLoopImpl(
|
|
|
1822
1954
|
signal,
|
|
1823
1955
|
options: {
|
|
1824
1956
|
...(opts ?? {}),
|
|
1825
|
-
overrideProfile:
|
|
1957
|
+
overrideProfile: resolveCurrentOverrideProfile() ?? null,
|
|
1826
1958
|
},
|
|
1827
1959
|
},
|
|
1828
1960
|
buildPluginTurnContext(ctx, reqId),
|
|
@@ -2076,8 +2208,9 @@ export async function runAgentLoopImpl(
|
|
|
2076
2208
|
};
|
|
2077
2209
|
const eventHandler = (event: AgentEvent) =>
|
|
2078
2210
|
dispatchAgentEvent(state, deps, event);
|
|
2079
|
-
|
|
2080
|
-
|
|
2211
|
+
emitTerminalExit = async (reason: AgentLoopExitReason): Promise<void> => {
|
|
2212
|
+
await eventHandler({ type: "agent_loop_exit", reason });
|
|
2213
|
+
};
|
|
2081
2214
|
|
|
2082
2215
|
const onCheckpoint = async (
|
|
2083
2216
|
checkpoint: CheckpointInfo,
|
|
@@ -2086,6 +2219,7 @@ export async function runAgentLoopImpl(
|
|
|
2086
2219
|
|
|
2087
2220
|
if (ctx.canHandoffAtCheckpoint()) {
|
|
2088
2221
|
yieldedForHandoff = true;
|
|
2222
|
+
pendingCheckpointYield = "handoff";
|
|
2089
2223
|
return "yield";
|
|
2090
2224
|
}
|
|
2091
2225
|
|
|
@@ -2093,7 +2227,8 @@ export async function runAgentLoopImpl(
|
|
|
2093
2227
|
// yield if we're approaching the preflight budget. This lets the
|
|
2094
2228
|
// conversation-agent-loop run compaction before the provider rejects.
|
|
2095
2229
|
if (overflowRecovery.enabled) {
|
|
2096
|
-
const midLoopThreshold =
|
|
2230
|
+
const midLoopThreshold =
|
|
2231
|
+
resolveCurrentContextBudget().preflightBudget * 0.85;
|
|
2097
2232
|
const estimated = await runTokenEstimatePipeline(checkpoint.history);
|
|
2098
2233
|
if (estimated > midLoopThreshold) {
|
|
2099
2234
|
rlog.warn(
|
|
@@ -2101,6 +2236,7 @@ export async function runAgentLoopImpl(
|
|
|
2101
2236
|
"Token estimate approaching budget — yielding for compaction",
|
|
2102
2237
|
);
|
|
2103
2238
|
yieldedForBudget = true;
|
|
2239
|
+
pendingCheckpointYield = "budget";
|
|
2104
2240
|
return "yield";
|
|
2105
2241
|
}
|
|
2106
2242
|
}
|
|
@@ -2129,7 +2265,9 @@ export async function runAgentLoopImpl(
|
|
|
2129
2265
|
turnCallSite,
|
|
2130
2266
|
loopTurnCtx,
|
|
2131
2267
|
turnOverrideProfile,
|
|
2132
|
-
|
|
2268
|
+
resolveCurrentMaxInputTokens(),
|
|
2269
|
+
resolveCurrentOverrideProfile,
|
|
2270
|
+
resolveCurrentMaxInputTokens,
|
|
2133
2271
|
);
|
|
2134
2272
|
|
|
2135
2273
|
rlog.info(
|
|
@@ -2137,6 +2275,11 @@ export async function runAgentLoopImpl(
|
|
|
2137
2275
|
"Agent loop run completed",
|
|
2138
2276
|
);
|
|
2139
2277
|
|
|
2278
|
+
if (yieldedForHandoff) {
|
|
2279
|
+
await emitTerminalExit?.("checkpoint_handoff");
|
|
2280
|
+
pendingCheckpointYield = null;
|
|
2281
|
+
}
|
|
2282
|
+
|
|
2140
2283
|
// ── Proactive mid-loop compaction ───────────────────────────────
|
|
2141
2284
|
// When the agent loop yielded because the token budget check in
|
|
2142
2285
|
// onCheckpoint detected approaching limits, run compaction on the
|
|
@@ -2146,12 +2289,14 @@ export async function runAgentLoopImpl(
|
|
|
2146
2289
|
let midLoopCompactAttempts = 0;
|
|
2147
2290
|
while (
|
|
2148
2291
|
yieldedForBudget &&
|
|
2149
|
-
midLoopCompactAttempts <
|
|
2292
|
+
midLoopCompactAttempts <
|
|
2293
|
+
resolveCurrentContextBudget().overflowRecovery.maxAttempts &&
|
|
2150
2294
|
!state.contextTooLargeDetected &&
|
|
2151
2295
|
!abortController.signal.aborted
|
|
2152
2296
|
) {
|
|
2153
2297
|
midLoopCompactAttempts++;
|
|
2154
2298
|
yieldedForBudget = false;
|
|
2299
|
+
pendingCheckpointYield = null;
|
|
2155
2300
|
|
|
2156
2301
|
rlog.info(
|
|
2157
2302
|
{ phase: "mid-loop-compact" },
|
|
@@ -2193,10 +2338,11 @@ export async function runAgentLoopImpl(
|
|
|
2193
2338
|
options: {
|
|
2194
2339
|
lastCompactedAt: ctx.contextCompactedAt ?? undefined,
|
|
2195
2340
|
force: true,
|
|
2196
|
-
targetInputTokensOverride:
|
|
2341
|
+
targetInputTokensOverride:
|
|
2342
|
+
resolveCurrentContextBudget().preflightBudget,
|
|
2197
2343
|
conversationOriginChannel:
|
|
2198
2344
|
getConversationOriginChannel(ctx.conversationId) ?? undefined,
|
|
2199
|
-
overrideProfile:
|
|
2345
|
+
overrideProfile: resolveCurrentOverrideProfile() ?? null,
|
|
2200
2346
|
},
|
|
2201
2347
|
},
|
|
2202
2348
|
buildPluginTurnContext(ctx, reqId),
|
|
@@ -2282,7 +2428,9 @@ export async function runAgentLoopImpl(
|
|
|
2282
2428
|
turnCallSite,
|
|
2283
2429
|
loopTurnCtx,
|
|
2284
2430
|
turnOverrideProfile,
|
|
2285
|
-
|
|
2431
|
+
resolveCurrentMaxInputTokens(),
|
|
2432
|
+
resolveCurrentOverrideProfile,
|
|
2433
|
+
resolveCurrentMaxInputTokens,
|
|
2286
2434
|
);
|
|
2287
2435
|
}
|
|
2288
2436
|
|
|
@@ -2296,7 +2444,8 @@ export async function runAgentLoopImpl(
|
|
|
2296
2444
|
{
|
|
2297
2445
|
phase: "mid-loop-compact",
|
|
2298
2446
|
midLoopCompactAttempts,
|
|
2299
|
-
maxAttempts:
|
|
2447
|
+
maxAttempts:
|
|
2448
|
+
resolveCurrentContextBudget().overflowRecovery.maxAttempts,
|
|
2300
2449
|
},
|
|
2301
2450
|
"Mid-loop compaction exhausted all attempts — escalating to convergence loop",
|
|
2302
2451
|
);
|
|
@@ -2339,7 +2488,9 @@ export async function runAgentLoopImpl(
|
|
|
2339
2488
|
turnCallSite,
|
|
2340
2489
|
loopTurnCtx,
|
|
2341
2490
|
turnOverrideProfile,
|
|
2342
|
-
|
|
2491
|
+
resolveCurrentMaxInputTokens(),
|
|
2492
|
+
resolveCurrentOverrideProfile,
|
|
2493
|
+
resolveCurrentMaxInputTokens,
|
|
2343
2494
|
);
|
|
2344
2495
|
|
|
2345
2496
|
if (state.orderingErrorDetected) {
|
|
@@ -2408,7 +2559,9 @@ export async function runAgentLoopImpl(
|
|
|
2408
2559
|
turnCallSite,
|
|
2409
2560
|
loopTurnCtx,
|
|
2410
2561
|
turnOverrideProfile,
|
|
2411
|
-
|
|
2562
|
+
resolveCurrentMaxInputTokens(),
|
|
2563
|
+
resolveCurrentOverrideProfile,
|
|
2564
|
+
resolveCurrentMaxInputTokens,
|
|
2412
2565
|
);
|
|
2413
2566
|
if (state.imageTooLargeDetected) {
|
|
2414
2567
|
rlog.error(
|
|
@@ -2479,18 +2632,21 @@ export async function runAgentLoopImpl(
|
|
|
2479
2632
|
toolTokenBudget,
|
|
2480
2633
|
},
|
|
2481
2634
|
);
|
|
2482
|
-
|
|
2635
|
+
const convergenceBudget = resolveCurrentContextBudget();
|
|
2636
|
+
let correctedTarget = convergenceBudget.preflightBudget;
|
|
2483
2637
|
if (actualTokens && estimatedTokensAtOverflow > 0) {
|
|
2484
2638
|
const estimationErrorRatio = actualTokens / estimatedTokensAtOverflow;
|
|
2485
2639
|
if (estimationErrorRatio > 1.0) {
|
|
2486
|
-
correctedTarget = Math.floor(
|
|
2640
|
+
correctedTarget = Math.floor(
|
|
2641
|
+
convergenceBudget.preflightBudget / estimationErrorRatio,
|
|
2642
|
+
);
|
|
2487
2643
|
rlog.warn(
|
|
2488
2644
|
{
|
|
2489
2645
|
phase: "convergence",
|
|
2490
2646
|
actualTokens,
|
|
2491
2647
|
estimatedTokens: estimatedTokensAtOverflow,
|
|
2492
2648
|
estimationErrorRatio: estimationErrorRatio.toFixed(2),
|
|
2493
|
-
preflightBudget,
|
|
2649
|
+
preflightBudget: convergenceBudget.preflightBudget,
|
|
2494
2650
|
correctedTarget,
|
|
2495
2651
|
},
|
|
2496
2652
|
"Adjusting compaction target based on observed estimation error",
|
|
@@ -2515,11 +2671,11 @@ export async function runAgentLoopImpl(
|
|
|
2515
2671
|
systemPrompt: ctx.systemPrompt,
|
|
2516
2672
|
tools: undefined,
|
|
2517
2673
|
compaction: emergencyConfig,
|
|
2518
|
-
maxInputTokens:
|
|
2674
|
+
maxInputTokens: resolveCurrentMaxInputTokens(),
|
|
2519
2675
|
previousEstimatedInputTokens: estimatedTokensAtOverflow,
|
|
2520
2676
|
force: true,
|
|
2521
2677
|
signal: abortController.signal,
|
|
2522
|
-
overrideProfile:
|
|
2678
|
+
overrideProfile: resolveCurrentOverrideProfile() ?? null,
|
|
2523
2679
|
nonPersistedPrefixCount:
|
|
2524
2680
|
ctx.contextWindowManager.nonPersistedPrefixCount,
|
|
2525
2681
|
});
|
|
@@ -2557,7 +2713,7 @@ export async function runAgentLoopImpl(
|
|
|
2557
2713
|
}
|
|
2558
2714
|
|
|
2559
2715
|
let convergenceAttempts = 0;
|
|
2560
|
-
const maxAttempts = overflowRecovery.maxAttempts;
|
|
2716
|
+
const maxAttempts = convergenceBudget.overflowRecovery.maxAttempts;
|
|
2561
2717
|
|
|
2562
2718
|
while (
|
|
2563
2719
|
state.contextTooLargeDetected &&
|
|
@@ -2586,7 +2742,7 @@ export async function runAgentLoopImpl(
|
|
|
2586
2742
|
{
|
|
2587
2743
|
providerName: estimationProviderName,
|
|
2588
2744
|
systemPrompt: ctx.systemPrompt,
|
|
2589
|
-
contextWindow:
|
|
2745
|
+
contextWindow: resolveCurrentContextWindowConfig(),
|
|
2590
2746
|
targetTokens: correctedTarget,
|
|
2591
2747
|
toolTokenBudget,
|
|
2592
2748
|
},
|
|
@@ -2594,7 +2750,7 @@ export async function runAgentLoopImpl(
|
|
|
2594
2750
|
(msgs, signal, opts) =>
|
|
2595
2751
|
ctx.contextWindowManager.maybeCompact(msgs, signal!, {
|
|
2596
2752
|
...(opts ?? {}),
|
|
2597
|
-
overrideProfile:
|
|
2753
|
+
overrideProfile: resolveCurrentOverrideProfile() ?? null,
|
|
2598
2754
|
}),
|
|
2599
2755
|
abortController.signal,
|
|
2600
2756
|
);
|
|
@@ -2670,7 +2826,9 @@ export async function runAgentLoopImpl(
|
|
|
2670
2826
|
turnCallSite,
|
|
2671
2827
|
loopTurnCtx,
|
|
2672
2828
|
turnOverrideProfile,
|
|
2673
|
-
|
|
2829
|
+
resolveCurrentMaxInputTokens(),
|
|
2830
|
+
resolveCurrentOverrideProfile,
|
|
2831
|
+
resolveCurrentMaxInputTokens,
|
|
2674
2832
|
);
|
|
2675
2833
|
|
|
2676
2834
|
// If the rerun still yields at checkpoint, the turn is still
|
|
@@ -2748,7 +2906,7 @@ export async function runAgentLoopImpl(
|
|
|
2748
2906
|
force: true,
|
|
2749
2907
|
minKeepRecentUserTurns: 0,
|
|
2750
2908
|
targetInputTokensOverride: correctedTarget,
|
|
2751
|
-
overrideProfile:
|
|
2909
|
+
overrideProfile: resolveCurrentOverrideProfile() ?? null,
|
|
2752
2910
|
},
|
|
2753
2911
|
},
|
|
2754
2912
|
buildPluginTurnContext(ctx, reqId),
|
|
@@ -2831,7 +2989,9 @@ export async function runAgentLoopImpl(
|
|
|
2831
2989
|
turnCallSite,
|
|
2832
2990
|
loopTurnCtx,
|
|
2833
2991
|
turnOverrideProfile,
|
|
2834
|
-
|
|
2992
|
+
resolveCurrentMaxInputTokens(),
|
|
2993
|
+
resolveCurrentOverrideProfile,
|
|
2994
|
+
resolveCurrentMaxInputTokens,
|
|
2835
2995
|
);
|
|
2836
2996
|
}
|
|
2837
2997
|
// action === "fail_gracefully" falls through to the final error below
|
|
@@ -2843,6 +3003,8 @@ export async function runAgentLoopImpl(
|
|
|
2843
3003
|
new Error("context_length_exceeded"),
|
|
2844
3004
|
{ phase: "agent_loop" },
|
|
2845
3005
|
);
|
|
3006
|
+
await emitTerminalExit?.("context_too_large");
|
|
3007
|
+
pendingCheckpointYield = null;
|
|
2846
3008
|
onEvent(buildConversationErrorMessage(ctx.conversationId, classified));
|
|
2847
3009
|
}
|
|
2848
3010
|
}
|
|
@@ -3041,11 +3203,11 @@ export async function runAgentLoopImpl(
|
|
|
3041
3203
|
state.exchangeLlmCallCount,
|
|
3042
3204
|
{
|
|
3043
3205
|
tokens: state.lastCallInputTokens,
|
|
3044
|
-
maxTokens:
|
|
3206
|
+
maxTokens: resolveCurrentMaxInputTokens(),
|
|
3045
3207
|
},
|
|
3046
3208
|
{
|
|
3047
3209
|
callSite: turnCallSite,
|
|
3048
|
-
overrideProfile:
|
|
3210
|
+
overrideProfile: resolveCurrentOverrideProfile() ?? null,
|
|
3049
3211
|
},
|
|
3050
3212
|
);
|
|
3051
3213
|
|
|
@@ -3105,6 +3267,10 @@ export async function runAgentLoopImpl(
|
|
|
3105
3267
|
|
|
3106
3268
|
// Re-check: the user may have cancelled during attachment resolution
|
|
3107
3269
|
if (abortController.signal.aborted) {
|
|
3270
|
+
if (pendingCheckpointYield === "budget") {
|
|
3271
|
+
await emitTerminalExit?.("aborted_after_checkpoint");
|
|
3272
|
+
pendingCheckpointYield = null;
|
|
3273
|
+
}
|
|
3108
3274
|
ctx.emitActivityState("idle", "generation_cancelled", "global", reqId);
|
|
3109
3275
|
ctx.traceEmitter.emit(
|
|
3110
3276
|
"generation_cancelled",
|
|
@@ -3246,6 +3412,10 @@ export async function runAgentLoopImpl(
|
|
|
3246
3412
|
aborted: abortController.signal.aborted,
|
|
3247
3413
|
};
|
|
3248
3414
|
if (isUserCancellation(err, errorCtx)) {
|
|
3415
|
+
if (pendingCheckpointYield === "budget") {
|
|
3416
|
+
await emitTerminalExit?.("aborted_after_checkpoint");
|
|
3417
|
+
pendingCheckpointYield = null;
|
|
3418
|
+
}
|
|
3249
3419
|
ctx.emitActivityState("idle", "generation_cancelled", "global", reqId);
|
|
3250
3420
|
rlog.info("Generation cancelled by user");
|
|
3251
3421
|
ctx.traceEmitter.emit(
|
|
@@ -3338,7 +3508,6 @@ export async function runAgentLoopImpl(
|
|
|
3338
3508
|
ctx.diskPressureCleanupModeActive = false;
|
|
3339
3509
|
ctx.preactivatedSkillIds = undefined;
|
|
3340
3510
|
ctx.currentTurnOverrideProfile = undefined;
|
|
3341
|
-
ctx.slackRuntimeContextNotice = undefined;
|
|
3342
3511
|
// Channel command intents (e.g. Telegram /start) are single-turn metadata.
|
|
3343
3512
|
// Clear at turn end so they never leak into subsequent unrelated messages.
|
|
3344
3513
|
ctx.commandIntent = undefined;
|