@vellumai/assistant 0.8.4 → 0.8.5
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 +2 -2
- package/docs/browser-use-architecture-phase2.md +1 -1
- package/knip.json +2 -1
- package/openapi.yaml +809 -11
- package/package.json +1 -1
- package/src/__tests__/anthropic-provider.test.ts +34 -37
- package/src/__tests__/assistant-event-hub-self-exclusion.test.ts +293 -0
- package/src/__tests__/assistant-feature-flags-integration.test.ts +3 -3
- package/src/__tests__/audit-log-rotation.test.ts +70 -16
- package/src/__tests__/background-workers-disk-pressure.test.ts +3 -3
- package/src/__tests__/btw-routes.test.ts +2 -3
- package/src/__tests__/call-controller.test.ts +0 -1
- package/src/__tests__/cancel-resolves-conversation-key.test.ts +1 -1
- package/src/__tests__/channel-guardian.test.ts +3 -3
- package/src/__tests__/checker.test.ts +6 -15
- package/src/__tests__/compaction-events.test.ts +1 -0
- package/src/__tests__/compactor-call-site-logging.test.ts +214 -0
- package/src/__tests__/computer-use-skill-manifest-regression.test.ts +5 -11
- package/src/__tests__/computer-use-tools.test.ts +2 -4
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +0 -1
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +1 -1
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -1
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +197 -2
- package/src/__tests__/conversation-agent-loop.test.ts +163 -122
- package/src/__tests__/conversation-app-control-instantiation.test.ts +2 -5
- package/src/__tests__/conversation-clear-safety.test.ts +25 -25
- package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +1 -1
- package/src/__tests__/conversation-disk-view-integration.test.ts +2 -2
- package/src/__tests__/conversation-error.test.ts +31 -0
- package/src/__tests__/conversation-fork-crud.test.ts +178 -15
- package/src/__tests__/conversation-lifecycle.test.ts +52 -11
- package/src/__tests__/{conversation-load-cleaned-at.test.ts → conversation-load-history-stripped.test.ts} +13 -13
- package/src/__tests__/conversation-provider-retry-repair.test.ts +1 -0
- package/src/__tests__/conversation-routes-disk-view.test.ts +109 -0
- package/src/__tests__/conversation-routes-slash-commands.test.ts +35 -0
- package/src/__tests__/conversation-skill-tools.test.ts +2 -5
- package/src/__tests__/conversation-store.test.ts +1 -1
- package/src/__tests__/conversation-sync-tags.test.ts +99 -32
- package/src/__tests__/conversation-workspace-cache-state.test.ts +1 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +1 -1
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +1 -1
- package/src/__tests__/credential-execution-feature-gates.test.ts +9 -7
- package/src/__tests__/credential-execution-tools.test.ts +6 -6
- package/src/__tests__/credential-security-invariants.test.ts +1 -0
- package/src/__tests__/credential-vault-unit.test.ts +2 -2
- package/src/__tests__/dynamic-page-surface.test.ts +2 -2
- package/src/__tests__/email-html-renderer.test.ts +12 -0
- package/src/__tests__/gateway-flag-listener.test.ts +237 -0
- package/src/__tests__/gemini-provider.test.ts +78 -0
- package/src/__tests__/guardian-dispatch.test.ts +0 -1
- package/src/__tests__/guardian-outbound-http.test.ts +7 -5
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +1 -1
- package/src/__tests__/heartbeat-disk-pressure.test.ts +4 -0
- package/src/__tests__/heartbeat-service.test.ts +4 -0
- package/src/__tests__/host-shell-tool.test.ts +1 -1
- package/src/__tests__/init-feature-flag-overrides.test.ts +5 -6
- package/src/__tests__/list-messages-tool-merge.test.ts +70 -11
- package/src/__tests__/llm-request-log-call-site.test.ts +136 -0
- package/src/__tests__/llm-request-log-source-clickhouse.test.ts +26 -0
- package/src/__tests__/llm-resolver.test.ts +77 -9
- package/src/__tests__/llm-usage-store.test.ts +66 -0
- package/src/__tests__/logger.test.ts +89 -0
- package/src/__tests__/mcp-abort-signal.test.ts +2 -2
- package/src/__tests__/media-generate-image.test.ts +31 -0
- package/src/__tests__/memory-v2-static-injector.test.ts +7 -7
- package/src/__tests__/model-intents.test.ts +2 -4
- package/src/__tests__/notification-guardian-path.test.ts +0 -1
- package/src/__tests__/onboarding-template-contract.test.ts +1 -1
- package/src/__tests__/openai-provider.test.ts +46 -0
- package/src/__tests__/openai-responses-provider.test.ts +114 -12
- package/src/__tests__/pending-interactions-resolved-event.test.ts +0 -1
- package/src/__tests__/platform-bash-auto-approve.test.ts +2 -2
- package/src/__tests__/platform.test.ts +2 -2
- package/src/__tests__/plugin-api-tool-definition.test.ts +92 -0
- package/src/__tests__/plugin-bootstrap.test.ts +2 -2
- package/src/__tests__/plugin-tool-contribution.test.ts +13 -6
- package/src/__tests__/plugin-types.test.ts +3 -2
- package/src/__tests__/prechat-onboarding-contract.test.ts +131 -98
- package/src/__tests__/pricing.test.ts +12 -0
- package/src/__tests__/prune-jobs-changes-parser.test.ts +61 -0
- package/src/__tests__/registry.test.ts +2 -8
- package/src/__tests__/require-fresh-approval.test.ts +2 -2
- package/src/__tests__/runtime-events-sse-bilingual.test.ts +154 -0
- package/src/__tests__/shell-tool-proxy-mode.test.ts +1 -1
- package/src/__tests__/skill-feature-flags.test.ts +2 -2
- package/src/__tests__/skill-projection-feature-flag.test.ts +4 -7
- package/src/__tests__/skill-projection.benchmark.test.ts +2 -6
- package/src/__tests__/skill-tool-factory.test.ts +1 -1
- package/src/__tests__/subagent-notify-parent.test.ts +1 -1
- package/src/__tests__/suggestion-routes.test.ts +1 -0
- package/src/__tests__/sync-message-contract.test.ts +59 -0
- package/src/__tests__/system-prompt.test.ts +145 -131
- package/src/__tests__/terminal-tools.test.ts +1 -1
- package/src/__tests__/tool-approval-handler.test.ts +1 -5
- package/src/__tests__/tool-execute-pipeline.test.ts +2 -2
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +2 -5
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +15 -5
- package/src/__tests__/tool-executor.test.ts +9 -62
- package/src/__tests__/tool-grant-request-escalation.test.ts +1 -6
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +0 -1
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +1 -6
- package/src/__tests__/trusted-contact-multichannel.test.ts +0 -1
- package/src/__tests__/ui-file-upload-surface.test.ts +2 -2
- package/src/__tests__/usage-routes.test.ts +3 -0
- package/src/__tests__/verification-control-plane-policy.test.ts +2 -2
- package/src/__tests__/workspace-git-service.test.ts +6 -5
- package/src/__tests__/workspace-migration-089-move-memory-tree-out-of-v3.test.ts +86 -0
- package/src/acp/__tests__/prepare-agent-env.test.ts +146 -0
- package/src/acp/prepare-agent-env.ts +78 -0
- package/src/acp/session-manager.ts +1 -1
- package/src/agent/loop.ts +8 -0
- package/src/api/README.md +5 -0
- package/src/api/index.ts +4 -0
- package/src/api/package.json +10 -0
- package/src/background-wake/background-wake-routes.test.ts +233 -0
- package/src/background-wake/runtime-registry.ts +24 -0
- package/src/cli/commands/__tests__/browser.test.ts +23 -5
- package/src/cli/commands/__tests__/domain-register.test.ts +110 -0
- package/src/cli/commands/__tests__/domain-status.test.ts +33 -33
- package/src/cli/commands/__tests__/inference-send.test.ts +108 -5
- package/src/cli/commands/__tests__/memory-v2-compare-render.test.ts +98 -0
- package/src/cli/commands/__tests__/memory-v2.test.ts +1 -0
- package/src/cli/commands/__tests__/memory-v3-render.test.ts +340 -0
- package/src/cli/commands/browser.ts +247 -0
- package/src/cli/commands/domain.ts +91 -41
- package/src/cli/commands/inference.ts +93 -40
- package/src/cli/commands/memory-v2-compare-render.ts +115 -0
- package/src/cli/commands/memory-v2.ts +176 -1
- package/src/cli/commands/memory-v3-render.ts +344 -0
- package/src/cli/commands/memory-v3.ts +316 -0
- package/src/cli/program.ts +2 -0
- package/src/config/assistant-feature-flags.ts +21 -9
- package/src/config/bundled-skills/document-editor/SKILL.md +11 -2
- package/src/config/bundled-skills/document-editor/TOOLS.json +18 -0
- package/src/config/bundled-skills/document-editor/tools/document-open.ts +12 -0
- package/src/config/bundled-skills/image-studio/SKILL.md +4 -0
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +2 -2
- package/src/config/bundled-skills/media-processing/tools/ingest-media.ts +13 -8
- package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +10 -3
- package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +16 -14
- package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +7 -2
- package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +7 -2
- package/src/config/bundled-tool-registry.ts +2 -0
- package/src/config/call-site-defaults.ts +7 -6
- package/src/config/feature-flag-registry.json +16 -0
- package/src/config/schemas/__tests__/memory-v2.test.ts +213 -1
- package/src/config/schemas/call-site-catalog.ts +21 -7
- package/src/config/schemas/llm.ts +12 -1
- package/src/config/schemas/memory-v2.ts +246 -0
- package/src/config/schemas/memory.ts +2 -1
- package/src/context/compactor.ts +52 -0
- package/src/conversations/__tests__/message-consolidation.test.ts +350 -0
- package/src/conversations/message-consolidation.ts +404 -0
- package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +1 -1
- package/src/daemon/__tests__/meet-manifest-loader.test.ts +1 -1
- package/src/daemon/conversation-agent-loop-handlers.ts +2 -13
- package/src/daemon/conversation-agent-loop.ts +126 -76
- package/src/daemon/conversation-error.ts +31 -1
- package/src/daemon/conversation-lifecycle.ts +27 -22
- package/src/daemon/conversation-runtime-assembly.ts +10 -9
- package/src/daemon/conversation-tool-setup.ts +63 -3
- package/src/daemon/conversation-usage.ts +2 -0
- package/src/daemon/conversation.ts +14 -29
- package/src/daemon/disk-pressure-guard.ts +14 -2
- package/src/daemon/handlers/config-model.test.ts +1 -0
- package/src/daemon/handlers/conversations.ts +11 -3
- package/src/daemon/host-browser-proxy.ts +5 -5
- package/src/daemon/host-cu-proxy.ts +4 -4
- package/src/daemon/host-file-proxy.ts +4 -4
- package/src/daemon/host-proxy-base.ts +4 -4
- package/src/daemon/host-transfer-proxy.ts +10 -10
- package/src/daemon/lifecycle.ts +23 -20
- package/src/daemon/meet-manifest-loader.ts +1 -7
- package/src/daemon/message-types/conversations.ts +6 -9
- package/src/daemon/message-types/home.ts +1 -13
- package/src/daemon/message-types/messages.ts +6 -14
- package/src/daemon/message-types/sync.ts +14 -0
- package/src/daemon/shutdown-handlers.ts +24 -5
- package/src/daemon/switch-inference-profile-tool.ts +52 -0
- package/src/daemon/tool-setup-types.ts +13 -0
- package/src/events/relationship-state-updated.ts +25 -0
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +1 -1
- package/src/home/home-greeting.ts +0 -9
- package/src/home/suggested-prompts.ts +0 -9
- package/src/ipc/gateway-flag-listener.ts +123 -0
- package/src/ipc/skill-routes/registries.ts +8 -12
- package/src/memory/__tests__/db-async-query.test.ts +165 -0
- package/src/memory/__tests__/db-maintenance.test.ts +115 -0
- package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +241 -0
- package/src/memory/__tests__/jobs-store-job-classes.test.ts +28 -1
- package/src/memory/__tests__/memory-retrospective-job.test.ts +7 -0
- package/src/memory/auto-analysis-enqueue.ts +5 -1
- package/src/memory/conversation-crud.ts +71 -70
- package/src/memory/conversation-starters-cadence.ts +3 -1
- package/src/memory/conversation-title-service.ts +19 -3
- package/src/memory/db-async-query.ts +214 -0
- package/src/memory/db-init.ts +10 -0
- package/src/memory/db-maintenance.ts +30 -21
- package/src/memory/graph/bootstrap.ts +8 -1
- package/src/memory/graph/capability-seed.ts +7 -3
- package/src/memory/graph/conversation-graph-memory.ts +100 -17
- package/src/memory/graph/extraction.ts +1 -5
- package/src/memory/graph/graph-search.ts +7 -1
- package/src/memory/indexer.ts +28 -18
- package/src/memory/job-handlers/cleanup.ts +76 -18
- package/src/memory/job-handlers/conversation-starters.ts +1 -4
- package/src/memory/jobs/embed-pkb-file.ts +6 -1
- package/src/memory/jobs-store.ts +14 -0
- package/src/memory/jobs-worker.ts +55 -22
- package/src/memory/llm-request-log-source-clickhouse.ts +42 -2
- package/src/memory/llm-request-log-source-local.ts +7 -0
- package/src/memory/llm-request-log-source.ts +9 -2
- package/src/memory/llm-request-log-store.ts +43 -1
- package/src/memory/llm-usage-store.ts +24 -0
- package/src/memory/memory-retrospective-enqueue.ts +8 -1
- package/src/memory/memory-retrospective-job.ts +5 -0
- package/src/memory/memory-v2-activation-log-store.ts +15 -6
- package/src/memory/migrations/260-rename-cleaned-at.ts +44 -0
- package/src/memory/migrations/261-llm-usage-add-raw-usage.ts +36 -0
- package/src/memory/migrations/262-memory-v3-coactivation.ts +57 -0
- package/src/memory/migrations/263-memory-v3-auto-edges.ts +50 -0
- package/src/memory/migrations/264-llm-request-log-call-site.ts +29 -0
- package/src/memory/migrations/index.ts +17 -0
- package/src/memory/migrations/registry.ts +33 -0
- package/src/memory/schema/conversations.ts +1 -1
- package/src/memory/schema/infrastructure.ts +21 -0
- package/src/memory/tool-usage-store.ts +36 -8
- package/src/memory/v2/__tests__/consolidation-job.test.ts +1 -0
- package/src/memory/v2/__tests__/harness-compare.test.ts +186 -0
- package/src/memory/v2/__tests__/harness-metrics.test.ts +74 -0
- package/src/memory/v2/__tests__/harness-oracle.test.ts +257 -0
- package/src/memory/v2/__tests__/harness-replay-input.test.ts +225 -0
- package/src/memory/v2/__tests__/harness-runner.test.ts +109 -0
- package/src/memory/v2/__tests__/injection.test.ts +127 -98
- package/src/memory/v2/__tests__/qdrant.test.ts +36 -0
- package/src/memory/v2/__tests__/router.test.ts +171 -3
- package/src/memory/v2/harness/compare.ts +57 -0
- package/src/memory/v2/harness/metrics.ts +124 -0
- package/src/memory/v2/harness/oracle.ts +145 -0
- package/src/memory/v2/harness/replay-input.ts +224 -0
- package/src/memory/v2/harness/retriever.ts +74 -0
- package/src/memory/v2/harness/router-retriever.ts +43 -0
- package/src/memory/v2/harness/runner.ts +106 -0
- package/src/memory/v2/harness/trace.ts +58 -0
- package/src/memory/v2/injection.ts +21 -15
- package/src/memory/v2/prompts/router.ts +26 -1
- package/src/memory/v2/qdrant.ts +14 -2
- package/src/memory/v2/router.ts +171 -18
- package/src/memory/v3/__tests__/coactivation-store.test.ts +422 -0
- package/src/memory/v3/__tests__/consolidation-job.test.ts +468 -0
- package/src/memory/v3/__tests__/edge-learning-job.test.ts +324 -0
- package/src/memory/v3/__tests__/edges.test.ts +563 -0
- package/src/memory/v3/__tests__/filter.test.ts +512 -0
- package/src/memory/v3/__tests__/gate.test.ts +574 -0
- package/src/memory/v3/__tests__/index-composition.test.ts +233 -0
- package/src/memory/v3/__tests__/loop.test.ts +530 -0
- package/src/memory/v3/__tests__/retriever.test.ts +226 -0
- package/src/memory/v3/__tests__/scouts.test.ts +440 -0
- package/src/memory/v3/__tests__/shadow-middleware.test.ts +312 -0
- package/src/memory/v3/__tests__/system-prompts.test.ts +154 -0
- package/src/memory/v3/__tests__/traversal.test.ts +469 -0
- package/src/memory/v3/__tests__/tree-index.test.ts +280 -0
- package/src/memory/v3/__tests__/tree-store.test.ts +529 -0
- package/src/memory/v3/__tests__/tree-walk.test.ts +707 -0
- package/src/memory/v3/__tests__/validate.test.ts +245 -0
- package/src/memory/v3/auto-edges.ts +223 -0
- package/src/memory/v3/coactivation-store.ts +124 -0
- package/src/memory/v3/consolidation-job.ts +323 -0
- package/src/memory/v3/edge-learning-job.ts +160 -0
- package/src/memory/v3/edges.ts +249 -0
- package/src/memory/v3/filter.ts +281 -0
- package/src/memory/v3/gate.ts +334 -0
- package/src/memory/v3/index-composition.ts +113 -0
- package/src/memory/v3/llm-capture.ts +46 -0
- package/src/memory/v3/loop.ts +382 -0
- package/src/memory/v3/maintenance.ts +144 -0
- package/src/memory/v3/prompt-context.ts +33 -0
- package/src/memory/v3/prompts/consolidation.ts +458 -0
- package/src/memory/v3/prompts/system-prompts.ts +196 -0
- package/src/memory/v3/retriever.ts +33 -0
- package/src/memory/v3/scouts.ts +420 -0
- package/src/memory/v3/shadow-middleware.ts +305 -0
- package/src/memory/v3/traversal.ts +206 -0
- package/src/memory/v3/tree-index.ts +237 -0
- package/src/memory/v3/tree-store.ts +394 -0
- package/src/memory/v3/tree-walk.ts +351 -0
- package/src/memory/v3/types.ts +65 -0
- package/src/memory/v3/validate.ts +300 -0
- package/src/notifications/adapters/macos.ts +18 -1
- package/src/notifications/adapters/platform.ts +1 -1
- package/src/notifications/decision-engine.ts +1 -4
- package/src/notifications/emit-signal.ts +29 -49
- package/src/permissions/prompter.ts +3 -3
- package/src/permissions/question-prompter.ts +5 -2
- package/src/permissions/secret-prompter.ts +2 -2
- package/src/plugin-api/index.ts +4 -0
- package/src/plugin-api/types.ts +7 -33
- package/src/plugins/defaults/index.ts +6 -0
- package/src/plugins/defaults/injectors.ts +18 -11
- package/src/plugins/external-plugin-loader.ts +5 -68
- package/src/plugins/types.ts +11 -16
- package/src/proactive-artifact/aux-message-injector.ts +17 -4
- package/src/prompts/__tests__/task-progress-hint-section.test.ts +3 -9
- package/src/prompts/persona-resolver.ts +36 -21
- package/src/prompts/sections.ts +39 -7
- package/src/prompts/system-prompt.ts +50 -185
- package/src/prompts/templates/BOOTSTRAP.md +2 -2
- package/src/prompts/templates/system-sections.ts +230 -8
- package/src/providers/__tests__/connection-model-compat.test.ts +234 -0
- package/src/providers/__tests__/retry-callsite.test.ts +85 -5
- package/src/providers/anthropic/client.ts +32 -66
- package/src/providers/call-site-routing.ts +14 -2
- package/src/providers/connection-model-compat.ts +38 -0
- package/src/providers/connection-resolution.ts +16 -2
- package/src/providers/gemini/client.ts +49 -6
- package/src/providers/inference/adapter-factory.ts +3 -0
- package/src/providers/minimax/client.ts +106 -0
- package/src/providers/model-catalog.ts +43 -0
- package/src/providers/model-intents.ts +1 -1
- package/src/providers/openai/chat-completions-provider.ts +6 -3
- package/src/providers/openai/codex-models.ts +18 -0
- package/src/providers/openai/responses-provider.ts +78 -21
- package/src/providers/provider-send-message.ts +7 -1
- package/src/providers/retry.ts +34 -3
- package/src/providers/thinking-config.ts +26 -1
- package/src/providers/usage-tracking.ts +2 -0
- package/src/runtime/AGENTS.md +2 -2
- package/src/runtime/agent-wake.ts +1 -0
- package/src/runtime/assistant-event-hub.ts +76 -6
- package/src/runtime/auth/route-policy.ts +36 -0
- package/src/runtime/btw-sidechain.ts +0 -6
- package/src/runtime/http-types.ts +0 -2
- package/src/runtime/migrations/vbundle-builder.ts +10 -3
- package/src/runtime/pending-interactions.ts +0 -1
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +106 -0
- package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +25 -6
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +512 -0
- package/src/runtime/routes/acp-routes.test.ts +255 -6
- package/src/runtime/routes/acp-routes.ts +8 -1
- package/src/runtime/routes/avatar-routes.ts +10 -10
- package/src/runtime/routes/background-wake-routes.ts +188 -0
- package/src/runtime/routes/browser-tabs-routes.ts +200 -0
- package/src/runtime/routes/btw-routes.ts +0 -6
- package/src/runtime/routes/conversation-cli-routes.ts +1 -1
- package/src/runtime/routes/conversation-list-routes.ts +12 -4
- package/src/runtime/routes/conversation-management-routes.ts +77 -20
- package/src/runtime/routes/conversation-query-routes.ts +142 -36
- package/src/runtime/routes/conversation-routes.ts +252 -410
- package/src/runtime/routes/conversation-starter-routes.ts +6 -3
- package/src/runtime/routes/disk-pressure-routes.ts +1 -1
- package/src/runtime/routes/domain-routes.ts +60 -10
- package/src/runtime/routes/email-routes.ts +5 -2
- package/src/runtime/routes/events-routes.ts +54 -10
- package/src/runtime/routes/group-routes.ts +24 -8
- package/src/runtime/routes/host-browser-routes.ts +10 -2
- package/src/runtime/routes/host-cu-routes.ts +2 -2
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +96 -3
- package/src/runtime/routes/index.ts +8 -0
- package/src/runtime/routes/inference-profile-session-handler.ts +22 -12
- package/src/runtime/routes/inference-profile-session-routes.ts +7 -1
- package/src/runtime/routes/llm-call-sites-routes.ts +32 -5
- package/src/runtime/routes/memory-item-routes.ts +8 -3
- package/src/runtime/routes/memory-v2-routes.ts +215 -5
- package/src/runtime/routes/memory-v3-routes.ts +316 -0
- package/src/runtime/routes/migration-routes.ts +21 -24
- package/src/runtime/routes/plugins-routes.ts +337 -0
- package/src/runtime/routes/rename-conversation-routes.ts +6 -2
- package/src/runtime/routes/secret-routes.ts +25 -5
- package/src/runtime/routes/settings-routes.ts +12 -11
- package/src/runtime/routes/slack-channel-routes.ts +5 -4
- package/src/runtime/routes/workspace-routes.ts +25 -10
- package/src/runtime/sync/resource-sync-events.ts +106 -38
- package/src/runtime/sync/sync-publisher.test.ts +49 -0
- package/src/runtime/sync/sync-publisher.ts +2 -1
- package/src/runtime/verification-outbound-actions.ts +73 -1
- package/src/telemetry/types.ts +12 -0
- package/src/telemetry/usage-telemetry-reporter.test.ts +48 -0
- package/src/telemetry/usage-telemetry-reporter.ts +1 -0
- package/src/tools/acp/spawn.test.ts +119 -0
- package/src/tools/acp/spawn.ts +15 -2
- package/src/tools/apps/definitions.ts +2 -8
- package/src/tools/ask-question/ask-question-tool.test.ts +3 -3
- package/src/tools/ask-question/ask-question-tool.ts +38 -45
- package/src/tools/browser/__tests__/pinned-tabs.test.ts +70 -0
- package/src/tools/browser/browser-execution.ts +16 -3
- package/src/tools/browser/cdp-client/__tests__/browser-tabs-factory.test.ts +402 -0
- package/src/tools/browser/cdp-client/__tests__/types.test.ts +3 -0
- package/src/tools/browser/cdp-client/cdp-inspect-client.ts +12 -0
- package/src/tools/browser/cdp-client/extension-cdp-client.ts +27 -1
- package/src/tools/browser/cdp-client/factory.ts +100 -17
- package/src/tools/browser/cdp-client/local-cdp-client.ts +12 -0
- package/src/tools/browser/cdp-client/types.ts +65 -0
- package/src/tools/browser/pinned-tabs.ts +96 -40
- package/src/tools/computer-use/definitions.ts +22 -78
- package/src/tools/credential-execution/make-authenticated-request.ts +3 -9
- package/src/tools/credential-execution/manage-secure-command-tool.ts +3 -9
- package/src/tools/credential-execution/run-authenticated-command.ts +3 -9
- package/src/tools/credentials/vault.ts +3 -9
- package/src/tools/document/document-tool.ts +59 -0
- package/src/tools/execution-target.ts +21 -23
- package/src/tools/executor.ts +6 -1
- package/src/tools/filesystem/edit.ts +3 -9
- package/src/tools/filesystem/list.ts +3 -9
- package/src/tools/filesystem/read.ts +3 -9
- package/src/tools/filesystem/write.ts +3 -9
- package/src/tools/host-filesystem/edit.ts +3 -9
- package/src/tools/host-filesystem/read.ts +3 -9
- package/src/tools/host-filesystem/transfer.ts +3 -9
- package/src/tools/host-filesystem/write.ts +3 -9
- package/src/tools/host-terminal/host-shell.ts +3 -9
- package/src/tools/mcp/mcp-tool-factory.ts +1 -8
- package/src/tools/memory/register.test.ts +1 -1
- package/src/tools/memory/register.ts +4 -9
- package/src/tools/network/web-fetch.ts +3 -9
- package/src/tools/network/web-search.ts +25 -32
- package/src/tools/registry.ts +7 -23
- package/src/tools/schema-transforms.ts +1 -1
- package/src/tools/skills/execute.ts +3 -9
- package/src/tools/skills/load.ts +3 -9
- package/src/tools/skills/skill-tool-factory.ts +1 -8
- package/src/tools/subagent/notify-parent.ts +3 -9
- package/src/tools/system/request-permission.ts +3 -9
- package/src/tools/terminal/shell.ts +3 -9
- package/src/tools/tool-defaults.ts +94 -0
- package/src/tools/types.ts +27 -98
- package/src/tools/ui-surface/definitions.ts +6 -22
- package/src/usage/pricing.ts +23 -0
- package/src/usage/types.ts +12 -0
- package/src/util/logger.ts +16 -7
- package/src/util/platform.ts +7 -2
- package/src/util/sqlite3-runtime.ts +65 -0
- package/src/workspace/migrations/086-revert-stale-gemini-mis-rewrites.ts +1 -0
- package/src/workspace/migrations/089-move-memory-tree-out-of-v3.ts +86 -0
- package/src/workspace/migrations/registry.ts +2 -0
- package/src/__tests__/compaction-strip-metadata-clear.test.ts +0 -206
- package/src/__tests__/message-complete-display-id.test.ts +0 -175
- package/src/daemon/query-complexity-router.ts +0 -75
- package/src/prompts/cache-boundary.ts +0 -8
|
@@ -159,8 +159,8 @@ mock.module("../daemon/disk-pressure-policy.js", () => ({
|
|
|
159
159
|
const updateMessageMetadataMock = mock(
|
|
160
160
|
(_id: string, _updates: Record<string, unknown>) => {},
|
|
161
161
|
);
|
|
162
|
-
const
|
|
163
|
-
(_conversationId: string) => {},
|
|
162
|
+
const setConversationHistoryStrippedAtMock = mock(
|
|
163
|
+
(_conversationId: string, _historyStrippedAt: number | null) => {},
|
|
164
164
|
);
|
|
165
165
|
const updateConversationSlackContextWatermarkMock = mock(
|
|
166
166
|
(_conversationId: string, _watermarkTs: string, _compactedAt?: number) => {},
|
|
@@ -180,8 +180,7 @@ mock.module("../memory/conversation-crud.js", () => ({
|
|
|
180
180
|
setConversationOriginChannelIfUnset: () => {},
|
|
181
181
|
updateConversationUsage: () => {},
|
|
182
182
|
updateMessageMetadata: updateMessageMetadataMock,
|
|
183
|
-
|
|
184
|
-
clearStrippedInjectionMetadataForConversationMock,
|
|
183
|
+
setConversationHistoryStrippedAt: setConversationHistoryStrippedAtMock,
|
|
185
184
|
getMessages: () => [],
|
|
186
185
|
getConversation: () => mockConversationRow,
|
|
187
186
|
provenanceFromTrustContext: () => ({
|
|
@@ -684,10 +683,8 @@ beforeEach(() => {
|
|
|
684
683
|
mockHasProactiveArtifactCompleted = true;
|
|
685
684
|
mockTryClaimProactiveArtifactTrigger = false;
|
|
686
685
|
runProactiveArtifactJobMock.mockClear();
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
() => {},
|
|
690
|
-
);
|
|
686
|
+
setConversationHistoryStrippedAtMock.mockClear();
|
|
687
|
+
setConversationHistoryStrippedAtMock.mockImplementation(() => {});
|
|
691
688
|
applyRuntimeInjectionsMock.mockClear();
|
|
692
689
|
buildUnifiedTurnContextBlockMock.mockClear();
|
|
693
690
|
resolveTurnTimezoneContextMock.mockClear();
|
|
@@ -1218,20 +1215,8 @@ describe("session-agent-loop", () => {
|
|
|
1218
1215
|
await runAgentLoopImpl(ctx, "hello", "msg-1", (msg) => events.push(msg));
|
|
1219
1216
|
|
|
1220
1217
|
expect(recordRequestLogMock).toHaveBeenCalledTimes(1);
|
|
1221
|
-
const call = recordRequestLogMock.mock.calls[0] as unknown as [
|
|
1222
|
-
|
|
1223
|
-
string,
|
|
1224
|
-
string,
|
|
1225
|
-
undefined,
|
|
1226
|
-
string,
|
|
1227
|
-
];
|
|
1228
|
-
expect(call).toEqual([
|
|
1229
|
-
"test-conv",
|
|
1230
|
-
JSON.stringify(rawRequest),
|
|
1231
|
-
JSON.stringify(rawResponse),
|
|
1232
|
-
undefined,
|
|
1233
|
-
"fireworks",
|
|
1234
|
-
]);
|
|
1218
|
+
const call = recordRequestLogMock.mock.calls[0] as unknown as unknown[];
|
|
1219
|
+
expect(call[4]).toBe("fireworks");
|
|
1235
1220
|
});
|
|
1236
1221
|
|
|
1237
1222
|
test("record request log falls back to the runtime provider when no actual provider is supplied", async () => {
|
|
@@ -1377,20 +1362,9 @@ describe("session-agent-loop", () => {
|
|
|
1377
1362
|
await runAgentLoopImpl(ctx, "hello", "msg-1", (msg) => events.push(msg));
|
|
1378
1363
|
|
|
1379
1364
|
expect(recordRequestLogMock).toHaveBeenCalledTimes(1);
|
|
1380
|
-
const call = recordRequestLogMock.mock.calls[0] as unknown as [
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
string,
|
|
1384
|
-
undefined,
|
|
1385
|
-
string,
|
|
1386
|
-
];
|
|
1387
|
-
expect(call).toEqual([
|
|
1388
|
-
"test-conv",
|
|
1389
|
-
JSON.stringify(rawRequest),
|
|
1390
|
-
JSON.stringify(rawResponse),
|
|
1391
|
-
undefined,
|
|
1392
|
-
"openai",
|
|
1393
|
-
]);
|
|
1365
|
+
const call = recordRequestLogMock.mock.calls[0] as unknown as unknown[];
|
|
1366
|
+
expect(call[1]).toBe(JSON.stringify(rawRequest));
|
|
1367
|
+
expect(call[2]).toBe(JSON.stringify(rawResponse));
|
|
1394
1368
|
});
|
|
1395
1369
|
});
|
|
1396
1370
|
|
|
@@ -2042,6 +2016,154 @@ describe("session-agent-loop", () => {
|
|
|
2042
2016
|
expect(complete).toBeDefined();
|
|
2043
2017
|
});
|
|
2044
2018
|
|
|
2019
|
+
test("emits budget_yield_unrecovered when auto_compress rerun yields at mid-loop budget", async () => {
|
|
2020
|
+
// Regression test for the silent-stall failure mode:
|
|
2021
|
+
// when every recovery layer has been applied (tier reducer
|
|
2022
|
+
// exhausted + auto_compress_latest_turn emergency compaction)
|
|
2023
|
+
// and the final `agentLoop.run` STILL yields at the mid-loop
|
|
2024
|
+
// budget checkpoint, the orchestrator used to fall through to
|
|
2025
|
+
// post-turn cleanup with NO `agent_loop_exit_reason` emitted —
|
|
2026
|
+
// the turn just stopped mid-action and `llm_request_logs` showed
|
|
2027
|
+
// a NULL exit reason on the final row. We now emit
|
|
2028
|
+
// `budget_yield_unrecovered` so the inspector and dashboards can
|
|
2029
|
+
// attribute the silent stall.
|
|
2030
|
+
const events: ServerMessage[] = [];
|
|
2031
|
+
let callCount = 0;
|
|
2032
|
+
|
|
2033
|
+
// Reducer exhausts all 4 tiers on first call so the convergence
|
|
2034
|
+
// loop runs exactly one iteration before falling through to
|
|
2035
|
+
// the auto_compress_latest_turn branch.
|
|
2036
|
+
mockReducerStepFn = (msgs: Message[]) => ({
|
|
2037
|
+
messages: msgs,
|
|
2038
|
+
tier: "injection_downgrade",
|
|
2039
|
+
state: {
|
|
2040
|
+
appliedTiers: [
|
|
2041
|
+
"forced_compaction",
|
|
2042
|
+
"tool_result_truncation",
|
|
2043
|
+
"media_stubbing",
|
|
2044
|
+
"injection_downgrade",
|
|
2045
|
+
],
|
|
2046
|
+
injectionMode: "minimal",
|
|
2047
|
+
exhausted: true,
|
|
2048
|
+
},
|
|
2049
|
+
estimatedTokens: 120_000,
|
|
2050
|
+
});
|
|
2051
|
+
|
|
2052
|
+
mockOverflowAction = "auto_compress_latest_turn";
|
|
2053
|
+
|
|
2054
|
+
// Sits between the preflight budget (preflightBudget =
|
|
2055
|
+
// 100k * 0.95 = 95k — anything above triggers preflight reducer
|
|
2056
|
+
// *before* we get to the convergence/auto_compress path under
|
|
2057
|
+
// test) and the mid-loop threshold (preflightBudget * 0.85 =
|
|
2058
|
+
// ≈80.75k — anything above flips yieldedForBudget on a checkpoint
|
|
2059
|
+
// call). 90k satisfies both so the path reaches call 3.
|
|
2060
|
+
mockEstimateTokens = 90_000;
|
|
2061
|
+
|
|
2062
|
+
const agentLoopRun: AgentLoopRun = async (
|
|
2063
|
+
messages,
|
|
2064
|
+
onEvent,
|
|
2065
|
+
_signal,
|
|
2066
|
+
_reqId,
|
|
2067
|
+
onCheckpoint,
|
|
2068
|
+
) => {
|
|
2069
|
+
callCount++;
|
|
2070
|
+
if (callCount <= 2) {
|
|
2071
|
+
// Calls 1 (initial) and 2 (convergence rerun): error so
|
|
2072
|
+
// `state.contextTooLargeDetected` stays true through
|
|
2073
|
+
// convergence exit and we enter the auto_compress branch.
|
|
2074
|
+
onEvent({
|
|
2075
|
+
type: "error",
|
|
2076
|
+
error: new Error("context_length_exceeded"),
|
|
2077
|
+
});
|
|
2078
|
+
onEvent({
|
|
2079
|
+
type: "usage",
|
|
2080
|
+
inputTokens: 100,
|
|
2081
|
+
outputTokens: 0,
|
|
2082
|
+
model: "test-model",
|
|
2083
|
+
providerDurationMs: 50,
|
|
2084
|
+
});
|
|
2085
|
+
return messages;
|
|
2086
|
+
}
|
|
2087
|
+
// Call 3: the auto_compress_latest_turn rerun. Invoke
|
|
2088
|
+
// onCheckpoint so the orchestrator's mid-loop budget check
|
|
2089
|
+
// flips `yieldedForBudget` to true, then return without
|
|
2090
|
+
// finishing — mirroring what AgentLoop.run does when its
|
|
2091
|
+
// checkpoint returns "yield".
|
|
2092
|
+
if (onCheckpoint) {
|
|
2093
|
+
await onCheckpoint({
|
|
2094
|
+
turnIndex: 0,
|
|
2095
|
+
toolCount: 1,
|
|
2096
|
+
hasToolUse: true,
|
|
2097
|
+
history: messages,
|
|
2098
|
+
});
|
|
2099
|
+
}
|
|
2100
|
+
return messages;
|
|
2101
|
+
};
|
|
2102
|
+
|
|
2103
|
+
const ctx = makeCtx({
|
|
2104
|
+
agentLoopRun,
|
|
2105
|
+
hasNoClient: true,
|
|
2106
|
+
contextWindowManager: {
|
|
2107
|
+
shouldCompact: () => ({ needed: false, estimatedTokens: 0 }),
|
|
2108
|
+
maybeCompact: async () => ({
|
|
2109
|
+
compacted: true,
|
|
2110
|
+
messages: [
|
|
2111
|
+
{ role: "user", content: [{ type: "text", text: "Hello" }] },
|
|
2112
|
+
] as Message[],
|
|
2113
|
+
compactedPersistedMessages: 3,
|
|
2114
|
+
summaryText: "Compressed summary",
|
|
2115
|
+
previousEstimatedInputTokens: 120000,
|
|
2116
|
+
estimatedInputTokens: 30000,
|
|
2117
|
+
maxInputTokens: 100000,
|
|
2118
|
+
thresholdTokens: 80000,
|
|
2119
|
+
compactedMessages: 5,
|
|
2120
|
+
summaryCalls: 1,
|
|
2121
|
+
summaryInputTokens: 300,
|
|
2122
|
+
summaryOutputTokens: 100,
|
|
2123
|
+
summaryModel: "mock-model",
|
|
2124
|
+
}),
|
|
2125
|
+
} as unknown as AgentLoopConversationContext["contextWindowManager"],
|
|
2126
|
+
});
|
|
2127
|
+
|
|
2128
|
+
await runAgentLoopImpl(ctx, "hello", "msg-1", (msg) => events.push(msg));
|
|
2129
|
+
|
|
2130
|
+
// Observability emit: exit reason was stamped onto the latest
|
|
2131
|
+
// llm_request_logs row.
|
|
2132
|
+
expect(setAgentLoopExitReasonOnLatestLogMock).toHaveBeenCalledWith(
|
|
2133
|
+
"test-conv",
|
|
2134
|
+
"budget_yield_unrecovered",
|
|
2135
|
+
);
|
|
2136
|
+
|
|
2137
|
+
// We did NOT also emit context_too_large — the auto_compress
|
|
2138
|
+
// branch resets `contextTooLargeDetected` before its rerun and
|
|
2139
|
+
// the rerun's yield-for-budget keeps it false, so the error
|
|
2140
|
+
// branch above stays skipped.
|
|
2141
|
+
expect(setAgentLoopExitReasonOnLatestLogMock).not.toHaveBeenCalledWith(
|
|
2142
|
+
"test-conv",
|
|
2143
|
+
"context_too_large",
|
|
2144
|
+
);
|
|
2145
|
+
|
|
2146
|
+
// User-facing emit: the classified BUDGET_YIELD_UNRECOVERED
|
|
2147
|
+
// error is sent to the client so the UI can render a notice
|
|
2148
|
+
// instead of leaving the turn looking like a silent ghost. The
|
|
2149
|
+
// assistant-side notice persistence is exercised in the overflow
|
|
2150
|
+
// suite (`conversation-agent-loop-overflow.test.ts`); this test
|
|
2151
|
+
// owns the observability + emit contract.
|
|
2152
|
+
const conversationError = events.find(
|
|
2153
|
+
(e) => e.type === "conversation_error",
|
|
2154
|
+
);
|
|
2155
|
+
expect(conversationError).toBeDefined();
|
|
2156
|
+
if (conversationError && "code" in conversationError) {
|
|
2157
|
+
expect(conversationError.code).toBe("BUDGET_YIELD_UNRECOVERED");
|
|
2158
|
+
expect(conversationError.retryable).toBe(true);
|
|
2159
|
+
expect(conversationError.errorCategory).toBe(
|
|
2160
|
+
"budget_yield_unrecovered",
|
|
2161
|
+
);
|
|
2162
|
+
} else {
|
|
2163
|
+
throw new Error("conversation_error missing `code` field");
|
|
2164
|
+
}
|
|
2165
|
+
});
|
|
2166
|
+
|
|
2045
2167
|
test("recovery loop is bounded by maxAttempts", async () => {
|
|
2046
2168
|
const events: ServerMessage[] = [];
|
|
2047
2169
|
let reducerCalls = 0;
|
|
@@ -3769,8 +3891,8 @@ describe("session-agent-loop", () => {
|
|
|
3769
3891
|
});
|
|
3770
3892
|
});
|
|
3771
3893
|
|
|
3772
|
-
describe("compaction-strip
|
|
3773
|
-
test("
|
|
3894
|
+
describe("compaction-strip marker persistence", () => {
|
|
3895
|
+
test("records historyStrippedAt when convergence strip runs", async () => {
|
|
3774
3896
|
// Reducer: succeed on first call, returning reduced messages.
|
|
3775
3897
|
mockReducerStepFn = (msgs: Message[]) => ({
|
|
3776
3898
|
messages: msgs,
|
|
@@ -3841,91 +3963,10 @@ describe("session-agent-loop", () => {
|
|
|
3841
3963
|
|
|
3842
3964
|
await runAgentLoopImpl(ctx, "hello", "msg-1", () => {});
|
|
3843
3965
|
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
const clearCalls =
|
|
3847
|
-
clearStrippedInjectionMetadataForConversationMock.mock.calls.filter(
|
|
3848
|
-
(call) => call[0] === "test-conv",
|
|
3849
|
-
);
|
|
3850
|
-
expect(clearCalls.length).toBeGreaterThanOrEqual(1);
|
|
3851
|
-
});
|
|
3852
|
-
|
|
3853
|
-
test("strip-site clear is non-fatal when the helper throws", async () => {
|
|
3854
|
-
clearStrippedInjectionMetadataForConversationMock.mockImplementation(
|
|
3855
|
-
() => {
|
|
3856
|
-
throw new Error("db write failed");
|
|
3857
|
-
},
|
|
3966
|
+
const stripCalls = setConversationHistoryStrippedAtMock.mock.calls.filter(
|
|
3967
|
+
(call) => call[0] === "test-conv",
|
|
3858
3968
|
);
|
|
3859
|
-
|
|
3860
|
-
mockReducerStepFn = (msgs: Message[]) => ({
|
|
3861
|
-
messages: msgs,
|
|
3862
|
-
tier: "forced_compaction",
|
|
3863
|
-
state: {
|
|
3864
|
-
appliedTiers: ["forced_compaction"],
|
|
3865
|
-
injectionMode: "full",
|
|
3866
|
-
exhausted: false,
|
|
3867
|
-
},
|
|
3868
|
-
estimatedTokens: 5000,
|
|
3869
|
-
});
|
|
3870
|
-
|
|
3871
|
-
let callCount = 0;
|
|
3872
|
-
const agentLoopRun: AgentLoopRun = async (messages, onEvent) => {
|
|
3873
|
-
callCount++;
|
|
3874
|
-
if (callCount === 1) {
|
|
3875
|
-
onEvent({
|
|
3876
|
-
type: "error",
|
|
3877
|
-
error: new Error("context_length_exceeded"),
|
|
3878
|
-
});
|
|
3879
|
-
onEvent({
|
|
3880
|
-
type: "usage",
|
|
3881
|
-
inputTokens: 100,
|
|
3882
|
-
outputTokens: 0,
|
|
3883
|
-
model: "test-model",
|
|
3884
|
-
providerDurationMs: 50,
|
|
3885
|
-
});
|
|
3886
|
-
return [
|
|
3887
|
-
...messages,
|
|
3888
|
-
{
|
|
3889
|
-
role: "assistant" as const,
|
|
3890
|
-
content: [{ type: "text", text: "partial" }] as ContentBlock[],
|
|
3891
|
-
},
|
|
3892
|
-
];
|
|
3893
|
-
}
|
|
3894
|
-
onEvent({
|
|
3895
|
-
type: "message_complete",
|
|
3896
|
-
message: {
|
|
3897
|
-
role: "assistant",
|
|
3898
|
-
content: [{ type: "text", text: "recovered" }],
|
|
3899
|
-
},
|
|
3900
|
-
});
|
|
3901
|
-
onEvent({
|
|
3902
|
-
type: "usage",
|
|
3903
|
-
inputTokens: 50,
|
|
3904
|
-
outputTokens: 25,
|
|
3905
|
-
model: "test-model",
|
|
3906
|
-
providerDurationMs: 100,
|
|
3907
|
-
});
|
|
3908
|
-
return [
|
|
3909
|
-
...messages,
|
|
3910
|
-
{
|
|
3911
|
-
role: "assistant" as const,
|
|
3912
|
-
content: [{ type: "text", text: "recovered" }] as ContentBlock[],
|
|
3913
|
-
},
|
|
3914
|
-
];
|
|
3915
|
-
};
|
|
3916
|
-
|
|
3917
|
-
const ctx = makeCtx({
|
|
3918
|
-
agentLoopRun,
|
|
3919
|
-
contextWindowManager: {
|
|
3920
|
-
shouldCompact: () => ({ needed: false, estimatedTokens: 0 }),
|
|
3921
|
-
maybeCompact: async () => ({ compacted: false }),
|
|
3922
|
-
} as unknown as AgentLoopConversationContext["contextWindowManager"],
|
|
3923
|
-
});
|
|
3924
|
-
|
|
3925
|
-
// Must not throw — the strip-site clear is wrapped in try/catch.
|
|
3926
|
-
await expect(
|
|
3927
|
-
runAgentLoopImpl(ctx, "hello", "msg-1", () => {}),
|
|
3928
|
-
).resolves.toBeUndefined();
|
|
3969
|
+
expect(stripCalls.length).toBeGreaterThanOrEqual(1);
|
|
3929
3970
|
});
|
|
3930
3971
|
});
|
|
3931
3972
|
});
|
|
@@ -110,15 +110,12 @@ mock.module("../tools/skills/skill-tool-factory.js", () => ({
|
|
|
110
110
|
description: entry.description,
|
|
111
111
|
category: entry.category,
|
|
112
112
|
defaultRiskLevel: RiskLevel.Medium,
|
|
113
|
+
executionTarget: "sandbox" as const,
|
|
113
114
|
origin: "skill" as const,
|
|
114
115
|
ownerSkillId: skillId,
|
|
115
116
|
ownerSkillVersionHash: versionHash,
|
|
116
117
|
ownerSkillBundled: bundled ?? undefined,
|
|
117
|
-
|
|
118
|
-
name: entry.name,
|
|
119
|
-
description: entry.description,
|
|
120
|
-
input_schema: entry.input_schema as object,
|
|
121
|
-
}),
|
|
118
|
+
input_schema: entry.input_schema as object,
|
|
122
119
|
execute: async () => ({ content: "", isError: false }),
|
|
123
120
|
})),
|
|
124
121
|
}));
|
|
@@ -27,8 +27,8 @@ mock.module("../config/env.js", () => ({
|
|
|
27
27
|
|
|
28
28
|
mock.module("../daemon/handlers/conversations.js", () => ({
|
|
29
29
|
cancelGeneration: () => true,
|
|
30
|
-
clearAllConversations: () => {
|
|
31
|
-
clearAll();
|
|
30
|
+
clearAllConversations: async () => {
|
|
31
|
+
await clearAll();
|
|
32
32
|
return 0;
|
|
33
33
|
},
|
|
34
34
|
switchConversation: async () => null,
|
|
@@ -129,26 +129,28 @@ describe("DELETE /v1/conversations — route handler", () => {
|
|
|
129
129
|
(r) => r.operationId === "clearAllConversations",
|
|
130
130
|
)!;
|
|
131
131
|
|
|
132
|
-
test("missing X-Confirm-Destructive header throws BadRequestError", () => {
|
|
133
|
-
expect(
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
132
|
+
test("missing X-Confirm-Destructive header throws BadRequestError", async () => {
|
|
133
|
+
await expect(
|
|
134
|
+
Promise.resolve().then(() =>
|
|
135
|
+
clearRoute.handler({
|
|
136
|
+
pathParams: {},
|
|
137
|
+
body: {},
|
|
138
|
+
headers: {},
|
|
139
|
+
}),
|
|
140
|
+
),
|
|
141
|
+
).rejects.toThrow(BadRequestError);
|
|
141
142
|
});
|
|
142
143
|
|
|
143
|
-
test("wrong X-Confirm-Destructive header value throws BadRequestError", () => {
|
|
144
|
-
expect(
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
144
|
+
test("wrong X-Confirm-Destructive header value throws BadRequestError", async () => {
|
|
145
|
+
await expect(
|
|
146
|
+
Promise.resolve().then(() =>
|
|
147
|
+
clearRoute.handler({
|
|
148
|
+
pathParams: {},
|
|
149
|
+
body: {},
|
|
150
|
+
headers: { "x-confirm-destructive": "wrong-value" },
|
|
151
|
+
}),
|
|
152
|
+
),
|
|
153
|
+
).rejects.toThrow(BadRequestError);
|
|
152
154
|
});
|
|
153
155
|
|
|
154
156
|
test("correct header clears data", async () => {
|
|
@@ -156,23 +158,21 @@ describe("DELETE /v1/conversations — route handler", () => {
|
|
|
156
158
|
await addMessage(conv.id, "user", "hello from safety test");
|
|
157
159
|
expect(getConversation(conv.id)).not.toBeNull();
|
|
158
160
|
|
|
159
|
-
const result = clearRoute.handler({
|
|
161
|
+
const result = await clearRoute.handler({
|
|
160
162
|
pathParams: {},
|
|
161
163
|
body: {},
|
|
162
164
|
headers: { "x-confirm-destructive": "clear-all-conversations" },
|
|
163
|
-
|
|
164
165
|
});
|
|
165
166
|
expect(result).toBeUndefined();
|
|
166
167
|
|
|
167
168
|
expect(getConversation(conv.id)).toBeNull();
|
|
168
169
|
});
|
|
169
170
|
|
|
170
|
-
test("lifecycle_events contains conversations_clear_all after successful clear", () => {
|
|
171
|
-
clearRoute.handler({
|
|
171
|
+
test("lifecycle_events contains conversations_clear_all after successful clear", async () => {
|
|
172
|
+
await clearRoute.handler({
|
|
172
173
|
pathParams: {},
|
|
173
174
|
body: {},
|
|
174
175
|
headers: { "x-confirm-destructive": "clear-all-conversations" },
|
|
175
|
-
|
|
176
176
|
});
|
|
177
177
|
|
|
178
178
|
const raw = (
|
|
@@ -23,7 +23,7 @@ mock.module("../daemon/conversation-store.js", () => ({
|
|
|
23
23
|
|
|
24
24
|
mock.module("../daemon/handlers/conversations.js", () => ({
|
|
25
25
|
cancelGeneration: () => true,
|
|
26
|
-
clearAllConversations: () => 0,
|
|
26
|
+
clearAllConversations: async () => 0,
|
|
27
27
|
switchConversation: async () => null,
|
|
28
28
|
undoLastMessage: async () => null,
|
|
29
29
|
regenerateResponse: async () => null,
|
|
@@ -231,7 +231,7 @@ describe("clearAll → disk view", () => {
|
|
|
231
231
|
resetConversationsDir();
|
|
232
232
|
});
|
|
233
233
|
|
|
234
|
-
test("empties the conversations directory", () => {
|
|
234
|
+
test("empties the conversations directory", async () => {
|
|
235
235
|
// Create two conversations
|
|
236
236
|
createConversation("Conv A");
|
|
237
237
|
createConversation("Conv B");
|
|
@@ -241,7 +241,7 @@ describe("clearAll → disk view", () => {
|
|
|
241
241
|
expect(entries.length).toBe(2);
|
|
242
242
|
|
|
243
243
|
// Clear all
|
|
244
|
-
clearAll();
|
|
244
|
+
await clearAll();
|
|
245
245
|
|
|
246
246
|
// Conversations directory should exist but be empty
|
|
247
247
|
expect(existsSync(conversationsDir)).toBe(true);
|
|
@@ -9,6 +9,7 @@ mock.module("../providers/registry.js", () => ({
|
|
|
9
9
|
|
|
10
10
|
import type { ErrorContext } from "../daemon/conversation-error.js";
|
|
11
11
|
import {
|
|
12
|
+
budgetYieldUnrecoveredClassification,
|
|
12
13
|
buildConversationErrorMessage,
|
|
13
14
|
classifyConversationError,
|
|
14
15
|
isUserCancellation,
|
|
@@ -947,3 +948,33 @@ describe("buildConversationErrorMessage", () => {
|
|
|
947
948
|
expect(msg.code).toBe("PROVIDER_WEB_SEARCH");
|
|
948
949
|
});
|
|
949
950
|
});
|
|
951
|
+
|
|
952
|
+
describe("budgetYieldUnrecoveredClassification", () => {
|
|
953
|
+
it("returns the BUDGET_YIELD_UNRECOVERED code and retryable=true", () => {
|
|
954
|
+
const classified = budgetYieldUnrecoveredClassification();
|
|
955
|
+
expect(classified.code).toBe("BUDGET_YIELD_UNRECOVERED");
|
|
956
|
+
expect(classified.retryable).toBe(true);
|
|
957
|
+
expect(classified.errorCategory).toBe("budget_yield_unrecovered");
|
|
958
|
+
});
|
|
959
|
+
|
|
960
|
+
it("returns a user-facing message that explains the situation", () => {
|
|
961
|
+
const classified = budgetYieldUnrecoveredClassification();
|
|
962
|
+
// The message must communicate (a) compaction was attempted, (b) send
|
|
963
|
+
// another message to continue. Avoid asserting exact wording so copy
|
|
964
|
+
// tweaks don't trip the test, but lock down the two semantic anchors
|
|
965
|
+
// a downstream client could test against.
|
|
966
|
+
expect(classified.userMessage).toContain("compact");
|
|
967
|
+
expect(classified.userMessage).toContain("Send another message");
|
|
968
|
+
});
|
|
969
|
+
|
|
970
|
+
it("survives the buildConversationErrorMessage envelope unchanged", () => {
|
|
971
|
+
const classified = budgetYieldUnrecoveredClassification();
|
|
972
|
+
const envelope = buildConversationErrorMessage("conv-1", classified);
|
|
973
|
+
expect(envelope.type).toBe("conversation_error");
|
|
974
|
+
expect(envelope.conversationId).toBe("conv-1");
|
|
975
|
+
expect(envelope.code).toBe("BUDGET_YIELD_UNRECOVERED");
|
|
976
|
+
expect(envelope.retryable).toBe(true);
|
|
977
|
+
expect(envelope.errorCategory).toBe("budget_yield_unrecovered");
|
|
978
|
+
expect(envelope.userMessage).toBe(classified.userMessage);
|
|
979
|
+
});
|
|
980
|
+
});
|