@vellumai/assistant 0.8.7 → 0.8.8-dev.202606052332.17fc8ea
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/Dockerfile +20 -4
- package/bun.lock +2 -2
- package/docker-entrypoint.sh +4 -2
- package/docker-init-apt-root.sh +3 -1
- package/docker-kata-apt-env.sh +3 -1
- package/docker-kata-runtime-family.sh +12 -0
- package/docs/architecture/memory.md +1 -1
- package/examples/plugins/echo/README.md +61 -66
- 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/server-message.ts +3 -3
- package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +7 -6
- package/openapi.yaml +3378 -335
- package/package.json +2 -2
- package/scripts/generate-openapi.ts +68 -41
- package/src/__tests__/agent-loop-exit-reason.test.ts +35 -93
- package/src/__tests__/agent-loop-provider-error-recording.test.ts +1 -1
- package/src/__tests__/agent-loop.test.ts +37 -87
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +2 -0
- package/src/__tests__/annotate-activity-metadata.test.ts +262 -0
- package/src/__tests__/annotate-risk-options.test.ts +2 -3
- package/src/__tests__/anthropic-provider.test.ts +95 -2
- package/src/__tests__/app-control-flow.test.ts +1 -1
- package/src/__tests__/app-dir-path-guard.test.ts +1 -0
- package/src/__tests__/approval-routes-http.test.ts +4 -1
- package/src/__tests__/assistant-event-hub.test.ts +25 -0
- package/src/__tests__/assistant-events-sse-shed.test.ts +8 -0
- package/src/__tests__/{conversation-stream-state.test.ts → assistant-stream-state.test.ts} +252 -91
- package/src/__tests__/auth-fallback-events-store.test.ts +116 -0
- package/src/__tests__/background-workers-disk-pressure.test.ts +6 -0
- package/src/__tests__/btw-routes.test.ts +62 -3
- package/src/__tests__/build-persisted-content.test.ts +184 -0
- package/src/__tests__/catalog-files.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__/clawhub-files.test.ts +1 -1
- package/src/__tests__/compaction-circuit.test.ts +258 -0
- package/src/__tests__/compaction-direct.test.ts +132 -0
- package/src/__tests__/compaction.benchmark.test.ts +0 -30
- package/src/__tests__/config-watcher.test.ts +1 -1
- package/src/__tests__/conversation-abort-tool-results.test.ts +57 -19
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +6 -5
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +10 -7
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +316 -1143
- package/src/__tests__/conversation-agent-loop.test.ts +638 -1655
- package/src/__tests__/conversation-analysis-routes.test.ts +6 -0
- package/src/__tests__/conversation-clean-command.test.ts +5 -2
- package/src/__tests__/conversation-history-web-search.test.ts +11 -1
- package/src/__tests__/conversation-pairing.test.ts +4 -31
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +6 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +30 -10
- package/src/__tests__/conversation-queue.test.ts +2 -0
- package/src/__tests__/conversation-routes-disk-view.test.ts +3 -0
- package/src/__tests__/conversation-routes-slash-commands.test.ts +6 -5
- package/src/__tests__/conversation-runtime-assembly.test.ts +310 -300
- package/src/__tests__/conversation-runtime-workspace.test.ts +105 -45
- package/src/__tests__/conversation-slash-commands.test.ts +8 -42
- package/src/__tests__/conversation-slash-queue.test.ts +6 -1
- package/src/__tests__/conversation-starter-routes.test.ts +14 -6
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +84 -0
- package/src/__tests__/conversation-sync-tags.test.ts +27 -15
- package/src/__tests__/conversation-title-service.test.ts +135 -2
- package/src/__tests__/conversation-workspace-cache-state.test.ts +17 -16
- package/src/__tests__/conversation-workspace-injection.test.ts +67 -2
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +7 -6
- package/src/__tests__/conversations-import-system-filter.test.ts +101 -0
- package/src/__tests__/cross-provider-web-search.test.ts +214 -1
- package/src/__tests__/db-acp-history.test.ts +101 -0
- package/src/__tests__/db-schedule-syntax-migration.test.ts +5 -0
- package/src/__tests__/dm-persistence.test.ts +5 -1
- package/src/__tests__/dynamic-page-surface.test.ts +31 -0
- package/src/__tests__/empty-response-hook.test.ts +304 -0
- package/src/__tests__/feature-flag-test-helpers.ts +2 -2
- package/src/__tests__/file-write-tool.test.ts +63 -0
- package/src/__tests__/gateway-only-guard.test.ts +12 -2
- package/src/__tests__/gemini-image-service.test.ts +13 -0
- package/src/__tests__/guardian-grant-minting.test.ts +1 -1
- package/src/__tests__/guardian-routing-invariants.test.ts +2 -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__/helpers/mock-provider.ts +110 -0
- package/src/__tests__/helpers/native-web-search-harness.ts +129 -0
- package/src/__tests__/history-repair-hook.test.ts +1 -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__/identity-intro-cache.test.ts +12 -100
- package/src/__tests__/identity-routes.test.ts +248 -7
- package/src/__tests__/inbound-slack-persistence.test.ts +5 -1
- package/src/__tests__/injector-background-turn.test.ts +3 -9
- package/src/__tests__/injector-chain.test.ts +139 -275
- package/src/__tests__/injector-disk-pressure.test.ts +75 -41
- package/src/__tests__/injector-document-comments.test.ts +3 -3
- package/src/__tests__/injector-pkb-v2-silenced.test.ts +30 -22
- package/src/__tests__/injector-v3-suppression.test.ts +31 -37
- package/src/__tests__/internal-telemetry-routes.test.ts +109 -0
- package/src/__tests__/list-messages-hidden-metadata.test.ts +38 -0
- package/src/__tests__/list-messages-page-latest.test.ts +60 -0
- package/src/__tests__/list-messages-tool-merge.test.ts +20 -0
- package/src/__tests__/llm-usage-store.test.ts +223 -1
- package/src/__tests__/memory-retrieval-hook.test.ts +297 -0
- package/src/__tests__/memory-v2-static-injector.test.ts +103 -35
- package/src/__tests__/native-web-search.test.ts +191 -0
- package/src/__tests__/onboarding-template-contract.test.ts +2 -0
- package/src/__tests__/openai-image-service.test.ts +17 -0
- package/src/__tests__/openai-provider.test.ts +31 -1
- package/src/__tests__/{overflow-reduce-pipeline.test.ts → overflow-reduction-loop.test.ts} +64 -284
- package/src/__tests__/persist-unsendable-image.test.ts +215 -0
- package/src/__tests__/persistence-secret-redaction.test.ts +1 -0
- package/src/__tests__/pkb-autoinject.test.ts +2 -5
- package/src/__tests__/plugin-api-shim.test.ts +3 -6
- package/src/__tests__/plugin-bootstrap.test.ts +14 -40
- package/src/__tests__/plugin-registry.test.ts +3 -76
- package/src/__tests__/plugin-types.test.ts +0 -193
- package/src/__tests__/process-message-display-content.test.ts +6 -2
- package/src/__tests__/reaction-persistence.test.ts +1 -1
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +5 -1
- package/src/__tests__/resolve-trust-class.test.ts +4 -4
- package/src/__tests__/runtime-events-sse-reconnect.test.ts +60 -23
- package/src/__tests__/schedule-routes.test.ts +603 -2
- package/src/__tests__/schedule-store.test.ts +41 -0
- package/src/__tests__/schedule-tools.test.ts +35 -0
- package/src/__tests__/send-endpoint-busy.test.ts +4 -1
- package/src/__tests__/server-history-render.test.ts +314 -1
- package/src/__tests__/skill-feature-flags-integration.test.ts +33 -0
- package/src/__tests__/skillssh-files.test.ts +1 -1
- package/src/__tests__/subagent-call-site-routing.test.ts +1 -1
- 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__/system-prompt.test.ts +20 -0
- package/src/__tests__/task-scheduler.test.ts +162 -1
- package/src/__tests__/terminal-tools.test.ts +6 -1
- package/src/__tests__/title-generate-hook.test.ts +319 -0
- package/src/__tests__/tool-error-hook.test.ts +278 -0
- package/src/__tests__/tool-preview-lifecycle.test.ts +468 -5
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +1 -0
- package/src/__tests__/tool-result-truncate-hook.test.ts +127 -0
- package/src/__tests__/tool-result-truncation.test.ts +0 -2
- package/src/__tests__/ui-choice-copy-surfaces.test.ts +254 -0
- package/src/__tests__/ui-work-result-surface.test.ts +159 -0
- package/src/__tests__/usage-routes.test.ts +285 -1
- package/src/__tests__/user-plugin-loader.test.ts +54 -286
- package/src/__tests__/voice-session-bridge.test.ts +6 -3
- package/src/__tests__/web-search-backend-failure.test.ts +166 -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-history-db.ts +82 -0
- package/src/acp/__tests__/helpers/exec-file-stub.ts +101 -0
- package/src/acp/__tests__/prepare-agent-env.test.ts +137 -0
- package/src/acp/__tests__/session-manager-persistence.test.ts +95 -28
- package/src/acp/__tests__/session-manager-resume.test.ts +736 -0
- package/src/acp/agent-process.ts +61 -1
- package/src/acp/auto-install.test.ts +196 -0
- package/src/acp/auto-install.ts +177 -0
- package/src/acp/client-handler.ts +31 -0
- package/src/acp/feature-gate.test.ts +48 -0
- package/src/acp/feature-gate.ts +34 -0
- package/src/acp/prepare-agent-env.ts +83 -29
- package/src/acp/resolve-agent.test.ts +320 -7
- package/src/acp/resolve-agent.ts +182 -18
- package/src/acp/resume-hint.ts +25 -0
- package/src/acp/session-manager.ts +495 -73
- package/src/acp/types.ts +8 -0
- package/src/agent/compaction-circuit.ts +60 -102
- package/src/agent/loop.ts +362 -485
- package/src/api/events/assistant-thinking-delta.ts +33 -0
- package/src/api/events/tool-output-chunk.ts +45 -0
- package/src/api/events/tool-use-preview-start.ts +32 -0
- package/src/api/events/trace-event.ts +69 -0
- package/src/api/index.ts +48 -13
- package/src/api/responses/conversation-message.ts +374 -0
- package/src/approvals/guardian-request-resolvers.ts +1 -1
- package/src/avatar/__tests__/avatar-store.test.ts +34 -29
- package/src/background-wake/next-wake.ts +1 -0
- package/src/cli/commands/__tests__/notifications.test.ts +58 -14
- package/src/cli/commands/notifications.ts +112 -60
- 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 +6 -0
- package/src/config/assistant-feature-flags.ts +22 -11
- package/src/config/bundled-skills/acp/SKILL.md +83 -31
- package/src/config/bundled-skills/acp/TOOLS.json +4 -4
- package/src/config/bundled-skills/app-builder/SKILL.md +224 -398
- package/src/config/bundled-skills/app-builder/TOOLS.json +29 -0
- 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/references/examples/README.md +17 -0
- package/src/config/bundled-skills/app-builder/references/examples/expense-tracker.md +515 -0
- package/src/config/bundled-skills/app-builder/references/examples/focus-timer.md +342 -0
- package/src/config/bundled-skills/app-builder/references/examples/habit-tracker.md +490 -0
- package/src/config/bundled-skills/app-builder/tools/app-list.ts +62 -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-skills/messaging/SKILL.md +0 -7
- package/src/config/bundled-tool-registry.ts +2 -0
- package/src/config/feature-flag-cache.ts +3 -3
- package/src/config/feature-flag-registry.json +48 -7
- package/src/config/schemas/__tests__/memory-v2.test.ts +1 -0
- package/src/config/schemas/__tests__/memory-v3.test.ts +25 -0
- package/src/config/schemas/heartbeat.ts +9 -0
- package/src/config/schemas/llm.ts +1 -0
- package/src/config/schemas/memory-v2.ts +8 -0
- package/src/config/schemas/memory-v3.ts +8 -0
- package/src/config/schemas/platform.ts +8 -0
- package/src/config/seed-inference-profiles.ts +2 -2
- package/src/config/skills.ts +13 -0
- package/src/context/compactor.ts +1 -1
- package/src/context/strip-injections.ts +128 -0
- package/src/context/token-estimator.ts +23 -0
- package/src/context/tool-result-truncation.ts +0 -23
- package/src/context/window-manager.ts +5 -7
- package/src/credential-execution/executable-discovery.ts +16 -0
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +6 -0
- package/src/daemon/__tests__/inference-profile-notification.test.ts +153 -0
- package/src/daemon/__tests__/native-web-search-metadata.test.ts +10 -8
- package/src/daemon/assistant-attachments.ts +1 -1
- package/src/daemon/config-watcher.ts +2 -2
- package/src/daemon/context-overflow-reducer.ts +0 -1
- package/src/daemon/conversation-agent-loop-handlers.ts +594 -153
- package/src/daemon/conversation-agent-loop.ts +301 -997
- package/src/daemon/conversation-history.ts +5 -4
- package/src/daemon/conversation-lifecycle.ts +3 -4
- package/src/daemon/conversation-messaging.ts +7 -6
- package/src/daemon/conversation-process.ts +11 -16
- package/src/daemon/conversation-registry.ts +159 -0
- package/src/daemon/conversation-runtime-assembly.ts +218 -398
- package/src/daemon/conversation-slash.ts +6 -25
- package/src/daemon/conversation-store.ts +9 -90
- package/src/daemon/conversation-surfaces.ts +222 -4
- package/src/daemon/conversation-tool-setup.ts +2 -29
- package/src/daemon/conversation-workspace.ts +17 -0
- package/src/daemon/conversation.ts +32 -20
- package/src/daemon/external-plugins-bootstrap.ts +17 -18
- package/src/daemon/handlers/config-a2a.ts +51 -36
- package/src/daemon/handlers/config-slack-channel.ts +20 -14
- package/src/daemon/handlers/config-telegram.ts +16 -2
- package/src/daemon/handlers/conversations.ts +3 -1
- package/src/daemon/handlers/shared.ts +156 -84
- package/src/daemon/handlers/skills.ts +42 -10
- package/src/daemon/lifecycle.ts +25 -0
- package/src/daemon/message-types/apps.ts +1 -29
- package/src/daemon/message-types/messages.ts +9 -57
- package/src/daemon/message-types/skills.ts +2 -0
- package/src/daemon/message-types/surfaces.ts +136 -3
- package/src/daemon/now-scratchpad.ts +21 -0
- package/src/daemon/orphan-reaper.test.ts +210 -0
- package/src/daemon/orphan-reaper.ts +240 -0
- package/src/daemon/overflow-reduction-loop.ts +230 -0
- package/src/daemon/persist-unsendable-image.ts +117 -0
- package/src/daemon/process-message.ts +1 -3
- package/src/daemon/server.ts +2 -0
- package/src/daemon/trace-emitter.ts +6 -4
- package/src/daemon/trust-context.ts +19 -0
- package/src/daemon/wake-target-adapter.ts +3 -1
- 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/home/home-greeting-cache.ts +24 -1
- package/src/ipc/__tests__/browser-ipc.test.ts +1 -1
- package/src/ipc/__tests__/ui-request-route.test.ts +3 -3
- package/src/ipc/gateway-client.test.ts +2 -2
- package/src/ipc/gateway-client.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/media/gemini-image-service.ts +15 -0
- package/src/media/openai-image-service.ts +14 -0
- package/src/media/types.ts +34 -0
- package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +56 -0
- package/src/memory/auth-fallback-events-store.ts +94 -0
- package/src/memory/conversation-starter-checkpoints.ts +1 -0
- package/src/memory/conversation-title-service.ts +65 -41
- package/src/memory/db-init.ts +6 -0
- package/src/memory/graph/__tests__/conversation-graph-memory-registry.test.ts +119 -0
- package/src/memory/graph/conversation-graph-memory.ts +65 -0
- package/src/memory/job-handlers/conversation-starters.ts +13 -2
- package/src/memory/jobs-store.ts +33 -0
- package/src/memory/jobs-worker.ts +32 -5
- package/src/memory/llm-usage-store.ts +224 -50
- package/src/memory/migrations/222-strip-placeholder-sentinels-from-messages.ts +6 -5
- package/src/memory/migrations/270-schedule-source-conversation.ts +13 -0
- package/src/memory/migrations/271-create-auth-fallback-events.ts +21 -0
- package/src/memory/migrations/272-acp-session-history-cwd.ts +36 -0
- package/src/memory/migrations/index.ts +3 -0
- package/src/memory/pkb/autoinject.ts +61 -0
- package/src/memory/pkb/context.ts +50 -0
- package/src/memory/pkb/types.ts +14 -0
- package/src/memory/schedule-attribution-sql.ts +104 -0
- package/src/memory/schema/acp.ts +4 -0
- package/src/memory/schema/infrastructure.ts +16 -0
- package/src/memory/usage-grouped-buckets.ts +6 -1
- package/src/memory/v2/__tests__/consolidation-job.test.ts +4 -4
- package/src/memory/v2/consolidation-job.ts +14 -5
- package/src/notifications/conversation-pairing.ts +8 -15
- package/src/notifications/decision-engine.ts +6 -3
- package/src/notifications/home-feed-side-effect.ts +12 -1
- package/src/permissions/prompter.ts +4 -0
- package/src/plugin-api/constants.ts +4 -0
- package/src/plugin-api/index.ts +7 -5
- package/src/plugin-api/types.ts +151 -1
- package/src/plugins/defaults/compaction/compact.ts +59 -0
- package/src/plugins/defaults/compaction/package.json +1 -1
- package/src/plugins/defaults/compaction/register.ts +8 -19
- package/src/plugins/defaults/empty-response/hooks/stop.ts +126 -0
- package/src/plugins/defaults/empty-response/register.ts +8 -13
- package/src/plugins/defaults/index.ts +2 -18
- package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +95 -0
- package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit-temp.ts +216 -0
- package/src/plugins/defaults/memory-retrieval/injector-chain.ts +35 -0
- package/src/plugins/defaults/{injectors/register.ts → memory-retrieval/injectors.ts} +288 -81
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/assign.test.ts +4 -4
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/health.test.ts +16 -0
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/live-integration.test.ts +4 -4
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/maintain-job.test.ts +5 -5
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/orchestrate.test.ts +48 -12
- package/src/plugins/defaults/memory-v3-shadow/__tests__/provider-blocks.test.ts +13 -0
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/reconcile.test.ts +2 -2
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/render-injection.test.ts +1 -1
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/router.test.ts +104 -32
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/selection-log-store.test.ts +8 -8
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/selector.test.ts +96 -30
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/shadow-plugin.test.ts +34 -16
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/assign.ts +5 -5
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/capabilities.ts +2 -2
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/health.ts +0 -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 +75 -0
- package/src/plugins/defaults/memory-v3-shadow/llm-retry.ts +32 -0
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/maintain-job.ts +8 -8
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/orchestrate.ts +26 -14
- package/src/plugins/defaults/{llm-call → memory-v3-shadow}/package.json +2 -2
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/page-content.ts +2 -2
- package/src/plugins/defaults/memory-v3-shadow/provider-blocks.ts +26 -0
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/reconcile.ts +3 -3
- package/src/plugins/defaults/memory-v3-shadow/register.ts +26 -0
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/render-injection.ts +1 -1
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/router.ts +51 -45
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/selection-log-store.ts +4 -4
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/selector.ts +61 -46
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/shadow-plugin.ts +69 -99
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/tree.ts +1 -1
- package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/types.ts +8 -0
- package/src/plugins/defaults/title-generate/hooks/stop.ts +75 -0
- package/src/plugins/defaults/title-generate/hooks/user-prompt-submit.ts +35 -0
- package/src/plugins/defaults/title-generate/package.json +1 -1
- package/src/plugins/defaults/title-generate/register.ts +18 -18
- package/src/plugins/defaults/tool-error/hooks/post-tool-use.ts +118 -0
- package/src/plugins/defaults/tool-error/package.json +1 -1
- package/src/plugins/defaults/tool-error/register.ts +9 -21
- package/src/plugins/defaults/tool-result-truncate/hooks/post-tool-use.ts +32 -0
- package/src/plugins/defaults/tool-result-truncate/register.ts +10 -21
- package/src/plugins/defaults/tool-result-truncate/terminal.ts +37 -18
- package/src/plugins/external-api.ts +2 -2
- package/src/plugins/pipeline.ts +6 -305
- package/src/plugins/registry.ts +10 -55
- package/src/plugins/types.ts +62 -797
- package/src/plugins/user-loader.ts +30 -127
- package/src/proactive-artifact/aux-message-injector.ts +4 -4
- package/src/proactive-artifact/job.test.ts +8 -13
- package/src/prompts/__tests__/system-prompt.test.ts +42 -0
- package/src/prompts/templates/BOOTSTRAP-ACTIVATION-RAIL.md +64 -0
- package/src/prompts/templates/BOOTSTRAP.md +2 -2
- package/src/prompts/templates/system-sections.ts +15 -0
- package/src/providers/anthropic/client.ts +37 -29
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +112 -0
- package/src/providers/openai/chat-completions-provider.ts +44 -0
- package/src/providers/openrouter/client.ts +1 -0
- package/src/providers/placeholder-sentinels.ts +35 -0
- package/src/runtime/__tests__/agent-wake.test.ts +10 -6
- package/src/runtime/__tests__/interactive-ui.test.ts +1 -1
- package/src/runtime/agent-wake.ts +2 -5
- package/src/runtime/assistant-event-hub.ts +37 -7
- package/src/runtime/{conversation-stream-state.ts → assistant-stream-state.ts} +132 -58
- package/src/runtime/channel-approvals.ts +1 -1
- package/src/runtime/http-router.ts +16 -21
- package/src/runtime/http-types.ts +16 -70
- package/src/runtime/interactive-ui.ts +1 -1
- package/src/runtime/pending-interactions.ts +1 -0
- package/src/runtime/routes/__tests__/acp-routes.test.ts +283 -55
- package/src/runtime/routes/__tests__/consolidation-routes.test.ts +265 -2
- package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +31 -1
- package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +6 -2
- 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/__tests__/tts-routes.test.ts +6 -2
- package/src/runtime/routes/acp-routes.test.ts +89 -25
- package/src/runtime/routes/acp-routes.ts +81 -29
- package/src/runtime/routes/app-management-routes.ts +6 -117
- package/src/runtime/routes/app-routes.ts +13 -15
- package/src/runtime/routes/approval-routes.ts +1 -1
- package/src/runtime/routes/attachment-routes.ts +26 -15
- package/src/runtime/routes/avatar-routes.ts +26 -0
- package/src/runtime/routes/browser-routes.ts +1 -1
- package/src/runtime/routes/browser-tabs-routes.ts +6 -10
- package/src/runtime/routes/btw-routes.ts +29 -23
- package/src/runtime/routes/consolidation-routes.ts +120 -20
- 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 +3 -1
- package/src/runtime/routes/conversation-routes.ts +372 -185
- package/src/runtime/routes/conversation-starter-routes.ts +13 -7
- package/src/runtime/routes/conversations-import-routes.ts +24 -7
- package/src/runtime/routes/documents-routes.ts +4 -0
- package/src/runtime/routes/domain-routes.ts +51 -37
- package/src/runtime/routes/epoch-millis-range.ts +34 -0
- package/src/runtime/routes/events-routes.ts +28 -34
- package/src/runtime/routes/gateway-log-routes.ts +26 -4
- package/src/runtime/routes/heartbeat-routes.ts +32 -12
- 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-intro-cache.ts +11 -34
- package/src/runtime/routes/identity-routes.ts +224 -18
- package/src/runtime/routes/image-generation-routes.ts +40 -2
- package/src/runtime/routes/inbound-message-handler.ts +1 -1
- package/src/runtime/routes/index.ts +2 -0
- package/src/runtime/routes/integrations/a2a.ts +12 -10
- package/src/runtime/routes/integrations/slack/__tests__/channel.test.ts +16 -0
- package/src/runtime/routes/integrations/slack/channel.ts +4 -0
- package/src/runtime/routes/integrations/slack/share.ts +27 -6
- package/src/runtime/routes/integrations/telegram.ts +6 -0
- package/src/runtime/routes/integrations/twilio.ts +42 -0
- package/src/runtime/routes/internal-telemetry-routes.ts +88 -0
- package/src/runtime/routes/log-export-routes.ts +8 -0
- package/src/runtime/routes/memory-v2-routes.ts +15 -8
- package/src/runtime/routes/memory-v3-routes.ts +66 -34
- package/src/runtime/routes/oauth-apps.ts +66 -12
- package/src/runtime/routes/oauth-providers.ts +44 -5
- package/src/runtime/routes/platform-routes.ts +81 -5
- package/src/runtime/routes/playground/__tests__/force-compact.test.ts +6 -4
- package/src/runtime/routes/playground/force-compact.ts +1 -1
- package/src/runtime/routes/playground/helpers.ts +1 -1
- package/src/runtime/routes/rename-conversation-routes.ts +5 -0
- package/src/runtime/routes/schedule-routes.ts +152 -42
- package/src/runtime/routes/secret-routes.ts +14 -2
- package/src/runtime/routes/skills-routes.ts +43 -14
- package/src/runtime/routes/surface-conversation-resolver.ts +4 -3
- package/src/runtime/routes/tool-call-confirmation-enrichment.test.ts +161 -0
- package/src/runtime/routes/tool-call-confirmation-enrichment.ts +107 -0
- package/src/runtime/routes/trust-rules-routes.ts +26 -2
- package/src/runtime/routes/tts-routes.ts +35 -0
- package/src/runtime/routes/types.ts +66 -8
- package/src/runtime/routes/usage-routes.ts +47 -39
- package/src/runtime/routes/webhook-routes.ts +41 -2
- package/src/runtime/routes/work-items-routes.ts +2 -4
- package/src/runtime/routes/workspace-routes.ts +4 -0
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +6 -0
- package/src/runtime/services/analyze-conversation.ts +2 -2
- package/src/runtime/services/conversation-serializer.ts +1 -1
- package/src/schedule/schedule-store.ts +20 -1
- package/src/schedule/schedule-usage-store.ts +83 -0
- package/src/schedule/scheduler.ts +12 -5
- package/src/signals/cancel.ts +2 -4
- package/src/skills/catalog-files.ts +2 -2
- package/src/skills/catalog-install.ts +3 -0
- package/src/skills/categories-cache.ts +118 -0
- package/src/skills/clawhub-files.ts +1 -2
- package/src/skills/skillssh-files.ts +1 -2
- package/src/subagent/manager.ts +17 -5
- package/src/telemetry/types.ts +29 -1
- package/src/telemetry/usage-telemetry-reporter.test.ts +112 -3
- package/src/telemetry/usage-telemetry-reporter.ts +57 -2
- package/src/tools/acp/context.ts +20 -0
- package/src/tools/acp/list-agents.test.ts +7 -1
- package/src/tools/acp/spawn.test.ts +158 -55
- package/src/tools/acp/spawn.ts +47 -72
- package/src/tools/acp/steer.test.ts +105 -8
- package/src/tools/acp/steer.ts +48 -17
- package/src/tools/apps/executors.ts +13 -8
- package/src/tools/executor.ts +1 -53
- package/src/tools/filesystem/write.ts +34 -0
- package/src/tools/network/__tests__/web-search-metadata.test.ts +7 -1
- package/src/tools/network/__tests__/web-search.test.ts +11 -3
- package/src/tools/network/web-search-error.test.ts +248 -0
- package/src/tools/network/web-search-error.ts +267 -0
- package/src/tools/network/web-search.ts +207 -48
- package/src/tools/schedule/create.ts +2 -0
- package/src/tools/subagent/spawn.ts +2 -4
- package/src/tools/terminal/safe-env.ts +10 -1
- package/src/tools/ui-surface/definitions.ts +34 -5
- package/src/tts/__tests__/provider-catalog-consistency.test.ts +85 -1
- package/src/tts/provider-catalog.ts +76 -1
- package/src/util/mutex.ts +47 -0
- package/src/workspace/git-service.ts +1 -42
- package/src/workspace/migrations/051-seed-conversation-summarization-callsite.ts +4 -5
- package/src/workspace/migrations/095-bump-heartbeat-interval-30m-to-60m.ts +51 -0
- package/src/workspace/migrations/096-reduce-quality-profile-effort.ts +72 -0
- package/src/workspace/migrations/097-enable-adaptive-thinking-managed-profiles.ts +117 -0
- package/src/workspace/migrations/registry.ts +6 -0
- package/docs/plugins.md +0 -836
- package/examples/plugins/echo/register.ts +0 -184
- package/src/__tests__/bootstrap-turn-cleanup.test.ts +0 -44
- 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__/empty-response-pipeline.test.ts +0 -423
- package/src/__tests__/llm-call-pipeline.test.ts +0 -287
- package/src/__tests__/memory-retrieval-pipeline.test.ts +0 -418
- package/src/__tests__/persistence-pipeline.test.ts +0 -503
- package/src/__tests__/pipeline-runner.test.ts +0 -564
- package/src/__tests__/title-generate-pipeline.test.ts +0 -211
- package/src/__tests__/token-estimate-pipeline.test.ts +0 -479
- package/src/__tests__/tool-error-pipeline.test.ts +0 -241
- package/src/__tests__/tool-execute-pipeline.test.ts +0 -417
- package/src/__tests__/tool-result-truncate-pipeline.test.ts +0 -341
- package/src/daemon/bootstrap-turn-cleanup.ts +0 -45
- package/src/gallery/default-gallery.ts +0 -1359
- package/src/gallery/gallery-manifest.ts +0 -28
- package/src/home/feature-gate.ts +0 -22
- package/src/memory/v3/provider-blocks.ts +0 -16
- 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/terminal.ts +0 -73
- package/src/plugins/defaults/empty-response/middlewares/emptyResponse.ts +0 -22
- package/src/plugins/defaults/empty-response/terminal.ts +0 -106
- package/src/plugins/defaults/injectors/package.json +0 -15
- package/src/plugins/defaults/llm-call/middlewares/llmCall.ts +0 -17
- package/src/plugins/defaults/llm-call/register.ts +0 -45
- package/src/plugins/defaults/memory-retrieval/middlewares/memoryRetrieval.ts +0 -17
- package/src/plugins/defaults/memory-retrieval/package.json +0 -15
- package/src/plugins/defaults/memory-retrieval/register.ts +0 -181
- 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/persistence/middlewares/persistence.ts +0 -19
- package/src/plugins/defaults/persistence/package.json +0 -15
- package/src/plugins/defaults/persistence/register.ts +0 -38
- package/src/plugins/defaults/persistence/terminal.ts +0 -83
- package/src/plugins/defaults/title-generate/terminal.ts +0 -31
- package/src/plugins/defaults/token-estimate/middlewares/tokenEstimate.ts +0 -23
- package/src/plugins/defaults/token-estimate/package.json +0 -15
- package/src/plugins/defaults/token-estimate/register.ts +0 -34
- package/src/plugins/defaults/token-estimate/terminal.ts +0 -40
- package/src/plugins/defaults/tool-error/middlewares/toolError.ts +0 -21
- package/src/plugins/defaults/tool-error/terminal.ts +0 -47
- package/src/plugins/defaults/tool-execute/middlewares/toolExecute.ts +0 -23
- package/src/plugins/defaults/tool-execute/package.json +0 -15
- package/src/plugins/defaults/tool-execute/register.ts +0 -49
- package/src/plugins/defaults/tool-result-truncate/middlewares/toolResultTruncate.ts +0 -23
- package/src/plugins/defaults/tool-result-truncate/types.ts +0 -22
- package/src/skills/category-inference.ts +0 -111
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/capabilities.test.ts +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/core.test.ts +0 -0
- /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__/needle.test.ts +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/snapshot.test.ts +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/tree.test.ts +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/types.test.ts +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}/core.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}/needle.ts +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/snapshot.ts +0 -0
- /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/working-set.ts +0 -0
|
@@ -1,210 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for the `compaction` plugin pipeline (PR 25).
|
|
3
|
-
*
|
|
4
|
-
* Covers:
|
|
5
|
-
* - Default plugin delegates to the manager's `maybeCompact` and returns the
|
|
6
|
-
* same `ContextWindowResult` object the manager produced.
|
|
7
|
-
* - A custom plugin layered on top can short-circuit before the terminal is
|
|
8
|
-
* reached and return a different summary, demonstrating that the pipeline
|
|
9
|
-
* slot is observable and replaceable without patching the manager.
|
|
10
|
-
*
|
|
11
|
-
* The tests drive `runPipeline` directly rather than going through the full
|
|
12
|
-
* orchestrator — the integration path (conversation-agent-loop) is exercised
|
|
13
|
-
* by `conversation-agent-loop-overflow.test.ts`, which must continue to pass
|
|
14
|
-
* as the acceptance criterion for this PR.
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
import { describe, expect, test } from "bun:test";
|
|
18
|
-
|
|
19
|
-
import type { TrustContext } from "../daemon/trust-context.js";
|
|
20
|
-
import {
|
|
21
|
-
DEFAULT_COMPACTION_PLUGIN_NAME,
|
|
22
|
-
defaultCompactionTerminal,
|
|
23
|
-
} from "../plugins/defaults/compaction/terminal.js";
|
|
24
|
-
import { runPipeline } from "../plugins/pipeline.js";
|
|
25
|
-
import {
|
|
26
|
-
type CompactionArgs,
|
|
27
|
-
type CompactionResult,
|
|
28
|
-
type Middleware,
|
|
29
|
-
PluginExecutionError,
|
|
30
|
-
type TurnContext,
|
|
31
|
-
} from "../plugins/types.js";
|
|
32
|
-
|
|
33
|
-
type ContextWindowResultShape = {
|
|
34
|
-
compacted: boolean;
|
|
35
|
-
summaryText: string;
|
|
36
|
-
messages: unknown[];
|
|
37
|
-
previousEstimatedInputTokens: number;
|
|
38
|
-
estimatedInputTokens: number;
|
|
39
|
-
maxInputTokens: number;
|
|
40
|
-
thresholdTokens: number;
|
|
41
|
-
compactedMessages: number;
|
|
42
|
-
compactedPersistedMessages: number;
|
|
43
|
-
summaryCalls: number;
|
|
44
|
-
summaryInputTokens: number;
|
|
45
|
-
summaryOutputTokens: number;
|
|
46
|
-
summaryModel: string;
|
|
47
|
-
reason?: string;
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
const trust: TrustContext = {
|
|
51
|
-
sourceChannel: "vellum",
|
|
52
|
-
trustClass: "guardian",
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
function makeTurnCtx(manager: {
|
|
56
|
-
maybeCompact: (...args: unknown[]) => Promise<unknown>;
|
|
57
|
-
}): TurnContext {
|
|
58
|
-
return {
|
|
59
|
-
requestId: "req-compaction-test",
|
|
60
|
-
conversationId: "conv-compaction-test",
|
|
61
|
-
turnIndex: 0,
|
|
62
|
-
trust,
|
|
63
|
-
// `TurnContext.contextWindowManager` is a typed optional field; the
|
|
64
|
-
// default compaction plugin reads it directly without a cast.
|
|
65
|
-
contextWindowManager:
|
|
66
|
-
manager as unknown as TurnContext["contextWindowManager"],
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function makeResult(
|
|
71
|
-
overrides: Partial<ContextWindowResultShape> = {},
|
|
72
|
-
): ContextWindowResultShape {
|
|
73
|
-
return {
|
|
74
|
-
compacted: true,
|
|
75
|
-
summaryText: "default-summary",
|
|
76
|
-
messages: [],
|
|
77
|
-
previousEstimatedInputTokens: 1000,
|
|
78
|
-
estimatedInputTokens: 100,
|
|
79
|
-
maxInputTokens: 100000,
|
|
80
|
-
thresholdTokens: 80000,
|
|
81
|
-
compactedMessages: 3,
|
|
82
|
-
compactedPersistedMessages: 3,
|
|
83
|
-
summaryCalls: 1,
|
|
84
|
-
summaryInputTokens: 500,
|
|
85
|
-
summaryOutputTokens: 120,
|
|
86
|
-
summaryModel: "default-model",
|
|
87
|
-
...overrides,
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
describe("compaction pipeline", () => {
|
|
92
|
-
test("default plugin delegates to the manager and returns its result unchanged", async () => {
|
|
93
|
-
const observed: {
|
|
94
|
-
messages: unknown;
|
|
95
|
-
signal: unknown;
|
|
96
|
-
options: unknown;
|
|
97
|
-
}[] = [];
|
|
98
|
-
const expected = makeResult({
|
|
99
|
-
summaryText: "manager-summary",
|
|
100
|
-
compactedMessages: 7,
|
|
101
|
-
});
|
|
102
|
-
const manager = {
|
|
103
|
-
maybeCompact: async (
|
|
104
|
-
messages: unknown,
|
|
105
|
-
signal: unknown,
|
|
106
|
-
options: unknown,
|
|
107
|
-
) => {
|
|
108
|
-
observed.push({ messages, signal, options });
|
|
109
|
-
return expected;
|
|
110
|
-
},
|
|
111
|
-
};
|
|
112
|
-
const turnCtx = makeTurnCtx(manager);
|
|
113
|
-
const args: CompactionArgs = {
|
|
114
|
-
messages: [{ role: "user", content: "hi" }],
|
|
115
|
-
signal: new AbortController().signal,
|
|
116
|
-
options: { lastCompactedAt: 42, precomputedEstimate: 1234 },
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
// No middleware registered — the runner invokes the terminal directly.
|
|
120
|
-
const result = (await runPipeline<CompactionArgs, CompactionResult>(
|
|
121
|
-
"compaction",
|
|
122
|
-
[],
|
|
123
|
-
(innerArgs) => defaultCompactionTerminal(innerArgs, turnCtx),
|
|
124
|
-
args,
|
|
125
|
-
turnCtx,
|
|
126
|
-
30000,
|
|
127
|
-
)) as ContextWindowResultShape;
|
|
128
|
-
|
|
129
|
-
// Terminal forwarded args verbatim to the manager — except for
|
|
130
|
-
// `signal`, which the pipeline runner replaces with a signal linked
|
|
131
|
-
// to its internal timeout controller. The linked signal must forward
|
|
132
|
-
// caller-originated aborts, which is verified in the dedicated
|
|
133
|
-
// pipeline-runner abort-propagation tests.
|
|
134
|
-
expect(observed).toHaveLength(1);
|
|
135
|
-
expect(observed[0]!.messages).toBe(args.messages);
|
|
136
|
-
expect(observed[0]!.signal).toBeInstanceOf(AbortSignal);
|
|
137
|
-
expect(observed[0]!.options).toBe(args.options);
|
|
138
|
-
|
|
139
|
-
// Returned result is the manager's object, unmodified — no wrapping
|
|
140
|
-
// or shape transformation is allowed in the default path.
|
|
141
|
-
expect(result).toBe(expected);
|
|
142
|
-
expect(result.summaryText).toBe("manager-summary");
|
|
143
|
-
expect(result.compactedMessages).toBe(7);
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
test("custom plugin short-circuits to a different summary without touching the manager", async () => {
|
|
147
|
-
let managerCallCount = 0;
|
|
148
|
-
const manager = {
|
|
149
|
-
maybeCompact: async () => {
|
|
150
|
-
managerCallCount++;
|
|
151
|
-
return makeResult({ summaryText: "should-not-run" });
|
|
152
|
-
},
|
|
153
|
-
};
|
|
154
|
-
const turnCtx = makeTurnCtx(manager);
|
|
155
|
-
|
|
156
|
-
const custom: Middleware<CompactionArgs, CompactionResult> =
|
|
157
|
-
async function customCompaction(_args, _next, _ctx) {
|
|
158
|
-
// Short-circuit — omit the `next` call so the terminal never fires.
|
|
159
|
-
return makeResult({
|
|
160
|
-
summaryText: "custom-plugin-summary",
|
|
161
|
-
compactedMessages: 0,
|
|
162
|
-
summaryCalls: 0,
|
|
163
|
-
reason: "short-circuited by custom plugin",
|
|
164
|
-
});
|
|
165
|
-
};
|
|
166
|
-
|
|
167
|
-
const args: CompactionArgs = {
|
|
168
|
-
messages: [],
|
|
169
|
-
signal: undefined,
|
|
170
|
-
options: undefined,
|
|
171
|
-
};
|
|
172
|
-
|
|
173
|
-
const result = (await runPipeline<CompactionArgs, CompactionResult>(
|
|
174
|
-
"compaction",
|
|
175
|
-
[custom],
|
|
176
|
-
(innerArgs) => defaultCompactionTerminal(innerArgs, turnCtx),
|
|
177
|
-
args,
|
|
178
|
-
turnCtx,
|
|
179
|
-
30000,
|
|
180
|
-
)) as ContextWindowResultShape;
|
|
181
|
-
|
|
182
|
-
expect(managerCallCount).toBe(0);
|
|
183
|
-
expect(result.summaryText).toBe("custom-plugin-summary");
|
|
184
|
-
expect(result.reason).toBe("short-circuited by custom plugin");
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
test("default terminal surfaces a PluginExecutionError when the manager is missing", async () => {
|
|
188
|
-
// Build a turn context without the extension field so the default
|
|
189
|
-
// terminal's lenient read fails — this guards against a future refactor
|
|
190
|
-
// that removes the handle-attach helper in the orchestrator.
|
|
191
|
-
const turnCtxWithoutManager: TurnContext = {
|
|
192
|
-
requestId: "req-missing",
|
|
193
|
-
conversationId: "conv-missing",
|
|
194
|
-
turnIndex: 0,
|
|
195
|
-
trust,
|
|
196
|
-
};
|
|
197
|
-
const args: CompactionArgs = {
|
|
198
|
-
messages: [],
|
|
199
|
-
signal: undefined,
|
|
200
|
-
options: undefined,
|
|
201
|
-
};
|
|
202
|
-
|
|
203
|
-
await expect(
|
|
204
|
-
defaultCompactionTerminal(args, turnCtxWithoutManager),
|
|
205
|
-
).rejects.toThrow(PluginExecutionError);
|
|
206
|
-
await expect(
|
|
207
|
-
defaultCompactionTerminal(args, turnCtxWithoutManager),
|
|
208
|
-
).rejects.toThrow(DEFAULT_COMPACTION_PLUGIN_NAME);
|
|
209
|
-
});
|
|
210
|
-
});
|
|
@@ -1,251 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for the compaction call-site recovery path added in JARVIS-587.
|
|
3
|
-
*
|
|
4
|
-
* When the `compaction` pipeline exceeds its 30s budget (manifest-wide
|
|
5
|
-
* `DEFAULT_TIMEOUTS.compaction`), the pipeline runner throws
|
|
6
|
-
* `PluginTimeoutError`. The three compaction call sites in
|
|
7
|
-
* `conversation-agent-loop.ts` (start-of-turn, mid-loop, emergency) catch
|
|
8
|
-
* that error, record the failure on the loop-held `CompactionCircuit`
|
|
9
|
-
* (`recordOutcome(turn, true, ...)`) so the circuit breaker counts it, and degrade
|
|
10
|
-
* gracefully.
|
|
11
|
-
*
|
|
12
|
-
* This file asserts the tight coupling between:
|
|
13
|
-
* (1) a `PluginTimeoutError`-driven failure and
|
|
14
|
-
* (2) the compaction circuit breaker's 3-strike threshold.
|
|
15
|
-
*
|
|
16
|
-
* The existing `circuit-breaker-pipeline.test.ts` already exercises the
|
|
17
|
-
* breaker's transitions end-to-end. These tests verify that our new
|
|
18
|
-
* catch-blocks feed the breaker the same `"failure"` outcome a normal
|
|
19
|
-
* summary-LLM throw would, and that repeated timeouts therefore trip the
|
|
20
|
-
* same 3-strike trip.
|
|
21
|
-
*/
|
|
22
|
-
|
|
23
|
-
import { afterEach, beforeEach, describe, expect, test } from "bun:test";
|
|
24
|
-
|
|
25
|
-
import {
|
|
26
|
-
type CircuitTurnInfo,
|
|
27
|
-
CompactionCircuit,
|
|
28
|
-
} from "../agent/compaction-circuit.js";
|
|
29
|
-
import type { ServerMessage } from "../daemon/message-protocol.js";
|
|
30
|
-
import type { TrustContext } from "../daemon/trust-context.js";
|
|
31
|
-
import { COMPACTION_CIRCUIT_FAILURE_THRESHOLD } from "../plugins/defaults/circuit-breaker/middlewares/circuitBreaker.js";
|
|
32
|
-
import { defaultCircuitBreakerPlugin } from "../plugins/defaults/circuit-breaker/register.js";
|
|
33
|
-
import { DEFAULT_TIMEOUTS, runPipeline } from "../plugins/pipeline.js";
|
|
34
|
-
import {
|
|
35
|
-
getMiddlewaresFor,
|
|
36
|
-
registerPlugin,
|
|
37
|
-
resetPluginRegistryForTests,
|
|
38
|
-
} from "../plugins/registry.js";
|
|
39
|
-
import {
|
|
40
|
-
type CompactionArgs,
|
|
41
|
-
type CompactionResult,
|
|
42
|
-
type Middleware,
|
|
43
|
-
PluginTimeoutError,
|
|
44
|
-
type TurnContext,
|
|
45
|
-
} from "../plugins/types.js";
|
|
46
|
-
|
|
47
|
-
// ─── Fixtures ───────────────────────────────────────────────────────────────
|
|
48
|
-
|
|
49
|
-
function makeCircuit(conversationId = "conv-timeout-test"): CompactionCircuit {
|
|
50
|
-
return new CompactionCircuit(conversationId);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const turn: CircuitTurnInfo = {
|
|
54
|
-
turnCount: 0,
|
|
55
|
-
trustContext: { sourceChannel: "vellum", trustClass: "guardian" },
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
const trust: TrustContext = {
|
|
59
|
-
sourceChannel: "vellum",
|
|
60
|
-
trustClass: "guardian",
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
function makeTurnCtx(conversationId: string): TurnContext {
|
|
64
|
-
return {
|
|
65
|
-
requestId: "req-timeout-test",
|
|
66
|
-
conversationId,
|
|
67
|
-
turnIndex: 0,
|
|
68
|
-
trust,
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
function collectEvents(): {
|
|
73
|
-
events: ServerMessage[];
|
|
74
|
-
onEvent: (msg: ServerMessage) => void;
|
|
75
|
-
} {
|
|
76
|
-
const events: ServerMessage[] = [];
|
|
77
|
-
return { events, onEvent: (msg) => events.push(msg) };
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// ─── Tests ──────────────────────────────────────────────────────────────────
|
|
81
|
-
|
|
82
|
-
describe("compaction timeout recovery (JARVIS-587)", () => {
|
|
83
|
-
beforeEach(() => {
|
|
84
|
-
resetPluginRegistryForTests();
|
|
85
|
-
registerPlugin(defaultCircuitBreakerPlugin);
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
afterEach(() => {
|
|
89
|
-
resetPluginRegistryForTests();
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
test("runPipeline('compaction', ...) throws PluginTimeoutError on budget breach", async () => {
|
|
93
|
-
// Baseline: the compaction pipeline still surfaces PluginTimeoutError when
|
|
94
|
-
// its timer fires. This guards the outer race from silently swallowing
|
|
95
|
-
// the timeout when the inner call is aborted by our Part A wiring.
|
|
96
|
-
const hang: Middleware<CompactionArgs, CompactionResult> = async (
|
|
97
|
-
_args,
|
|
98
|
-
_next,
|
|
99
|
-
) =>
|
|
100
|
-
new Promise<CompactionResult>(() => {
|
|
101
|
-
// intentionally never resolves
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
let caught: unknown;
|
|
105
|
-
try {
|
|
106
|
-
await runPipeline<CompactionArgs, CompactionResult>(
|
|
107
|
-
"compaction",
|
|
108
|
-
[hang],
|
|
109
|
-
async () => ({ compacted: false }) as unknown as CompactionResult,
|
|
110
|
-
{ messages: [] as unknown, signal: undefined, options: undefined },
|
|
111
|
-
makeTurnCtx("conv-budget-breach"),
|
|
112
|
-
// Override the manifest timeout to keep the test fast.
|
|
113
|
-
20,
|
|
114
|
-
);
|
|
115
|
-
} catch (err) {
|
|
116
|
-
caught = err;
|
|
117
|
-
}
|
|
118
|
-
expect(caught).toBeInstanceOf(PluginTimeoutError);
|
|
119
|
-
expect((caught as PluginTimeoutError).pipeline).toBe("compaction");
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
test("recordOutcome(failed=true) driven by PluginTimeoutError trips the breaker at the 3rd strike", async () => {
|
|
123
|
-
// Simulates the production sequence: each mid-loop compaction hits the
|
|
124
|
-
// pipeline's 30s ceiling, the catch path calls
|
|
125
|
-
// `circuit.recordOutcome(turn, true, onEvent)`. After three such catches
|
|
126
|
-
// the circuit breaker must be open — matching the same invariant the
|
|
127
|
-
// existing breaker test file exercises for normal summary-LLM throws.
|
|
128
|
-
const circuit = makeCircuit();
|
|
129
|
-
const { onEvent, events } = collectEvents();
|
|
130
|
-
|
|
131
|
-
// First two timeouts — circuit still closed.
|
|
132
|
-
await circuit.recordOutcome(turn, true, onEvent);
|
|
133
|
-
await circuit.recordOutcome(turn, true, onEvent);
|
|
134
|
-
expect(circuit.consecutiveCompactionFailures).toBe(2);
|
|
135
|
-
expect(circuit.compactionCircuitOpenUntil).toBeNull();
|
|
136
|
-
expect(events).toHaveLength(0);
|
|
137
|
-
|
|
138
|
-
// Third timeout — breaker trips and emits the canonical transition event.
|
|
139
|
-
await circuit.recordOutcome(turn, true, onEvent);
|
|
140
|
-
expect(circuit.consecutiveCompactionFailures).toBe(
|
|
141
|
-
COMPACTION_CIRCUIT_FAILURE_THRESHOLD,
|
|
142
|
-
);
|
|
143
|
-
expect(circuit.compactionCircuitOpenUntil).not.toBeNull();
|
|
144
|
-
expect(events).toHaveLength(1);
|
|
145
|
-
expect(events[0]).toEqual({
|
|
146
|
-
type: "compaction_circuit_open",
|
|
147
|
-
conversationId: circuit.conversationId,
|
|
148
|
-
reason: "3_consecutive_failures",
|
|
149
|
-
openUntil: circuit.compactionCircuitOpenUntil as number,
|
|
150
|
-
});
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
test("a successful compaction after two timeouts resets the counter", async () => {
|
|
154
|
-
// The recovery path doesn't interfere with the breaker's normal reset —
|
|
155
|
-
// once a compaction call eventually succeeds, the streak is broken and
|
|
156
|
-
// the next failure starts counting from 1.
|
|
157
|
-
const circuit = makeCircuit();
|
|
158
|
-
const { onEvent } = collectEvents();
|
|
159
|
-
|
|
160
|
-
await circuit.recordOutcome(turn, true, onEvent);
|
|
161
|
-
await circuit.recordOutcome(turn, true, onEvent);
|
|
162
|
-
expect(circuit.consecutiveCompactionFailures).toBe(2);
|
|
163
|
-
|
|
164
|
-
await circuit.recordOutcome(turn, false, onEvent);
|
|
165
|
-
expect(circuit.consecutiveCompactionFailures).toBe(0);
|
|
166
|
-
expect(circuit.compactionCircuitOpenUntil).toBeNull();
|
|
167
|
-
|
|
168
|
-
await circuit.recordOutcome(turn, true, onEvent);
|
|
169
|
-
expect(circuit.consecutiveCompactionFailures).toBe(1);
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
test("compaction call-site recovery remains defense-in-depth even when DEFAULT_TIMEOUTS.compaction is null", () => {
|
|
173
|
-
// At the time this PR landed, `DEFAULT_TIMEOUTS.compaction` was null
|
|
174
|
-
// (pipeline timeouts globally disabled — see #27608). That makes the
|
|
175
|
-
// call-site catch blocks unreachable in production right now, but the
|
|
176
|
-
// catch blocks still matter: any future reintroduction of a per-pipeline
|
|
177
|
-
// compaction timeout immediately benefits from circuit-breaker recording
|
|
178
|
-
// and graceful-degradation without needing to re-touch every call site.
|
|
179
|
-
//
|
|
180
|
-
// This test just documents the current value so a future change that
|
|
181
|
-
// reintroduces a timeout must also decide (intentionally) whether the
|
|
182
|
-
// recovery path should continue to fire.
|
|
183
|
-
const value = DEFAULT_TIMEOUTS.compaction;
|
|
184
|
-
expect(value === null || typeof value === "number").toBe(true);
|
|
185
|
-
});
|
|
186
|
-
});
|
|
187
|
-
|
|
188
|
-
describe("abort propagation end-to-end (Part A + updateSummary fallback)", () => {
|
|
189
|
-
beforeEach(() => {
|
|
190
|
-
resetPluginRegistryForTests();
|
|
191
|
-
registerPlugin(defaultCircuitBreakerPlugin);
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
afterEach(() => {
|
|
195
|
-
resetPluginRegistryForTests();
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
test("caller-provided signal is replaced with a linked signal that fires on timeout", async () => {
|
|
199
|
-
// Minimal proof that Part A actually wires the signal through the
|
|
200
|
-
// compaction pipeline: when the pipeline runner's timer fires, the
|
|
201
|
-
// signal seen by the inner terminal is aborted — allowing
|
|
202
|
-
// `updateSummary`'s try/catch around `provider.sendMessage` to trigger
|
|
203
|
-
// the local-fallback path instead of the call hanging indefinitely.
|
|
204
|
-
let observedSignal: AbortSignal | undefined;
|
|
205
|
-
const waitForAbort: Middleware<CompactionArgs, CompactionResult> = async (
|
|
206
|
-
args,
|
|
207
|
-
_next,
|
|
208
|
-
) => {
|
|
209
|
-
observedSignal = args.signal;
|
|
210
|
-
return new Promise<CompactionResult>((_resolve, reject) => {
|
|
211
|
-
args.signal?.addEventListener("abort", () => {
|
|
212
|
-
reject(
|
|
213
|
-
Object.assign(new Error("aborted by signal"), {
|
|
214
|
-
name: "AbortError",
|
|
215
|
-
}),
|
|
216
|
-
);
|
|
217
|
-
});
|
|
218
|
-
});
|
|
219
|
-
};
|
|
220
|
-
|
|
221
|
-
const callerController = new AbortController();
|
|
222
|
-
|
|
223
|
-
let caught: unknown;
|
|
224
|
-
try {
|
|
225
|
-
await runPipeline<CompactionArgs, CompactionResult>(
|
|
226
|
-
"compaction",
|
|
227
|
-
[waitForAbort, ...getMiddlewaresFor("compaction")],
|
|
228
|
-
async () => ({ compacted: false }) as unknown as CompactionResult,
|
|
229
|
-
{
|
|
230
|
-
messages: [] as unknown,
|
|
231
|
-
signal: callerController.signal,
|
|
232
|
-
options: undefined,
|
|
233
|
-
},
|
|
234
|
-
makeTurnCtx("conv-abort-test"),
|
|
235
|
-
20,
|
|
236
|
-
);
|
|
237
|
-
} catch (err) {
|
|
238
|
-
caught = err;
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
expect(caught).toBeInstanceOf(PluginTimeoutError);
|
|
242
|
-
expect(observedSignal).toBeDefined();
|
|
243
|
-
// The runner swaps the caller's signal for a linked signal — the two are
|
|
244
|
-
// distinct objects but both should end up aborted once the timer fires.
|
|
245
|
-
expect(observedSignal).not.toBe(callerController.signal);
|
|
246
|
-
expect(observedSignal!.aborted).toBe(true);
|
|
247
|
-
// Caller's own signal is untouched — pipeline timeout does not cascade
|
|
248
|
-
// outward onto the caller's controller.
|
|
249
|
-
expect(callerController.signal.aborted).toBe(false);
|
|
250
|
-
});
|
|
251
|
-
});
|