@vellumai/assistant 0.8.8 → 0.8.9-dev.202606091853.fbaa2ae
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 +263 -121
- package/package.json +2 -2
- 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__/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__/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-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__/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-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__/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__/send-endpoint-busy.test.ts +4 -1
- 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__/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/responses/conversation-message.ts +22 -2
- 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 -16
- package/src/config/llm-resolver.ts +39 -7
- 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 +18 -36
- 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/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/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 +34 -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 +22 -0
- 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
|
@@ -150,11 +150,25 @@ const STREAMING_ERROR_PATTERNS = [
|
|
|
150
150
|
];
|
|
151
151
|
|
|
152
152
|
// User-initiated cancellation patterns — these should NOT produce conversation_error
|
|
153
|
-
// Image-input validation patterns — Anthropic 400s with
|
|
154
|
-
// block
|
|
155
|
-
//
|
|
153
|
+
// Image-input validation patterns — Anthropic 400s with one of these messages
|
|
154
|
+
// when an image block violates a hard limit. The first matches the per-side
|
|
155
|
+
// pixel cap ("image dimensions exceed max allowed size"); the second matches the
|
|
156
|
+
// base64 payload cap ("image exceeds 5 MB maximum: 7465044 bytes > 5242880
|
|
157
|
+
// bytes"). Distinct classification matters because retrying with the same
|
|
158
|
+
// oversized image is futile — the recovery path must strip or downscale it.
|
|
156
159
|
const IMAGE_DIMENSIONS_TOO_LARGE_PATTERNS = [
|
|
157
160
|
/image dimensions? exceeds? max allowed size/i,
|
|
161
|
+
/image exceeds \d+\s*MB maximum/i,
|
|
162
|
+
];
|
|
163
|
+
|
|
164
|
+
const VISION_NOT_SUPPORTED_PATTERNS = [
|
|
165
|
+
/no endpoints found that support image input/i,
|
|
166
|
+
/does not support image/i,
|
|
167
|
+
/doesn't support image input/i,
|
|
168
|
+
/image input is not supported/i,
|
|
169
|
+
/this model does not support vision/i,
|
|
170
|
+
/vision is not supported/i,
|
|
171
|
+
/multi-?modal.*not.*support/i,
|
|
158
172
|
];
|
|
159
173
|
|
|
160
174
|
const CANCEL_PATTERNS = [/abort/i, /cancel/i];
|
|
@@ -447,11 +461,20 @@ function classifyCore(
|
|
|
447
461
|
return {
|
|
448
462
|
code: "IMAGE_TOO_LARGE",
|
|
449
463
|
userMessage:
|
|
450
|
-
"An
|
|
464
|
+
"An image in this conversation was too large for the AI provider and was automatically reduced. Send your message again to continue.",
|
|
451
465
|
retryable: false,
|
|
452
466
|
errorCategory: "image_dimensions_too_large",
|
|
453
467
|
};
|
|
454
468
|
}
|
|
469
|
+
if (isVisionNotSupported(message)) {
|
|
470
|
+
return {
|
|
471
|
+
code: "PROVIDER_API",
|
|
472
|
+
userMessage:
|
|
473
|
+
"This model doesn't support image input. Remove the image or switch to a vision-capable model.",
|
|
474
|
+
retryable: false,
|
|
475
|
+
errorCategory: "vision_not_supported",
|
|
476
|
+
};
|
|
477
|
+
}
|
|
455
478
|
// Extract the provider detail after "API error (NNN): " prefix
|
|
456
479
|
const detailMatch = message.match(/API error \(\d+\):\s*(.+)/i);
|
|
457
480
|
const detail = detailMatch?.[1];
|
|
@@ -481,6 +504,10 @@ function isImageDimensionsTooLarge(message: string): boolean {
|
|
|
481
504
|
return IMAGE_DIMENSIONS_TOO_LARGE_PATTERNS.some((p) => p.test(message));
|
|
482
505
|
}
|
|
483
506
|
|
|
507
|
+
function isVisionNotSupported(message: string): boolean {
|
|
508
|
+
return VISION_NOT_SUPPORTED_PATTERNS.some((p) => p.test(message));
|
|
509
|
+
}
|
|
510
|
+
|
|
484
511
|
/** Check whether an error message indicates a web-search-specific ordering failure. */
|
|
485
512
|
function isWebSearchOrderingError(message: string): boolean {
|
|
486
513
|
return WEB_SEARCH_ORDERING_PATTERNS.some((p) => p.test(message));
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { v4 as uuid } from "uuid";
|
|
2
2
|
|
|
3
|
-
import { getSummaryFromContextMessage } from "../context/window-manager.js";
|
|
4
3
|
import {
|
|
5
4
|
deleteLastExchange,
|
|
6
5
|
deleteMessageById,
|
|
@@ -13,6 +12,7 @@ import { enqueueMemoryJob } from "../memory/jobs-store.js";
|
|
|
13
12
|
import { relinkLlmRequestLogs } from "../memory/llm-request-log-store.js";
|
|
14
13
|
import { withQdrantBreaker } from "../memory/qdrant-circuit-breaker.js";
|
|
15
14
|
import { getQdrantClient } from "../memory/qdrant-client.js";
|
|
15
|
+
import { getSummaryFromContextMessage } from "../plugins/defaults/compaction/window-manager.js";
|
|
16
16
|
import type { ContentBlock, Message } from "../providers/types.js";
|
|
17
17
|
import { getLogger } from "../util/logger.js";
|
|
18
18
|
import { truncate } from "../util/truncate.js";
|
|
@@ -1,23 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Conversation lifecycle
|
|
3
|
-
*
|
|
2
|
+
* Conversation lifecycle helpers extracted from Conversation: abort and
|
|
3
|
+
* dispose. Each operates on a context interface so the Conversation class
|
|
4
4
|
* can delegate without exposing its full surface.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { getConfig } from "../config/loader.js";
|
|
8
|
-
import { createContextSummaryMessage } from "../context/window-manager.js";
|
|
9
8
|
import type { EventBus } from "../events/bus.js";
|
|
10
9
|
import type { AssistantDomainEvents } from "../events/domain-events.js";
|
|
11
10
|
import type { ToolProfiler } from "../events/tool-profiling-listener.js";
|
|
12
11
|
import { enqueueAutoAnalysisIfEnabled } from "../memory/auto-analysis-enqueue.js";
|
|
13
12
|
import { isAutoAnalysisConversation } from "../memory/auto-analysis-guard.js";
|
|
14
|
-
import { getConversation, getMessages } from "../memory/conversation-crud.js";
|
|
15
13
|
import { enqueueMemoryJob, isMemoryEnabled } from "../memory/jobs-store.js";
|
|
16
14
|
import { enqueueMemoryRetrospectiveIfEnabled } from "../memory/memory-retrospective-enqueue.js";
|
|
17
|
-
import { shouldExposePersonalMemory } from "../memory/v2/static-context.js";
|
|
18
15
|
import type { PermissionPrompter } from "../permissions/prompter.js";
|
|
19
16
|
import type { SecretPrompter } from "../permissions/secret-prompter.js";
|
|
20
|
-
import {
|
|
17
|
+
import { disposeContextWindowManager } from "../plugins/defaults/compaction/manager-store.js";
|
|
21
18
|
import type { ContentBlock, Message } from "../providers/types.js";
|
|
22
19
|
import {
|
|
23
20
|
isUntrustedTrustClass,
|
|
@@ -28,15 +25,8 @@ import { type AbortReason, createAbortReason } from "../util/abort-reasons.js";
|
|
|
28
25
|
import { getLogger } from "../util/logger.js";
|
|
29
26
|
import { unregisterCallNotifiers } from "./conversation-notifiers.js";
|
|
30
27
|
import type { MessageQueue } from "./conversation-queue-manager.js";
|
|
31
|
-
import { stripInjectionsForCompaction } from "./conversation-runtime-assembly.js";
|
|
32
28
|
import { resetSkillToolProjection } from "./conversation-skill-tools.js";
|
|
33
|
-
import type {
|
|
34
|
-
SurfaceData,
|
|
35
|
-
SurfaceType,
|
|
36
|
-
UsageStats,
|
|
37
|
-
} from "./message-protocol.js";
|
|
38
|
-
import { filterMessagesForUntrustedActor } from "./message-provenance.js";
|
|
39
|
-
import { resolveTrustClass, type TrustContext } from "./trust-context.js";
|
|
29
|
+
import type { SurfaceData, SurfaceType } from "./message-protocol.js";
|
|
40
30
|
|
|
41
31
|
const log = getLogger("conversation-lifecycle");
|
|
42
32
|
|
|
@@ -75,17 +65,6 @@ export function reinjectImageSourcePaths(
|
|
|
75
65
|
|
|
76
66
|
// ── Context Interfaces ───────────────────────────────────────────────
|
|
77
67
|
|
|
78
|
-
export interface LoadFromDbContext {
|
|
79
|
-
readonly conversationId: string;
|
|
80
|
-
messages: Message[];
|
|
81
|
-
usageStats: UsageStats;
|
|
82
|
-
contextCompactedMessageCount: number;
|
|
83
|
-
contextCompactedAt: number | null;
|
|
84
|
-
trustContext?: TrustContext;
|
|
85
|
-
loadedHistoryTrustClass?: TrustClass;
|
|
86
|
-
loadedHistoryPersonalMemoryAllowed?: boolean;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
68
|
export interface AbortContext {
|
|
90
69
|
readonly conversationId: string;
|
|
91
70
|
isProcessing(): boolean;
|
|
@@ -127,236 +106,6 @@ export interface DisposeContext extends AbortContext {
|
|
|
127
106
|
abort(): void;
|
|
128
107
|
}
|
|
129
108
|
|
|
130
|
-
// ── loadFromDb ───────────────────────────────────────────────────────
|
|
131
|
-
|
|
132
|
-
export async function loadFromDb(ctx: LoadFromDbContext): Promise<void> {
|
|
133
|
-
const trustClass = ctx.trustContext?.trustClass;
|
|
134
|
-
const allDbMessages = getMessages(ctx.conversationId);
|
|
135
|
-
const dbMessages = isUntrustedTrustClass(trustClass)
|
|
136
|
-
? filterMessagesForUntrustedActor(allDbMessages)
|
|
137
|
-
: allDbMessages;
|
|
138
|
-
|
|
139
|
-
const conv = getConversation(ctx.conversationId);
|
|
140
|
-
const contextSummary = !isUntrustedTrustClass(trustClass)
|
|
141
|
-
? conv?.contextSummary?.trim() || null
|
|
142
|
-
: null;
|
|
143
|
-
if (isUntrustedTrustClass(trustClass)) {
|
|
144
|
-
// Compacted summaries may include trusted/guardian-only details, so we
|
|
145
|
-
// disable summary-based context for untrusted actor views.
|
|
146
|
-
ctx.contextCompactedMessageCount = 0;
|
|
147
|
-
ctx.contextCompactedAt = null;
|
|
148
|
-
} else {
|
|
149
|
-
ctx.contextCompactedMessageCount = Math.max(
|
|
150
|
-
0,
|
|
151
|
-
Math.min(conv?.contextCompactedMessageCount ?? 0, dbMessages.length),
|
|
152
|
-
);
|
|
153
|
-
ctx.contextCompactedAt = conv?.contextCompactedAt ?? null;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// Every injection-strip event (`/clean` or compaction) updates
|
|
157
|
-
// `historyStrippedAt`. Messages older than this should skip metadata
|
|
158
|
-
// rehydration and have any injection prefixes still embedded in their
|
|
159
|
-
// content stripped, so the post-strip view survives reload and forks.
|
|
160
|
-
const historyStrippedAt = conv?.historyStrippedAt ?? null;
|
|
161
|
-
const slicedDbMessages = dbMessages.slice(ctx.contextCompactedMessageCount);
|
|
162
|
-
let preStrippedCount = 0;
|
|
163
|
-
if (historyStrippedAt != null) {
|
|
164
|
-
const boundary = slicedDbMessages.findIndex(
|
|
165
|
-
(m) => m.createdAt >= historyStrippedAt,
|
|
166
|
-
);
|
|
167
|
-
preStrippedCount = boundary === -1 ? slicedDbMessages.length : boundary;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
// Mirror the injection-time gate (`shouldExposePersonalMemory` in
|
|
171
|
-
// `conversation-agent-loop.ts`) so background/local conversations
|
|
172
|
-
// (sourceChannel `undefined` or `"vellum"`) can rehydrate the persisted
|
|
173
|
-
// v2 static memory block. Use `resolveTrustClass` for parity with the
|
|
174
|
-
// agent loop — it folds in the HTTP-auth-disabled dev bypass so
|
|
175
|
-
// rehydration and injection agree on the effective trust class.
|
|
176
|
-
const personalMemoryAllowed = shouldExposePersonalMemory({
|
|
177
|
-
sourceChannel: ctx.trustContext?.sourceChannel,
|
|
178
|
-
isTrustedActor: resolveTrustClass(ctx.trustContext) === "guardian",
|
|
179
|
-
});
|
|
180
|
-
const parsedMessages: Message[] = slicedDbMessages.map((m, index, arr) => {
|
|
181
|
-
const isPreStripped = index < preStrippedCount;
|
|
182
|
-
const role = m.role as "user" | "assistant";
|
|
183
|
-
let content: ContentBlock[];
|
|
184
|
-
try {
|
|
185
|
-
const parsed = JSON.parse(m.content);
|
|
186
|
-
content = Array.isArray(parsed)
|
|
187
|
-
? parsed
|
|
188
|
-
: [{ type: "text", text: m.content }];
|
|
189
|
-
} catch {
|
|
190
|
-
log.warn(
|
|
191
|
-
{ conversationId: ctx.conversationId, messageId: m.id },
|
|
192
|
-
"Invalid JSON in persisted message content, replacing with safe text block",
|
|
193
|
-
);
|
|
194
|
-
content = [{ type: "text", text: m.content }];
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
content = reinjectImageSourcePaths(content, role, m.metadata);
|
|
198
|
-
|
|
199
|
-
// Re-inject persisted injection blocks from metadata so it survives
|
|
200
|
-
// conversation reloads (eviction, restart, fork).
|
|
201
|
-
if (role === "user" && m.metadata && !isPreStripped) {
|
|
202
|
-
try {
|
|
203
|
-
const meta = JSON.parse(m.metadata);
|
|
204
|
-
const isTail = index === arr.length - 1;
|
|
205
|
-
|
|
206
|
-
// Rehydrate in reverse injection order (innermost block first)
|
|
207
|
-
// so the resulting layout matches `applyRuntimeInjections`'s
|
|
208
|
-
// after-memory-prefix splices in ascending injector order
|
|
209
|
-
// (pkb-context 30, pkb-reminder 35, memory-v2-static 38,
|
|
210
|
-
// now-md 40 — the v2 static block lands inside the memory
|
|
211
|
-
// prefix, so now-md splices *after* it):
|
|
212
|
-
// [<workspace>, <turn_context>, <memory>dynamic</memory>,
|
|
213
|
-
// <info>v2static</info>, <NOW.md>, <system_reminder>,
|
|
214
|
-
// <knowledge_base>, ...original]
|
|
215
|
-
// The v2 static block is replayed verbatim from stored metadata,
|
|
216
|
-
// so rows may carry either `<info>…</info>` or `<memory>…</memory>`
|
|
217
|
-
// depending on when they were persisted.
|
|
218
|
-
// Required so Anthropic's prefix cache keeps matching msg[0]
|
|
219
|
-
// across daemon restart and conversation eviction. The tail
|
|
220
|
-
// row only rehydrates `memoryInjectedBlock` — the next turn
|
|
221
|
-
// re-injects the rest fresh.
|
|
222
|
-
if (!isTail && typeof meta.pkbContextBlock === "string") {
|
|
223
|
-
content = [
|
|
224
|
-
{ type: "text" as const, text: meta.pkbContextBlock },
|
|
225
|
-
...content,
|
|
226
|
-
];
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
if (!isTail && typeof meta.pkbSystemReminderBlock === "string") {
|
|
230
|
-
content = [
|
|
231
|
-
{ type: "text" as const, text: meta.pkbSystemReminderBlock },
|
|
232
|
-
...content,
|
|
233
|
-
];
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
if (!isTail && typeof meta.nowScratchpadBlock === "string") {
|
|
237
|
-
content = [
|
|
238
|
-
{ type: "text" as const, text: meta.nowScratchpadBlock },
|
|
239
|
-
...content,
|
|
240
|
-
];
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
// The v2 static memory block (essentials/threads/recent/buffer
|
|
244
|
-
// wrapped in either `<info>…</info>` or `<memory>…</memory>`)
|
|
245
|
-
// carries personal user memory. Trust-gated to mirror
|
|
246
|
-
// `shouldExposePersonalMemory` at injection time — untrusted-actor
|
|
247
|
-
// views must not read persisted personal memory back through
|
|
248
|
-
// metadata. Skipped on the tail row because the next turn
|
|
249
|
-
// re-injects fresh content on full-mode turns.
|
|
250
|
-
if (
|
|
251
|
-
!isTail &&
|
|
252
|
-
personalMemoryAllowed &&
|
|
253
|
-
typeof meta.memoryV2StaticBlock === "string"
|
|
254
|
-
) {
|
|
255
|
-
content = [
|
|
256
|
-
{ type: "text" as const, text: meta.memoryV2StaticBlock },
|
|
257
|
-
...content,
|
|
258
|
-
];
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
// Memory remains rehydrated on all rows (existing behavior).
|
|
262
|
-
// Strip any pre-existing wrapper before re-wrapping so historical
|
|
263
|
-
// rows persisted with the wrapper (v2 path before the
|
|
264
|
-
// injectedBlockText contract was unified with v1's unwrapped form)
|
|
265
|
-
// don't render double-wrapped after rehydrate. Only unwrap when
|
|
266
|
-
// the full <memory>...</memory> pair is present so we don't mutate
|
|
267
|
-
// legitimate unwrapped payloads that happen to start with
|
|
268
|
-
// "<memory>\n" or end with "\n</memory>".
|
|
269
|
-
if (typeof meta.memoryInjectedBlock === "string") {
|
|
270
|
-
const block = meta.memoryInjectedBlock;
|
|
271
|
-
const inner =
|
|
272
|
-
block.startsWith("<memory>\n") && block.endsWith("\n</memory>")
|
|
273
|
-
? block.slice("<memory>\n".length, -"\n</memory>".length)
|
|
274
|
-
: block;
|
|
275
|
-
content = [
|
|
276
|
-
{
|
|
277
|
-
type: "text" as const,
|
|
278
|
-
text: `<memory>\n${inner}\n</memory>`,
|
|
279
|
-
},
|
|
280
|
-
...content,
|
|
281
|
-
];
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
if (!isTail && typeof meta.turnContextBlock === "string") {
|
|
285
|
-
content = [
|
|
286
|
-
{ type: "text" as const, text: meta.turnContextBlock },
|
|
287
|
-
...content,
|
|
288
|
-
];
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
if (!isTail && typeof meta.workspaceBlock === "string") {
|
|
292
|
-
content = [
|
|
293
|
-
{ type: "text" as const, text: meta.workspaceBlock },
|
|
294
|
-
...content,
|
|
295
|
-
];
|
|
296
|
-
}
|
|
297
|
-
} catch {
|
|
298
|
-
/* ignore parse errors — metadata may be malformed */
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
return { role, content };
|
|
303
|
-
});
|
|
304
|
-
|
|
305
|
-
// Strip pre-clean messages only; post-clean messages keep the fresh
|
|
306
|
-
// injections they were generated with.
|
|
307
|
-
const messagesBeforeRepair =
|
|
308
|
-
preStrippedCount === 0
|
|
309
|
-
? parsedMessages
|
|
310
|
-
: [
|
|
311
|
-
...stripInjectionsForCompaction(
|
|
312
|
-
parsedMessages.slice(0, preStrippedCount),
|
|
313
|
-
),
|
|
314
|
-
...parsedMessages.slice(preStrippedCount),
|
|
315
|
-
];
|
|
316
|
-
|
|
317
|
-
// Normalize the canonical persisted history once at load. Every consumer
|
|
318
|
-
// of `ctx.messages` outside the agent loop (history edit/undo, PKB context
|
|
319
|
-
// tracking, surfaces) reads this list directly, so it must satisfy the
|
|
320
|
-
// provider pairing/alternation rules before any of them run. The agent
|
|
321
|
-
// loop's pre-run repair only repairs the transient per-turn message list it
|
|
322
|
-
// sends to the provider and never writes back here, so this pass is not
|
|
323
|
-
// redundant with it.
|
|
324
|
-
const { messages: repairedMessages, stats } =
|
|
325
|
-
repairHistory(messagesBeforeRepair);
|
|
326
|
-
if (
|
|
327
|
-
stats.assistantToolResultsMigrated > 0 ||
|
|
328
|
-
stats.missingToolResultsInserted > 0 ||
|
|
329
|
-
stats.orphanToolResultsDowngraded > 0 ||
|
|
330
|
-
stats.consecutiveSameRoleMerged > 0
|
|
331
|
-
) {
|
|
332
|
-
log.warn(
|
|
333
|
-
{ conversationId: ctx.conversationId, phase: "load", ...stats },
|
|
334
|
-
"Repaired persisted history",
|
|
335
|
-
);
|
|
336
|
-
}
|
|
337
|
-
ctx.messages = repairedMessages;
|
|
338
|
-
|
|
339
|
-
if (contextSummary) {
|
|
340
|
-
ctx.messages.unshift(createContextSummaryMessage(contextSummary));
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
if (conv) {
|
|
344
|
-
ctx.usageStats = {
|
|
345
|
-
inputTokens: conv.totalInputTokens,
|
|
346
|
-
outputTokens: conv.totalOutputTokens,
|
|
347
|
-
estimatedCost: conv.totalEstimatedCost,
|
|
348
|
-
};
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
ctx.loadedHistoryTrustClass = trustClass;
|
|
352
|
-
ctx.loadedHistoryPersonalMemoryAllowed = personalMemoryAllowed;
|
|
353
|
-
|
|
354
|
-
log.info(
|
|
355
|
-
{ conversationId: ctx.conversationId, count: ctx.messages.length },
|
|
356
|
-
"Loaded messages from DB",
|
|
357
|
-
);
|
|
358
|
-
}
|
|
359
|
-
|
|
360
109
|
// ── abort ─────────────────────────────────────────────────────────────
|
|
361
110
|
|
|
362
111
|
export function abortConversation(
|
|
@@ -493,4 +242,11 @@ export function disposeConversation(ctx: DisposeContext): void {
|
|
|
493
242
|
ctx.accumulatedSurfaceState.clear();
|
|
494
243
|
ctx.lastSurfaceAction.clear();
|
|
495
244
|
ctx.workspaceTopLevelContext = null;
|
|
245
|
+
// The compaction module owns the per-conversation ContextWindowManager, so
|
|
246
|
+
// teardown releases it directly. Moving this behind a compaction-plugin hook
|
|
247
|
+
// would let the module own disposal end-to-end, but the per-turn `stop` hook
|
|
248
|
+
// would first require relocating the manager's only
|
|
249
|
+
// cross-turn state — `nonPersistedPrefixCount` — off the manager so a
|
|
250
|
+
// per-turn dispose/rebuild stays correct.
|
|
251
|
+
disposeContextWindowManager(ctx.conversationId);
|
|
496
252
|
}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { estimateContentBlockTokens } from "../context/token-estimator.js";
|
|
10
|
-
import { getSummaryFromContextMessage } from "../
|
|
10
|
+
import { getSummaryFromContextMessage } from "../plugins/defaults/compaction/window-manager.js";
|
|
11
11
|
import type { ContentBlock, Message } from "../providers/types.js";
|
|
12
12
|
|
|
13
13
|
export interface StripMediaOptions {
|
|
@@ -173,15 +173,28 @@ export function estimateUnconditionalStubTokens(
|
|
|
173
173
|
const msg = messages[msgIndex];
|
|
174
174
|
for (const block of msg.content) {
|
|
175
175
|
if (block.type === "image" && msgIndex !== latestUserIndex) {
|
|
176
|
-
stubTokens += estimateContentBlockTokens(
|
|
176
|
+
stubTokens += estimateContentBlockTokens(
|
|
177
|
+
imageBlockToStub(block),
|
|
178
|
+
options,
|
|
179
|
+
);
|
|
177
180
|
} else if (block.type === "file" && msgIndex !== latestUserIndex) {
|
|
178
|
-
stubTokens += estimateContentBlockTokens(
|
|
179
|
-
|
|
181
|
+
stubTokens += estimateContentBlockTokens(
|
|
182
|
+
fileBlockToStub(block),
|
|
183
|
+
options,
|
|
184
|
+
);
|
|
185
|
+
} else if (block.type === "tool_result" && block.contentBlocks) {
|
|
186
|
+
// guard:allow-tool-result-only — web_search_tool_result has no contentBlocks
|
|
180
187
|
for (const cb of block.contentBlocks) {
|
|
181
188
|
if (cb.type === "image") {
|
|
182
|
-
stubTokens += estimateContentBlockTokens(
|
|
189
|
+
stubTokens += estimateContentBlockTokens(
|
|
190
|
+
imageBlockToStub(cb),
|
|
191
|
+
options,
|
|
192
|
+
);
|
|
183
193
|
} else if (cb.type === "file") {
|
|
184
|
-
stubTokens += estimateContentBlockTokens(
|
|
194
|
+
stubTokens += estimateContentBlockTokens(
|
|
195
|
+
fileBlockToStub(cb),
|
|
196
|
+
options,
|
|
197
|
+
);
|
|
185
198
|
}
|
|
186
199
|
}
|
|
187
200
|
}
|
|
@@ -43,6 +43,7 @@ import {
|
|
|
43
43
|
} from "../messaging/providers/slack/message-metadata.js";
|
|
44
44
|
import type { SecretPrompter } from "../permissions/secret-prompter.js";
|
|
45
45
|
import type { Message } from "../providers/types.js";
|
|
46
|
+
import type { AuthContext } from "../runtime/auth/types.js";
|
|
46
47
|
import { getLogger } from "../util/logger.js";
|
|
47
48
|
import type { MessageQueue } from "./conversation-queue-manager.js";
|
|
48
49
|
import type { SlackInboundMessageMetadata } from "./handlers/shared.js";
|
|
@@ -193,6 +194,9 @@ export interface MessagingConversationContext {
|
|
|
193
194
|
currentRequestId?: string;
|
|
194
195
|
readonly queue: MessageQueue;
|
|
195
196
|
trustContext?: TrustContext;
|
|
197
|
+
authContext?: AuthContext;
|
|
198
|
+
currentTurnAuthContext?: AuthContext;
|
|
199
|
+
currentTurnSourceActorPrincipalId?: string;
|
|
196
200
|
getTurnChannelContext(): TurnChannelContext | null;
|
|
197
201
|
getTurnInterfaceContext(): TurnInterfaceContext | null;
|
|
198
202
|
}
|
|
@@ -302,6 +306,10 @@ export interface EnqueueMessageOptions {
|
|
|
302
306
|
displayContent?: string;
|
|
303
307
|
transport?: ConversationTransportMetadata;
|
|
304
308
|
clientMessageId?: string;
|
|
309
|
+
/** JWT-verified requester principal captured for queued host-proxy routing. */
|
|
310
|
+
sourceActorPrincipalId?: string;
|
|
311
|
+
/** Auth context snapshot captured for queued turn-scoped authorization. */
|
|
312
|
+
authContext?: AuthContext;
|
|
305
313
|
}
|
|
306
314
|
|
|
307
315
|
// ── enqueueMessage ───────────────────────────────────────────────────
|
|
@@ -322,7 +330,14 @@ export function enqueueMessage(
|
|
|
322
330
|
displayContent,
|
|
323
331
|
transport,
|
|
324
332
|
clientMessageId,
|
|
333
|
+
authContext,
|
|
325
334
|
} = options;
|
|
335
|
+
const queuedAuthContext =
|
|
336
|
+
authContext ?? ctx.currentTurnAuthContext ?? ctx.authContext;
|
|
337
|
+
const sourceActorPrincipalId =
|
|
338
|
+
options.sourceActorPrincipalId ??
|
|
339
|
+
ctx.currentTurnSourceActorPrincipalId ??
|
|
340
|
+
queuedAuthContext?.actorPrincipalId;
|
|
326
341
|
|
|
327
342
|
if (!ctx.isProcessing()) {
|
|
328
343
|
return { queued: false, requestId };
|
|
@@ -347,6 +362,8 @@ export function enqueueMessage(
|
|
|
347
362
|
turnChannelContext,
|
|
348
363
|
turnInterfaceContext,
|
|
349
364
|
isInteractive,
|
|
365
|
+
sourceActorPrincipalId,
|
|
366
|
+
authContext: queuedAuthContext,
|
|
350
367
|
transport,
|
|
351
368
|
displayContent,
|
|
352
369
|
sentAt: Date.now(),
|