@vellumai/assistant 0.8.6 → 0.8.7
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/AGENTS.md +4 -4
- package/Dockerfile +1 -0
- package/bun.lock +11 -2
- package/docker-entrypoint.sh +8 -6
- package/docs/plugins.md +63 -28
- package/examples/plugins/echo/register.ts +4 -7
- package/knip.json +1 -0
- package/node_modules/@vellumai/environments/bun.lock +24 -0
- package/node_modules/@vellumai/environments/package.json +18 -0
- package/node_modules/@vellumai/environments/src/__tests__/package-boundary.test.ts +95 -0
- package/node_modules/@vellumai/environments/src/index.ts +11 -0
- package/node_modules/@vellumai/environments/src/seeds.ts +73 -0
- package/node_modules/@vellumai/environments/src/types.ts +70 -0
- package/node_modules/@vellumai/environments/tsconfig.json +20 -0
- package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +11 -0
- package/node_modules/@vellumai/skill-host-contracts/src/client.ts +3 -4
- package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +6 -2
- package/openapi.yaml +3735 -353
- package/package.json +7 -3
- package/scripts/generate-openapi.ts +20 -13
- package/src/__tests__/agent-loop-callsite-precedence.test.ts +42 -80
- package/src/__tests__/agent-loop-exit-reason.test.ts +240 -39
- package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +141 -0
- package/src/__tests__/agent-loop-override-profile.test.ts +19 -32
- package/src/__tests__/agent-loop-provider-error-recording.test.ts +6 -4
- package/src/__tests__/agent-loop-thinking.test.ts +17 -12
- package/src/__tests__/agent-loop.test.ts +207 -341
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +4 -2
- package/src/__tests__/agent-wake-override-profile.test.ts +22 -40
- package/src/__tests__/anthropic-provider.test.ts +201 -55
- package/src/__tests__/app-builder-skill-instructions.test.ts +22 -0
- package/src/__tests__/app-control-flow.test.ts +5 -0
- package/src/__tests__/approval-cascade.test.ts +4 -11
- package/src/__tests__/approval-routes-http.test.ts +4 -2
- package/src/__tests__/assistant-event.test.ts +15 -0
- package/src/__tests__/assistant-feature-flags-integration.test.ts +2 -2
- package/src/__tests__/avatar-e2e.test.ts +7 -37
- package/src/__tests__/avatar-generator.test.ts +12 -42
- package/src/__tests__/avatar-identity-sync.test.ts +28 -3
- package/src/__tests__/background-shell-bash.test.ts +3 -7
- package/src/__tests__/btw-routes.test.ts +7 -12
- package/src/__tests__/call-pointer-messages.test.ts +5 -3
- package/src/__tests__/call-site-routing-provider.test.ts +22 -40
- package/src/__tests__/catalog-files.test.ts +1 -0
- package/src/__tests__/channel-approval-routes.test.ts +48 -20
- package/src/__tests__/channel-approvals.test.ts +3 -1
- package/src/__tests__/channel-invite-transport.test.ts +1 -5
- package/src/__tests__/channel-readiness-routes.test.ts +0 -4
- package/src/__tests__/channel-readiness-slack-remote.test.ts +2 -7
- package/src/__tests__/channel-retry-sweep.test.ts +71 -79
- package/src/__tests__/circuit-breaker-pipeline.test.ts +3 -3
- package/src/__tests__/clawhub-files.test.ts +1 -0
- package/src/__tests__/compaction-events.test.ts +5 -17
- package/src/__tests__/compaction-pipeline.test.ts +1 -1
- package/src/__tests__/compaction-timeout-recovery.test.ts +37 -48
- package/src/__tests__/compaction-trail-store.test.ts +1 -79
- package/src/__tests__/compactor-image-manifest-trust.test.ts +112 -0
- package/src/__tests__/computer-use-tools.test.ts +2 -2
- package/src/__tests__/config-watcher.test.ts +28 -0
- package/src/__tests__/context-search-agent-runner.test.ts +6 -3
- package/src/__tests__/context-token-estimator.test.ts +34 -0
- package/src/__tests__/context-window-manager-compact-retry.test.ts +291 -0
- package/src/__tests__/conversation-abort-tool-results.test.ts +14 -7
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +3 -2
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +12 -27
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +430 -90
- package/src/__tests__/conversation-agent-loop.test.ts +581 -62
- package/src/__tests__/conversation-analysis-routes.test.ts +1 -3
- package/src/__tests__/conversation-app-control-lifecycle.test.ts +1 -1
- package/src/__tests__/conversation-clear-safety.test.ts +20 -10
- package/src/__tests__/conversation-confirmation-signals.test.ts +15 -45
- package/src/__tests__/conversation-disk-view-integration.test.ts +2 -2
- package/src/__tests__/conversation-disk-view.test.ts +10 -17
- package/src/__tests__/conversation-fork-crud.test.ts +86 -172
- package/src/__tests__/conversation-fork-route.test.ts +16 -14
- package/src/__tests__/conversation-init.benchmark.test.ts +6 -6
- package/src/__tests__/conversation-lifecycle.test.ts +3 -2
- package/src/__tests__/conversation-load-history-repair.test.ts +3 -2
- package/src/__tests__/conversation-load-history-stripped.test.ts +1 -1
- package/src/__tests__/conversation-message-sync-tags.test.ts +3 -4
- package/src/__tests__/conversation-pairing.test.ts +34 -4
- package/src/__tests__/conversation-pre-run-repair.test.ts +1 -1
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +4 -0
- package/src/__tests__/conversation-process-callsite.test.ts +27 -30
- package/src/__tests__/conversation-provider-retry-repair.test.ts +53 -44
- package/src/__tests__/conversation-queue.test.ts +270 -164
- package/src/__tests__/conversation-routes-disk-view.test.ts +3 -2
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +2 -2
- package/src/__tests__/conversation-routes-slash-commands.test.ts +2 -2
- package/src/__tests__/conversation-runtime-assembly.test.ts +20 -22
- package/src/__tests__/conversation-runtime-workspace.test.ts +19 -1
- package/src/__tests__/conversation-slash-queue.test.ts +37 -31
- package/src/__tests__/conversation-slash-unknown.test.ts +13 -15
- package/src/__tests__/conversation-speed-override.test.ts +8 -22
- package/src/__tests__/conversation-stream-state.test.ts +484 -0
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +6 -15
- package/src/__tests__/conversation-surfaces-app-control.test.ts +32 -4
- package/src/__tests__/conversation-surfaces-state-update.test.ts +5 -2
- package/src/__tests__/conversation-surfaces-table-action.test.ts +6 -15
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +23 -11
- package/src/__tests__/conversation-unread-route.test.ts +14 -2
- package/src/__tests__/conversation-usage.test.ts +0 -2
- package/src/__tests__/conversation-wipe.test.ts +1 -1
- package/src/__tests__/conversation-workspace-cache-state.test.ts +3 -1
- package/src/__tests__/conversation-workspace-injection.test.ts +48 -22
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +27 -7
- package/src/__tests__/credential-execution-tools.test.ts +1 -2
- package/src/__tests__/credential-security-invariants.test.ts +0 -1
- package/src/__tests__/cross-provider-web-search.test.ts +6 -2
- package/src/__tests__/cu-unified-flow.test.ts +26 -1
- package/src/__tests__/db-schedule-syntax-migration.test.ts +11 -0
- package/src/__tests__/disk-pressure-guard.test.ts +66 -0
- package/src/__tests__/disk-pressure-routes.test.ts +9 -2
- package/src/__tests__/dm-persistence.test.ts +7 -2
- package/src/__tests__/dynamic-page-surface.test.ts +68 -0
- package/src/__tests__/edit-propagation.test.ts +1 -2
- package/src/__tests__/empty-response-pipeline.test.ts +127 -5
- package/src/__tests__/filing-service.test.ts +2 -2
- package/src/__tests__/first-greeting.test.ts +55 -14
- package/src/__tests__/gemini-inline-media.test.ts +78 -0
- package/src/__tests__/gemini-provider.test.ts +351 -28
- package/src/__tests__/guardian-routing-state.test.ts +60 -71
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +9 -7
- package/src/__tests__/heartbeat-disk-pressure.test.ts +1 -0
- package/src/__tests__/heartbeat-service.test.ts +2 -1
- package/src/__tests__/history-repair-hook.test.ts +161 -0
- package/src/__tests__/history-repair-observability.test.ts +1 -1
- package/src/__tests__/history-repair.test.ts +2 -1
- package/src/__tests__/host-app-control-proxy.test.ts +2 -0
- package/src/__tests__/host-cu-proxy.test.ts +2 -0
- package/src/__tests__/host-file-edit-tool.test.ts +4 -2
- package/src/__tests__/host-file-proxy.test.ts +31 -0
- package/src/__tests__/host-file-read-tool.test.ts +4 -2
- package/src/__tests__/host-file-write-tool.test.ts +9 -3
- package/src/__tests__/host-proxy-preactivation.test.ts +53 -14
- package/src/__tests__/host-shell-tool.test.ts +9 -4
- package/src/__tests__/http-user-message-parity.test.ts +2 -2
- package/src/__tests__/identity-intro-cache.test.ts +35 -14
- package/src/__tests__/inbound-slack-persistence.test.ts +7 -2
- package/src/__tests__/injector-background-turn.test.ts +1 -1
- package/src/__tests__/injector-chain.test.ts +1 -1
- package/src/__tests__/injector-disk-pressure.test.ts +1 -1
- package/src/__tests__/injector-document-comments.test.ts +1 -1
- package/src/__tests__/injector-pkb-v2-silenced.test.ts +1 -1
- package/src/__tests__/injector-v3-suppression.test.ts +220 -0
- package/src/__tests__/list-messages-attachments.test.ts +7 -8
- package/src/__tests__/list-messages-hidden-metadata.test.ts +17 -15
- package/src/__tests__/list-messages-page-latest.test.ts +0 -1
- package/src/__tests__/list-messages-tool-merge.test.ts +36 -6
- package/src/__tests__/llm-call-pipeline.test.ts +21 -15
- package/src/__tests__/llm-request-log-turn-query.test.ts +42 -86
- package/src/__tests__/llm-resolver.test.ts +23 -47
- package/src/__tests__/llm-usage-store.test.ts +45 -0
- package/src/__tests__/log-export-routes.test.ts +59 -0
- package/src/__tests__/managed-skill-lifecycle.test.ts +1 -8
- package/src/__tests__/mcp-auth-routes.test.ts +15 -10
- package/src/__tests__/mcp-health-check.test.ts +18 -13
- package/src/__tests__/memory-retrieval-pipeline.test.ts +1 -1
- package/src/__tests__/memory-v2-static-injector.test.ts +1 -1
- package/src/__tests__/messaging-send-tool.test.ts +8 -4
- package/src/__tests__/migration-export-http.test.ts +12 -12
- package/src/__tests__/migration-import-commit-http.test.ts +8 -8
- package/src/__tests__/migration-import-preflight-http.test.ts +7 -7
- package/src/__tests__/migration-validate-http.test.ts +3 -3
- package/src/__tests__/native-web-search.test.ts +14 -20
- package/src/__tests__/notification-decision-identity.test.ts +9 -18
- package/src/__tests__/notification-decision-recipient-context.test.ts +3 -6
- package/src/__tests__/oauth-commands-routes.test.ts +1 -1
- package/src/__tests__/onboarding-template-contract.test.ts +10 -0
- package/src/__tests__/openai-provider.test.ts +66 -70
- package/src/__tests__/openai-responses-provider.test.ts +21 -77
- package/src/__tests__/outbound-slack-persistence.test.ts +2 -1
- package/src/__tests__/overflow-reduce-pipeline.test.ts +2 -4
- package/src/__tests__/parallel-tool.benchmark.test.ts +24 -36
- package/src/__tests__/persistence-pipeline.test.ts +15 -26
- package/src/__tests__/persistence-secret-redaction.test.ts +2 -1
- package/src/__tests__/pipeline-runner.test.ts +2 -3
- package/src/__tests__/plugin-bootstrap.test.ts +51 -25
- package/src/__tests__/plugin-route-contribution.test.ts +6 -16
- package/src/__tests__/plugin-skill-contribution.test.ts +7 -17
- package/src/__tests__/plugin-tool-contribution.test.ts +10 -26
- package/src/__tests__/plugin-types.test.ts +7 -14
- package/src/__tests__/prechat-onboarding-contract.test.ts +23 -0
- package/src/__tests__/process-message-background-slack.test.ts +17 -16
- package/src/__tests__/process-message-display-content.test.ts +30 -42
- package/src/__tests__/provider-commit-message-generator.test.ts +19 -14
- package/src/__tests__/provider-error-scenarios.test.ts +7 -6
- package/src/__tests__/provider-platform-proxy-integration.test.ts +3 -8
- package/src/__tests__/provider-send-message-override-profile.test.ts +9 -25
- package/src/__tests__/provider-streaming.benchmark.test.ts +12 -22
- package/src/__tests__/provider-usage-tracking.test.ts +0 -6
- package/src/__tests__/ratelimit.test.ts +9 -4
- package/src/__tests__/relay-server.test.ts +20 -13
- package/src/__tests__/retry-openrouter-only-normalization.test.ts +5 -8
- package/src/__tests__/retry-thinking-tool-choice.test.ts +10 -13
- package/src/__tests__/retry-verbosity-normalization.test.ts +5 -8
- package/src/__tests__/runtime-events-sse-reconnect.test.ts +353 -0
- package/src/__tests__/schedule-routes.test.ts +80 -10
- package/src/__tests__/schedule-store.test.ts +67 -0
- package/src/__tests__/schedule-tools.test.ts +125 -0
- package/src/__tests__/secret-ingress-http.test.ts +2 -2
- package/src/__tests__/secret-prompt-log-hygiene.test.ts +11 -7
- package/src/__tests__/secret-prompter-channel-fallback.test.ts +11 -9
- package/src/__tests__/secret-response-routing.test.ts +13 -11
- package/src/__tests__/send-endpoint-busy.test.ts +2 -1
- package/src/__tests__/shell-observability.test.ts +249 -0
- package/src/__tests__/skill-feature-flags-integration.test.ts +11 -11
- package/src/__tests__/skill-feature-flags.test.ts +6 -6
- package/src/__tests__/skill-load-feature-flag.test.ts +10 -10
- package/src/__tests__/skills-files-catalog-fallback.test.ts +10 -0
- package/src/__tests__/skillssh-files.test.ts +1 -0
- package/src/__tests__/starter-task-flow.test.ts +6 -6
- package/src/__tests__/strip-memory-injections.test.ts +102 -14
- package/src/__tests__/subagent-call-site-routing.test.ts +2 -2
- package/src/__tests__/suggestion-routes.test.ts +3 -3
- package/src/__tests__/sync-message-contract.test.ts +19 -16
- package/src/__tests__/system-prompt.test.ts +54 -0
- package/src/__tests__/terminal-tools.test.ts +3 -24
- package/src/__tests__/thread-backfill.test.ts +4 -9
- package/src/__tests__/title-generate-pipeline.test.ts +1 -1
- package/src/__tests__/token-estimate-pipeline.test.ts +2 -4
- package/src/__tests__/tool-error-pipeline.test.ts +2 -2
- package/src/__tests__/tool-execute-pipeline.test.ts +1 -1
- package/src/__tests__/tool-preview-lifecycle.test.ts +13 -11
- package/src/__tests__/tool-result-truncate-pipeline.test.ts +9 -12
- package/src/__tests__/tool-result-truncation.test.ts +3 -1
- package/src/__tests__/tools-audio-read.test.ts +113 -0
- package/src/__tests__/turn-boundary-resolution.test.ts +44 -84
- package/src/__tests__/turn-events-store.test.ts +11 -7
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +8 -6
- package/src/__tests__/voice-session-bridge.test.ts +13 -7
- package/src/acp/__tests__/prepare-agent-env.test.ts +143 -31
- package/src/acp/prepare-agent-env.ts +52 -11
- package/src/agent/compaction-circuit.ts +140 -0
- package/src/agent/loop.ts +409 -85
- package/src/api/README.md +19 -17
- package/src/api/constants/tool-execution.ts +21 -0
- package/src/api/events/assistant-activity-state.ts +75 -0
- package/src/api/events/assistant-outbound-attachment.ts +25 -27
- package/src/api/events/assistant-text-delta.ts +6 -8
- package/src/api/events/assistant-turn-start.ts +5 -7
- package/src/api/events/avatar-updated.ts +24 -0
- package/src/api/events/compaction-circuit-closed.ts +26 -0
- package/src/api/events/compaction-circuit-open.ts +28 -0
- package/src/api/events/confirmation-request.ts +114 -0
- package/src/api/events/contact-request.ts +33 -0
- package/src/api/events/conversation-error.ts +77 -0
- package/src/api/events/conversation-list-invalidated.ts +38 -0
- package/src/api/events/conversation-title-updated.ts +24 -0
- package/src/api/events/disk-pressure-status-changed.ts +61 -0
- package/src/api/events/document-comment-created.ts +24 -28
- package/src/api/events/document-comment-deleted.ts +6 -8
- package/src/api/events/document-comment-reopened.ts +6 -8
- package/src/api/events/document-comment-resolved.ts +8 -10
- package/src/api/events/document-editor-update.ts +27 -0
- package/src/api/events/error.ts +32 -0
- package/src/api/events/generation-cancelled.ts +4 -6
- package/src/api/events/generation-handoff.ts +13 -15
- package/src/api/events/home-feed-updated.ts +26 -0
- package/src/api/events/identity-changed.ts +32 -0
- package/src/api/events/interaction-resolved.ts +50 -0
- package/src/api/events/message-complete.ts +10 -12
- package/src/api/events/message-dequeued.ts +21 -0
- package/src/api/events/message-queued-deleted.ts +23 -0
- package/src/api/events/message-queued.ts +22 -0
- package/src/api/events/message-request-complete.ts +29 -0
- package/src/api/events/navigate-settings.ts +20 -0
- package/src/api/events/notification-intent.ts +33 -0
- package/src/api/events/open-url.ts +6 -8
- package/src/api/events/question-request.ts +67 -0
- package/src/api/events/relationship-state-updated.ts +4 -6
- package/src/api/events/secret-request.ts +42 -0
- package/src/api/events/subagent-event.ts +79 -0
- package/src/api/events/subagent-spawned.ts +40 -0
- package/src/api/events/subagent-status-changed.ts +65 -0
- package/src/api/events/sync-changed.ts +29 -0
- package/src/api/events/tool-result.ts +129 -0
- package/src/api/events/tool-use-start.ts +8 -10
- package/src/api/events/turn-profile-auto-routed.ts +28 -0
- package/src/api/events/ui-surface-complete.ts +30 -0
- package/src/api/events/ui-surface-dismiss.ts +22 -0
- package/src/api/events/ui-surface-show.ts +67 -0
- package/src/api/events/ui-surface-update.ts +26 -0
- package/src/api/events/usage-update.ts +34 -0
- package/src/api/events/user-message-echo.ts +35 -0
- package/src/api/index.ts +354 -0
- package/src/api/requests/dictation.ts +45 -0
- package/src/api/responses/disk-pressure-status.ts +26 -0
- package/src/api/responses/home.ts +217 -0
- package/src/api/responses/llm-context-response.ts +2 -0
- package/src/api/responses/memory-v3-selection-log.ts +50 -0
- package/src/api/responses/subagent-detail.ts +48 -0
- package/src/approvals/guardian-decision-primitive.ts +7 -15
- package/src/approvals/guardian-request-resolvers.ts +6 -9
- package/src/avatar/__tests__/avatar-manifest.test.ts +236 -0
- package/src/avatar/__tests__/avatar-store.test.ts +193 -0
- package/src/avatar/avatar-manifest.ts +195 -0
- package/src/avatar/avatar-store.ts +113 -0
- package/src/avatar/traits-png-sync.ts +8 -2
- package/src/background-wake/next-wake.test.ts +31 -1
- package/src/background-wake/next-wake.ts +4 -1
- package/src/calls/call-conversation-messages.ts +6 -4
- package/src/calls/guardian-action-sweep.ts +6 -4
- package/src/calls/relay-server.ts +12 -8
- package/src/calls/voice-session-bridge.ts +13 -27
- package/src/cli/commands/__tests__/memory-v3.test.ts +245 -0
- package/src/cli/commands/avatar.ts +17 -11
- package/src/cli/commands/conversations.ts +15 -1
- package/src/cli/commands/db/__tests__/repair.test.ts +540 -0
- package/src/cli/commands/db/__tests__/status.test.ts +253 -0
- package/src/cli/commands/db/format.ts +48 -0
- package/src/cli/commands/db/index.ts +29 -0
- package/src/cli/commands/db/repair-step-conversation-backfill.ts +345 -0
- package/src/cli/commands/db/repair-step-integrity.ts +146 -0
- package/src/cli/commands/db/repair-steps.ts +164 -0
- package/src/cli/commands/db/repair.ts +141 -0
- package/src/cli/commands/db/status.ts +366 -0
- package/src/cli/commands/memory-v3.ts +159 -445
- package/src/cli/lib/cli-colors.ts +24 -6
- package/src/cli/program.ts +4 -5
- package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
- package/src/config/assistant-feature-flags.ts +2 -2
- package/src/config/bundled-skills/app-builder/SKILL.md +14 -3
- package/src/config/bundled-skills/media-processing/services/reduce.ts +6 -9
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +7 -2
- package/src/config/bundled-skills/schedule/SKILL.md +1 -1
- package/src/config/bundled-skills/schedule/TOOLS.json +8 -0
- package/src/config/call-site-defaults.ts +2 -7
- package/src/config/feature-flag-registry.json +25 -9
- package/src/config/schemas/__tests__/memory-v2.test.ts +1 -226
- package/src/config/schemas/call-site-catalog.ts +8 -15
- package/src/config/schemas/llm.ts +2 -3
- package/src/config/schemas/memory-lifecycle.ts +24 -0
- package/src/config/schemas/memory-v2.ts +0 -253
- package/src/config/schemas/memory-v3.ts +39 -0
- package/src/config/schemas/memory.ts +6 -1
- package/src/config/schemas/timeouts.ts +3 -1
- package/src/context/compactor.ts +54 -31
- package/src/context/token-estimator.ts +19 -0
- package/src/context/tool-result-truncation.ts +1 -43
- package/src/context/window-manager.ts +138 -20
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +2 -2
- package/src/daemon/__tests__/web-search-status-text.test.ts +10 -6
- package/src/daemon/approval-generators.ts +4 -4
- package/src/daemon/config-watcher.ts +7 -1
- package/src/daemon/conversation-agent-loop-handlers.ts +225 -88
- package/src/daemon/conversation-agent-loop.ts +284 -584
- package/src/daemon/conversation-error.ts +7 -7
- package/src/daemon/conversation-history.ts +22 -6
- package/src/daemon/conversation-launch.ts +4 -8
- package/src/daemon/conversation-lifecycle.ts +10 -38
- package/src/daemon/conversation-messaging.ts +1 -3
- package/src/daemon/conversation-notifiers.ts +7 -5
- package/src/daemon/conversation-process.ts +100 -79
- package/src/daemon/conversation-runtime-assembly.ts +47 -21
- package/src/daemon/conversation-store.ts +6 -5
- package/src/daemon/conversation-surfaces.ts +55 -69
- package/src/daemon/conversation-tool-setup.ts +3 -0
- package/src/daemon/conversation.ts +91 -126
- package/src/daemon/daemon-skill-host.ts +2 -6
- package/src/daemon/disk-pressure-guard.ts +35 -29
- package/src/daemon/external-plugins-bootstrap.ts +46 -24
- package/src/daemon/first-greeting.ts +26 -4
- package/src/daemon/guardian-action-generators.ts +2 -2
- package/src/daemon/handlers/conversations.ts +6 -22
- package/src/daemon/handlers/shared.ts +4 -0
- package/src/daemon/handlers/skills.ts +15 -14
- package/src/daemon/host-app-control-proxy.ts +54 -1
- package/src/daemon/host-cu-proxy.ts +46 -22
- package/src/daemon/host-file-proxy.ts +25 -1
- package/src/daemon/host-proxy-preactivation.ts +25 -6
- package/src/daemon/lifecycle.ts +28 -55
- package/src/daemon/message-protocol.ts +2 -3
- package/src/daemon/message-provenance.ts +49 -0
- package/src/daemon/message-types/contacts.ts +3 -20
- package/src/daemon/message-types/conversations.ts +13 -111
- package/src/daemon/message-types/documents.ts +3 -9
- package/src/daemon/message-types/home.ts +4 -17
- package/src/daemon/message-types/integrations.ts +2 -6
- package/src/daemon/message-types/messages.ts +28 -343
- package/src/daemon/message-types/notifications.ts +2 -32
- package/src/daemon/message-types/settings.ts +3 -8
- package/src/daemon/message-types/skills.ts +2 -0
- package/src/daemon/message-types/surfaces.ts +2 -0
- package/src/daemon/message-types/sync.ts +12 -25
- package/src/daemon/message-types/workspace.ts +3 -11
- package/src/daemon/process-message.ts +49 -46
- package/src/daemon/server.ts +12 -0
- package/src/daemon/tool-side-effects.ts +10 -7
- package/src/daemon/trust-context.ts +13 -0
- package/src/daemon/wake-target-adapter.ts +11 -1
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +3 -1
- package/src/heartbeat/heartbeat-run-store.ts +31 -0
- package/src/heartbeat/heartbeat-service.ts +16 -0
- package/src/home/feature-gate.ts +22 -0
- package/src/home/feed-types.ts +36 -221
- package/src/ipc/__tests__/email-ipc.test.ts +0 -9
- package/src/ipc/routes/__tests__/route-adapter.test.ts +244 -0
- package/src/ipc/routes/route-adapter.ts +45 -6
- package/src/ipc/skill-routes/__tests__/memory.test.ts +18 -9
- package/src/ipc/skill-routes/__tests__/providers.test.ts +10 -10
- package/src/ipc/skill-routes/__tests__/registries.test.ts +28 -18
- package/src/ipc/skill-routes/memory.ts +26 -13
- package/src/ipc/skill-routes/providers.ts +5 -6
- package/src/ipc/skill-routes/registries.ts +13 -61
- package/src/live-voice/__tests__/live-voice-archive.test.ts +24 -11
- package/src/memory/__tests__/conversation-queries.test.ts +192 -8
- package/src/memory/__tests__/db-maintenance.test.ts +128 -0
- package/src/memory/__tests__/jobs-store-job-classes.test.ts +5 -4
- package/src/memory/__tests__/memory-retrospective-job.test.ts +10 -6
- package/src/memory/__tests__/memory-v3-selections-migration.test.ts +103 -0
- package/src/memory/context-search/agent-runner.ts +2 -4
- package/src/memory/conversation-crud.ts +39 -8
- package/src/memory/conversation-queries.ts +78 -22
- package/src/memory/db-init.ts +8 -0
- package/src/memory/db-maintenance.ts +18 -2
- package/src/memory/graph/consolidation.ts +8 -11
- package/src/memory/graph/conversation-graph-memory.ts +41 -8
- package/src/memory/graph/extraction.ts +6 -9
- package/src/memory/graph/narrative.ts +2 -2
- package/src/memory/graph/pattern-scan.ts +2 -2
- package/src/memory/graph/retriever.ts +20 -26
- package/src/memory/graph/tools.ts +4 -4
- package/src/memory/job-handlers/conversation-starters.ts +32 -32
- package/src/memory/job-handlers/summarization.ts +1 -2
- package/src/memory/jobs-store.ts +3 -1
- package/src/memory/jobs-worker.ts +51 -39
- package/src/memory/llm-request-log-source-clickhouse.ts +5 -31
- package/src/memory/llm-request-log-source-local.ts +0 -11
- package/src/memory/llm-request-log-source.ts +9 -25
- package/src/memory/llm-request-log-store.ts +0 -41
- package/src/memory/llm-usage-store.ts +10 -0
- package/src/memory/memory-marker.ts +17 -0
- package/src/memory/memory-retrospective-job.ts +6 -2
- package/src/memory/memory-v2-activation-log-store.ts +1 -83
- package/src/memory/migrations/267-llm-usage-events-add-assistant-version.ts +46 -0
- package/src/memory/migrations/268-add-memory-v3-selections.ts +28 -0
- package/src/memory/migrations/269-schedule-script-timeout.ts +11 -0
- package/src/memory/migrations/270-messages-role-created-at-index.ts +18 -0
- package/src/memory/migrations/__tests__/267-llm-usage-events-add-assistant-version.test.ts +117 -0
- package/src/memory/migrations/index.ts +4 -0
- package/src/memory/schema/infrastructure.ts +11 -0
- package/src/memory/v2/__tests__/consolidation-job.test.ts +124 -0
- package/src/memory/v2/__tests__/migration.test.ts +11 -3
- package/src/memory/v2/__tests__/page-index.test.ts +37 -1
- package/src/memory/v2/__tests__/router.test.ts +14 -4
- package/src/memory/v2/__tests__/sweep-job.test.ts +6 -5
- package/src/memory/v2/backfill-jobs.ts +6 -0
- package/src/memory/v2/consolidation-job.ts +89 -9
- package/src/memory/v2/migration.ts +5 -3
- package/src/memory/v2/page-index.ts +11 -0
- package/src/memory/v2/router.ts +8 -11
- package/src/memory/v2/sweep-job.ts +8 -11
- package/src/memory/v2/types.ts +1 -0
- package/src/memory/v3/__tests__/assign.test.ts +242 -0
- package/src/memory/v3/__tests__/capabilities.test.ts +118 -0
- package/src/memory/v3/__tests__/core.test.ts +39 -0
- package/src/memory/v3/__tests__/fixtures/eval-turns.json +36 -0
- package/src/memory/v3/__tests__/fixtures/live-turns.json +37 -0
- package/src/memory/v3/__tests__/health.test.ts +203 -0
- package/src/memory/v3/__tests__/live-integration.test.ts +330 -0
- package/src/memory/v3/__tests__/maintain-job.test.ts +288 -0
- package/src/memory/v3/__tests__/needle.test.ts +107 -0
- package/src/memory/v3/__tests__/orchestrate.test.ts +400 -0
- package/src/memory/v3/__tests__/reconcile.test.ts +274 -0
- package/src/memory/v3/__tests__/render-injection.test.ts +61 -0
- package/src/memory/v3/__tests__/router.test.ts +260 -0
- package/src/memory/v3/__tests__/selection-log-store.test.ts +179 -0
- package/src/memory/v3/__tests__/selector.test.ts +404 -0
- package/src/memory/v3/__tests__/shadow-plugin.test.ts +414 -0
- package/src/memory/v3/__tests__/snapshot.test.ts +168 -0
- package/src/memory/v3/__tests__/tree.test.ts +192 -0
- package/src/memory/v3/__tests__/types.test.ts +54 -0
- package/src/memory/v3/__tests__/working-set-eviction.test.ts +106 -0
- package/src/memory/v3/__tests__/working-set-skeleton.test.ts +44 -0
- package/src/memory/v3/assign.ts +268 -0
- package/src/memory/v3/capabilities.ts +124 -0
- package/src/memory/v3/core.ts +26 -0
- package/src/memory/v3/data/README.md +84 -0
- package/src/memory/v3/data/assignments.json +5 -0
- package/src/memory/v3/data/core.json +1 -0
- package/src/memory/v3/data/leaves/domain-a/topic-x.md +9 -0
- package/src/memory/v3/data/leaves/domain-a/topic-y.md +9 -0
- package/src/memory/v3/data/leaves/domain-b/topic-z.md +9 -0
- package/src/memory/v3/health.ts +0 -0
- package/src/memory/v3/maintain-job.ts +314 -0
- package/src/memory/v3/needle.ts +115 -0
- package/src/memory/v3/orchestrate.ts +114 -0
- package/src/memory/v3/page-content.ts +34 -0
- package/src/memory/v3/provider-blocks.ts +16 -0
- package/src/memory/v3/reconcile.ts +523 -0
- package/src/memory/v3/render-injection.ts +32 -0
- package/src/memory/v3/router.ts +184 -0
- package/src/memory/v3/selection-log-store.ts +84 -0
- package/src/memory/v3/selector.ts +211 -0
- package/src/memory/v3/shadow-plugin.ts +379 -0
- package/src/memory/v3/snapshot.ts +209 -0
- package/src/memory/v3/tree.ts +174 -0
- package/src/memory/v3/types.ts +46 -60
- package/src/memory/v3/working-set.ts +88 -0
- package/src/messaging/providers/slack/render-transcript.test.ts +1 -1
- package/src/messaging/providers/slack/render-transcript.ts +2 -2
- package/src/messaging/style-analyzer.ts +8 -11
- package/src/notifications/conversation-pairing.ts +8 -6
- package/src/notifications/decision-engine.ts +10 -13
- package/src/notifications/preference-extractor.ts +11 -14
- package/src/permissions/prompter.ts +42 -36
- package/src/permissions/question-prompter.test.ts +35 -26
- package/src/permissions/question-prompter.ts +6 -10
- package/src/plugin-api/index.ts +2 -0
- package/src/plugin-api/types.ts +25 -3
- package/src/plugins/defaults/circuit-breaker/middlewares/circuitBreaker.ts +93 -0
- package/src/plugins/defaults/circuit-breaker/package.json +15 -0
- package/src/plugins/defaults/circuit-breaker/register.ts +39 -0
- package/src/plugins/defaults/compaction/middlewares/compaction.ts +25 -0
- package/src/plugins/defaults/compaction/package.json +15 -0
- package/src/plugins/defaults/compaction/register.ts +35 -0
- package/src/plugins/defaults/compaction/terminal.ts +73 -0
- package/src/plugins/defaults/empty-response/middlewares/emptyResponse.ts +22 -0
- package/src/plugins/defaults/empty-response/package.json +15 -0
- package/src/plugins/defaults/empty-response/register.ts +28 -0
- package/src/plugins/defaults/empty-response/terminal.ts +106 -0
- package/src/plugins/defaults/history-repair/hooks/user-prompt-submit.ts +35 -0
- package/src/plugins/defaults/history-repair/package.json +15 -0
- package/src/plugins/defaults/history-repair/register.ts +24 -0
- package/src/{daemon/history-repair.ts → plugins/defaults/history-repair/terminal.ts} +48 -35
- package/src/plugins/defaults/index.ts +29 -40
- package/src/plugins/defaults/injectors/package.json +15 -0
- package/src/plugins/defaults/{injectors.ts → injectors/register.ts} +14 -38
- package/src/plugins/defaults/llm-call/middlewares/llmCall.ts +17 -0
- package/src/plugins/defaults/llm-call/package.json +15 -0
- package/src/plugins/defaults/{llm-call.ts → llm-call/register.ts} +6 -38
- package/src/plugins/defaults/memory-retrieval/middlewares/memoryRetrieval.ts +17 -0
- package/src/plugins/defaults/memory-retrieval/package.json +15 -0
- package/src/plugins/defaults/{memory-retrieval.ts → memory-retrieval/register.ts} +10 -48
- package/src/plugins/defaults/{overflow-reduce.ts → overflow-reduce/middlewares/overflowReduce.ts} +18 -77
- package/src/plugins/defaults/overflow-reduce/package.json +15 -0
- package/src/plugins/defaults/overflow-reduce/register.ts +42 -0
- package/src/plugins/defaults/persistence/middlewares/persistence.ts +19 -0
- package/src/plugins/defaults/persistence/package.json +15 -0
- package/src/plugins/defaults/persistence/register.ts +38 -0
- package/src/plugins/defaults/persistence/terminal.ts +83 -0
- package/src/plugins/defaults/title-generate/package.json +15 -0
- package/src/plugins/defaults/title-generate/register.ts +35 -0
- package/src/plugins/defaults/title-generate/terminal.ts +31 -0
- package/src/plugins/defaults/token-estimate/middlewares/tokenEstimate.ts +23 -0
- package/src/plugins/defaults/token-estimate/package.json +15 -0
- package/src/plugins/defaults/token-estimate/register.ts +34 -0
- package/src/plugins/defaults/token-estimate/terminal.ts +40 -0
- package/src/plugins/defaults/tool-error/middlewares/toolError.ts +21 -0
- package/src/plugins/defaults/tool-error/package.json +15 -0
- package/src/plugins/defaults/tool-error/register.ts +35 -0
- package/src/plugins/defaults/tool-error/terminal.ts +47 -0
- package/src/plugins/defaults/tool-execute/middlewares/toolExecute.ts +23 -0
- package/src/plugins/defaults/tool-execute/package.json +15 -0
- package/src/plugins/defaults/{tool-execute.ts → tool-execute/register.ts} +8 -46
- package/src/plugins/defaults/tool-result-truncate/middlewares/toolResultTruncate.ts +23 -0
- package/src/plugins/defaults/tool-result-truncate/package.json +15 -0
- package/src/plugins/defaults/tool-result-truncate/register.ts +35 -0
- package/src/plugins/defaults/tool-result-truncate/terminal.ts +113 -0
- package/src/plugins/defaults/tool-result-truncate/types.ts +22 -0
- package/src/plugins/external-plugin-loader.ts +2 -2
- package/src/plugins/pipeline.ts +0 -12
- package/src/plugins/types.ts +51 -90
- package/src/plugins/user-loader.ts +4 -3
- package/src/proactive-artifact/aux-message-injector.ts +0 -1
- package/src/proactive-artifact/job.test.ts +20 -8
- package/src/proactive-artifact/job.ts +3 -1
- package/src/prompts/sections.ts +20 -7
- package/src/prompts/templates/BOOTSTRAP-CONTENT-AUTOMATION.md +2 -2
- package/src/prompts/templates/BOOTSTRAP.md +5 -1
- package/src/prompts/templates/system-sections.ts +6 -0
- package/src/providers/__tests__/retry-callsite.test.ts +25 -25
- package/src/providers/__tests__/satellite-connection-routing.test.ts +7 -21
- package/src/providers/anthropic/client.ts +24 -5
- package/src/providers/call-site-routing.ts +1 -9
- package/src/providers/gemini/client.ts +152 -34
- package/src/providers/gemini/inline-media.ts +74 -0
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +0 -2
- package/src/providers/openai/chat-completions-provider.ts +1 -4
- package/src/providers/openai/responses-provider.ts +1 -4
- package/src/providers/openrouter/client.ts +1 -6
- package/src/providers/provider-send-message.ts +6 -6
- package/src/providers/ratelimit.ts +1 -9
- package/src/providers/retry.ts +0 -5
- package/src/providers/types.ts +11 -2
- package/src/providers/usage-tracking.ts +1 -9
- package/src/runtime/__tests__/agent-wake.test.ts +131 -26
- package/src/runtime/__tests__/background-job-runner.test.ts +1 -3
- package/src/runtime/agent-wake.ts +93 -18
- package/src/runtime/assistant-event-hub.ts +2 -2
- package/src/runtime/auth/__tests__/guard-tests.test.ts +75 -109
- package/src/runtime/auth/__tests__/route-policy.test.ts +153 -170
- package/src/runtime/auth/route-policy.ts +42 -1079
- package/src/runtime/background-job-runner.ts +1 -4
- package/src/runtime/btw-sidechain.ts +3 -1
- package/src/runtime/channel-approvals.ts +3 -14
- package/src/runtime/channel-invite-transport.ts +5 -6
- package/src/runtime/channel-readiness-service.ts +2 -5
- package/src/runtime/channel-retry-sweep.ts +12 -16
- package/src/runtime/conversation-stream-state.ts +294 -0
- package/src/runtime/http-router.ts +19 -22
- package/src/runtime/http-types.ts +12 -6
- package/src/runtime/invite-instruction-generator.ts +3 -3
- package/src/runtime/pending-interactions.ts +2 -2
- package/src/runtime/routes/__tests__/avatar-state-routes.test.ts +565 -0
- package/src/runtime/routes/__tests__/content-source-routes.test.ts +4 -4
- package/src/runtime/routes/__tests__/conversation-compaction-routes.test.ts +62 -32
- package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +237 -0
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +13 -22
- package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +7 -2
- package/src/runtime/routes/__tests__/sanity-routes.test.ts +6 -6
- package/src/runtime/routes/__tests__/stt-routes.test.ts +3 -3
- package/src/runtime/routes/__tests__/suggest-trust-rule-routes.test.ts +5 -2
- package/src/runtime/routes/__tests__/tts-routes.test.ts +3 -3
- package/src/runtime/routes/acp-routes.test.ts +97 -75
- package/src/runtime/routes/acp-routes.ts +29 -6
- package/src/runtime/routes/app-management-routes.ts +97 -24
- package/src/runtime/routes/app-routes.ts +25 -5
- package/src/runtime/routes/approval-routes.ts +16 -4
- package/src/runtime/routes/attachment-routes.ts +25 -1
- package/src/runtime/routes/audio-routes.ts +1 -0
- package/src/runtime/routes/audit-routes.ts +5 -0
- package/src/runtime/routes/auth-routes.ts +5 -0
- package/src/runtime/routes/avatar-routes.ts +238 -59
- package/src/runtime/routes/background-tool-routes.ts +9 -0
- package/src/runtime/routes/background-wake-routes.ts +13 -3
- package/src/runtime/routes/backup-routes.ts +45 -0
- package/src/runtime/routes/bookmark-routes.ts +13 -0
- package/src/runtime/routes/brain-graph-routes.ts +9 -0
- package/src/runtime/routes/browser-routes.ts +5 -0
- package/src/runtime/routes/browser-tabs-routes.ts +5 -0
- package/src/runtime/routes/btw-routes.ts +5 -1
- package/src/runtime/routes/cache-routes.ts +13 -0
- package/src/runtime/routes/call-routes.ts +21 -10
- package/src/runtime/routes/channel-availability-routes.ts +5 -1
- package/src/runtime/routes/channel-readiness-routes.ts +37 -4
- package/src/runtime/routes/channel-route-definitions.ts +21 -0
- package/src/runtime/routes/channel-verification-routes.ts +21 -0
- package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +9 -2
- package/src/runtime/routes/client-routes.ts +9 -0
- package/src/runtime/routes/consolidation-routes.ts +13 -5
- package/src/runtime/routes/contact-prompt-routes.ts +9 -0
- package/src/runtime/routes/contact-routes.ts +90 -23
- package/src/runtime/routes/content-source-routes.ts +5 -1
- package/src/runtime/routes/conversation-analysis-routes.ts +5 -1
- package/src/runtime/routes/conversation-attention-routes.ts +5 -0
- package/src/runtime/routes/conversation-cli-routes.ts +54 -7
- package/src/runtime/routes/conversation-compaction-routes.ts +54 -25
- package/src/runtime/routes/conversation-list-routes.ts +81 -12
- package/src/runtime/routes/conversation-management-routes.ts +57 -14
- package/src/runtime/routes/conversation-query-routes.ts +88 -41
- package/src/runtime/routes/conversation-routes.ts +74 -19
- package/src/runtime/routes/conversation-starter-routes.ts +22 -13
- package/src/runtime/routes/conversations-import-routes.ts +6 -1
- package/src/runtime/routes/credential-prompt-routes.ts +5 -0
- package/src/runtime/routes/credential-routes.ts +25 -6
- package/src/runtime/routes/debug-bash-routes.ts +5 -0
- package/src/runtime/routes/debug-routes.ts +11 -2
- package/src/runtime/routes/defer-routes.ts +13 -0
- package/src/runtime/routes/diagnostics-routes.ts +37 -46
- package/src/runtime/routes/disk-pressure-routes.ts +17 -31
- package/src/runtime/routes/document-comments-routes.ts +46 -27
- package/src/runtime/routes/documents-routes.ts +21 -10
- package/src/runtime/routes/domain-routes.ts +61 -28
- package/src/runtime/routes/email-routes.ts +33 -0
- package/src/runtime/routes/events-routes.ts +114 -9
- package/src/runtime/routes/filing-routes.ts +9 -4
- package/src/runtime/routes/gateway-log-routes.ts +5 -0
- package/src/runtime/routes/global-search-routes.ts +53 -50
- package/src/runtime/routes/group-routes.ts +21 -5
- package/src/runtime/routes/guardian-action-routes.ts +9 -0
- package/src/runtime/routes/guardian-approval-interception.ts +0 -31
- package/src/runtime/routes/heartbeat-routes.ts +25 -9
- package/src/runtime/routes/home-feed-routes.ts +23 -19
- package/src/runtime/routes/home-state-routes.ts +8 -40
- package/src/runtime/routes/host-app-control-routes.ts +5 -0
- package/src/runtime/routes/host-bash-routes.ts +5 -0
- package/src/runtime/routes/host-browser-routes.ts +13 -0
- package/src/runtime/routes/host-cu-routes.ts +5 -0
- package/src/runtime/routes/host-file-routes.ts +26 -6
- package/src/runtime/routes/host-transfer-routes.ts +13 -2
- package/src/runtime/routes/http-adapter.ts +1 -2
- package/src/runtime/routes/identity-intro-cache.ts +17 -6
- package/src/runtime/routes/identity-routes.ts +12 -2
- package/src/runtime/routes/image-generation-routes.ts +5 -0
- package/src/runtime/routes/inbound-message-handler.ts +15 -11
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +0 -12
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +15 -19
- package/src/runtime/routes/inference-profile-session-routes.ts +13 -3
- package/src/runtime/routes/inference-provider-connection-routes.ts +21 -5
- package/src/runtime/routes/inference-send-routes.ts +11 -11
- package/src/runtime/routes/integrations/a2a.ts +30 -7
- package/src/runtime/routes/integrations/slack/channel.ts +19 -3
- package/src/runtime/routes/integrations/slack/share.ts +9 -2
- package/src/runtime/routes/integrations/telegram.ts +28 -9
- package/src/runtime/routes/integrations/twilio.ts +35 -7
- package/src/runtime/routes/integrations/vercel.ts +3 -3
- package/src/runtime/routes/internal-oauth-routes.ts +5 -0
- package/src/runtime/routes/internal-twilio-routes.ts +13 -0
- package/src/runtime/routes/llm-call-sites-routes.ts +39 -4
- package/src/runtime/routes/log-export-routes.ts +28 -10
- package/src/runtime/routes/mcp-auth-routes.ts +25 -0
- package/src/runtime/routes/memory-item-routes.ts +21 -10
- package/src/runtime/routes/memory-v2-routes.ts +90 -36
- package/src/runtime/routes/memory-v3-routes.ts +273 -407
- package/src/runtime/routes/migration-rollback-routes.ts +5 -1
- package/src/runtime/routes/migration-routes.ts +29 -0
- package/src/runtime/routes/notification-routes.ts +17 -1
- package/src/runtime/routes/oauth-apps.ts +33 -11
- package/src/runtime/routes/oauth-commands-routes.ts +37 -14
- package/src/runtime/routes/oauth-connect-routes.ts +9 -0
- package/src/runtime/routes/oauth-lifecycle-routes.ts +5 -1
- package/src/runtime/routes/oauth-providers.ts +35 -10
- package/src/runtime/routes/platform-routes.ts +21 -0
- package/src/runtime/routes/playground/__tests__/force-compact.test.ts +3 -2
- package/src/runtime/routes/playground/__tests__/inject-failures.test.ts +37 -16
- package/src/runtime/routes/playground/__tests__/reset-circuit.test.ts +7 -3
- package/src/runtime/routes/playground/__tests__/state.test.ts +10 -3
- package/src/runtime/routes/playground/force-compact.ts +1 -1
- package/src/runtime/routes/playground/helpers.ts +0 -1
- package/src/runtime/routes/playground/inject-failures.ts +13 -8
- package/src/runtime/routes/playground/reset-circuit.ts +14 -9
- package/src/runtime/routes/playground/seed-conversation.ts +1 -1
- package/src/runtime/routes/playground/seeded-conversations.ts +3 -3
- package/src/runtime/routes/playground/state.ts +4 -3
- package/src/runtime/routes/plugins-routes.ts +22 -19
- package/src/runtime/routes/profiler-routes.ts +17 -4
- package/src/runtime/routes/ps-routes.ts +5 -0
- package/src/runtime/routes/publish-routes.ts +13 -3
- package/src/runtime/routes/question-routes.ts +5 -0
- package/src/runtime/routes/recording-routes.ts +25 -12
- package/src/runtime/routes/rename-conversation-routes.ts +5 -0
- package/src/runtime/routes/sanity-routes.ts +9 -2
- package/src/runtime/routes/schedule-routes.ts +137 -47
- package/src/runtime/routes/secret-routes.ts +17 -4
- package/src/runtime/routes/sequence-routes.ts +33 -0
- package/src/runtime/routes/settings-routes.ts +65 -19
- package/src/runtime/routes/skills-routes.ts +133 -69
- package/src/runtime/routes/slack-channel-routes.ts +5 -0
- package/src/runtime/routes/stt-routes.ts +13 -6
- package/src/runtime/routes/subagents-routes.ts +24 -18
- package/src/runtime/routes/suggest-trust-rule-routes.ts +7 -2
- package/src/runtime/routes/surface-action-routes.ts +9 -0
- package/src/runtime/routes/surface-content-routes.ts +10 -2
- package/src/runtime/routes/task-routes.ts +37 -0
- package/src/runtime/routes/telemetry-routes.ts +9 -0
- package/src/runtime/routes/trace-event-routes.ts +42 -1
- package/src/runtime/routes/trust-rules-routes.ts +5 -0
- package/src/runtime/routes/tts-routes.ts +13 -6
- package/src/runtime/routes/types.ts +17 -8
- package/src/runtime/routes/ui-request-routes.ts +5 -0
- package/src/runtime/routes/upgrade-broadcast-routes.ts +5 -0
- package/src/runtime/routes/usage-routes.ts +71 -3
- package/src/runtime/routes/user-routes-cli.ts +9 -0
- package/src/runtime/routes/user-routes.ts +5 -1
- package/src/runtime/routes/wake-conversation-routes.ts +5 -0
- package/src/runtime/routes/watcher-routes.ts +21 -0
- package/src/runtime/routes/webhook-routes.ts +9 -0
- package/src/runtime/routes/wipe-conversation-routes.ts +5 -0
- package/src/runtime/routes/work-items-routes.ts +47 -19
- package/src/runtime/routes/workspace-commit-routes.ts +5 -0
- package/src/runtime/routes/workspace-routes.test.ts +42 -0
- package/src/runtime/routes/workspace-routes.ts +120 -9
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +2 -4
- package/src/runtime/services/analyze-conversation.ts +3 -6
- package/src/runtime/services/conversation-serializer.ts +24 -2
- package/src/runtime/sync/resource-sync-events.ts +16 -2
- package/src/runtime/sync/sync-publisher.ts +2 -2
- package/src/schedule/run-script.ts +28 -3
- package/src/schedule/schedule-store.ts +8 -0
- package/src/schedule/scheduler.ts +3 -1
- package/src/signals/user-message.ts +5 -8
- package/src/skills/catalog-files.ts +4 -1
- package/src/skills/clawhub-files.ts +2 -0
- package/src/skills/skillssh-files.ts +2 -0
- package/src/subagent/manager.ts +3 -6
- package/src/telemetry/types.ts +26 -0
- package/src/telemetry/usage-telemetry-reporter.test.ts +138 -1
- package/src/telemetry/usage-telemetry-reporter.ts +31 -0
- package/src/tools/acp/spawn.test.ts +88 -38
- package/src/tools/apps/definitions.ts +8 -4
- package/src/tools/ask-question/ask-question-tool.test.ts +120 -105
- package/src/tools/ask-question/ask-question-tool.ts +85 -90
- package/src/tools/computer-use/definitions.ts +28 -24
- package/src/tools/credential-execution/make-authenticated-request.ts +56 -51
- package/src/tools/credential-execution/manage-secure-command-tool.ts +2 -2
- package/src/tools/credential-execution/run-authenticated-command.ts +82 -77
- package/src/tools/credentials/vault.ts +112 -111
- package/src/tools/execution-target.ts +1 -1
- package/src/tools/execution-timeout.ts +3 -4
- package/src/tools/filesystem/edit.ts +45 -42
- package/src/tools/filesystem/list.ts +33 -30
- package/src/tools/filesystem/read.ts +54 -35
- package/src/tools/filesystem/write.ts +34 -31
- package/src/tools/host-filesystem/edit.ts +44 -42
- package/src/tools/host-filesystem/read.ts +49 -35
- package/src/tools/host-filesystem/transfer.ts +121 -108
- package/src/tools/host-filesystem/write.ts +33 -31
- package/src/tools/host-terminal/host-shell.ts +50 -48
- package/src/tools/memory/register.ts +23 -24
- package/src/tools/network/web-fetch.ts +49 -46
- package/src/tools/network/web-search.ts +16 -13
- package/src/tools/registry.ts +39 -16
- package/src/tools/schedule/create.ts +11 -0
- package/src/tools/schedule/update.ts +16 -0
- package/src/tools/shared/filesystem/audio-read.ts +122 -0
- package/src/tools/shared/filesystem/image-read.ts +1 -1
- package/src/tools/skills/execute.ts +34 -31
- package/src/tools/skills/load.ts +29 -23
- package/src/tools/subagent/notify-parent.ts +35 -32
- package/src/tools/system/avatar-generator.ts +13 -22
- package/src/tools/system/request-permission.ts +30 -27
- package/src/tools/terminal/shell.ts +190 -61
- package/src/tools/tool-defaults.ts +20 -9
- package/src/tools/tool-manifest.ts +4 -4
- package/src/tools/types.ts +74 -23
- package/src/tools/ui-surface/definitions.ts +69 -9
- package/src/usage/types.ts +10 -0
- package/src/util/errors.ts +2 -2
- package/src/util/map-limit.ts +27 -0
- package/src/util/platform.ts +15 -12
- package/src/work-items/work-item-runner.ts +7 -2
- package/src/workspace/migrations/028-recover-conversations-from-disk-view.ts +7 -20
- package/src/workspace/migrations/092-backfill-v3-leaves.ts +169 -0
- package/src/workspace/migrations/093-backfill-leaf-ids.ts +144 -0
- package/src/workspace/migrations/094-seed-avatar-manifest.ts +155 -0
- package/src/workspace/migrations/__tests__/094-seed-avatar-manifest.test.ts +136 -0
- package/src/workspace/migrations/__tests__/backfill-leaf-ids.test.ts +175 -0
- package/src/workspace/migrations/__tests__/backfill-v3-leaves.test.ts +124 -0
- package/src/workspace/migrations/registry.ts +6 -0
- package/src/workspace/provider-commit-message-generator.ts +15 -17
- package/tsconfig.json +4 -1
- package/src/__tests__/history-repair-pipeline.test.ts +0 -396
- package/src/cli/commands/__tests__/memory-v3-render.test.ts +0 -340
- package/src/cli/commands/memory-v3-render.ts +0 -491
- package/src/daemon/message-types/disk-pressure.ts +0 -9
- package/src/email/feature-gate.ts +0 -23
- package/src/memory/v3/__tests__/coactivation-store.test.ts +0 -422
- package/src/memory/v3/__tests__/consolidation-job.test.ts +0 -466
- package/src/memory/v3/__tests__/coretrieval-seed.test.ts +0 -270
- package/src/memory/v3/__tests__/edge-learning-job.test.ts +0 -324
- package/src/memory/v3/__tests__/edges.test.ts +0 -706
- package/src/memory/v3/__tests__/filter.test.ts +0 -560
- package/src/memory/v3/__tests__/gate.test.ts +0 -637
- package/src/memory/v3/__tests__/index-composition.test.ts +0 -291
- package/src/memory/v3/__tests__/loop.test.ts +0 -775
- package/src/memory/v3/__tests__/retriever.test.ts +0 -226
- package/src/memory/v3/__tests__/scouts.test.ts +0 -489
- package/src/memory/v3/__tests__/shadow-diff.test.ts +0 -225
- package/src/memory/v3/__tests__/shadow-middleware.test.ts +0 -398
- package/src/memory/v3/__tests__/system-prompts.test.ts +0 -154
- package/src/memory/v3/__tests__/traversal.test.ts +0 -508
- package/src/memory/v3/__tests__/tree-index.test.ts +0 -280
- package/src/memory/v3/__tests__/tree-store.test.ts +0 -529
- package/src/memory/v3/__tests__/tree-walk.test.ts +0 -784
- package/src/memory/v3/__tests__/validate.test.ts +0 -277
- package/src/memory/v3/auto-edges.ts +0 -223
- package/src/memory/v3/coactivation-store.ts +0 -124
- package/src/memory/v3/consolidation-job.ts +0 -323
- package/src/memory/v3/coretrieval-seed.ts +0 -240
- package/src/memory/v3/edge-learning-job.ts +0 -160
- package/src/memory/v3/edges.ts +0 -286
- package/src/memory/v3/filter.ts +0 -286
- package/src/memory/v3/gate.ts +0 -349
- package/src/memory/v3/index-composition.ts +0 -126
- package/src/memory/v3/llm-capture.ts +0 -46
- package/src/memory/v3/loop.ts +0 -430
- package/src/memory/v3/maintenance.ts +0 -144
- package/src/memory/v3/prompt-context.ts +0 -33
- package/src/memory/v3/prompts/consolidation.ts +0 -458
- package/src/memory/v3/prompts/system-prompts.ts +0 -196
- package/src/memory/v3/retriever.ts +0 -33
- package/src/memory/v3/scouts.ts +0 -431
- package/src/memory/v3/shadow-diff.ts +0 -287
- package/src/memory/v3/shadow-middleware.ts +0 -347
- package/src/memory/v3/traversal.ts +0 -211
- package/src/memory/v3/tree-index.ts +0 -237
- package/src/memory/v3/tree-store.ts +0 -394
- package/src/memory/v3/tree-walk.ts +0 -356
- package/src/memory/v3/validate.ts +0 -323
- package/src/plugins/defaults/circuit-breaker.ts +0 -141
- package/src/plugins/defaults/compaction.ts +0 -141
- package/src/plugins/defaults/empty-response.ts +0 -124
- package/src/plugins/defaults/history-repair.ts +0 -83
- package/src/plugins/defaults/persistence.ts +0 -146
- package/src/plugins/defaults/title-generate.ts +0 -90
- package/src/plugins/defaults/token-estimate.ts +0 -101
- package/src/plugins/defaults/tool-error.ts +0 -119
- package/src/plugins/defaults/tool-result-truncate.ts +0 -84
- package/src/runtime/routes/__tests__/memory-v3-simulate-params.test.ts +0 -35
package/src/agent/loop.ts
CHANGED
|
@@ -7,23 +7,34 @@ import {
|
|
|
7
7
|
getCalibrationProviderKey,
|
|
8
8
|
} from "../context/token-estimator.js";
|
|
9
9
|
import { calculateMaxToolResultChars } from "../context/tool-result-truncation.js";
|
|
10
|
+
import type { ContextWindowResult } from "../context/window-manager.js";
|
|
10
11
|
import type { ToolActivityMetadata } from "../daemon/message-types/web-activity.js";
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
12
|
+
import { defaultCompactionTerminal } from "../plugins/defaults/compaction/terminal.js";
|
|
13
|
+
import { defaultEmptyResponseTerminal } from "../plugins/defaults/empty-response/terminal.js";
|
|
14
|
+
import { defaultTokenEstimateTerminal } from "../plugins/defaults/token-estimate/terminal.js";
|
|
15
|
+
import { defaultToolErrorTerminal } from "../plugins/defaults/tool-error/terminal.js";
|
|
16
|
+
import { defaultToolResultTruncateTerminal } from "../plugins/defaults/tool-result-truncate/terminal.js";
|
|
17
|
+
import type {
|
|
18
|
+
ToolResultTruncateArgs,
|
|
19
|
+
ToolResultTruncateResult,
|
|
20
|
+
} from "../plugins/defaults/tool-result-truncate/types.js";
|
|
14
21
|
import { DEFAULT_TIMEOUTS, runPipeline } from "../plugins/pipeline.js";
|
|
15
22
|
import { getMiddlewaresFor } from "../plugins/registry.js";
|
|
16
23
|
import type {
|
|
24
|
+
CompactionArgs,
|
|
25
|
+
CompactionCircuitEvent,
|
|
26
|
+
CompactionResult,
|
|
17
27
|
EmptyResponseArgs,
|
|
18
28
|
EmptyResponseDecision,
|
|
29
|
+
EstimateArgs,
|
|
30
|
+
EstimateResult,
|
|
19
31
|
LLMCallArgs,
|
|
20
32
|
LLMCallResult,
|
|
21
33
|
ToolErrorArgs,
|
|
22
34
|
ToolErrorDecision,
|
|
23
|
-
ToolResultTruncateArgs,
|
|
24
|
-
ToolResultTruncateResult,
|
|
25
35
|
TurnContext,
|
|
26
36
|
} from "../plugins/types.js";
|
|
37
|
+
import { PluginTimeoutError } from "../plugins/types.js";
|
|
27
38
|
import { normalizeThinkingConfigForWire } from "../providers/thinking-config.js";
|
|
28
39
|
import type {
|
|
29
40
|
ContentBlock,
|
|
@@ -40,9 +51,17 @@ import {
|
|
|
40
51
|
import { AssistantError, ErrorCode, ProviderError } from "../util/errors.js";
|
|
41
52
|
import { getLogger } from "../util/logger.js";
|
|
42
53
|
import { isRetryableNetworkError } from "../util/retry.js";
|
|
54
|
+
import { CompactionCircuit } from "./compaction-circuit.js";
|
|
43
55
|
|
|
44
56
|
const log = getLogger("agent-loop");
|
|
45
57
|
|
|
58
|
+
/** Fraction of the preflight budget at which a checkpoint triggers mid-loop compaction. */
|
|
59
|
+
const MID_LOOP_YIELD_THRESHOLD_RATIO = 0.85;
|
|
60
|
+
|
|
61
|
+
/** In-context message count above which the budget gate raises the safety-margin floor. */
|
|
62
|
+
const LONG_HISTORY_MESSAGE_THRESHOLD = 50;
|
|
63
|
+
const LONG_HISTORY_SAFETY_MARGIN_FLOOR = 0.15;
|
|
64
|
+
|
|
46
65
|
export interface AgentLoopConfig {
|
|
47
66
|
maxTokens: number;
|
|
48
67
|
maxInputTokens?: number; // context window size for tool result truncation
|
|
@@ -66,7 +85,28 @@ export interface CheckpointInfo {
|
|
|
66
85
|
history: Message[]; // current history snapshot for token estimation
|
|
67
86
|
}
|
|
68
87
|
|
|
69
|
-
|
|
88
|
+
/**
|
|
89
|
+
* Why a checkpoint paused the loop. Surfaced back to the caller via
|
|
90
|
+
* {@link AgentLoopRunResult.exitReason} so the orchestrator reacts to
|
|
91
|
+
* the loop's own signal (hand off to a queued message vs. compact and
|
|
92
|
+
* re-enter) instead of the checkpoint callback mutating orchestrator state.
|
|
93
|
+
*/
|
|
94
|
+
export type ExitReason = "handoff" | "budget";
|
|
95
|
+
|
|
96
|
+
export type CheckpointDecision = "continue" | ExitReason;
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Result of {@link AgentLoop.run}.
|
|
100
|
+
*
|
|
101
|
+
* `exitReason` carries the reason the loop paused at a checkpoint so the
|
|
102
|
+
* orchestrator reads the loop's own signal instead of inferring it from
|
|
103
|
+
* callback side-effects. It is `null` whenever the loop reached a terminal
|
|
104
|
+
* stop (completion, error, abort, or a tool-requested yield-to-user).
|
|
105
|
+
*/
|
|
106
|
+
export interface AgentLoopRunResult {
|
|
107
|
+
history: Message[];
|
|
108
|
+
exitReason: ExitReason | null;
|
|
109
|
+
}
|
|
70
110
|
|
|
71
111
|
/**
|
|
72
112
|
* Why an agent turn reached a terminal state.
|
|
@@ -246,6 +286,24 @@ export type AgentEvent =
|
|
|
246
286
|
*/
|
|
247
287
|
estimatedInputTokens?: number;
|
|
248
288
|
}
|
|
289
|
+
| {
|
|
290
|
+
/**
|
|
291
|
+
* Emitted when the loop begins compacting the running history because
|
|
292
|
+
* the mid-loop budget gate tripped. The daemon's event dispatcher
|
|
293
|
+
* translates it into a "compacting context" activity state so clients
|
|
294
|
+
* surface that the turn paused to summarize context.
|
|
295
|
+
*/
|
|
296
|
+
type: "context_compacting";
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Circuit-breaker transitions emitted when auto-compaction is paused
|
|
300
|
+
* (`compaction_circuit_open`, after three consecutive summary-LLM
|
|
301
|
+
* failures) or resumed (`compaction_circuit_closed`). These are already
|
|
302
|
+
* in wire-contract shape; the daemon's event dispatcher forwards them to
|
|
303
|
+
* the client unchanged so the "auto-compaction paused" banner shows and
|
|
304
|
+
* dismisses.
|
|
305
|
+
*/
|
|
306
|
+
| CompactionCircuitEvent
|
|
249
307
|
| {
|
|
250
308
|
/**
|
|
251
309
|
* Emitted when an agent turn reaches a terminal state. Checkpoint
|
|
@@ -378,6 +436,86 @@ export interface ResolvedSystemPrompt {
|
|
|
378
436
|
model?: string;
|
|
379
437
|
}
|
|
380
438
|
|
|
439
|
+
/**
|
|
440
|
+
* Orchestrator-supplied hooks the loop invokes when the mid-loop budget gate
|
|
441
|
+
* trips and inline compaction runs. The loop owns the trigger, the
|
|
442
|
+
* `compaction` pipeline call, the result interpretation (circuit-breaker
|
|
443
|
+
* bookkeeping + the exhaustion decision), and the inline continue; these hooks
|
|
444
|
+
* bridge the durable / injection state the loop is intentionally blind to.
|
|
445
|
+
* Durable persistence ({@link applyResult}) and re-injection
|
|
446
|
+
* ({@link reinject}) remain orchestrator-supplied for now and are expected to
|
|
447
|
+
* move into the loop in a future change.
|
|
448
|
+
*/
|
|
449
|
+
export interface MidLoopCompaction {
|
|
450
|
+
/** Strip runtime injections, commit stripped messages, and resolve pipeline options. */
|
|
451
|
+
prepare: (history: Message[]) => {
|
|
452
|
+
rawHistory: Message[];
|
|
453
|
+
options: CompactionArgs["options"];
|
|
454
|
+
};
|
|
455
|
+
/** Commit a successful compaction result to durable state. */
|
|
456
|
+
applyResult: (
|
|
457
|
+
result: ContextWindowResult,
|
|
458
|
+
rawHistory: Message[],
|
|
459
|
+
) => Promise<void>;
|
|
460
|
+
/** Re-apply runtime injections and return the history to continue from. */
|
|
461
|
+
reinject: () => Promise<Message[]>;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
export interface AgentLoopRunOptions {
|
|
465
|
+
signal?: AbortSignal;
|
|
466
|
+
requestId?: string;
|
|
467
|
+
onCheckpoint?: (
|
|
468
|
+
checkpoint: CheckpointInfo,
|
|
469
|
+
) => CheckpointDecision | Promise<CheckpointDecision>;
|
|
470
|
+
callSite?: LLMCallSite;
|
|
471
|
+
/**
|
|
472
|
+
* Per-turn context supplied by the orchestrator. Every pipeline
|
|
473
|
+
* invocation inside the loop clones from this value (overwriting only
|
|
474
|
+
* `turnIndex`/`requestId`) so middleware sees the real conversation
|
|
475
|
+
* identity, trust class, and `contextWindowManager` rather than the
|
|
476
|
+
* `"agent-loop"` sentinel used when the loop is instantiated standalone
|
|
477
|
+
* in unit tests.
|
|
478
|
+
*/
|
|
479
|
+
turnContext?: TurnContext;
|
|
480
|
+
/**
|
|
481
|
+
* Ad-hoc inference-profile override applied to every LLM call the loop
|
|
482
|
+
* issues. When set, each `SendMessageOptions.config` carries
|
|
483
|
+
* `overrideProfile = <name>` so the provider's resolver layers
|
|
484
|
+
* `llm.profiles[<name>]` between the workspace `activeProfile` and any
|
|
485
|
+
* call-site named profile. Missing profile names silently fall through.
|
|
486
|
+
*/
|
|
487
|
+
overrideProfile?: string;
|
|
488
|
+
resolveOverrideProfile?: () => string | undefined;
|
|
489
|
+
/**
|
|
490
|
+
* Resolves the orchestrator's effective context window for this turn: the
|
|
491
|
+
* provider max-input-token ceiling (read by tool-result truncation) plus the
|
|
492
|
+
* `overflowRecovery` config that drives the mid-loop budget gate. Resolved
|
|
493
|
+
* fresh per checkpoint so a mid-turn profile change is reflected. Absent →
|
|
494
|
+
* truncation falls back to `this.config.maxInputTokens` and the budget gate
|
|
495
|
+
* is skipped (agent wakes pass `overflowRecovery.enabled = false`).
|
|
496
|
+
*/
|
|
497
|
+
resolveContextWindow?: () => {
|
|
498
|
+
maxInputTokens: number;
|
|
499
|
+
overflowRecovery: { enabled: boolean; safetyMarginRatio: number };
|
|
500
|
+
};
|
|
501
|
+
/**
|
|
502
|
+
* Hooks for inline mid-loop compaction. When supplied and the budget gate
|
|
503
|
+
* trips, the loop compacts in place and continues instead of yielding
|
|
504
|
+
* `exitReason = "budget"`. Callers without a compaction path (agent wakes,
|
|
505
|
+
* convergence/auto-compress reruns) omit this and keep yielding for budget.
|
|
506
|
+
*/
|
|
507
|
+
compaction?: MidLoopCompaction;
|
|
508
|
+
/**
|
|
509
|
+
* When true, the latest user message carries a volatile per-turn block
|
|
510
|
+
* (e.g. a memory-v3 `<memory>` injection) that varies across otherwise
|
|
511
|
+
* identical turns. Forwarded to each `SendMessageOptions.config` so the
|
|
512
|
+
* provider anchors its long-TTL cache breakpoint on the most recent STABLE
|
|
513
|
+
* user message instead of the volatile latest one, keeping the cached
|
|
514
|
+
* prefix reusable. Default unset → existing behavior.
|
|
515
|
+
*/
|
|
516
|
+
mutableLatestUserMessage?: boolean;
|
|
517
|
+
}
|
|
518
|
+
|
|
381
519
|
/**
|
|
382
520
|
* Callback shape the loop uses to execute a tool invocation.
|
|
383
521
|
*
|
|
@@ -425,6 +563,20 @@ export type LoopToolExecutor = (
|
|
|
425
563
|
activityMetadata?: ToolActivityMetadata;
|
|
426
564
|
}>;
|
|
427
565
|
|
|
566
|
+
export interface AgentLoopConstructorOptions {
|
|
567
|
+
config?: Partial<AgentLoopConfig>;
|
|
568
|
+
tools?: ToolDefinition[];
|
|
569
|
+
toolExecutor?: LoopToolExecutor;
|
|
570
|
+
resolveTools?: (history: Message[]) => ToolDefinition[];
|
|
571
|
+
resolveSystemPrompt?: (history: Message[]) => ResolvedSystemPrompt;
|
|
572
|
+
/**
|
|
573
|
+
* Conversation this loop drives. Used to scope the loop-held compaction
|
|
574
|
+
* circuit breaker; defaults to an empty key for test loops that never
|
|
575
|
+
* exercise compaction.
|
|
576
|
+
*/
|
|
577
|
+
conversationId?: string;
|
|
578
|
+
}
|
|
579
|
+
|
|
428
580
|
export class AgentLoop {
|
|
429
581
|
private provider: Provider;
|
|
430
582
|
private systemPrompt: string;
|
|
@@ -436,15 +588,28 @@ export class AgentLoop {
|
|
|
436
588
|
| null;
|
|
437
589
|
private toolExecutor: LoopToolExecutor | null;
|
|
438
590
|
|
|
591
|
+
/**
|
|
592
|
+
* Loop-held compaction circuit breaker. The loop has a 1:1 lifetime with its
|
|
593
|
+
* conversation, so it is the source of truth for the cross-turn failure
|
|
594
|
+
* counter and cooldown deadline. Non-loop callers (the orchestrator's
|
|
595
|
+
* compaction paths, `Conversation.forceCompact`, and the dev-only playground
|
|
596
|
+
* routes) reach it via `agentLoop.compactionCircuit`.
|
|
597
|
+
*/
|
|
598
|
+
readonly compactionCircuit: CompactionCircuit;
|
|
599
|
+
|
|
439
600
|
constructor(
|
|
440
601
|
provider: Provider,
|
|
441
602
|
systemPrompt: string,
|
|
442
|
-
|
|
443
|
-
tools?: ToolDefinition[],
|
|
444
|
-
toolExecutor?: LoopToolExecutor,
|
|
445
|
-
resolveTools?: (history: Message[]) => ToolDefinition[],
|
|
446
|
-
resolveSystemPrompt?: (history: Message[]) => ResolvedSystemPrompt,
|
|
603
|
+
options?: AgentLoopConstructorOptions,
|
|
447
604
|
) {
|
|
605
|
+
const {
|
|
606
|
+
config,
|
|
607
|
+
tools,
|
|
608
|
+
toolExecutor,
|
|
609
|
+
resolveTools,
|
|
610
|
+
resolveSystemPrompt,
|
|
611
|
+
conversationId,
|
|
612
|
+
} = options ?? {};
|
|
448
613
|
this.provider = provider;
|
|
449
614
|
this.systemPrompt = systemPrompt;
|
|
450
615
|
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
@@ -452,6 +617,7 @@ export class AgentLoop {
|
|
|
452
617
|
this.resolveTools = resolveTools ?? null;
|
|
453
618
|
this.resolveSystemPrompt = resolveSystemPrompt ?? null;
|
|
454
619
|
this.toolExecutor = toolExecutor ?? null;
|
|
620
|
+
this.compactionCircuit = new CompactionCircuit(conversationId ?? "");
|
|
455
621
|
}
|
|
456
622
|
|
|
457
623
|
/**
|
|
@@ -481,44 +647,148 @@ export class AgentLoop {
|
|
|
481
647
|
return estimateToolsTokens(this.getResolvedTools(history));
|
|
482
648
|
}
|
|
483
649
|
|
|
650
|
+
/**
|
|
651
|
+
* Estimate total prompt tokens for `history` via the `tokenEstimate`
|
|
652
|
+
* pipeline. Args are shallow-frozen so a mutating middleware cannot strip
|
|
653
|
+
* context from the loop's live `history`.
|
|
654
|
+
*/
|
|
655
|
+
private estimateTokens(
|
|
656
|
+
history: Message[],
|
|
657
|
+
turnContext: TurnContext,
|
|
658
|
+
): Promise<EstimateResult> {
|
|
659
|
+
return runPipeline<EstimateArgs, EstimateResult>(
|
|
660
|
+
"tokenEstimate",
|
|
661
|
+
getMiddlewaresFor("tokenEstimate"),
|
|
662
|
+
defaultTokenEstimateTerminal,
|
|
663
|
+
{
|
|
664
|
+
history: Object.freeze([...history]) as Message[],
|
|
665
|
+
systemPrompt: this.systemPrompt,
|
|
666
|
+
tools: Object.freeze([
|
|
667
|
+
...this.getResolvedTools(history),
|
|
668
|
+
]) as ToolDefinition[],
|
|
669
|
+
providerName: getCalibrationProviderKey(this.provider),
|
|
670
|
+
},
|
|
671
|
+
turnContext,
|
|
672
|
+
DEFAULT_TIMEOUTS.tokenEstimate,
|
|
673
|
+
);
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
/**
|
|
677
|
+
* Record a compaction outcome against the loop's circuit breaker. Three
|
|
678
|
+
* consecutive failures trip a cooldown that suspends auto-compaction; a
|
|
679
|
+
* success resets the counter. Any open/closed transition is emitted on the
|
|
680
|
+
* loop's own event channel via `onEvent`.
|
|
681
|
+
*
|
|
682
|
+
* Bookkeeping is best-effort — a failure here must not turn a recoverable
|
|
683
|
+
* compaction outcome into a user-visible turn failure.
|
|
684
|
+
*/
|
|
685
|
+
private async recordCompactionOutcome(
|
|
686
|
+
turnContext: TurnContext,
|
|
687
|
+
summaryFailed: boolean,
|
|
688
|
+
onEvent: (event: AgentEvent) => void | Promise<void>,
|
|
689
|
+
): Promise<void> {
|
|
690
|
+
try {
|
|
691
|
+
await this.compactionCircuit.recordOutcome(
|
|
692
|
+
{
|
|
693
|
+
currentRequestId: turnContext.requestId,
|
|
694
|
+
currentTurnTrustContext: turnContext.trust,
|
|
695
|
+
turnCount: turnContext.turnIndex,
|
|
696
|
+
},
|
|
697
|
+
summaryFailed,
|
|
698
|
+
onEvent,
|
|
699
|
+
);
|
|
700
|
+
} catch (recordError) {
|
|
701
|
+
log.error(
|
|
702
|
+
{ err: recordError, requestId: turnContext.requestId },
|
|
703
|
+
"Recording a compaction outcome against the circuit breaker failed; suppressing to keep the agent loop alive",
|
|
704
|
+
);
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
/**
|
|
709
|
+
* Compact the running history in place when the mid-loop budget gate trips.
|
|
710
|
+
*
|
|
711
|
+
* Runs the `compaction` pipeline natively (like {@link estimateTokens}) on
|
|
712
|
+
* the stripped history, then re-applies injections via the supplied hooks.
|
|
713
|
+
* Returns the history to continue from, or `null` when the compactor timed
|
|
714
|
+
* out or exhausted its retry budget so the caller yields
|
|
715
|
+
* `exitReason = "budget"` and the orchestrator escalates.
|
|
716
|
+
*/
|
|
717
|
+
private async compact(
|
|
718
|
+
history: Message[],
|
|
719
|
+
turnContext: TurnContext,
|
|
720
|
+
compaction: MidLoopCompaction,
|
|
721
|
+
signal: AbortSignal | undefined,
|
|
722
|
+
onEvent: (event: AgentEvent) => void | Promise<void>,
|
|
723
|
+
): Promise<Message[] | null> {
|
|
724
|
+
await onEvent({ type: "context_compacting" });
|
|
725
|
+
const { rawHistory, options } = compaction.prepare(history);
|
|
726
|
+
let result: CompactionResult;
|
|
727
|
+
try {
|
|
728
|
+
result = await runPipeline<CompactionArgs, CompactionResult>(
|
|
729
|
+
"compaction",
|
|
730
|
+
getMiddlewaresFor("compaction"),
|
|
731
|
+
(args) => defaultCompactionTerminal(args, turnContext),
|
|
732
|
+
{ messages: rawHistory, signal, options },
|
|
733
|
+
turnContext,
|
|
734
|
+
DEFAULT_TIMEOUTS.compaction,
|
|
735
|
+
);
|
|
736
|
+
} catch (error) {
|
|
737
|
+
if (error instanceof PluginTimeoutError) {
|
|
738
|
+
// A timeout counts as a compaction failure against the circuit breaker.
|
|
739
|
+
await this.recordCompactionOutcome(turnContext, true, onEvent);
|
|
740
|
+
return null;
|
|
741
|
+
}
|
|
742
|
+
throw error;
|
|
743
|
+
}
|
|
744
|
+
// `CompactionResult` is intentionally `unknown` at the plugin boundary so
|
|
745
|
+
// plugin consumers don't import the window manager; the loop ran the
|
|
746
|
+
// pipeline, so it interprets the concrete result here.
|
|
747
|
+
const compactResult = result as ContextWindowResult;
|
|
748
|
+
// `force: true` bypasses the cooldown/threshold gates, but early returns
|
|
749
|
+
// for "no eligible messages" / "insufficient messages" still leave
|
|
750
|
+
// `summaryFailed` undefined. Only record an outcome when the summary LLM
|
|
751
|
+
// actually ran.
|
|
752
|
+
if (compactResult.summaryFailed !== undefined) {
|
|
753
|
+
await this.recordCompactionOutcome(
|
|
754
|
+
turnContext,
|
|
755
|
+
compactResult.summaryFailed,
|
|
756
|
+
onEvent,
|
|
757
|
+
);
|
|
758
|
+
}
|
|
759
|
+
if (compactResult.compacted) {
|
|
760
|
+
await compaction.applyResult(compactResult, rawHistory);
|
|
761
|
+
}
|
|
762
|
+
if (compactResult.exhausted ?? false) {
|
|
763
|
+
return null;
|
|
764
|
+
}
|
|
765
|
+
return compaction.reinject();
|
|
766
|
+
}
|
|
767
|
+
|
|
484
768
|
async run(
|
|
485
769
|
messages: Message[],
|
|
486
770
|
onEvent: (event: AgentEvent) => void | Promise<void>,
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
* Optional ad-hoc inference-profile override applied to every LLM call
|
|
504
|
-
* the loop issues. When set, each `SendMessageOptions.config` carries
|
|
505
|
-
* `overrideProfile = <name>` so the provider's resolver layers
|
|
506
|
-
* `llm.profiles[<name>]` between the workspace `activeProfile` and any
|
|
507
|
-
* call-site named profile. Missing profile names silently fall through.
|
|
508
|
-
* Used by per-conversation pinned profiles to override the workspace
|
|
509
|
-
* default for the lifetime of an agent loop run.
|
|
510
|
-
*/
|
|
511
|
-
overrideProfile?: string,
|
|
512
|
-
effectiveMaxInputTokens?: number,
|
|
513
|
-
resolveOverrideProfile?: () => string | undefined,
|
|
514
|
-
resolveEffectiveMaxInputTokens?: () => number | undefined,
|
|
515
|
-
): Promise<Message[]> {
|
|
516
|
-
const history = [...messages];
|
|
517
|
-
const initialHistoryLength = messages.length;
|
|
771
|
+
options?: AgentLoopRunOptions,
|
|
772
|
+
): Promise<AgentLoopRunResult> {
|
|
773
|
+
const {
|
|
774
|
+
signal,
|
|
775
|
+
requestId,
|
|
776
|
+
onCheckpoint,
|
|
777
|
+
callSite,
|
|
778
|
+
turnContext,
|
|
779
|
+
overrideProfile,
|
|
780
|
+
resolveOverrideProfile,
|
|
781
|
+
resolveContextWindow,
|
|
782
|
+
compaction,
|
|
783
|
+
mutableLatestUserMessage,
|
|
784
|
+
} = options ?? {};
|
|
785
|
+
let history = [...messages];
|
|
786
|
+
let producedVisibleTextThisRun = false;
|
|
518
787
|
let toolUseTurns = 0;
|
|
519
788
|
let consecutiveErrorTurns = 0;
|
|
520
789
|
let emptyResponseRetries = 0;
|
|
521
790
|
let lastLlmCallTime = 0;
|
|
791
|
+
let exitReason: ExitReason | null = null;
|
|
522
792
|
const rlog = requestId ? log.child({ requestId }) : log;
|
|
523
793
|
|
|
524
794
|
// Per-run substitution map for sensitive output placeholders.
|
|
@@ -617,6 +887,15 @@ export class AgentLoop {
|
|
|
617
887
|
providerConfig.cacheTtl = this.config.cacheTtl;
|
|
618
888
|
}
|
|
619
889
|
|
|
890
|
+
// Cache-anchor signal for volatile latest-user-message turns (e.g.
|
|
891
|
+
// memory-v3 injects its `<memory>` block into the latest user
|
|
892
|
+
// message). Not part of the call-site schema, so it is always sourced
|
|
893
|
+
// from the per-run option regardless of `callSite`. Only set when true
|
|
894
|
+
// so the wire/config stays byte-identical when off.
|
|
895
|
+
if (mutableLatestUserMessage) {
|
|
896
|
+
providerConfig.mutableLatestUserMessage = true;
|
|
897
|
+
}
|
|
898
|
+
|
|
620
899
|
// Per-call LLM call-site identifier. Surfaces on the per-call
|
|
621
900
|
// `config.callSite` so `RetryProvider.normalizeSendMessageOptions`
|
|
622
901
|
// can route through `resolveCallSiteConfig` against
|
|
@@ -692,7 +971,7 @@ export class AgentLoop {
|
|
|
692
971
|
// Also strip old AX tree snapshots to keep TTFT from growing
|
|
693
972
|
// linearly with step count in computer-use sessions.
|
|
694
973
|
const providerHistory = compactAxTreeHistory(
|
|
695
|
-
|
|
974
|
+
stripOldMediaBlocks(history),
|
|
696
975
|
);
|
|
697
976
|
|
|
698
977
|
// Wrap the provider call in the `llmCall` pipeline so middleware
|
|
@@ -711,9 +990,9 @@ export class AgentLoop {
|
|
|
711
990
|
const llmCallArgs: LLMCallArgs = {
|
|
712
991
|
provider: this.provider,
|
|
713
992
|
messages: providerHistory,
|
|
714
|
-
tools: currentTools.length > 0 ? currentTools : undefined,
|
|
715
|
-
systemPrompt: turnSystemPrompt,
|
|
716
993
|
options: {
|
|
994
|
+
tools: currentTools.length > 0 ? currentTools : undefined,
|
|
995
|
+
systemPrompt: turnSystemPrompt,
|
|
717
996
|
config: providerConfig,
|
|
718
997
|
onEvent: (event) => {
|
|
719
998
|
if (event.type === "text_delta") {
|
|
@@ -811,13 +1090,7 @@ export class AgentLoop {
|
|
|
811
1090
|
response = await runPipeline<LLMCallArgs, LLMCallResult>(
|
|
812
1091
|
"llmCall",
|
|
813
1092
|
getMiddlewaresFor("llmCall"),
|
|
814
|
-
(args) =>
|
|
815
|
-
args.provider.sendMessage(
|
|
816
|
-
args.messages,
|
|
817
|
-
args.tools,
|
|
818
|
-
args.systemPrompt,
|
|
819
|
-
args.options,
|
|
820
|
-
),
|
|
1093
|
+
(args) => args.provider.sendMessage(args.messages, args.options),
|
|
821
1094
|
llmCallArgs,
|
|
822
1095
|
turnCtx,
|
|
823
1096
|
DEFAULT_TIMEOUTS.llmCall,
|
|
@@ -839,8 +1112,8 @@ export class AgentLoop {
|
|
|
839
1112
|
const rawRequest = {
|
|
840
1113
|
provider: this.provider.name,
|
|
841
1114
|
messages: llmCallArgs.messages,
|
|
842
|
-
tools: llmCallArgs.tools,
|
|
843
|
-
systemPrompt: llmCallArgs.systemPrompt,
|
|
1115
|
+
tools: llmCallArgs.options?.tools,
|
|
1116
|
+
systemPrompt: llmCallArgs.options?.systemPrompt,
|
|
844
1117
|
config: llmCallArgs.options?.config,
|
|
845
1118
|
};
|
|
846
1119
|
onEvent({
|
|
@@ -972,25 +1245,20 @@ export class AgentLoop {
|
|
|
972
1245
|
// The actual decision (nudge vs. accept vs. error) is delegated to
|
|
973
1246
|
// the `emptyResponse` plugin pipeline. The pipeline returns a
|
|
974
1247
|
// decision; the loop carries out the side-effect (pushing the nudge
|
|
975
|
-
// or surfacing the error). See `plugins/defaults/empty-response.ts`
|
|
1248
|
+
// or surfacing the error). See `plugins/defaults/empty-response/register.ts`
|
|
976
1249
|
// for the default decision logic.
|
|
977
1250
|
const hasVisibleText = response.content.some(
|
|
978
1251
|
(block) => block.type === "text" && block.text.trim().length > 0,
|
|
979
1252
|
);
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
);
|
|
990
|
-
if (hasText) return true;
|
|
991
|
-
}
|
|
992
|
-
return false;
|
|
993
|
-
})();
|
|
1253
|
+
// Track whether the model produced visible text earlier in this
|
|
1254
|
+
// run() invocation. Run-scoped rather than derived from `history` so
|
|
1255
|
+
// it survives inline compaction rewriting the message array: an empty
|
|
1256
|
+
// completion after a compaction must not be nudged into re-sending
|
|
1257
|
+
// text the user already saw.
|
|
1258
|
+
const priorAssistantHadVisibleText = producedVisibleTextThisRun;
|
|
1259
|
+
if (hasVisibleText) {
|
|
1260
|
+
producedVisibleTextThisRun = true;
|
|
1261
|
+
}
|
|
994
1262
|
|
|
995
1263
|
const emptyResponseArgs: EmptyResponseArgs = {
|
|
996
1264
|
responseContent: response.content,
|
|
@@ -999,6 +1267,7 @@ export class AgentLoop {
|
|
|
999
1267
|
emptyResponseRetries,
|
|
1000
1268
|
maxEmptyResponseRetries: MAX_EMPTY_RESPONSE_RETRIES,
|
|
1001
1269
|
priorAssistantHadVisibleText,
|
|
1270
|
+
stopReason: response.stopReason,
|
|
1002
1271
|
};
|
|
1003
1272
|
const emptyResponseCtx = resolveLoopTurnContext(
|
|
1004
1273
|
turnContext,
|
|
@@ -1201,8 +1470,7 @@ export class AgentLoop {
|
|
|
1201
1470
|
// truncation strategy (e.g. a summariser) while the default
|
|
1202
1471
|
// middleware preserves the historical tail-drop behaviour.
|
|
1203
1472
|
const contextWindowTokens =
|
|
1204
|
-
|
|
1205
|
-
effectiveMaxInputTokens ??
|
|
1473
|
+
resolveContextWindow?.().maxInputTokens ??
|
|
1206
1474
|
this.config.maxInputTokens ??
|
|
1207
1475
|
180_000;
|
|
1208
1476
|
const maxChars = calculateMaxToolResultChars(contextWindowTokens);
|
|
@@ -1352,8 +1620,8 @@ export class AgentLoop {
|
|
|
1352
1620
|
history.push({ role: "user", content: resultBlocks });
|
|
1353
1621
|
|
|
1354
1622
|
// Invoke checkpoint callback after tool results are in history.
|
|
1355
|
-
//
|
|
1356
|
-
//
|
|
1623
|
+
// Handoff is offered first so a queued message takes precedence over
|
|
1624
|
+
// the mid-loop budget yield below.
|
|
1357
1625
|
if (onCheckpoint) {
|
|
1358
1626
|
const decision = await onCheckpoint({
|
|
1359
1627
|
turnIndex: toolUseTurns - 1, // 0-based (toolUseTurns was already incremented)
|
|
@@ -1361,7 +1629,60 @@ export class AgentLoop {
|
|
|
1361
1629
|
hasToolUse: true,
|
|
1362
1630
|
history,
|
|
1363
1631
|
});
|
|
1364
|
-
if (decision
|
|
1632
|
+
if (decision !== "continue") {
|
|
1633
|
+
exitReason = decision;
|
|
1634
|
+
break;
|
|
1635
|
+
}
|
|
1636
|
+
}
|
|
1637
|
+
|
|
1638
|
+
// Mid-loop budget gate: when overflow recovery is enabled, estimate
|
|
1639
|
+
// the running context size as it approaches the preflight budget.
|
|
1640
|
+
// With a `compaction` hook the loop compacts in place and continues;
|
|
1641
|
+
// without one it yields (`exitReason = "budget"`) so the orchestrator
|
|
1642
|
+
// can recover before the next provider call risks a hard
|
|
1643
|
+
// context-too-large rejection. Keyed off the loop's own
|
|
1644
|
+
// `history.length` (the messages actually in context this turn,
|
|
1645
|
+
// including tool iterations) rather than the durable conversation
|
|
1646
|
+
// count.
|
|
1647
|
+
const contextWindow = resolveContextWindow?.();
|
|
1648
|
+
if (contextWindow?.overflowRecovery.enabled) {
|
|
1649
|
+
const { maxInputTokens, overflowRecovery } = contextWindow;
|
|
1650
|
+
const safetyMargin =
|
|
1651
|
+
history.length > LONG_HISTORY_MESSAGE_THRESHOLD
|
|
1652
|
+
? Math.max(
|
|
1653
|
+
overflowRecovery.safetyMarginRatio,
|
|
1654
|
+
LONG_HISTORY_SAFETY_MARGIN_FLOOR,
|
|
1655
|
+
)
|
|
1656
|
+
: overflowRecovery.safetyMarginRatio;
|
|
1657
|
+
const preflightBudget = Math.floor(
|
|
1658
|
+
maxInputTokens * (1 - safetyMargin),
|
|
1659
|
+
);
|
|
1660
|
+
const midLoopThreshold =
|
|
1661
|
+
preflightBudget * MID_LOOP_YIELD_THRESHOLD_RATIO;
|
|
1662
|
+
const estimated = await this.estimateTokens(history, turnCtx);
|
|
1663
|
+
if (estimated > midLoopThreshold) {
|
|
1664
|
+
if (compaction) {
|
|
1665
|
+
rlog.info(
|
|
1666
|
+
{ phase: "mid-loop", estimated, threshold: midLoopThreshold },
|
|
1667
|
+
"Token estimate approaching budget — compacting in place",
|
|
1668
|
+
);
|
|
1669
|
+
const compacted = await this.compact(
|
|
1670
|
+
history,
|
|
1671
|
+
turnCtx,
|
|
1672
|
+
compaction,
|
|
1673
|
+
signal,
|
|
1674
|
+
onEvent,
|
|
1675
|
+
);
|
|
1676
|
+
if (compacted) {
|
|
1677
|
+
history = compacted;
|
|
1678
|
+
continue;
|
|
1679
|
+
}
|
|
1680
|
+
}
|
|
1681
|
+
rlog.warn(
|
|
1682
|
+
{ phase: "mid-loop", estimated, threshold: midLoopThreshold },
|
|
1683
|
+
"Token estimate approaching budget — yielding for compaction",
|
|
1684
|
+
);
|
|
1685
|
+
exitReason = "budget";
|
|
1365
1686
|
break;
|
|
1366
1687
|
}
|
|
1367
1688
|
}
|
|
@@ -1412,7 +1733,7 @@ export class AgentLoop {
|
|
|
1412
1733
|
"Agent loop exited",
|
|
1413
1734
|
);
|
|
1414
1735
|
|
|
1415
|
-
return history;
|
|
1736
|
+
return { history, exitReason };
|
|
1416
1737
|
}
|
|
1417
1738
|
}
|
|
1418
1739
|
|
|
@@ -1513,7 +1834,7 @@ export function compactAxTreeHistory(messages: Message[]): Message[] {
|
|
|
1513
1834
|
* turn. Using the last user message unconditionally would leave the most
|
|
1514
1835
|
* recent tool screenshots unprotected from stripping.
|
|
1515
1836
|
*/
|
|
1516
|
-
function
|
|
1837
|
+
function stripOldMediaBlocks(history: Message[]): Message[] {
|
|
1517
1838
|
// Find the last user message that contains tool_result blocks.
|
|
1518
1839
|
let lastToolResultUserIdx = -1;
|
|
1519
1840
|
for (let i = history.length - 1; i >= 0; i--) {
|
|
@@ -1530,29 +1851,32 @@ function stripOldImageBlocks(history: Message[]): Message[] {
|
|
|
1530
1851
|
// Keep the most recent tool-result user message intact (current turn)
|
|
1531
1852
|
if (idx === lastToolResultUserIdx || msg.role !== "user") return msg;
|
|
1532
1853
|
|
|
1533
|
-
// Check if any tool_result blocks
|
|
1534
|
-
const
|
|
1854
|
+
// Check if any tool_result blocks carry embedded media (image or audio).
|
|
1855
|
+
const isMedia = (cb: ContentBlock) =>
|
|
1856
|
+
cb.type === "image" || cb.type === "file";
|
|
1857
|
+
const hasMedia = msg.content.some(
|
|
1535
1858
|
(b) =>
|
|
1536
1859
|
b.type === "tool_result" &&
|
|
1537
|
-
(b as ToolResultContent).contentBlocks?.some(
|
|
1538
|
-
(cb) => cb.type === "image",
|
|
1539
|
-
),
|
|
1860
|
+
(b as ToolResultContent).contentBlocks?.some(isMedia),
|
|
1540
1861
|
);
|
|
1541
|
-
if (!
|
|
1862
|
+
if (!hasMedia) return msg;
|
|
1542
1863
|
|
|
1543
|
-
// Strip
|
|
1864
|
+
// Strip media from tool_result blocks, replacing with a text marker. The
|
|
1865
|
+
// model already saw/heard the media in the turn it was captured; resending
|
|
1866
|
+
// the bytes every turn (a 12 MB audio clip isn't optimized like images)
|
|
1867
|
+
// bloats the request until compaction.
|
|
1544
1868
|
return {
|
|
1545
1869
|
...msg,
|
|
1546
1870
|
content: msg.content.map((b) => {
|
|
1547
1871
|
if (b.type !== "tool_result") return b;
|
|
1548
1872
|
const tr = b as ToolResultContent;
|
|
1549
|
-
if (!tr.contentBlocks?.some(
|
|
1873
|
+
if (!tr.contentBlocks?.some(isMedia)) return b;
|
|
1550
1874
|
return {
|
|
1551
1875
|
...tr,
|
|
1552
1876
|
contentBlocks: undefined,
|
|
1553
1877
|
content:
|
|
1554
1878
|
(tr.content || "") +
|
|
1555
|
-
"\n[
|
|
1879
|
+
"\n[Media (image/audio) was captured and shown previously — binary data removed to save context.]",
|
|
1556
1880
|
};
|
|
1557
1881
|
}),
|
|
1558
1882
|
};
|