@vellumai/assistant 0.8.8 → 0.8.9-dev.202606091926.ebb2d62
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +6 -6
- package/bun.lock +2 -2
- package/docs/activation-funnel-telemetry.md +310 -0
- package/examples/plugins/echo/README.md +61 -60
- package/examples/plugins/echo/hooks/post-tool-use.ts +18 -0
- package/examples/plugins/echo/hooks/stop.ts +16 -0
- package/examples/plugins/echo/hooks/user-prompt-submit.ts +18 -0
- package/examples/plugins/echo/package.json +1 -2
- package/examples/plugins/echo/src/emit.ts +19 -0
- package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +7 -6
- package/openapi.yaml +273 -121
- package/package.json +2 -2
- package/scripts/sync-llm-catalog.ts +2 -0
- package/src/__tests__/activation-early-marking.test.ts +120 -0
- package/src/__tests__/agent-loop-callsite-precedence.test.ts +69 -14
- package/src/__tests__/agent-loop-exit-reason.test.ts +204 -144
- package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +50 -35
- package/src/__tests__/agent-loop-output-hooks.test.ts +357 -0
- package/src/__tests__/agent-loop-override-profile.test.ts +25 -6
- package/src/__tests__/agent-loop-provider-error-recording.test.ts +41 -21
- package/src/__tests__/agent-loop-thinking.test.ts +36 -20
- package/src/__tests__/agent-loop.test.ts +441 -96
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +14 -14
- package/src/__tests__/agent-wake-override-profile.test.ts +17 -21
- package/src/__tests__/anthropic-provider.test.ts +23 -8
- package/src/__tests__/app-builder-tool-scripts.test.ts +21 -0
- package/src/__tests__/app-control-flow.test.ts +1 -1
- package/src/__tests__/app-dir-path-guard.test.ts +1 -0
- package/src/__tests__/app-executors.test.ts +132 -0
- package/src/__tests__/approval-cascade.test.ts +6 -5
- package/src/__tests__/approval-routes-http.test.ts +4 -1
- package/src/__tests__/background-workers-disk-pressure.test.ts +1 -1
- package/src/__tests__/build-persisted-content.test.ts +75 -1
- package/src/__tests__/channel-approval-routes.test.ts +1 -1
- package/src/__tests__/channel-approvals.test.ts +1 -1
- package/src/__tests__/compaction-circuit.test.ts +258 -0
- package/src/__tests__/compaction-direct.test.ts +146 -0
- package/src/__tests__/compaction-events.test.ts +7 -7
- package/src/__tests__/compaction.benchmark.test.ts +1 -1
- package/src/__tests__/compactor-web-search-strip.test.ts +213 -0
- package/src/__tests__/config-managed-gemini-defaults.test.ts +2 -46
- package/src/__tests__/context-overflow-reducer.test.ts +265 -125
- package/src/__tests__/context-window-manager-compact-retry.test.ts +121 -15
- package/src/__tests__/conversation-abort-tool-results.test.ts +7 -5
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +7 -10
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +78 -119
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +158 -234
- package/src/__tests__/conversation-agent-loop.test.ts +342 -623
- package/src/__tests__/conversation-clean-command.test.ts +5 -2
- package/src/__tests__/conversation-confirmation-signals.test.ts +6 -5
- package/src/__tests__/conversation-crud-inference-profile.test.ts +7 -9
- package/src/__tests__/conversation-error.test.ts +15 -1
- package/src/__tests__/conversation-history-web-search.test.ts +6 -1
- package/src/__tests__/conversation-media-retry.test.ts +1 -1
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +44 -4
- package/src/__tests__/conversation-process-callsite.test.ts +15 -15
- package/src/__tests__/conversation-provider-retry-repair.test.ts +66 -65
- package/src/__tests__/conversation-queue.test.ts +10 -10
- package/src/__tests__/conversation-runtime-assembly.test.ts +1059 -231
- package/src/__tests__/conversation-runtime-workspace.test.ts +115 -20
- package/src/__tests__/conversation-slash-queue.test.ts +7 -5
- package/src/__tests__/conversation-slash-unknown.test.ts +7 -5
- package/src/__tests__/conversation-speed-override.test.ts +11 -10
- package/src/__tests__/conversation-starter-routes.test.ts +14 -6
- package/src/__tests__/conversation-surfaces-activation-emit.test.ts +395 -0
- package/src/__tests__/conversation-surfaces-app-control.test.ts +48 -1
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +73 -4
- package/src/__tests__/conversation-undo.test.ts +2 -2
- package/src/__tests__/conversation-workspace-cache-state.test.ts +24 -21
- package/src/__tests__/conversation-workspace-injection.test.ts +69 -7
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +15 -12
- package/src/__tests__/conversations-import-system-filter.test.ts +101 -0
- package/src/__tests__/corrected-target.test.ts +93 -0
- package/src/__tests__/credential-execution-feature-gates.test.ts +5 -4
- package/src/__tests__/credential-security-invariants.test.ts +1 -0
- package/src/__tests__/cu-unified-flow.test.ts +36 -0
- package/src/__tests__/db-acp-history.test.ts +101 -0
- package/src/__tests__/dynamic-page-surface.test.ts +31 -0
- package/src/__tests__/embedding-managed-proxy-selection.test.ts +6 -40
- package/src/__tests__/empty-response-hook.test.ts +1 -1
- package/src/__tests__/file-write-tool.test.ts +63 -0
- package/src/__tests__/gateway-only-guard.test.ts +17 -2
- package/src/__tests__/guardian-grant-minting.test.ts +1 -1
- package/src/__tests__/guardian-routing-invariants.test.ts +93 -4
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +1 -1
- package/src/__tests__/heartbeat-disk-pressure.test.ts +1 -0
- package/src/__tests__/heartbeat-service.test.ts +1 -0
- package/src/__tests__/history-repair-hook.test.ts +5 -1
- package/src/__tests__/host-app-control-proxy.test.ts +45 -0
- package/src/__tests__/host-app-control-routes.test.ts +1 -1
- package/src/__tests__/host-cu-routes-targeted.test.ts +3 -3
- package/src/__tests__/inference-profile-reaper.test.ts +62 -0
- package/src/__tests__/inference-profile-session-handler.test.ts +86 -0
- package/src/__tests__/injector-background-turn.test.ts +13 -23
- package/src/__tests__/injector-chain.test.ts +268 -44
- package/src/__tests__/injector-disk-pressure.test.ts +210 -52
- package/src/__tests__/injector-document-comments.test.ts +97 -114
- package/src/__tests__/injector-pkb-v2-silenced.test.ts +2 -2
- package/src/__tests__/injector-v3-suppression.test.ts +4 -4
- package/src/__tests__/list-messages-client-message-id.test.ts +91 -0
- package/src/__tests__/list-messages-hidden-metadata.test.ts +38 -0
- package/src/__tests__/llm-catalog-parity.test.ts +4 -0
- package/src/__tests__/llm-resolver.test.ts +73 -0
- package/src/__tests__/memory-retrieval-hook.test.ts +156 -38
- package/src/__tests__/memory-v2-static-injector.test.ts +86 -8
- package/src/__tests__/notification-decision-strategy.test.ts +3 -3
- package/src/__tests__/parallel-tool.benchmark.test.ts +35 -8
- package/src/__tests__/persist-unsendable-image-downscale.test.ts +145 -0
- package/src/__tests__/persist-unsendable-image.test.ts +97 -1
- package/src/__tests__/persistence-secret-redaction.test.ts +78 -0
- package/src/__tests__/plugin-api-shim.test.ts +6 -9
- package/src/__tests__/plugin-bootstrap.test.ts +91 -81
- package/src/__tests__/plugin-registry.test.ts +3 -49
- package/src/__tests__/plugin-skill-contribution.test.ts +15 -14
- package/src/__tests__/plugin-tool-contribution.test.ts +7 -4
- package/src/__tests__/plugin-types.test.ts +0 -70
- package/src/__tests__/post-turn-tool-result-truncation.test.ts +69 -0
- package/src/__tests__/pre-model-call-sanitize.test.ts +109 -0
- package/src/__tests__/published-app-updater.test.ts +138 -0
- package/src/__tests__/reaction-persistence.test.ts +1 -1
- package/src/__tests__/retry-thinking-adaptive-only.test.ts +245 -0
- package/src/__tests__/send-endpoint-busy.test.ts +4 -1
- package/src/__tests__/server-history-render.test.ts +39 -0
- package/src/__tests__/skill-feature-flags-integration.test.ts +31 -0
- package/src/__tests__/steer-tool-repair.test.ts +1 -1
- package/src/__tests__/subagent-call-site-routing.test.ts +1 -1
- package/src/__tests__/subagent-detail.test.ts +25 -7
- package/src/__tests__/subagent-fork-notifications.test.ts +1 -3
- package/src/__tests__/subagent-fork-spawn.test.ts +1 -1
- package/src/__tests__/subagent-manager-notify.test.ts +1 -3
- package/src/__tests__/subagent-notify-parent.test.ts +1 -3
- package/src/__tests__/subagent-spawn-tool-fork.test.ts +1 -1
- package/src/__tests__/title-generate-hook.test.ts +5 -1
- package/src/__tests__/tool-error-hook.test.ts +1 -1
- package/src/__tests__/tool-result-truncate-hook.test.ts +1 -1
- package/src/__tests__/tool-start-timestamp.test.ts +218 -0
- package/src/__tests__/user-plugin-loader.test.ts +54 -286
- package/src/__tests__/web-fetch.test.ts +45 -0
- package/src/acp/__tests__/agent-process.test.ts +161 -0
- package/src/acp/__tests__/client-handler.test.ts +40 -0
- package/src/acp/__tests__/helpers/acp-config-stub.ts +0 -2
- package/src/acp/__tests__/helpers/acp-history-db.ts +82 -0
- package/src/acp/__tests__/helpers/exec-file-stub.ts +106 -0
- package/src/acp/__tests__/prepare-agent-env.test.ts +97 -0
- package/src/acp/__tests__/session-manager-persistence.test.ts +95 -28
- package/src/acp/__tests__/session-manager-resume.test.ts +888 -0
- package/src/acp/agent-process.ts +61 -1
- package/src/acp/auto-install.test.ts +280 -0
- package/src/acp/auto-install.ts +232 -0
- package/src/acp/client-handler.ts +31 -0
- package/src/acp/prepare-agent-env.ts +80 -27
- package/src/acp/resolve-agent.test.ts +188 -28
- package/src/acp/resolve-agent.ts +119 -42
- package/src/acp/resume-hint.ts +23 -0
- package/src/acp/session-manager.ts +507 -73
- package/src/agent/compaction-circuit.ts +60 -102
- package/src/agent/loop.ts +403 -251
- package/src/api/events/tool-result.ts +9 -0
- package/src/api/events/tool-use-start.ts +7 -0
- package/src/api/responses/conversation-message.ts +72 -13
- package/src/api/responses/memory-v3-selection-log.ts +19 -10
- package/src/approvals/guardian-request-resolvers.ts +27 -1
- package/src/background-wake/next-wake.ts +1 -0
- package/src/cli/commands/__tests__/memory-v3.test.ts +191 -210
- package/src/cli/commands/channel-verification-sessions.ts +6 -6
- package/src/cli/commands/db/__tests__/repair.test.ts +3 -1
- package/src/cli/commands/memory-v3.ts +57 -199
- package/src/cli/commands/plugins.ts +43 -37
- package/src/cli/lib/__tests__/install-from-github.test.ts +790 -111
- package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +196 -0
- package/src/cli/lib/__tests__/plugin-details.test.ts +381 -0
- package/src/cli/lib/__tests__/plugin-marketplace.test.ts +270 -0
- package/src/cli/lib/__tests__/search-plugins.test.ts +233 -32
- package/src/cli/lib/install-from-github.ts +797 -60
- package/src/cli/lib/plugin-catalog-cache.ts +84 -0
- package/src/cli/lib/plugin-details.ts +416 -0
- package/src/cli/lib/plugin-marketplace.ts +215 -0
- package/src/cli/lib/search-plugins.ts +201 -29
- package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
- package/src/config/acp-defaults.test.ts +10 -0
- package/src/config/acp-defaults.ts +9 -3
- package/src/config/acp-schema.ts +1 -7
- package/src/config/bundled-skills/acp/SKILL.md +80 -41
- package/src/config/bundled-skills/acp/TOOLS.json +4 -4
- package/src/config/bundled-skills/app-builder/SKILL.md +224 -381
- package/src/config/bundled-skills/app-builder/TOOLS.json +72 -2
- package/src/config/bundled-skills/app-builder/references/DESIGN_SYSTEM.md +48 -0
- package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +57 -0
- package/src/config/bundled-skills/app-builder/references/SLIDES.md +38 -0
- package/src/config/bundled-skills/app-builder/tools/app-list.ts +62 -0
- package/src/config/bundled-skills/app-builder/tools/app-update.ts +18 -0
- package/src/config/bundled-skills/document-editor/SKILL.md +28 -23
- package/src/config/bundled-skills/document-editor/TOOLS.json +1 -1
- package/src/config/bundled-tool-registry.ts +4 -0
- package/src/config/call-site-defaults.ts +0 -3
- package/src/config/feature-flag-registry.json +10 -56
- package/src/config/llm-resolver.ts +39 -7
- package/src/config/loader.ts +5 -22
- package/src/config/schemas/__tests__/memory-v3.test.ts +25 -9
- package/src/config/schemas/call-site-catalog.ts +0 -21
- package/src/config/schemas/heartbeat.ts +9 -0
- package/src/config/schemas/llm.ts +17 -3
- package/src/config/schemas/memory-v3.ts +58 -8
- package/src/config/seed-inference-profiles.ts +18 -0
- package/src/context/compactor.ts +22 -4
- package/src/context/post-turn-tool-result-truncation.ts +39 -1
- package/src/context/strip-injections.ts +8 -2
- package/src/daemon/conversation-agent-loop-handlers.ts +120 -42
- package/src/daemon/conversation-agent-loop.ts +308 -1297
- package/src/daemon/conversation-error.ts +31 -4
- package/src/daemon/conversation-history.ts +1 -1
- package/src/daemon/conversation-lifecycle.ts +11 -255
- package/src/daemon/conversation-media-retry.ts +19 -6
- package/src/daemon/conversation-messaging.ts +17 -0
- package/src/daemon/conversation-process.ts +22 -141
- package/src/daemon/conversation-queue-manager.ts +8 -0
- package/src/daemon/conversation-registry.ts +159 -0
- package/src/daemon/conversation-runtime-assembly.ts +361 -393
- package/src/daemon/conversation-store.ts +9 -90
- package/src/daemon/conversation-surfaces.ts +165 -11
- package/src/daemon/conversation-workspace.ts +17 -0
- package/src/daemon/conversation.ts +444 -62
- package/src/daemon/disk-pressure-policy.ts +0 -1
- package/src/daemon/external-plugins-bootstrap.ts +36 -46
- package/src/daemon/handlers/config-channels.ts +11 -2
- package/src/daemon/handlers/conversations.ts +3 -1
- package/src/daemon/handlers/shared.ts +9 -1
- package/src/daemon/handlers/skills.ts +4 -1
- package/src/daemon/host-app-control-proxy.ts +72 -57
- package/src/daemon/host-proxy-preactivation.ts +1 -3
- package/src/daemon/lifecycle.ts +21 -7
- package/src/daemon/persist-unsendable-image.ts +62 -25
- package/src/daemon/process-message.ts +1 -1
- package/src/daemon/server.ts +2 -0
- package/src/daemon/tool-side-effects.ts +15 -0
- package/src/daemon/wake-conversation-ops.ts +269 -0
- package/src/embedded/plugin-api.ts +2 -2
- package/src/export/__tests__/transcript-formatter.test.ts +5 -0
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +3 -0
- package/src/heartbeat/heartbeat-run-store.ts +23 -1
- package/src/heartbeat/heartbeat-service.ts +26 -0
- package/src/ipc/__tests__/browser-ipc.test.ts +1 -1
- package/src/ipc/__tests__/ui-request-route.test.ts +3 -3
- package/src/ipc/skill-routes/__tests__/memory.test.ts +15 -0
- package/src/ipc/skill-routes/memory.ts +4 -2
- package/src/memory/__tests__/activation-session-store.test.ts +41 -0
- package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +87 -0
- package/src/memory/__tests__/onboarding-events-store.test.ts +80 -0
- package/src/memory/activation-session-store.ts +43 -0
- package/src/memory/conversation-crud.ts +29 -19
- package/src/memory/conversation-starter-checkpoints.ts +1 -0
- package/src/memory/db-init.ts +6 -0
- package/src/memory/embedding-backend.ts +5 -22
- package/src/memory/job-handlers/conversation-starters.ts +13 -2
- package/src/memory/jobs/__tests__/embed-concept-page.test.ts +5 -4
- package/src/memory/jobs-worker.ts +25 -1
- package/src/memory/migrations/272-acp-session-history-cwd.ts +36 -0
- package/src/memory/migrations/273-onboarding-events-funnel-columns.ts +46 -0
- package/src/memory/migrations/274-create-activation-sessions.ts +15 -0
- package/src/memory/migrations/index.ts +3 -0
- package/src/memory/onboarding-events-store.ts +66 -18
- package/src/memory/schema/acp.ts +4 -0
- package/src/memory/schema/infrastructure.ts +13 -0
- package/src/memory/v2/__tests__/consolidation-job.test.ts +4 -97
- package/src/memory/v2/__tests__/page-store.test.ts +22 -0
- package/src/memory/v2/consolidation-job.ts +2 -63
- package/src/memory/v2/types.ts +5 -0
- package/src/messaging/providers/telegram-bot/api.ts +14 -5
- package/src/notifications/__tests__/copy-composer.test.ts +244 -0
- package/src/notifications/access-request-copy.ts +298 -0
- package/src/notifications/adapters/slack.ts +3 -3
- package/src/notifications/adapters/telegram.ts +9 -2
- package/src/notifications/copy-composer.ts +49 -267
- package/src/notifications/decision-engine.ts +16 -35
- package/src/notifications/home-feed-side-effect.ts +1 -6
- package/src/plugin-api/constants.ts +4 -0
- package/src/plugin-api/index.ts +40 -11
- package/src/plugin-api/types.ts +108 -0
- package/src/plugins/defaults/compaction/compact.ts +106 -0
- package/src/{daemon → plugins/defaults/compaction}/context-overflow-reducer.ts +250 -42
- package/src/plugins/defaults/compaction/corrected-target.ts +53 -0
- package/src/plugins/defaults/compaction/manager-store.ts +57 -0
- package/src/plugins/defaults/compaction/package.json +1 -2
- package/src/{context → plugins/defaults/compaction}/window-manager.ts +95 -25
- package/src/plugins/defaults/empty-response/package.json +0 -1
- package/src/plugins/defaults/history-repair/package.json +0 -1
- package/src/plugins/defaults/index.ts +156 -26
- package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +100 -52
- package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit.ts +285 -0
- package/src/plugins/defaults/memory-retrieval/injector-chain.ts +2 -2
- package/src/plugins/defaults/{injectors/register.ts → memory-retrieval/injectors.ts} +148 -73
- package/src/plugins/defaults/memory-retrieval/package.json +14 -0
- package/src/plugins/defaults/memory-retrieval/unified-turn-context.ts +223 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/capabilities.test.ts +71 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/dense.test.ts +181 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/edge.test.ts +247 -0
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/live-integration.test.ts +147 -134
- package/src/plugins/defaults/memory-v3-shadow/__tests__/maintain-job.test.ts +456 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/orchestrate.test.ts +662 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +306 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/render-injection.test.ts +91 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/section-dense-store.test.ts +402 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/section-needle.test.ts +135 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/sections.test.ts +125 -0
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/selection-log-store.test.ts +74 -19
- package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-integration.test.ts +446 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +592 -0
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/types.test.ts +2 -24
- package/src/plugins/defaults/memory-v3-shadow/capabilities.ts +91 -0
- package/src/plugins/defaults/memory-v3-shadow/dense.ts +97 -0
- package/src/plugins/defaults/memory-v3-shadow/edge.ts +252 -0
- package/src/plugins/defaults/memory-v3-shadow/hooks/post-compact.ts +14 -0
- package/src/plugins/defaults/memory-v3-shadow/hooks/user-prompt-submit.ts +19 -0
- package/src/plugins/defaults/memory-v3-shadow/injector.ts +76 -0
- package/src/plugins/defaults/memory-v3-shadow/maintain-job.ts +555 -0
- package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +266 -0
- package/src/plugins/defaults/memory-v3-shadow/package.json +14 -0
- package/src/plugins/defaults/memory-v3-shadow/page-content.ts +71 -0
- package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +204 -0
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/render-injection.ts +16 -8
- package/src/plugins/defaults/memory-v3-shadow/section-dense-store.ts +236 -0
- package/src/plugins/defaults/memory-v3-shadow/section-needle.ts +200 -0
- package/src/plugins/defaults/memory-v3-shadow/sections.ts +115 -0
- package/src/plugins/defaults/memory-v3-shadow/selection-log-store.ts +156 -0
- package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +382 -0
- package/src/plugins/defaults/memory-v3-shadow/types.ts +92 -0
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/working-set.ts +4 -1
- package/src/plugins/defaults/title-generate/package.json +0 -1
- package/src/plugins/defaults/tool-error/package.json +0 -1
- package/src/plugins/defaults/tool-result-truncate/package.json +0 -1
- package/src/plugins/external-api.ts +12 -2
- package/src/plugins/pipeline.ts +6 -293
- package/src/plugins/registry.ts +9 -37
- package/src/plugins/types.ts +76 -381
- package/src/plugins/user-loader.ts +30 -127
- package/src/prompts/__tests__/system-prompt.test.ts +6 -0
- package/src/prompts/system-prompt.ts +61 -10
- package/src/prompts/templates/BOOTSTRAP-ACTIVATION-RAIL.md +71 -4
- package/src/providers/anthropic/client.ts +9 -10
- package/src/providers/inference/kimi-cjk-token-ids.ts +493 -0
- package/src/providers/inference/logit-bias.ts +55 -0
- package/src/providers/model-catalog.ts +57 -0
- package/src/providers/openai/__tests__/vision-not-supported.test.ts +75 -0
- package/src/providers/openai/chat-completions-provider.ts +44 -1
- package/src/providers/retry.ts +57 -7
- package/src/providers/types.ts +6 -0
- package/src/runtime/__tests__/agent-wake.test.ts +555 -691
- package/src/runtime/__tests__/interactive-ui.test.ts +1 -1
- package/src/runtime/agent-wake.ts +108 -209
- package/src/runtime/assistant-event-hub.ts +1 -1
- package/src/runtime/channel-approvals.ts +1 -1
- package/src/runtime/interactive-ui.ts +1 -1
- package/src/runtime/routes/__tests__/acp-routes.test.ts +466 -55
- package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +423 -73
- package/src/runtime/routes/__tests__/stt-routes.test.ts +112 -0
- package/src/runtime/routes/__tests__/surface-action-routes.test.ts +5 -4
- package/src/runtime/routes/__tests__/surface-content-routes.test.ts +4 -1
- package/src/runtime/routes/acp-routes.test.ts +185 -32
- package/src/runtime/routes/acp-routes.ts +328 -30
- package/src/runtime/routes/app-management-routes.ts +3 -0
- package/src/runtime/routes/approval-routes.ts +1 -1
- package/src/runtime/routes/browser-routes.ts +1 -1
- package/src/runtime/routes/browser-tabs-routes.ts +6 -10
- package/src/runtime/routes/channel-verification-routes.ts +14 -5
- package/src/runtime/routes/conversation-cli-routes.ts +1 -1
- package/src/runtime/routes/conversation-list-routes.ts +1 -1
- package/src/runtime/routes/conversation-query-routes.ts +1 -1
- package/src/runtime/routes/conversation-routes.ts +30 -2
- package/src/runtime/routes/conversation-starter-routes.ts +13 -7
- package/src/runtime/routes/conversations-import-routes.ts +24 -7
- package/src/runtime/routes/host-app-control-routes.ts +1 -1
- package/src/runtime/routes/host-cu-routes.ts +1 -1
- package/src/runtime/routes/identity-routes.ts +18 -3
- package/src/runtime/routes/inbound-message-handler.ts +1 -1
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +33 -34
- package/src/runtime/routes/inference-profile-session-handler.ts +11 -0
- package/src/runtime/routes/inference-profile-session-reaper.ts +6 -0
- package/src/runtime/routes/memory-v3-routes.ts +65 -305
- package/src/runtime/routes/playground/__tests__/force-compact.test.ts +1 -1
- package/src/runtime/routes/playground/helpers.ts +1 -1
- package/src/runtime/routes/plugins-routes.ts +337 -35
- package/src/runtime/routes/stt-routes.ts +45 -12
- package/src/runtime/routes/surface-conversation-resolver.ts +4 -3
- package/src/runtime/routes/work-items-routes.ts +2 -4
- package/src/runtime/routes/workspace-routes.ts +50 -15
- package/src/runtime/services/conversation-serializer.ts +1 -1
- package/src/runtime/verification-outbound-actions.ts +147 -2
- package/src/runtime/verification-templates.ts +29 -3
- package/src/services/published-app-updater.ts +30 -8
- package/src/signals/cancel.ts +2 -4
- package/src/subagent/manager.ts +21 -5
- package/src/telemetry/__tests__/activation-funnel.test.ts +95 -0
- package/src/telemetry/activation-funnel.ts +167 -0
- package/src/telemetry/types.ts +13 -0
- package/src/telemetry/usage-telemetry-reporter.test.ts +154 -0
- package/src/telemetry/usage-telemetry-reporter.ts +26 -1
- package/src/tools/acp/context.ts +20 -0
- package/src/tools/acp/list-agents.test.ts +9 -19
- package/src/tools/acp/list-agents.ts +3 -15
- package/src/tools/acp/spawn.test.ts +173 -202
- package/src/tools/acp/spawn.ts +37 -172
- package/src/tools/acp/steer.test.ts +105 -8
- package/src/tools/acp/steer.ts +48 -17
- package/src/tools/apps/executors.ts +166 -50
- package/src/tools/browser/browser-execution.ts +12 -2
- package/src/tools/filesystem/write.ts +34 -0
- package/src/tools/network/web-fetch.ts +65 -24
- package/src/tools/skills/load.ts +1 -1
- package/src/tools/subagent/spawn.ts +2 -4
- package/src/tools/ui-surface/definitions.ts +32 -5
- package/src/workspace/migrations/051-seed-conversation-summarization-callsite.ts +4 -5
- package/src/workspace/migrations/097-enable-adaptive-thinking-managed-profiles.ts +69 -45
- package/docs/plugins.md +0 -832
- package/examples/plugins/echo/register.ts +0 -143
- package/src/__tests__/circuit-breaker-pipeline.test.ts +0 -405
- package/src/__tests__/compaction-pipeline.test.ts +0 -210
- package/src/__tests__/compaction-timeout-recovery.test.ts +0 -251
- package/src/__tests__/overflow-reduce-pipeline.test.ts +0 -667
- package/src/__tests__/pipeline-runner.test.ts +0 -554
- package/src/daemon/wake-target-adapter.ts +0 -253
- package/src/memory/v3/__tests__/assign.test.ts +0 -242
- package/src/memory/v3/__tests__/capabilities.test.ts +0 -118
- package/src/memory/v3/__tests__/core.test.ts +0 -39
- package/src/memory/v3/__tests__/health.test.ts +0 -219
- package/src/memory/v3/__tests__/maintain-job.test.ts +0 -288
- package/src/memory/v3/__tests__/needle.test.ts +0 -107
- package/src/memory/v3/__tests__/orchestrate.test.ts +0 -436
- package/src/memory/v3/__tests__/provider-blocks.test.ts +0 -13
- package/src/memory/v3/__tests__/reconcile.test.ts +0 -274
- package/src/memory/v3/__tests__/render-injection.test.ts +0 -61
- package/src/memory/v3/__tests__/router.test.ts +0 -332
- package/src/memory/v3/__tests__/selector.test.ts +0 -470
- package/src/memory/v3/__tests__/shadow-plugin.test.ts +0 -432
- package/src/memory/v3/__tests__/snapshot.test.ts +0 -168
- package/src/memory/v3/__tests__/tree.test.ts +0 -192
- package/src/memory/v3/assign.ts +0 -268
- package/src/memory/v3/capabilities.ts +0 -124
- package/src/memory/v3/core.ts +0 -26
- package/src/memory/v3/health.ts +0 -0
- package/src/memory/v3/maintain-job.ts +0 -314
- package/src/memory/v3/needle.ts +0 -115
- package/src/memory/v3/orchestrate.ts +0 -126
- package/src/memory/v3/page-content.ts +0 -34
- package/src/memory/v3/provider-blocks.ts +0 -26
- package/src/memory/v3/reconcile.ts +0 -523
- package/src/memory/v3/router.ts +0 -190
- package/src/memory/v3/selection-log-store.ts +0 -84
- package/src/memory/v3/selector.ts +0 -226
- package/src/memory/v3/shadow-plugin.ts +0 -411
- package/src/memory/v3/snapshot.ts +0 -209
- package/src/memory/v3/tree.ts +0 -174
- package/src/memory/v3/types.ts +0 -59
- package/src/notifications/__tests__/emit-signal-home-feed.test.ts +0 -187
- package/src/plugins/defaults/circuit-breaker/middlewares/circuitBreaker.ts +0 -93
- package/src/plugins/defaults/circuit-breaker/package.json +0 -15
- package/src/plugins/defaults/circuit-breaker/register.ts +0 -39
- package/src/plugins/defaults/compaction/middlewares/compaction.ts +0 -25
- package/src/plugins/defaults/compaction/register.ts +0 -35
- package/src/plugins/defaults/compaction/terminal.ts +0 -73
- package/src/plugins/defaults/empty-response/register.ts +0 -23
- package/src/plugins/defaults/history-repair/register.ts +0 -24
- package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit-temp.ts +0 -216
- package/src/plugins/defaults/overflow-reduce/middlewares/overflowReduce.ts +0 -126
- package/src/plugins/defaults/overflow-reduce/package.json +0 -15
- package/src/plugins/defaults/overflow-reduce/register.ts +0 -42
- package/src/plugins/defaults/title-generate/register.ts +0 -35
- package/src/plugins/defaults/tool-error/register.ts +0 -23
- package/src/plugins/defaults/tool-result-truncate/register.ts +0 -24
- package/src/proactive-artifact/aux-message-injector.ts +0 -97
- package/src/proactive-artifact/decision.test.ts +0 -226
- package/src/proactive-artifact/decision.ts +0 -165
- package/src/proactive-artifact/index.ts +0 -7
- package/src/proactive-artifact/job.test.ts +0 -962
- package/src/proactive-artifact/job.ts +0 -372
- package/src/proactive-artifact/message-copy.ts +0 -58
- package/src/proactive-artifact/trigger-state.test.ts +0 -286
- package/src/proactive-artifact/trigger-state.ts +0 -123
- package/src/util/map-limit.ts +0 -27
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/fixtures/eval-turns.json +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/fixtures/live-turns.json +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/working-set-eviction.test.ts +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/working-set-skeleton.test.ts +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/README.md +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/assignments.json +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/core.json +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-a/topic-x.md +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-a/topic-y.md +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-b/topic-z.md +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/llm-retry.ts +0 -0
|
@@ -56,6 +56,11 @@ let runCalls: Array<{
|
|
|
56
56
|
let runResults: CompactionRunResult[] = [];
|
|
57
57
|
const estimateReturns: number[] = [];
|
|
58
58
|
|
|
59
|
+
// Captured arguments from each runEmergencyCompaction invocation, so the
|
|
60
|
+
// emergencyCompact tests can assert the manager fills in the fields it owns.
|
|
61
|
+
let emergencyCalls: Record<string, unknown>[] = [];
|
|
62
|
+
let emergencyResult: CompactionRunResult | undefined;
|
|
63
|
+
|
|
59
64
|
mock.module("../context/token-estimator.js", () => ({
|
|
60
65
|
estimatePromptTokens: (): number => {
|
|
61
66
|
const next = estimateReturns.shift();
|
|
@@ -92,9 +97,18 @@ mock.module("../context/compactor.js", () => ({
|
|
|
92
97
|
}
|
|
93
98
|
return result;
|
|
94
99
|
},
|
|
100
|
+
runEmergencyCompaction: async (
|
|
101
|
+
args: Record<string, unknown>,
|
|
102
|
+
): Promise<CompactionRunResult> => {
|
|
103
|
+
emergencyCalls.push(args);
|
|
104
|
+
if (!emergencyResult) {
|
|
105
|
+
throw new Error("emergencyResult not seeded");
|
|
106
|
+
}
|
|
107
|
+
return emergencyResult;
|
|
108
|
+
},
|
|
95
109
|
}));
|
|
96
110
|
|
|
97
|
-
import { ContextWindowManager } from "../
|
|
111
|
+
import { ContextWindowManager } from "../plugins/defaults/compaction/window-manager.js";
|
|
98
112
|
import type { Message, Provider } from "../providers/types.js";
|
|
99
113
|
|
|
100
114
|
function makeProvider(): Provider {
|
|
@@ -142,24 +156,28 @@ function compactResult(
|
|
|
142
156
|
};
|
|
143
157
|
}
|
|
144
158
|
|
|
159
|
+
function makeConfig(maxAttempts: number = 3) {
|
|
160
|
+
return {
|
|
161
|
+
enabled: true,
|
|
162
|
+
maxInputTokens: 200_000,
|
|
163
|
+
targetBudgetRatio: 0.3,
|
|
164
|
+
compactThreshold: 0.8,
|
|
165
|
+
summaryBudgetRatio: 0.05,
|
|
166
|
+
overflowRecovery: {
|
|
167
|
+
enabled: true,
|
|
168
|
+
safetyMarginRatio: 0.05,
|
|
169
|
+
maxAttempts,
|
|
170
|
+
interactiveLatestTurnCompression: "summarize" as const,
|
|
171
|
+
nonInteractiveLatestTurnCompression: "summarize" as const,
|
|
172
|
+
},
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
|
|
145
176
|
function buildManager(maxAttempts: number = 3): ContextWindowManager {
|
|
146
177
|
return new ContextWindowManager({
|
|
147
178
|
provider: makeProvider(),
|
|
148
179
|
systemPrompt: "you are a test assistant",
|
|
149
|
-
config:
|
|
150
|
-
enabled: true,
|
|
151
|
-
maxInputTokens: 200_000,
|
|
152
|
-
targetBudgetRatio: 0.3,
|
|
153
|
-
compactThreshold: 0.8,
|
|
154
|
-
summaryBudgetRatio: 0.05,
|
|
155
|
-
overflowRecovery: {
|
|
156
|
-
enabled: true,
|
|
157
|
-
safetyMarginRatio: 0.05,
|
|
158
|
-
maxAttempts,
|
|
159
|
-
interactiveLatestTurnCompression: "summarize",
|
|
160
|
-
nonInteractiveLatestTurnCompression: "summarize",
|
|
161
|
-
},
|
|
162
|
-
},
|
|
180
|
+
config: makeConfig(maxAttempts),
|
|
163
181
|
conversationId: "conv-test",
|
|
164
182
|
});
|
|
165
183
|
}
|
|
@@ -289,3 +307,91 @@ describe("ContextWindowManager.maybeCompact retry budget", () => {
|
|
|
289
307
|
expect(result.estimatedInputTokens).toBe(165_000);
|
|
290
308
|
});
|
|
291
309
|
});
|
|
310
|
+
|
|
311
|
+
describe("ContextWindowManager.emergencyCompact", () => {
|
|
312
|
+
beforeEach(() => {
|
|
313
|
+
emergencyCalls = [];
|
|
314
|
+
emergencyResult = undefined;
|
|
315
|
+
estimateReturns.length = 0;
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
test("supplies manager-owned fields and forwards only overflow inputs", async () => {
|
|
319
|
+
/**
|
|
320
|
+
* The manager owns provider, system prompt, token budget, conversation
|
|
321
|
+
* id, compaction config, and non-persisted prefix count; the caller
|
|
322
|
+
* provides only the overflow-specific inputs.
|
|
323
|
+
*/
|
|
324
|
+
// GIVEN a manager seeded with a non-persisted prefix and a canned result
|
|
325
|
+
emergencyResult = compactResult({
|
|
326
|
+
compacted: true,
|
|
327
|
+
compactedMessages: 40,
|
|
328
|
+
summaryText: "emergency summary",
|
|
329
|
+
});
|
|
330
|
+
const manager = buildManager();
|
|
331
|
+
manager.seedNonPersistedPrefix(3);
|
|
332
|
+
const messages = makeMessages(8);
|
|
333
|
+
const signal = new AbortController().signal;
|
|
334
|
+
|
|
335
|
+
// WHEN emergency compaction runs
|
|
336
|
+
const result = await manager.emergencyCompact(
|
|
337
|
+
messages,
|
|
338
|
+
{ previousEstimatedInputTokens: 242_201, overrideProfile: "fast" },
|
|
339
|
+
signal,
|
|
340
|
+
);
|
|
341
|
+
|
|
342
|
+
// THEN the manager fills its owned fields and forwards the caller inputs
|
|
343
|
+
expect(emergencyCalls.length).toBe(1);
|
|
344
|
+
const args = emergencyCalls[0]!;
|
|
345
|
+
expect(args.conversationId).toBe("conv-test");
|
|
346
|
+
expect(args.systemPrompt).toBe("you are a test assistant");
|
|
347
|
+
expect(args.maxInputTokens).toBe(200_000);
|
|
348
|
+
expect(args.nonPersistedPrefixCount).toBe(3);
|
|
349
|
+
expect(args.tools).toBeUndefined();
|
|
350
|
+
expect(args.force).toBe(true);
|
|
351
|
+
expect(args.signal).toBe(signal);
|
|
352
|
+
expect(args.messages).toBe(messages);
|
|
353
|
+
expect(args.previousEstimatedInputTokens).toBe(242_201);
|
|
354
|
+
expect(args.overrideProfile).toBe("fast");
|
|
355
|
+
expect((args.provider as { name: string }).name).toBe("mock-provider");
|
|
356
|
+
expect(result.summaryText).toBe("emergency summary");
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
test("defaults overrideProfile to null when omitted", async () => {
|
|
360
|
+
/**
|
|
361
|
+
* Callers that don't resolve a per-conversation profile get an explicit
|
|
362
|
+
* null forwarded to the summary call.
|
|
363
|
+
*/
|
|
364
|
+
// GIVEN a manager and a canned result
|
|
365
|
+
emergencyResult = compactResult({ compacted: true });
|
|
366
|
+
const manager = buildManager();
|
|
367
|
+
|
|
368
|
+
// WHEN emergency compaction runs without an override profile
|
|
369
|
+
await manager.emergencyCompact(makeMessages(6), {
|
|
370
|
+
previousEstimatedInputTokens: 210_000,
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
// THEN overrideProfile is forwarded as null
|
|
374
|
+
expect(emergencyCalls[0]!.overrideProfile).toBeNull();
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
test("throws when the manager has no conversation id", async () => {
|
|
378
|
+
/**
|
|
379
|
+
* Emergency compaction needs a conversation id for attachment and
|
|
380
|
+
* timestamp lookups; a manager without one cannot run it.
|
|
381
|
+
*/
|
|
382
|
+
// GIVEN a manager constructed without a conversation id
|
|
383
|
+
const manager = new ContextWindowManager({
|
|
384
|
+
provider: makeProvider(),
|
|
385
|
+
systemPrompt: "you are a test assistant",
|
|
386
|
+
config: makeConfig(),
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
// WHEN/THEN emergency compaction rejects without invoking the compactor
|
|
390
|
+
await expect(
|
|
391
|
+
manager.emergencyCompact(makeMessages(4), {
|
|
392
|
+
previousEstimatedInputTokens: 210_000,
|
|
393
|
+
}),
|
|
394
|
+
).rejects.toThrow(/conversationId/);
|
|
395
|
+
expect(emergencyCalls.length).toBe(0);
|
|
396
|
+
});
|
|
397
|
+
});
|
|
@@ -167,9 +167,10 @@ mock.module("../memory/retriever.js", () => ({
|
|
|
167
167
|
injectMemoryRecallAsUserBlock: (msgs: Message[]) => msgs,
|
|
168
168
|
}));
|
|
169
169
|
|
|
170
|
-
mock.module("../
|
|
170
|
+
mock.module("../plugins/defaults/compaction/window-manager.js", () => ({
|
|
171
171
|
ContextWindowManager: class {
|
|
172
172
|
constructor() {}
|
|
173
|
+
updateConfig() {}
|
|
173
174
|
shouldCompact() {
|
|
174
175
|
return { needed: false, estimatedTokens: 0 };
|
|
175
176
|
}
|
|
@@ -198,10 +199,11 @@ mock.module("../agent/loop.js", () => ({
|
|
|
198
199
|
getActiveModel() {
|
|
199
200
|
return undefined;
|
|
200
201
|
}
|
|
201
|
-
async run(
|
|
202
|
-
messages: Message[]
|
|
203
|
-
onEvent: (event: AgentEvent) => void
|
|
204
|
-
): Promise<AgentLoopRunResult> {
|
|
202
|
+
async run(options: {
|
|
203
|
+
messages: Message[];
|
|
204
|
+
onEvent: (event: AgentEvent) => void;
|
|
205
|
+
}): Promise<AgentLoopRunResult> {
|
|
206
|
+
const { messages, onEvent } = options;
|
|
205
207
|
// Prime the assistant row anchor — production code emits this from
|
|
206
208
|
// `AgentLoop.run` just before `provider.sendMessage`.
|
|
207
209
|
await onEvent({ type: "llm_call_started" });
|
|
@@ -2,11 +2,11 @@ import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
|
|
|
2
2
|
|
|
3
3
|
import { CompactionCircuit } from "../agent/compaction-circuit.js";
|
|
4
4
|
import type { AgentLoop } from "../agent/loop.js";
|
|
5
|
-
import type {
|
|
5
|
+
import type { Conversation } from "../daemon/conversation.js";
|
|
6
6
|
import type { DiskPressureStatus } from "../daemon/disk-pressure-guard.js";
|
|
7
7
|
import type { ServerMessage } from "../daemon/message-protocol.js";
|
|
8
8
|
|
|
9
|
-
type Context =
|
|
9
|
+
type Context = Conversation;
|
|
10
10
|
|
|
11
11
|
mock.module("../util/logger.js", () => ({
|
|
12
12
|
getLogger: () =>
|
|
@@ -96,7 +96,7 @@ mock.module("../memory/conversation-crud.js", () => ({
|
|
|
96
96
|
getMessageById: () => null,
|
|
97
97
|
getConversationOriginChannel: () => null,
|
|
98
98
|
getConversationOriginInterface: () => null,
|
|
99
|
-
|
|
99
|
+
resolveOverrideProfile: () => null,
|
|
100
100
|
provenanceFromTrustContext: () => ({}),
|
|
101
101
|
setConversationHistoryStrippedAt: () => {},
|
|
102
102
|
updateConversationContextWindow: () => {},
|
|
@@ -106,9 +106,7 @@ mock.module("../memory/conversation-crud.js", () => ({
|
|
|
106
106
|
|
|
107
107
|
import { runAgentLoopImpl } from "../daemon/conversation-agent-loop.js";
|
|
108
108
|
|
|
109
|
-
function makeCtx(
|
|
110
|
-
overrides: Partial<Context> = {},
|
|
111
|
-
): AgentLoopConversationContext {
|
|
109
|
+
function makeCtx(overrides: Partial<Context> = {}): Conversation {
|
|
112
110
|
let processing = true;
|
|
113
111
|
return {
|
|
114
112
|
conversationId: "conv-123",
|
|
@@ -137,6 +135,8 @@ function makeCtx(
|
|
|
137
135
|
} as unknown as Context["contextWindowManager"],
|
|
138
136
|
contextCompactedMessageCount: 0,
|
|
139
137
|
contextCompactedAt: null,
|
|
138
|
+
conversationType: "background",
|
|
139
|
+
source: "memory",
|
|
140
140
|
memoryPolicy: { scopeId: "default", includeDefaultFallback: true },
|
|
141
141
|
currentActiveSurfaceId: undefined,
|
|
142
142
|
currentPage: undefined,
|
|
@@ -145,8 +145,6 @@ function makeCtx(
|
|
|
145
145
|
surfaceActionRequestIds: new Set<string>(),
|
|
146
146
|
currentTurnSurfaces: [],
|
|
147
147
|
workingDir: "/tmp",
|
|
148
|
-
workspaceTopLevelContext: null,
|
|
149
|
-
workspaceTopLevelDirty: false,
|
|
150
148
|
channelCapabilities: undefined,
|
|
151
149
|
commandIntent: undefined,
|
|
152
150
|
trustContext: undefined,
|
|
@@ -172,7 +170,6 @@ function makeCtx(
|
|
|
172
170
|
hasNoClient: false,
|
|
173
171
|
prompter: {} as Context["prompter"],
|
|
174
172
|
queue: {} as Context["queue"],
|
|
175
|
-
refreshWorkspaceTopLevelContextIfNeeded: () => {},
|
|
176
173
|
markWorkspaceTopLevelDirty: () => {},
|
|
177
174
|
emitActivityState: () => {},
|
|
178
175
|
getQueueDepth: () => 0,
|
|
@@ -183,7 +180,7 @@ function makeCtx(
|
|
|
183
180
|
getTurnChannelContext: () => null,
|
|
184
181
|
graphMemory: {} as Context["graphMemory"],
|
|
185
182
|
...overrides,
|
|
186
|
-
} as
|
|
183
|
+
} as unknown as Conversation;
|
|
187
184
|
}
|
|
188
185
|
|
|
189
186
|
describe("runAgentLoopImpl disk pressure gate", () => {
|
|
@@ -15,7 +15,7 @@ import { createRequire } from "node:module";
|
|
|
15
15
|
import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
|
|
16
16
|
|
|
17
17
|
import { CompactionCircuit } from "../agent/compaction-circuit.js";
|
|
18
|
-
import type {
|
|
18
|
+
import type { AgentLoopRunOptions } from "../agent/loop.js";
|
|
19
19
|
import type { LLMCallSite } from "../config/schemas/llm.js";
|
|
20
20
|
import { resetPluginRegistryAndRegisterDefaults } from "../plugins/defaults/index.js";
|
|
21
21
|
import type { Message, ToolDefinition } from "../providers/types.js";
|
|
@@ -102,23 +102,26 @@ mock.module("../context/token-estimator.js", () => ({
|
|
|
102
102
|
estimateToolsTokens: () => 0,
|
|
103
103
|
}));
|
|
104
104
|
|
|
105
|
-
mock.module(
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
105
|
+
mock.module(
|
|
106
|
+
"../plugins/defaults/compaction/context-overflow-reducer.js",
|
|
107
|
+
() => ({
|
|
108
|
+
createInitialReducerState: () => ({
|
|
109
|
+
appliedTiers: [],
|
|
110
|
+
injectionMode: "full" as const,
|
|
111
|
+
exhausted: false,
|
|
112
|
+
}),
|
|
113
|
+
reduceContextOverflow: async (msgs: Message[]) => ({
|
|
114
|
+
messages: msgs,
|
|
115
|
+
tier: "forced_compaction",
|
|
116
|
+
state: {
|
|
117
|
+
appliedTiers: ["forced_compaction"],
|
|
118
|
+
injectionMode: "full",
|
|
119
|
+
exhausted: true,
|
|
120
|
+
},
|
|
121
|
+
estimatedTokens: 1000,
|
|
122
|
+
}),
|
|
120
123
|
}),
|
|
121
|
-
|
|
124
|
+
);
|
|
122
125
|
|
|
123
126
|
mock.module("../daemon/context-overflow-policy.js", () => ({
|
|
124
127
|
resolveOverflowAction: () => "fail_gracefully",
|
|
@@ -150,12 +153,26 @@ mock.module("../memory/conversation-crud.js", () => ({
|
|
|
150
153
|
updateMessageMetadata: () => {},
|
|
151
154
|
getMessages: () => [],
|
|
152
155
|
getConversation: () => mockConversationRow,
|
|
153
|
-
|
|
154
|
-
|
|
156
|
+
resolveOverrideProfile: (
|
|
157
|
+
fields: {
|
|
158
|
+
conversationType?: string | null;
|
|
159
|
+
inferenceProfile?: string | null;
|
|
160
|
+
inferenceProfileExpiresAt?: number | null;
|
|
161
|
+
} | null,
|
|
155
162
|
) => {
|
|
156
|
-
if (
|
|
157
|
-
|
|
158
|
-
|
|
163
|
+
if (
|
|
164
|
+
fields?.conversationType === "background" ||
|
|
165
|
+
fields?.conversationType === "scheduled"
|
|
166
|
+
) {
|
|
167
|
+
return undefined;
|
|
168
|
+
}
|
|
169
|
+
if (
|
|
170
|
+
fields?.inferenceProfileExpiresAt != null &&
|
|
171
|
+
fields.inferenceProfileExpiresAt <= Date.now()
|
|
172
|
+
) {
|
|
173
|
+
return undefined;
|
|
174
|
+
}
|
|
175
|
+
return fields?.inferenceProfile ?? undefined;
|
|
159
176
|
},
|
|
160
177
|
provenanceFromTrustContext: () => ({
|
|
161
178
|
source: "user",
|
|
@@ -343,10 +360,8 @@ mock.module("../memory/llm-request-log-store.js", () => ({
|
|
|
343
360
|
|
|
344
361
|
// ── Imports (after mocks) ────────────────────────────────────────────
|
|
345
362
|
|
|
346
|
-
import {
|
|
347
|
-
|
|
348
|
-
runAgentLoopImpl,
|
|
349
|
-
} from "../daemon/conversation-agent-loop.js";
|
|
363
|
+
import type { Conversation } from "../daemon/conversation.js";
|
|
364
|
+
import { runAgentLoopImpl } from "../daemon/conversation-agent-loop.js";
|
|
350
365
|
|
|
351
366
|
// ── Test helpers ─────────────────────────────────────────────────────
|
|
352
367
|
|
|
@@ -362,22 +377,20 @@ let mutateBeforeResolveOverrideProfile: (() => void) | undefined;
|
|
|
362
377
|
|
|
363
378
|
function makeCtx(
|
|
364
379
|
captured: CapturedAgentLoopRun[],
|
|
365
|
-
overrides?: Partial<
|
|
366
|
-
):
|
|
380
|
+
overrides?: Partial<Conversation>,
|
|
381
|
+
): Conversation {
|
|
367
382
|
const agentLoopRun = async (
|
|
368
|
-
|
|
369
|
-
_onEvent: (event: AgentEvent) => void,
|
|
370
|
-
options?: AgentLoopRunOptions,
|
|
383
|
+
options: AgentLoopRunOptions,
|
|
371
384
|
): Promise<Message[]> => {
|
|
372
385
|
mutateBeforeResolveOverrideProfile?.();
|
|
373
386
|
captured.push({
|
|
374
|
-
callSite: options
|
|
375
|
-
overrideProfile: options
|
|
376
|
-
resolvedOverrideProfile: options
|
|
377
|
-
resolvedMaxInputTokens: options
|
|
387
|
+
callSite: options.callSite,
|
|
388
|
+
overrideProfile: options.overrideProfile,
|
|
389
|
+
resolvedOverrideProfile: options.resolveOverrideProfile?.(),
|
|
390
|
+
resolvedMaxInputTokens: options.resolveContextWindow?.().maxInputTokens,
|
|
378
391
|
});
|
|
379
392
|
return [
|
|
380
|
-
...messages,
|
|
393
|
+
...options.messages,
|
|
381
394
|
{
|
|
382
395
|
role: "assistant" as const,
|
|
383
396
|
content: [{ type: "text" as const, text: "response" }],
|
|
@@ -406,7 +419,7 @@ function makeCtx(
|
|
|
406
419
|
getResolvedTools: () => [] as ToolDefinition[],
|
|
407
420
|
getActiveModel: () => undefined,
|
|
408
421
|
compactionCircuit: new CompactionCircuit("test-conv"),
|
|
409
|
-
} as unknown as
|
|
422
|
+
} as unknown as Conversation["agentLoop"],
|
|
410
423
|
provider: {
|
|
411
424
|
name: "mock-provider",
|
|
412
425
|
sendMessage: async () => ({
|
|
@@ -415,13 +428,14 @@ function makeCtx(
|
|
|
415
428
|
usage: { inputTokens: 0, outputTokens: 0 },
|
|
416
429
|
stopReason: "end_turn",
|
|
417
430
|
}),
|
|
418
|
-
} as unknown as
|
|
431
|
+
} as unknown as Conversation["provider"],
|
|
419
432
|
systemPrompt: "system prompt",
|
|
420
433
|
|
|
421
434
|
contextWindowManager: {
|
|
435
|
+
updateConfig: () => {},
|
|
422
436
|
shouldCompact: () => ({ needed: false, estimatedTokens: 0 }),
|
|
423
437
|
maybeCompact: async () => ({ compacted: false }),
|
|
424
|
-
} as unknown as
|
|
438
|
+
} as unknown as Conversation["contextWindowManager"],
|
|
425
439
|
contextCompactedMessageCount: 0,
|
|
426
440
|
contextCompactedAt: null,
|
|
427
441
|
|
|
@@ -435,8 +449,6 @@ function makeCtx(
|
|
|
435
449
|
currentTurnSurfaces: [],
|
|
436
450
|
|
|
437
451
|
workingDir: "/tmp",
|
|
438
|
-
workspaceTopLevelContext: null,
|
|
439
|
-
workspaceTopLevelDirty: false,
|
|
440
452
|
channelCapabilities: undefined,
|
|
441
453
|
commandIntent: undefined,
|
|
442
454
|
trustContext: undefined,
|
|
@@ -446,15 +458,15 @@ function makeCtx(
|
|
|
446
458
|
preactivatedSkillIds: undefined,
|
|
447
459
|
skillProjectionState: new Map(),
|
|
448
460
|
skillProjectionCache:
|
|
449
|
-
new Map() as unknown as
|
|
461
|
+
new Map() as unknown as Conversation["skillProjectionCache"],
|
|
450
462
|
|
|
451
463
|
traceEmitter: {
|
|
452
464
|
emit: () => {},
|
|
453
|
-
} as unknown as
|
|
465
|
+
} as unknown as Conversation["traceEmitter"],
|
|
454
466
|
profiler: {
|
|
455
467
|
startRequest: () => {},
|
|
456
468
|
emitSummary: () => {},
|
|
457
|
-
} as unknown as
|
|
469
|
+
} as unknown as Conversation["profiler"],
|
|
458
470
|
usageStats: {
|
|
459
471
|
totalInputTokens: 0,
|
|
460
472
|
totalOutputTokens: 0,
|
|
@@ -467,13 +479,12 @@ function makeCtx(
|
|
|
467
479
|
lastAttachmentWarnings: [],
|
|
468
480
|
|
|
469
481
|
hasNoClient: false,
|
|
470
|
-
prompter: {} as unknown as
|
|
471
|
-
queue: {} as unknown as
|
|
482
|
+
prompter: {} as unknown as Conversation["prompter"],
|
|
483
|
+
queue: {} as unknown as Conversation["queue"],
|
|
472
484
|
|
|
473
485
|
getWorkspaceGitService: () => ({ ensureInitialized: async () => {} }),
|
|
474
486
|
commitTurnChanges: async () => {},
|
|
475
487
|
|
|
476
|
-
refreshWorkspaceTopLevelContextIfNeeded: () => {},
|
|
477
488
|
markWorkspaceTopLevelDirty: () => {},
|
|
478
489
|
emitActivityState: () => {},
|
|
479
490
|
getQueueDepth: () => 0,
|
|
@@ -500,10 +511,10 @@ function makeCtx(
|
|
|
500
511
|
}),
|
|
501
512
|
retrackCachedNodes: () => {},
|
|
502
513
|
recordPkbQueryVectors: () => {},
|
|
503
|
-
} as unknown as
|
|
514
|
+
} as unknown as Conversation["graphMemory"],
|
|
504
515
|
|
|
505
516
|
...overrides,
|
|
506
|
-
} as
|
|
517
|
+
} as unknown as Conversation;
|
|
507
518
|
}
|
|
508
519
|
|
|
509
520
|
// ── Tests ────────────────────────────────────────────────────────────
|
|
@@ -541,20 +552,11 @@ afterAll(() => {
|
|
|
541
552
|
|
|
542
553
|
describe("runAgentLoopImpl — per-conversation inferenceProfile", () => {
|
|
543
554
|
test("non-background conversation with inferenceProfile threads it through as overrideProfile", async () => {
|
|
544
|
-
|
|
545
|
-
|
|
555
|
+
const captured: CapturedAgentLoopRun[] = [];
|
|
556
|
+
const ctx = makeCtx(captured, {
|
|
546
557
|
conversationType: "standard",
|
|
547
558
|
inferenceProfile: "quality-optimized",
|
|
548
|
-
|
|
549
|
-
contextCompactedMessageCount: 0,
|
|
550
|
-
totalInputTokens: 0,
|
|
551
|
-
totalOutputTokens: 0,
|
|
552
|
-
totalEstimatedCost: 0,
|
|
553
|
-
title: null,
|
|
554
|
-
};
|
|
555
|
-
|
|
556
|
-
const captured: CapturedAgentLoopRun[] = [];
|
|
557
|
-
const ctx = makeCtx(captured);
|
|
559
|
+
});
|
|
558
560
|
|
|
559
561
|
await runAgentLoopImpl(ctx, "hello", "msg-1", () => {});
|
|
560
562
|
|
|
@@ -564,21 +566,12 @@ describe("runAgentLoopImpl — per-conversation inferenceProfile", () => {
|
|
|
564
566
|
}
|
|
565
567
|
});
|
|
566
568
|
|
|
567
|
-
test("background conversation ignores inferenceProfile
|
|
568
|
-
|
|
569
|
-
|
|
569
|
+
test("background conversation ignores inferenceProfile", async () => {
|
|
570
|
+
const captured: CapturedAgentLoopRun[] = [];
|
|
571
|
+
const ctx = makeCtx(captured, {
|
|
570
572
|
conversationType: "background",
|
|
571
573
|
inferenceProfile: "quality-optimized",
|
|
572
|
-
|
|
573
|
-
contextCompactedMessageCount: 0,
|
|
574
|
-
totalInputTokens: 0,
|
|
575
|
-
totalOutputTokens: 0,
|
|
576
|
-
totalEstimatedCost: 0,
|
|
577
|
-
title: null,
|
|
578
|
-
};
|
|
579
|
-
|
|
580
|
-
const captured: CapturedAgentLoopRun[] = [];
|
|
581
|
-
const ctx = makeCtx(captured);
|
|
574
|
+
});
|
|
582
575
|
|
|
583
576
|
await runAgentLoopImpl(ctx, "hello", "msg-1", () => {});
|
|
584
577
|
|
|
@@ -588,22 +581,9 @@ describe("runAgentLoopImpl — per-conversation inferenceProfile", () => {
|
|
|
588
581
|
}
|
|
589
582
|
});
|
|
590
583
|
|
|
591
|
-
test("absence of inferenceProfile
|
|
592
|
-
// `mockConversationRow` already defaults to inferenceProfile: null.
|
|
593
|
-
// Also explicitly cover the case where the column is missing entirely.
|
|
594
|
-
mockConversationRow = {
|
|
595
|
-
id: "conv-1",
|
|
596
|
-
conversationType: "standard",
|
|
597
|
-
contextSummary: null,
|
|
598
|
-
contextCompactedMessageCount: 0,
|
|
599
|
-
totalInputTokens: 0,
|
|
600
|
-
totalOutputTokens: 0,
|
|
601
|
-
totalEstimatedCost: 0,
|
|
602
|
-
title: null,
|
|
603
|
-
};
|
|
604
|
-
|
|
584
|
+
test("absence of inferenceProfile behaves identically to today (no override)", async () => {
|
|
605
585
|
const captured: CapturedAgentLoopRun[] = [];
|
|
606
|
-
const ctx = makeCtx(captured);
|
|
586
|
+
const ctx = makeCtx(captured, { conversationType: "standard" });
|
|
607
587
|
|
|
608
588
|
await runAgentLoopImpl(ctx, "hello", "msg-1", () => {});
|
|
609
589
|
|
|
@@ -613,26 +593,17 @@ describe("runAgentLoopImpl — per-conversation inferenceProfile", () => {
|
|
|
613
593
|
}
|
|
614
594
|
});
|
|
615
595
|
|
|
616
|
-
test("explicit options.overrideProfile takes precedence over the
|
|
596
|
+
test("explicit options.overrideProfile takes precedence over the conversation override", async () => {
|
|
617
597
|
// Subagent path: SubagentManager forwards the parent's pinned profile
|
|
618
598
|
// into the spawned (background) conversation's runAgentLoop call via
|
|
619
599
|
// `options.overrideProfile`. The agent loop must respect that even
|
|
620
|
-
// though the subagent's own conversation
|
|
600
|
+
// though the subagent's own conversation is `background` (which
|
|
621
601
|
// would otherwise zero out the override per the rule above).
|
|
622
|
-
|
|
623
|
-
|
|
602
|
+
const captured: CapturedAgentLoopRun[] = [];
|
|
603
|
+
const ctx = makeCtx(captured, {
|
|
624
604
|
conversationType: "background",
|
|
625
605
|
inferenceProfile: null,
|
|
626
|
-
|
|
627
|
-
contextCompactedMessageCount: 0,
|
|
628
|
-
totalInputTokens: 0,
|
|
629
|
-
totalOutputTokens: 0,
|
|
630
|
-
totalEstimatedCost: 0,
|
|
631
|
-
title: null,
|
|
632
|
-
};
|
|
633
|
-
|
|
634
|
-
const captured: CapturedAgentLoopRun[] = [];
|
|
635
|
-
const ctx = makeCtx(captured);
|
|
606
|
+
});
|
|
636
607
|
|
|
637
608
|
await runAgentLoopImpl(ctx, "hello", "msg-1", () => {}, {
|
|
638
609
|
overrideProfile: "fast",
|
|
@@ -645,27 +616,15 @@ describe("runAgentLoopImpl — per-conversation inferenceProfile", () => {
|
|
|
645
616
|
});
|
|
646
617
|
|
|
647
618
|
test("re-resolves inferenceProfile when a tool changes it mid-turn", async () => {
|
|
648
|
-
|
|
649
|
-
|
|
619
|
+
const captured: CapturedAgentLoopRun[] = [];
|
|
620
|
+
const ctx = makeCtx(captured, {
|
|
650
621
|
conversationType: "standard",
|
|
651
622
|
inferenceProfile: null,
|
|
652
|
-
|
|
653
|
-
contextCompactedMessageCount: 0,
|
|
654
|
-
totalInputTokens: 0,
|
|
655
|
-
totalOutputTokens: 0,
|
|
656
|
-
totalEstimatedCost: 0,
|
|
657
|
-
title: null,
|
|
658
|
-
};
|
|
623
|
+
});
|
|
659
624
|
mutateBeforeResolveOverrideProfile = () => {
|
|
660
|
-
|
|
661
|
-
...mockConversationRow!,
|
|
662
|
-
inferenceProfile: "quality-optimized",
|
|
663
|
-
};
|
|
625
|
+
ctx.inferenceProfile = "quality-optimized";
|
|
664
626
|
};
|
|
665
627
|
|
|
666
|
-
const captured: CapturedAgentLoopRun[] = [];
|
|
667
|
-
const ctx = makeCtx(captured);
|
|
668
|
-
|
|
669
628
|
await runAgentLoopImpl(ctx, "hello", "msg-1", () => {});
|
|
670
629
|
|
|
671
630
|
expect(captured.length).toBeGreaterThan(0);
|