@vellumai/assistant 0.7.1 → 0.7.3
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 +48 -50
- package/Dockerfile +1 -0
- package/README.md +1 -2
- package/__tests__/permissions/gateway-threshold-reader.test.ts +9 -3
- package/bun.lock +26 -26
- package/docs/architecture/memory.md +5 -2
- package/docs/architecture/security.md +20 -0
- package/docs/plugins.md +7 -9
- package/knip.json +1 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +1 -0
- package/node_modules/@vellumai/gateway-client/src/ipc-client.ts +52 -5
- package/node_modules/@vellumai/gateway-client/src/types.ts +11 -0
- package/node_modules/@vellumai/service-contracts/package.json +2 -0
- package/node_modules/@vellumai/service-contracts/src/__tests__/contracts.test.ts +4 -0
- package/node_modules/@vellumai/service-contracts/src/__tests__/ingress.test.ts +107 -0
- package/node_modules/@vellumai/service-contracts/src/index.ts +5 -1
- package/node_modules/@vellumai/service-contracts/src/ingress.ts +24 -0
- package/node_modules/@vellumai/service-contracts/src/twilio-ingress.ts +84 -0
- package/node_modules/@vellumai/slack-text/src/index.test.ts +18 -35
- package/node_modules/@vellumai/slack-text/src/index.ts +2 -48
- package/node_modules/@vellumai/twilio-client/bun.lock +24 -0
- package/node_modules/@vellumai/twilio-client/package.json +18 -0
- package/node_modules/@vellumai/twilio-client/src/__tests__/twilio-client.test.ts +128 -0
- package/node_modules/@vellumai/twilio-client/src/index.ts +179 -0
- package/node_modules/@vellumai/twilio-client/tsconfig.json +20 -0
- package/openapi.yaml +1020 -40
- package/package.json +6 -3
- package/src/__tests__/app-builder-tool-scripts.test.ts +3 -3
- package/src/__tests__/app-bundler.test.ts +170 -1
- package/src/__tests__/app-control-flow.test.ts +384 -0
- package/src/__tests__/app-control-no-global-cgevent.test.ts +98 -0
- package/src/__tests__/app-control-tool-schemas.test.ts +621 -0
- package/src/__tests__/app-executors.test.ts +30 -43
- package/src/__tests__/approval-routes-http.test.ts +23 -6
- package/src/__tests__/assistant-event-hub-machine-name.test.ts +146 -0
- package/src/__tests__/assistant-event-hub-targeted.test.ts +257 -0
- package/src/__tests__/assistant-event-hub.test.ts +157 -2
- package/src/__tests__/assistant-feature-flags-integration.test.ts +29 -7
- package/src/__tests__/auto-analysis-end-to-end.test.ts +62 -1
- package/src/__tests__/background-shell-host-bash.test.ts +14 -15
- package/src/__tests__/background-workers-disk-pressure.test.ts +268 -0
- package/src/__tests__/bootstrap-turn-cleanup.test.ts +44 -0
- package/src/__tests__/btw-routes.test.ts +13 -4
- package/src/__tests__/call-controller.test.ts +49 -1
- package/src/__tests__/call-conversation-messages.test.ts +8 -2
- package/src/__tests__/call-domain.test.ts +0 -2
- package/src/__tests__/call-routes-http.test.ts +0 -2
- package/src/__tests__/channel-inbound-disk-pressure.test.ts +537 -0
- package/src/__tests__/channel-readiness-service.test.ts +62 -2
- package/src/__tests__/checker.test.ts +3 -4
- package/src/__tests__/config-loader-backfill.test.ts +461 -147
- package/src/__tests__/config-loader-platform-defaults.test.ts +196 -0
- package/src/__tests__/config-schema-cmd.test.ts +0 -1
- package/src/__tests__/config-schema.test.ts +1 -0
- package/src/__tests__/config-set-platform-guard.test.ts +48 -4
- package/src/__tests__/config-watcher-cleanup-throttle.test.ts +20 -11
- package/src/__tests__/config-watcher.test.ts +142 -71
- package/src/__tests__/context-search-agent-runner.test.ts +61 -3
- package/src/__tests__/context-search-conversations-source.test.ts +0 -24
- package/src/__tests__/context-search-fanout.test.ts +0 -1
- package/src/__tests__/context-search-memory-source.test.ts +3 -7
- package/src/__tests__/context-search-memory-v2-source.test.ts +0 -2
- package/src/__tests__/context-search-pkb-source.test.ts +0 -1
- package/src/__tests__/context-search-workspace-source.test.ts +0 -1
- package/src/__tests__/conversation-abort-tool-results.test.ts +6 -0
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +223 -0
- package/src/__tests__/conversation-agent-loop.test.ts +454 -5
- package/src/__tests__/conversation-app-control-instantiation.test.ts +392 -0
- package/src/__tests__/conversation-app-control-lifecycle.test.ts +237 -0
- package/src/__tests__/conversation-error.test.ts +150 -3
- package/src/__tests__/conversation-init.benchmark.test.ts +0 -2
- package/src/__tests__/conversation-lifecycle.test.ts +36 -0
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +283 -0
- package/src/__tests__/conversation-process-callsite.test.ts +43 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +6 -0
- package/src/__tests__/conversation-routes-disk-view.test.ts +6 -0
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +120 -72
- package/src/__tests__/conversation-routes-slash-commands.test.ts +1 -0
- package/src/__tests__/conversation-runtime-assembly.test.ts +65 -0
- package/src/__tests__/conversation-slash-commands.test.ts +0 -4
- package/src/__tests__/conversation-slash-unknown.test.ts +6 -0
- package/src/__tests__/conversation-speed-override.test.ts +0 -3
- package/src/__tests__/conversation-store.test.ts +0 -18
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +202 -0
- package/src/__tests__/conversation-surfaces-app-control.test.ts +328 -0
- package/src/__tests__/conversation-surfaces-data-persist.test.ts +404 -0
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +2 -5
- package/src/__tests__/conversation-workspace-injection.test.ts +6 -0
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +6 -0
- package/src/__tests__/credential-execution-feature-gates.test.ts +5 -12
- package/src/__tests__/credential-execution-managed-contract.test.ts +3 -131
- package/src/__tests__/credentials-cli.test.ts +12 -12
- package/src/__tests__/cu-unified-flow.test.ts +351 -23
- package/src/__tests__/daemon-credential-client.test.ts +101 -19
- package/src/__tests__/date-context.test.ts +164 -2
- package/src/__tests__/db-schedule-syntax-migration.test.ts +2 -0
- package/src/__tests__/disk-pressure-guard.test.ts +262 -0
- package/src/__tests__/disk-pressure-lifecycle.test.ts +168 -0
- package/src/__tests__/disk-pressure-policy.test.ts +241 -0
- package/src/__tests__/disk-pressure-routes.test.ts +379 -0
- package/src/__tests__/disk-pressure-tools.test.ts +277 -0
- package/src/__tests__/disk-usage.test.ts +150 -0
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
- package/src/__tests__/events-client-registration.test.ts +52 -0
- package/src/__tests__/events-dev-bypass-actor.test.ts +162 -0
- package/src/__tests__/file-write-tool.test.ts +4 -10
- package/src/__tests__/filing-service.test.ts +3 -4
- package/src/__tests__/gateway-only-enforcement.test.ts +0 -1
- package/src/__tests__/guardian-verification-voice-binding.test.ts +0 -2
- package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +0 -2
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +0 -1
- package/src/__tests__/heartbeat-disk-pressure.test.ts +183 -0
- package/src/__tests__/heartbeat-service.test.ts +968 -2
- package/src/__tests__/helpers/call-route-handler.ts +7 -1
- package/src/__tests__/host-app-control-proxy.test.ts +772 -0
- package/src/__tests__/host-app-control-routes.test.ts +263 -0
- package/src/__tests__/host-bash-proxy.test.ts +439 -47
- package/src/__tests__/host-bash-routes.test.ts +459 -0
- package/src/__tests__/host-browser-proxy.test.ts +24 -22
- package/src/__tests__/host-browser-routes.test.ts +39 -13
- package/src/__tests__/host-cu-proxy.test.ts +248 -52
- package/src/__tests__/host-cu-routes-targeted.test.ts +429 -0
- package/src/__tests__/host-file-edit-tool.test.ts +47 -1
- package/src/__tests__/host-file-proxy-targeted.test.ts +378 -0
- package/src/__tests__/host-file-proxy.test.ts +301 -45
- package/src/__tests__/host-file-read-tool.test.ts +17 -0
- package/src/__tests__/host-file-routes-targeted.test.ts +420 -0
- package/src/__tests__/host-file-write-tool.test.ts +42 -1
- package/src/__tests__/host-proxy-base.test.ts +312 -0
- package/src/__tests__/host-shell-tool.test.ts +22 -4
- package/src/__tests__/host-transfer-proxy-targeted.test.ts +932 -0
- package/src/__tests__/host-transfer-proxy.test.ts +121 -22
- package/src/__tests__/host-transfer-routes-targeted.test.ts +662 -0
- package/src/__tests__/http-user-message-parity.test.ts +108 -1
- package/src/__tests__/identity-intro-cache.test.ts +29 -0
- package/src/__tests__/identity-routes.test.ts +103 -1
- package/src/__tests__/init-feature-flag-overrides.test.ts +26 -3
- package/src/__tests__/injector-chain.test.ts +18 -6
- package/src/__tests__/injector-disk-pressure.test.ts +224 -0
- package/src/__tests__/inline-command-runner.test.ts +0 -1
- package/src/__tests__/inline-skill-load-permissions.test.ts +5 -11
- package/src/__tests__/integration-status.test.ts +85 -5
- package/src/__tests__/intent-routing.test.ts +0 -1
- package/src/__tests__/jobs-store-qdrant-breaker.test.ts +95 -5
- package/src/__tests__/lifecycle-memory-v2-seed.test.ts +17 -0
- package/src/__tests__/managed-profile-guard.test.ts +18 -0
- package/src/__tests__/managed-skill-lifecycle.test.ts +0 -1
- package/src/__tests__/mcp-abort-signal.test.ts +130 -0
- package/src/__tests__/mcp-auth-routes.test.ts +197 -0
- package/src/__tests__/mcp-cli.test.ts +338 -2
- package/src/__tests__/memory-admin-recall.test.ts +3 -11
- package/src/__tests__/memory-jobs-worker-lanes.test.ts +188 -0
- package/src/__tests__/memory-retrieval-pipeline.test.ts +22 -1
- package/src/__tests__/migration-import-commit-http.test.ts +108 -2
- package/src/__tests__/mock-gateway-ipc.ts +1 -0
- package/src/__tests__/normalize-onboarding.test.ts +180 -0
- package/src/__tests__/oauth-cli.test.ts +0 -2
- package/src/__tests__/oauth-connect-routes.test.ts +316 -0
- package/src/__tests__/oauth-provider-seed-logos.test.ts +24 -2
- package/src/__tests__/oauth2-gateway-transport.test.ts +0 -1
- package/src/__tests__/onboarding-persona-write.test.ts +308 -0
- package/src/__tests__/openai-provider.test.ts +45 -8
- package/src/__tests__/persist-onboarding-artifacts.test.ts +44 -64
- package/src/__tests__/persistence-secret-redaction.test.ts +299 -0
- package/src/__tests__/platform-bash-auto-approve.test.ts +5 -9
- package/src/__tests__/platform-callback-registration.test.ts +21 -4
- package/src/__tests__/platform.test.ts +2 -1
- package/src/__tests__/playbook-execution.test.ts +0 -43
- package/src/__tests__/plugin-tool-contribution.test.ts +47 -0
- package/src/__tests__/prechat-onboarding-contract.test.ts +214 -25
- package/src/__tests__/process-message-background-slack.test.ts +2 -0
- package/src/__tests__/provider-commit-message-generator.test.ts +0 -1
- package/src/__tests__/provider-tool-name.test.ts +23 -0
- package/src/__tests__/public-ingress-urls.test.ts +97 -0
- package/src/__tests__/relay-server.test.ts +15 -4
- package/src/__tests__/require-fresh-approval.test.ts +0 -1
- package/src/__tests__/retry-backoff.test.ts +87 -0
- package/src/__tests__/runtime-events-sse.test.ts +2 -2
- package/src/__tests__/sanitize-config-for-transfer.test.ts +24 -2
- package/src/__tests__/schedule-retry.test.ts +715 -0
- package/src/__tests__/scheduler-disk-pressure.test.ts +148 -0
- package/src/__tests__/script-proxy-mitm-handler.test.ts +1 -1
- package/src/__tests__/secret-ingress-http.test.ts +1 -1
- package/src/__tests__/send-endpoint-busy.test.ts +3 -0
- package/src/__tests__/shell-tool-proxy-mode.test.ts +0 -1
- package/src/__tests__/skill-feature-flags.test.ts +43 -41
- package/src/__tests__/skill-load-feature-flag.test.ts +13 -14
- package/src/__tests__/skill-load-inline-command.test.ts +0 -51
- package/src/__tests__/skill-load-inline-includes.test.ts +0 -43
- package/src/__tests__/skill-projection.benchmark.test.ts +0 -1
- package/src/__tests__/skill-script-runner-sandbox.test.ts +0 -1
- package/src/__tests__/slack-channel-config.test.ts +9 -14
- package/src/__tests__/suggestion-routes.test.ts +46 -0
- package/src/__tests__/system-prompt-ask-mode.test.ts +0 -1
- package/src/__tests__/system-prompt.test.ts +0 -1
- package/src/__tests__/telegram-config.test.ts +0 -1
- package/src/__tests__/test-preload.ts +8 -0
- package/src/__tests__/tool-approval-handler.test.ts +3 -4
- package/src/__tests__/tool-audit-listener.test.ts +48 -0
- package/src/__tests__/tool-execute-pipeline.test.ts +0 -1
- package/src/__tests__/tool-execution-abort-cleanup.test.ts +0 -1
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +0 -1
- package/src/__tests__/tool-executor.test.ts +0 -1
- package/src/__tests__/twilio-config.test.ts +3 -16
- package/src/__tests__/twilio-routes.test.ts +3 -5
- package/src/__tests__/twilio-validation.test.ts +93 -0
- package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +1 -4
- package/src/__tests__/verification-control-plane-policy.test.ts +2 -4
- package/src/__tests__/voice-ingress-preflight.test.ts +19 -0
- package/src/__tests__/workspace-migration-006-services-config.test.ts +3 -2
- package/src/__tests__/workspace-migration-065-bump-stale-heartbeat-interval.test.ts +122 -0
- package/src/__tests__/workspace-migration-066-seed-heartbeat-callsite-cost-default.test.ts +285 -0
- package/src/__tests__/workspace-migration-068-release-notes-local-timezone.test.ts +90 -0
- package/src/__tests__/workspace-migration-backfill-installation-id.test.ts +1 -5
- package/src/__tests__/workspace-migration-down-functions.test.ts +8 -8
- package/src/__tests__/workspace-migration-safe-storage-limits-release.test.ts +90 -0
- package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +10 -6
- package/src/approvals/guardian-decision-primitive.ts +13 -0
- package/src/approvals/guardian-request-resolvers.ts +16 -17
- package/src/backup/__tests__/paths.test.ts +0 -22
- package/src/backup/__tests__/restore.test.ts +51 -151
- package/src/backup/paths.ts +2 -18
- package/src/backup/restore.ts +107 -231
- package/src/backup/snapshot-lock.ts +2 -27
- package/src/bundler/app-bundler.ts +51 -3
- package/src/bundler/compiler-tools.ts +3 -2
- package/src/calls/call-conversation-messages.ts +46 -10
- package/src/calls/relay-server.ts +4 -44
- package/src/calls/twilio-config.ts +2 -17
- package/src/calls/twilio-rest.ts +33 -105
- package/src/calls/twilio-routes.ts +11 -12
- package/src/channels/types.ts +8 -7
- package/src/cli/commands/__tests__/backup.test.ts +6 -277
- package/src/cli/commands/__tests__/gateway.test.ts +288 -0
- package/src/cli/commands/__tests__/memory-v2.test.ts +4 -0
- package/src/cli/commands/__tests__/webhooks.test.ts +0 -5
- package/src/cli/commands/backup.ts +6 -331
- package/src/cli/commands/bash.ts +35 -108
- package/src/cli/commands/clients.ts +36 -37
- package/src/cli/commands/contacts.ts +137 -25
- package/src/cli/commands/conversations.ts +2 -5
- package/src/cli/commands/credentials.ts +71 -7
- package/src/cli/commands/domain.ts +66 -15
- package/src/cli/commands/gateway.ts +183 -0
- package/src/cli/commands/keys.ts +9 -6
- package/src/cli/commands/mcp.ts +116 -156
- package/src/cli/commands/memory-v2.ts +303 -7
- package/src/cli/commands/oauth/__tests__/connect.test.ts +437 -1
- package/src/cli/commands/oauth/connect.ts +127 -1
- package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +0 -4
- package/src/cli/commands/platform/__tests__/connect.test.ts +7 -3
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +7 -3
- package/src/cli/commands/platform/__tests__/status.test.ts +116 -21
- package/src/cli/commands/platform/disconnect.ts +5 -4
- package/src/cli/commands/platform/index.ts +16 -25
- package/src/cli/commands/status.ts +57 -0
- package/src/cli/lib/daemon-credential-client.ts +110 -28
- package/src/cli/program.ts +6 -2
- package/src/config/assistant-feature-flags.ts +79 -12
- package/src/config/bundled-skills/acp/SKILL.md +6 -0
- package/src/config/bundled-skills/acp/TOOLS.json +1 -22
- package/src/config/bundled-skills/app-builder/SKILL.md +14 -109
- package/src/config/bundled-skills/app-builder/TOOLS.json +1 -28
- package/src/config/bundled-skills/app-builder/tools/app-create.ts +1 -10
- package/src/config/bundled-skills/app-control/SKILL.md +75 -0
- package/src/config/bundled-skills/app-control/TOOLS.json +299 -0
- package/src/config/bundled-skills/app-control/tools/app-control-click.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-combo.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-drag.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-observe.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-press.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-sequence.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-start.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-stop.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-type.ts +12 -0
- package/src/config/bundled-skills/computer-use/SKILL.md +6 -0
- package/src/config/bundled-skills/computer-use/TOOLS.json +67 -43
- package/src/config/bundled-skills/contacts/TOOLS.json +0 -16
- package/src/config/bundled-skills/document/TOOLS.json +0 -8
- package/src/config/bundled-skills/followups/TOOLS.json +0 -12
- package/src/config/bundled-skills/image-studio/SKILL.md +4 -0
- package/src/config/bundled-skills/image-studio/TOOLS.json +0 -4
- package/src/config/bundled-skills/media-processing/TOOLS.json +0 -24
- package/src/config/bundled-skills/messaging/TOOLS.json +0 -40
- package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +4 -3
- package/src/config/bundled-skills/phone-calls/TOOLS.json +0 -12
- package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +25 -4
- package/src/config/bundled-skills/playbooks/TOOLS.json +0 -16
- package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +2 -2
- package/src/config/bundled-skills/playbooks/tools/playbook-delete.ts +2 -2
- package/src/config/bundled-skills/playbooks/tools/playbook-list.ts +2 -2
- package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +2 -2
- package/src/config/bundled-skills/schedule/TOOLS.json +14 -14
- package/src/config/bundled-skills/sequences/TOOLS.json +0 -36
- package/src/config/bundled-skills/settings/SKILL.md +4 -0
- package/src/config/bundled-skills/settings/TOOLS.json +0 -12
- package/src/config/bundled-skills/skill-management/SKILL.md +6 -0
- package/src/config/bundled-skills/skill-management/TOOLS.json +0 -8
- package/src/config/bundled-skills/subagent/SKILL.md +6 -2
- package/src/config/bundled-skills/subagent/TOOLS.json +0 -20
- package/src/config/bundled-skills/transcribe/SKILL.md +4 -0
- package/src/config/bundled-skills/transcribe/TOOLS.json +0 -4
- package/src/config/bundled-tool-registry.ts +21 -0
- package/src/config/env-registry.ts +0 -2
- package/src/config/env.ts +19 -20
- package/src/config/feature-flag-registry.json +47 -135
- package/src/config/loader.ts +197 -104
- package/src/config/sanitize-for-transfer.ts +2 -0
- package/src/config/schemas/__tests__/memory-lifecycle.test.ts +80 -0
- package/src/config/schemas/__tests__/memory-v2.test.ts +17 -9
- package/src/config/schemas/call-site-catalog.ts +14 -0
- package/src/config/schemas/calls.ts +0 -9
- package/src/config/schemas/channels.ts +0 -5
- package/src/config/schemas/heartbeat.ts +64 -1
- package/src/config/schemas/ingress.ts +10 -6
- package/src/config/schemas/llm.ts +7 -10
- package/src/config/schemas/memory-lifecycle.ts +90 -24
- package/src/config/schemas/memory-v2.ts +121 -13
- package/src/config/schemas/platform.ts +49 -3
- package/src/config/schemas/services.ts +29 -15
- package/src/config/schemas/skills.ts +0 -6
- package/src/config/seed-inference-profiles.ts +230 -33
- package/src/contacts/contact-store.ts +0 -55
- package/src/contacts/contacts-write.ts +0 -27
- package/src/context/window-manager.ts +1 -2
- package/src/credential-execution/feature-gates.ts +10 -10
- package/src/credential-execution/process-manager.ts +12 -41
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +187 -5
- package/src/daemon/assistant-attachments.ts +4 -4
- package/src/daemon/bootstrap-turn-cleanup.ts +45 -0
- package/src/daemon/config-watcher.ts +89 -60
- package/src/daemon/conversation-agent-loop-handlers.ts +27 -3
- package/src/daemon/conversation-agent-loop.ts +202 -61
- package/src/daemon/conversation-error.ts +87 -15
- package/src/daemon/conversation-lifecycle.ts +9 -4
- package/src/daemon/conversation-process.ts +24 -11
- package/src/daemon/conversation-runtime-assembly.ts +28 -2
- package/src/daemon/conversation-store.ts +2 -2
- package/src/daemon/conversation-surfaces.ts +305 -4
- package/src/daemon/conversation-tool-setup.ts +66 -62
- package/src/daemon/conversation.ts +38 -24
- package/src/daemon/date-context.ts +71 -22
- package/src/daemon/disk-pressure-background-gate.ts +73 -0
- package/src/daemon/disk-pressure-guard.ts +343 -0
- package/src/daemon/disk-pressure-policy.ts +163 -0
- package/src/daemon/doordash-steps.ts +1 -1
- package/src/daemon/handlers/shared.ts +4 -2
- package/src/daemon/handlers/skills.ts +3 -4
- package/src/daemon/host-app-control-proxy.ts +389 -0
- package/src/daemon/host-bash-proxy.ts +117 -82
- package/src/daemon/host-browser-proxy.ts +67 -82
- package/src/daemon/host-cu-proxy.ts +127 -86
- package/src/daemon/host-file-proxy.ts +129 -69
- package/src/daemon/host-proxy-base.ts +294 -0
- package/src/daemon/host-proxy-preactivation.ts +82 -0
- package/src/daemon/host-transfer-proxy.ts +338 -129
- package/src/daemon/lifecycle.ts +194 -145
- package/src/daemon/meet-host-supervisor.ts +4 -4
- package/src/daemon/meet-manifest-loader.ts +0 -1
- package/src/daemon/memory-v2-startup.ts +14 -4
- package/src/daemon/message-protocol.ts +6 -8
- package/src/daemon/message-types/contacts.ts +23 -1
- package/src/daemon/message-types/conversations.ts +15 -8
- package/src/daemon/message-types/disk-pressure.ts +9 -0
- package/src/daemon/message-types/host-app-control.ts +150 -0
- package/src/daemon/message-types/host-bash.ts +4 -0
- package/src/daemon/message-types/host-cu.ts +2 -0
- package/src/daemon/message-types/host-file.ts +4 -0
- package/src/daemon/message-types/host-transfer.ts +3 -0
- package/src/daemon/message-types/messages.ts +3 -0
- package/src/daemon/message-types/schedules.ts +8 -3
- package/src/daemon/message-types/skills.ts +2 -2
- package/src/daemon/process-message.ts +18 -1
- package/src/daemon/profiler-run-store.ts +5 -5
- package/src/daemon/shutdown-handlers.ts +0 -3
- package/src/daemon/tool-setup-types.ts +51 -0
- package/src/daemon/tool-side-effects.ts +1 -1
- package/src/documents/document-store.ts +85 -0
- package/src/events/tool-audit-listener.ts +2 -1
- package/src/filing/filing-service.ts +30 -5
- package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +24 -23
- package/src/heartbeat/__tests__/heartbeat-run-store.test.ts +252 -0
- package/src/heartbeat/heartbeat-run-store.ts +249 -0
- package/src/heartbeat/heartbeat-service.ts +459 -54
- package/src/home/__tests__/post-connect-feed.test.ts +99 -0
- package/src/home/__tests__/relationship-state-writer.test.ts +11 -9
- package/src/home/__tests__/suggested-prompts.test.ts +89 -0
- package/src/home/feed-scheduler.ts +18 -0
- package/src/home/post-connect-feed.ts +68 -0
- package/src/home/relationship-state-writer.ts +17 -92
- package/src/home/suggested-prompts.ts +46 -10
- package/src/inbound/platform-callback-registration.ts +8 -15
- package/src/inbound/public-ingress-urls.ts +32 -34
- package/src/ipc/__tests__/clients-list-ipc.test.ts +169 -0
- package/src/ipc/__tests__/route-error-envelope.test.ts +80 -0
- package/src/ipc/assistant-server.ts +70 -3
- package/src/ipc/cli-client.ts +32 -1
- package/src/ipc/gateway-client.ts +37 -3
- package/src/live-voice/live-voice-archive.ts +4 -4
- package/src/live-voice/live-voice-metrics.ts +10 -10
- package/src/live-voice/protocol.ts +5 -7
- package/src/mcp/__tests__/mcp-auth-orchestrator.test.ts +304 -0
- package/src/mcp/mcp-auth-orchestrator.ts +213 -0
- package/src/mcp/mcp-auth-state.ts +133 -0
- package/src/mcp/mcp-oauth-provider.ts +19 -0
- package/src/media/image-service.ts +1 -7
- package/src/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +21 -13
- package/src/memory/__tests__/jobs-store-job-classes.test.ts +24 -0
- package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +52 -22
- package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +0 -6
- package/src/memory/__tests__/memory-v2-concept-frequency.test.ts +272 -0
- package/src/memory/__tests__/qdrant-client-sentinel.test.ts +49 -0
- package/src/memory/__tests__/sparse-tokenize.test.ts +66 -0
- package/src/memory/admin.ts +5 -9
- package/src/memory/anisotropy.test.ts +247 -0
- package/src/memory/anisotropy.ts +443 -0
- package/src/memory/auto-analysis-constants.ts +17 -0
- package/src/memory/auto-analysis-guard.ts +5 -15
- package/src/memory/canonical-guardian-store.ts +7 -7
- package/src/memory/context-search/__tests__/agent-runner-redaction.test.ts +122 -0
- package/src/memory/context-search/agent-protocol.ts +6 -6
- package/src/memory/context-search/agent-runner.ts +51 -9
- package/src/memory/context-search/sources/conversations.ts +2 -11
- package/src/memory/context-search/sources/memory-v2.ts +22 -9
- package/src/memory/context-search/sources/memory.ts +0 -1
- package/src/memory/context-search/types.ts +0 -1
- package/src/memory/conversation-crud.ts +5 -13
- package/src/memory/conversation-key-store.ts +2 -15
- package/src/memory/db-init.ts +6 -0
- package/src/memory/embedding-backend.ts +9 -21
- package/src/memory/embedding-runtime-manager.ts +119 -5
- package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +81 -25
- package/src/memory/graph/conversation-graph-memory.ts +43 -78
- package/src/memory/graph/extraction.ts +1 -3
- package/src/memory/graph/graph-search.test.ts +10 -67
- package/src/memory/graph/graph-search.ts +9 -20
- package/src/memory/graph/retriever.test.ts +6 -0
- package/src/memory/graph/retriever.ts +34 -10
- package/src/memory/graph/tools.ts +1 -1
- package/src/memory/indexer.ts +54 -45
- package/src/memory/job-handlers/backfill.ts +2 -11
- package/src/memory/job-handlers/cleanup.ts +43 -0
- package/src/memory/job-handlers/embedding.ts +6 -8
- package/src/memory/job-handlers/summarization.ts +2 -7
- package/src/memory/jobs/__tests__/embed-concept-page.test.ts +8 -2
- package/src/memory/jobs/embed-concept-page.ts +28 -2
- package/src/memory/jobs/embed-pkb-file.test.ts +2 -2
- package/src/memory/jobs-store.ts +114 -22
- package/src/memory/jobs-worker.ts +193 -106
- package/src/memory/memory-v2-activation-log-store.ts +33 -15
- package/src/memory/memory-v2-concept-frequency.ts +169 -0
- package/src/memory/migrations/237-heartbeat-runs.ts +45 -0
- package/src/memory/migrations/238-schedule-retry-policy.ts +20 -0
- package/src/memory/migrations/239-trace-events-created-at-index.ts +18 -0
- package/src/memory/migrations/index.ts +6 -0
- package/src/memory/migrations/registry.ts +8 -0
- package/src/memory/pkb/pkb-search.test.ts +6 -0
- package/src/memory/pkb/pkb-search.ts +7 -0
- package/src/memory/qdrant-client.ts +49 -32
- package/src/memory/rerank-local.ts +374 -0
- package/src/memory/schema/infrastructure.ts +15 -0
- package/src/memory/search/semantic.ts +13 -67
- package/src/memory/sparse-tokenize.ts +49 -0
- package/src/memory/trace-event-store.ts +1 -17
- package/src/memory/v2/__tests__/activation.test.ts +387 -344
- package/src/memory/v2/__tests__/consolidation-job.test.ts +40 -8
- package/src/memory/v2/__tests__/injection.test.ts +181 -169
- package/src/memory/v2/__tests__/prompts-consolidation.test.ts +61 -2
- package/src/memory/v2/__tests__/qdrant.test.ts +16 -0
- package/src/memory/v2/__tests__/reranker.test.ts +338 -0
- package/src/memory/v2/__tests__/sim.test.ts +154 -188
- package/src/memory/v2/__tests__/skill-store.test.ts +71 -65
- package/src/memory/v2/__tests__/sparse-bm25.test.ts +292 -0
- package/src/memory/v2/__tests__/static-context.test.ts +76 -2
- package/src/memory/v2/activation.ts +213 -239
- package/src/memory/v2/consolidation-job.ts +65 -17
- package/src/memory/v2/constants.ts +7 -0
- package/src/memory/v2/injection.ts +123 -103
- package/src/memory/v2/prompts/consolidation.ts +348 -92
- package/src/memory/v2/qdrant.ts +198 -1
- package/src/memory/v2/reranker.ts +177 -0
- package/src/memory/v2/sim.ts +113 -77
- package/src/memory/v2/skill-content.ts +4 -3
- package/src/memory/v2/skill-store.ts +91 -53
- package/src/memory/v2/sparse-bm25.ts +245 -0
- package/src/memory/v2/static-context.ts +28 -5
- package/src/memory/v2/types.ts +10 -10
- package/src/messaging/providers/gmail/types.ts +0 -49
- package/src/messaging/providers/slack/adapter.ts +1 -31
- package/src/messaging/providers/slack/types.ts +0 -32
- package/src/notifications/README.md +10 -10
- package/src/notifications/broadcaster.ts +1 -1
- package/src/notifications/copy-composer.ts +13 -0
- package/src/notifications/guardian-question-mode.ts +5 -5
- package/src/notifications/signal.ts +4 -0
- package/src/oauth/AGENTS.md +3 -1
- package/src/oauth/__tests__/oauth-connect-state.test.ts +137 -0
- package/src/oauth/connect-orchestrator.ts +6 -0
- package/src/oauth/connection-resolver.test.ts +66 -1
- package/src/oauth/connection-resolver.ts +55 -1
- package/src/oauth/credential-token-resolver.ts +1 -3
- package/src/oauth/manual-token-connection.ts +0 -4
- package/src/oauth/oauth-connect-state.ts +77 -0
- package/src/oauth/seed-providers.ts +58 -1
- package/src/outbound-proxy/index.ts +1 -37
- package/src/outbound-proxy/logging.ts +1 -1
- package/src/outbound-proxy/policy.ts +6 -5
- package/src/outbound-proxy/router.ts +2 -1
- package/src/permissions/approval-policy.test.ts +6 -275
- package/src/permissions/approval-policy.ts +0 -51
- package/src/permissions/checker.test.ts +0 -1
- package/src/permissions/checker.ts +3 -17
- package/src/permissions/gateway-threshold-reader.ts +2 -0
- package/src/permissions/prompter.ts +34 -1
- package/src/permissions/secret-prompter.ts +6 -2
- package/src/plugins/defaults/injectors.ts +35 -2
- package/src/plugins/defaults/memory-retrieval.ts +5 -6
- package/src/plugins/types.ts +7 -0
- package/src/proactive-artifact/aux-message-injector.ts +74 -0
- package/src/proactive-artifact/decision.test.ts +226 -0
- package/src/proactive-artifact/decision.ts +165 -0
- package/src/proactive-artifact/index.ts +7 -0
- package/src/proactive-artifact/job.test.ts +867 -0
- package/src/proactive-artifact/job.ts +352 -0
- package/src/proactive-artifact/message-copy.ts +41 -0
- package/src/proactive-artifact/trigger-state.test.ts +277 -0
- package/src/proactive-artifact/trigger-state.ts +119 -0
- package/src/prompts/bootstrap-cleanup.ts +27 -0
- package/src/prompts/normalize-onboarding.ts +80 -0
- package/src/prompts/persona-resolver.ts +101 -9
- package/src/prompts/system-prompt.ts +23 -24
- package/src/prompts/templates/BOOTSTRAP.md +13 -5
- package/src/prompts/templates/SOUL.md +13 -1
- package/src/providers/__tests__/retry-callsite.test.ts +222 -1
- package/src/providers/model-intents.ts +7 -0
- package/src/providers/openrouter/client.ts +8 -0
- package/src/providers/retry.ts +50 -0
- package/src/providers/speech-to-text/provider-catalog.ts +7 -8
- package/src/providers/types.ts +1 -0
- package/src/runtime/__tests__/agent-wake.test.ts +456 -3
- package/src/runtime/agent-wake.ts +238 -100
- package/src/runtime/assistant-event-hub.ts +151 -99
- package/src/runtime/auth/__tests__/middleware.test.ts +11 -56
- package/src/runtime/auth/__tests__/route-policy.test.ts +64 -0
- package/src/runtime/auth/middleware.ts +0 -96
- package/src/runtime/auth/route-policy.ts +32 -0
- package/src/runtime/auth/same-actor.ts +216 -0
- package/src/runtime/btw-sidechain.ts +2 -3
- package/src/runtime/channel-invite-transport.ts +2 -48
- package/src/runtime/channel-invite-transports/email.ts +1 -1
- package/src/runtime/channel-invite-transports/slack.ts +1 -1
- package/src/runtime/channel-invite-transports/telegram.ts +1 -1
- package/src/runtime/channel-invite-transports/voice.ts +1 -1
- package/src/runtime/channel-invite-transports/whatsapp.ts +1 -1
- package/src/runtime/channel-invite-types.ts +54 -0
- package/src/runtime/channel-readiness-service.ts +32 -13
- package/src/runtime/channel-retry-sweep.ts +65 -1
- package/src/runtime/guardian-reply-router.ts +10 -0
- package/src/runtime/http-server.ts +3 -329
- package/src/runtime/http-types.ts +0 -5
- package/src/runtime/local-actor-identity.ts +52 -11
- package/src/runtime/migrations/__tests__/vbundle-import-parity.test.ts +413 -0
- package/src/runtime/migrations/__tests__/vbundle-import-policy.test.ts +260 -0
- package/src/runtime/migrations/__tests__/vbundle-import-version-compat.test.ts +189 -0
- package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +153 -1
- package/src/runtime/migrations/__tests__/vbundle-symlink-importer.test.ts +451 -0
- package/src/runtime/migrations/__tests__/vbundle-symlink-streaming-importer.test.ts +0 -0
- package/src/runtime/migrations/__tests__/vbundle-symlink-streaming.test.ts +515 -0
- package/src/runtime/migrations/__tests__/vbundle-symlink-tar.test.ts +437 -0
- package/src/runtime/migrations/__tests__/vbundle-symlink-walker.test.ts +319 -0
- package/src/runtime/migrations/__tests__/vbundle-validator-v1-schema.test.ts +51 -1
- package/src/runtime/migrations/migration-transport.ts +7 -7
- package/src/runtime/migrations/vbundle-builder.ts +327 -60
- package/src/runtime/migrations/vbundle-import-analyzer.ts +4 -4
- package/src/runtime/migrations/vbundle-import-policy.ts +172 -0
- package/src/runtime/migrations/vbundle-importer.ts +245 -68
- package/src/runtime/migrations/vbundle-streaming-importer.ts +326 -35
- package/src/runtime/migrations/vbundle-streaming-validator.ts +157 -4
- package/src/runtime/migrations/vbundle-tar-stream.ts +15 -6
- package/src/runtime/migrations/vbundle-validator.ts +114 -0
- package/src/runtime/pending-interactions.ts +43 -9
- package/src/runtime/routes/__tests__/backup-routes.test.ts +22 -150
- package/src/runtime/routes/__tests__/client-routes.test.ts +155 -0
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +98 -5
- package/src/runtime/routes/__tests__/gateway-log-routes.test.ts +242 -0
- package/src/runtime/routes/__tests__/heartbeat-routes.test.ts +112 -0
- package/src/runtime/routes/approval-interception-types.ts +13 -0
- package/src/runtime/routes/approval-strategies/guardian-text-engine-strategy.ts +1 -1
- package/src/runtime/routes/backup-routes.ts +15 -38
- package/src/runtime/routes/btw-routes.ts +14 -37
- package/src/runtime/routes/client-routes.ts +21 -2
- package/src/runtime/routes/contact-prompt-routes.ts +183 -0
- package/src/runtime/routes/contact-routes.ts +0 -25
- package/src/runtime/routes/conversation-query-routes.ts +36 -1
- package/src/runtime/routes/conversation-routes.ts +65 -39
- package/src/runtime/routes/debug-bash-routes.ts +163 -0
- package/src/runtime/routes/disk-pressure-routes.ts +121 -0
- package/src/runtime/routes/document-pdf-renderer.ts +169 -0
- package/src/runtime/routes/documents-routes.ts +32 -75
- package/src/runtime/routes/errors.ts +19 -4
- package/src/runtime/routes/events-routes.ts +38 -0
- package/src/runtime/routes/gateway-log-routes.ts +79 -0
- package/src/runtime/routes/guardian-approval-interception.ts +2 -8
- package/src/runtime/routes/heartbeat-routes.ts +103 -38
- package/src/runtime/routes/host-app-control-routes.ts +134 -0
- package/src/runtime/routes/host-bash-routes.ts +56 -6
- package/src/runtime/routes/host-browser-routes.ts +108 -13
- package/src/runtime/routes/host-cu-routes.ts +66 -9
- package/src/runtime/routes/host-file-routes.ts +54 -5
- package/src/runtime/routes/host-transfer-routes.ts +122 -19
- package/src/runtime/routes/http-adapter.ts +1 -0
- package/src/runtime/routes/identity-intro-cache.ts +30 -0
- package/src/runtime/routes/identity-routes.ts +21 -180
- package/src/runtime/routes/inbound-message-handler.ts +78 -21
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +0 -7
- package/src/runtime/routes/inbound-stages/edit-intercept.ts +0 -8
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +3 -0
- package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +0 -20
- package/src/runtime/routes/inbound-stages/transcribe-audio.ts +5 -13
- package/src/runtime/routes/index.ts +14 -0
- package/src/runtime/routes/mcp-auth-routes.ts +132 -0
- package/src/runtime/routes/memory-item-routes.test.ts +41 -15
- package/src/runtime/routes/memory-item-routes.ts +10 -12
- package/src/runtime/routes/memory-v2-routes.ts +474 -1
- package/src/runtime/routes/migration-routes.ts +96 -0
- package/src/runtime/routes/oauth-connect-routes.ts +153 -0
- package/src/runtime/routes/schedule-routes.ts +7 -0
- package/src/runtime/verification-outbound-actions.ts +4 -4
- package/src/runtime/verification-templates.ts +4 -7
- package/src/schedule/integration-status.ts +66 -2
- package/src/schedule/recurrence-engine.ts +4 -1
- package/src/schedule/retry-backoff.ts +18 -0
- package/src/schedule/retry-policy.ts +82 -0
- package/src/schedule/run-script.ts +37 -5
- package/src/schedule/schedule-recovery.ts +64 -0
- package/src/schedule/schedule-store.ts +106 -2
- package/src/schedule/scheduler-types.ts +25 -0
- package/src/schedule/scheduler.ts +83 -39
- package/src/security/encrypted-store.ts +2 -0
- package/src/security/oauth-callback-registry.ts +8 -0
- package/src/security/secure-keys.ts +55 -0
- package/src/sequence/analytics.ts +5 -5
- package/src/sequence/engine.ts +1 -1
- package/src/skills/catalog-files.ts +2 -8
- package/src/skills/include-graph.ts +5 -5
- package/src/skills/remote-skill-policy.ts +10 -16
- package/src/skills/skill-file-provider.ts +1 -1
- package/src/skills/skill-file-types.ts +13 -0
- package/src/skills/skillssh-audit-types.ts +28 -0
- package/src/skills/skillssh-registry.ts +8 -21
- package/src/subagent/index.ts +1 -7
- package/src/subagent/manager.ts +1 -15
- package/src/tasks/task-runner.ts +0 -1
- package/src/tasks/task-store.ts +0 -3
- package/src/telemetry/types.ts +2 -0
- package/src/telemetry/usage-telemetry-reporter.test.ts +21 -0
- package/src/telemetry/usage-telemetry-reporter.ts +1 -0
- package/src/tools/app-control/skill-proxy-bridge.ts +28 -0
- package/src/tools/apps/executors.ts +56 -69
- package/src/tools/background-tool-registry.ts +17 -3
- package/src/tools/browser/__tests__/browser-status.test.ts +21 -18
- package/src/tools/browser/browser-execution.ts +2 -2
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +55 -4
- package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +12 -6
- package/src/tools/browser/cdp-client/factory.ts +23 -24
- package/src/tools/browser/cdp-client/index.ts +1 -14
- package/src/tools/computer-use/definitions.ts +42 -20
- package/src/tools/executor.ts +2 -0
- package/src/tools/host-filesystem/edit.test.ts +151 -0
- package/src/tools/host-filesystem/edit.ts +68 -0
- package/src/tools/host-filesystem/read.test.ts +129 -0
- package/src/tools/host-filesystem/read.ts +68 -0
- package/src/tools/host-filesystem/transfer.test.ts +127 -2
- package/src/tools/host-filesystem/transfer.ts +78 -3
- package/src/tools/host-filesystem/write.test.ts +134 -0
- package/src/tools/host-filesystem/write.ts +68 -0
- package/src/tools/host-terminal/host-shell.ts +66 -1
- package/src/tools/mcp/mcp-tool-factory.ts +2 -1
- package/src/tools/memory/register.test.ts +12 -9
- package/src/tools/memory/register.ts +1 -2
- package/src/tools/provider-tool-name.ts +28 -0
- package/src/tools/registry.ts +30 -9
- package/src/tools/schedule/create.ts +6 -0
- package/src/tools/schedule/list.ts +2 -0
- package/src/tools/schedule/update.ts +10 -0
- package/src/tools/shared/filesystem/file-ops-service.ts +2 -0
- package/src/tools/shared/filesystem/path-policy.ts +25 -1
- package/src/tools/skills/load.ts +0 -32
- package/src/tools/terminal/shell.ts +9 -1
- package/src/tools/tool-approval-handler.ts +32 -11
- package/src/tools/types.ts +28 -2
- package/src/tts/provider-catalog.ts +3 -5
- package/src/usage/pricing.ts +1 -1
- package/src/util/disk-usage.ts +138 -0
- package/src/util/platform.ts +21 -11
- package/src/util/process-liveness.ts +26 -0
- package/src/workspace/hatched-date.ts +86 -0
- package/src/workspace/heartbeat-service.ts +19 -0
- package/src/workspace/migrations/003-seed-device-id.ts +1 -1
- package/src/workspace/migrations/006-services-config.ts +8 -5
- package/src/workspace/migrations/016-extract-feature-flags-to-protected.ts +3 -9
- package/src/workspace/migrations/021-move-signals-to-workspace.ts +4 -10
- package/src/workspace/migrations/022-move-hooks-to-workspace.ts +4 -10
- package/src/workspace/migrations/023-move-config-files-to-workspace.ts +4 -11
- package/src/workspace/migrations/024-move-runtime-files-to-workspace.ts +3 -10
- package/src/workspace/migrations/040-seed-latency-callsite-defaults.ts +3 -2
- package/src/workspace/migrations/050-seed-main-agent-opus-callsite.ts +2 -1
- package/src/workspace/migrations/059-move-pid-to-workspace.ts +3 -8
- package/src/workspace/migrations/061-move-backup-key-to-workspace.ts +3 -8
- package/src/workspace/migrations/065-bump-stale-heartbeat-interval.ts +60 -0
- package/src/workspace/migrations/066-seed-heartbeat-callsite-cost-default.ts +146 -0
- package/src/workspace/migrations/067-release-notes-safe-storage-limits.ts +72 -0
- package/src/workspace/migrations/068-release-notes-local-timezone.ts +65 -0
- package/src/workspace/migrations/AGENTS.md +1 -1
- package/src/workspace/migrations/migrate-to-workspace-volume.ts +4 -10
- package/src/workspace/migrations/registry.ts +8 -0
- package/src/workspace/migrations/utils.ts +21 -0
- package/src/__tests__/conversation-tool-setup-memory-scope.test.ts +0 -167
- package/src/__tests__/host-browser-e2e-cloud.test.ts +0 -443
- package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +0 -226
- package/src/__tests__/host-browser-ws-events-e2e.test.ts +0 -427
- package/src/__tests__/twilio-rest.test.ts +0 -34
- package/src/backup/__tests__/backup-key.test.ts +0 -152
- package/src/backup/__tests__/backup-worker.test.ts +0 -782
- package/src/backup/__tests__/offsite-writer.test.ts +0 -641
- package/src/backup/__tests__/stream-crypt.test.ts +0 -228
- package/src/backup/backup-key.ts +0 -137
- package/src/backup/backup-worker.ts +0 -472
- package/src/backup/offsite-writer.ts +0 -222
- package/src/backup/stream-crypt.ts +0 -263
- package/src/daemon/message-types/pairing.ts +0 -58
- package/src/memory/v2/__tests__/skill-qdrant.test.ts +0 -657
- package/src/memory/v2/skill-qdrant.ts +0 -395
- package/src/outbound-proxy/config.ts +0 -20
- package/src/outbound-proxy/health.ts +0 -18
- package/src/outbound-proxy/types.ts +0 -150
- package/src/runtime/capability-tokens.ts +0 -190
- package/src/signals/bash.ts +0 -198
- package/src/signals/mcp-reload.ts +0 -18
|
@@ -45,25 +45,28 @@ mock.module("../../../util/logger.js", () => ({
|
|
|
45
45
|
|
|
46
46
|
// Stub the v1 retriever so we don't reach Qdrant. Both modes return zero
|
|
47
47
|
// nodes — the v1 injection branch becomes a no-op, isolating the assertion
|
|
48
|
-
// to "did the v2 routing fire?".
|
|
48
|
+
// to "did the v2 routing fire?". Tracked via `mock()` so tests can also
|
|
49
|
+
// assert that v1 retrieval is *not* called when v2 is enabled.
|
|
50
|
+
const loadContextMemoryMock = mock(async () => ({
|
|
51
|
+
nodes: [],
|
|
52
|
+
serendipityNodes: [],
|
|
53
|
+
latencyMs: 1,
|
|
54
|
+
metrics: null,
|
|
55
|
+
queryVector: undefined,
|
|
56
|
+
sparseVector: undefined,
|
|
57
|
+
userQueryVector: undefined,
|
|
58
|
+
userQuerySparseVector: undefined,
|
|
59
|
+
}));
|
|
60
|
+
const retrieveForTurnMock = mock(async () => ({
|
|
61
|
+
nodes: [],
|
|
62
|
+
latencyMs: 1,
|
|
63
|
+
metrics: null,
|
|
64
|
+
queryVector: undefined,
|
|
65
|
+
sparseVector: undefined,
|
|
66
|
+
}));
|
|
49
67
|
mock.module("../retriever.js", () => ({
|
|
50
|
-
loadContextMemory:
|
|
51
|
-
|
|
52
|
-
serendipityNodes: [],
|
|
53
|
-
latencyMs: 1,
|
|
54
|
-
metrics: null,
|
|
55
|
-
queryVector: undefined,
|
|
56
|
-
sparseVector: undefined,
|
|
57
|
-
userQueryVector: undefined,
|
|
58
|
-
userQuerySparseVector: undefined,
|
|
59
|
-
}),
|
|
60
|
-
retrieveForTurn: async () => ({
|
|
61
|
-
nodes: [],
|
|
62
|
-
latencyMs: 1,
|
|
63
|
-
metrics: null,
|
|
64
|
-
queryVector: undefined,
|
|
65
|
-
sparseVector: undefined,
|
|
66
|
-
}),
|
|
68
|
+
loadContextMemory: loadContextMemoryMock,
|
|
69
|
+
retrieveForTurn: retrieveForTurnMock,
|
|
67
70
|
}));
|
|
68
71
|
|
|
69
72
|
// Programmable embedding + Qdrant state. Mirrors the pattern in
|
|
@@ -232,7 +235,7 @@ function makeMemory(): InstanceType<typeof ConversationGraphMemory> {
|
|
|
232
235
|
// `initialized = true` skips the context-load branch and the
|
|
233
236
|
// `fetchRecentSummaries` DB read it depends on, isolating the per-turn path
|
|
234
237
|
// for these unit tests. Context-load is covered by its own block below.
|
|
235
|
-
const m = new ConversationGraphMemory("
|
|
238
|
+
const m = new ConversationGraphMemory("conv-test-1");
|
|
236
239
|
(m as unknown as { initialized: boolean }).initialized = true;
|
|
237
240
|
return m;
|
|
238
241
|
}
|
|
@@ -262,6 +265,8 @@ beforeEach(() => {
|
|
|
262
265
|
testDbHandle = createTestDb();
|
|
263
266
|
qdrantState.queryResponses.dense.length = 0;
|
|
264
267
|
qdrantState.queryResponses.sparse.length = 0;
|
|
268
|
+
loadContextMemoryMock.mockClear();
|
|
269
|
+
retrieveForTurnMock.mockClear();
|
|
265
270
|
_resetMemoryV2QdrantForTests();
|
|
266
271
|
});
|
|
267
272
|
|
|
@@ -333,16 +338,57 @@ describe("ConversationGraphMemory.prepareMemory — v2 routing (per-turn path)",
|
|
|
333
338
|
|
|
334
339
|
expect(result.mode).toBe("per-turn");
|
|
335
340
|
expect(result.injectedBlockText).not.toBeNull();
|
|
336
|
-
expect(result.injectedBlockText).toContain("<memory>");
|
|
341
|
+
expect(result.injectedBlockText).not.toContain("<memory>");
|
|
337
342
|
expect(result.injectedBlockText).toContain("### alice-vscode");
|
|
338
343
|
|
|
339
|
-
// The leading content block on the user message is the v2 block
|
|
344
|
+
// The leading content block on the user message is the v2 block,
|
|
345
|
+
// wrapped exactly once.
|
|
340
346
|
const lastMsg = result.runMessages[result.runMessages.length - 1];
|
|
341
347
|
expect(lastMsg?.role).toBe("user");
|
|
342
348
|
const firstBlock = lastMsg?.content[0];
|
|
343
349
|
expect(firstBlock?.type).toBe("text");
|
|
344
350
|
if (firstBlock?.type !== "text") throw new Error("unexpected block type");
|
|
345
|
-
expect(firstBlock.text
|
|
351
|
+
expect(firstBlock.text.startsWith("<memory>\n")).toBe(true);
|
|
352
|
+
expect(firstBlock.text.endsWith("\n</memory>")).toBe(true);
|
|
353
|
+
// No nested wrapper.
|
|
354
|
+
expect(firstBlock.text.match(/<memory>/g)?.length).toBe(1);
|
|
355
|
+
|
|
356
|
+
// v1 retrieval is fully bypassed when v2 is enabled.
|
|
357
|
+
expect(retrieveForTurnMock).not.toHaveBeenCalled();
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
test("reinjectCachedMemory after v2 injection wraps exactly once (no double-wrap)", async () => {
|
|
361
|
+
// Regression for the double-wrap bug: v2 cached `lastInjectedBlock`
|
|
362
|
+
// already wrapped, then `reinjectCachedMemory` re-wrapped via
|
|
363
|
+
// `injectTextBlock`, producing `<memory>\n<memory>\n...\n</memory>\n</memory>`.
|
|
364
|
+
_setOverridesForTesting({ "memory-v2-enabled": true });
|
|
365
|
+
stageTurn([{ slug: "alice-vscode", denseScore: 0.9 }]);
|
|
366
|
+
|
|
367
|
+
const memory = makeMemory();
|
|
368
|
+
const config = makeConfig(true);
|
|
369
|
+
const messages = makeMessages("Tell me about Alice's editor preferences");
|
|
370
|
+
|
|
371
|
+
const initial = await memory.prepareMemory(
|
|
372
|
+
messages,
|
|
373
|
+
config,
|
|
374
|
+
new AbortController().signal,
|
|
375
|
+
noopEvent,
|
|
376
|
+
);
|
|
377
|
+
expect(initial.injectedBlockText).not.toBeNull();
|
|
378
|
+
|
|
379
|
+
// Simulate post-compaction: caller re-runs `applyRuntimeInjections`
|
|
380
|
+
// (which strips memory injections) and then asks for the cached
|
|
381
|
+
// memory to be re-prepended.
|
|
382
|
+
const reinjected = memory.reinjectCachedMemory(messages);
|
|
383
|
+
const lastMsg = reinjected.runMessages[reinjected.runMessages.length - 1];
|
|
384
|
+
const firstBlock = lastMsg?.content[0];
|
|
385
|
+
expect(firstBlock?.type).toBe("text");
|
|
386
|
+
if (firstBlock?.type !== "text") throw new Error("unexpected block type");
|
|
387
|
+
expect(firstBlock.text.startsWith("<memory>\n")).toBe(true);
|
|
388
|
+
expect(firstBlock.text.endsWith("\n</memory>")).toBe(true);
|
|
389
|
+
expect(firstBlock.text.match(/<memory>/g)?.length).toBe(1);
|
|
390
|
+
expect(firstBlock.text.match(/<\/memory>/g)?.length).toBe(1);
|
|
391
|
+
expect(firstBlock.text).toContain("### alice-vscode");
|
|
346
392
|
});
|
|
347
393
|
|
|
348
394
|
test("flag on + config on with empty Qdrant hits → no v2 block, v1 fallback skipped", async () => {
|
|
@@ -371,7 +417,7 @@ describe("ConversationGraphMemory.prepareMemory — v2 routing (context-load pat
|
|
|
371
417
|
stageTurn([{ slug: "alice-vscode", denseScore: 0.9 }]);
|
|
372
418
|
|
|
373
419
|
// Fresh memory → initialized=false → runContextLoad branch.
|
|
374
|
-
const memory = new ConversationGraphMemory("
|
|
420
|
+
const memory = new ConversationGraphMemory("conv-test-cl");
|
|
375
421
|
const config = makeConfig(true);
|
|
376
422
|
const messages = makeMessages("first message of the conversation here");
|
|
377
423
|
|
|
@@ -384,14 +430,24 @@ describe("ConversationGraphMemory.prepareMemory — v2 routing (context-load pat
|
|
|
384
430
|
|
|
385
431
|
expect(result.mode).toBe("context-load");
|
|
386
432
|
expect(result.injectedBlockText).not.toBeNull();
|
|
387
|
-
expect(result.injectedBlockText).toContain("
|
|
433
|
+
expect(result.injectedBlockText).toContain("### alice-vscode");
|
|
434
|
+
// injectedBlockText is the unwrapped inner content; the wrapper is
|
|
435
|
+
// applied at injection time on the run message.
|
|
436
|
+
expect(result.injectedBlockText).not.toContain("<memory>");
|
|
437
|
+
const lastMsg = result.runMessages[result.runMessages.length - 1];
|
|
438
|
+
const firstBlock = lastMsg?.content[0];
|
|
439
|
+
if (firstBlock?.type !== "text") throw new Error("unexpected block type");
|
|
440
|
+
expect(firstBlock.text.match(/<memory>/g)?.length).toBe(1);
|
|
441
|
+
|
|
442
|
+
// v1 retrieval is fully bypassed when v2 is enabled.
|
|
443
|
+
expect(loadContextMemoryMock).not.toHaveBeenCalled();
|
|
388
444
|
});
|
|
389
445
|
|
|
390
446
|
test("flag off → v2 not run on first turn either", async () => {
|
|
391
447
|
_setOverridesForTesting({ "memory-v2-enabled": false });
|
|
392
448
|
stageTurn([{ slug: "alice-vscode", denseScore: 0.9 }]);
|
|
393
449
|
|
|
394
|
-
const memory = new ConversationGraphMemory("
|
|
450
|
+
const memory = new ConversationGraphMemory("conv-test-cl-off");
|
|
395
451
|
const config = makeConfig(true);
|
|
396
452
|
const messages = makeMessages("first message of the conversation here");
|
|
397
453
|
|
|
@@ -62,14 +62,12 @@ export class ConversationGraphMemory {
|
|
|
62
62
|
private initialized = false;
|
|
63
63
|
private needsReload = false;
|
|
64
64
|
private stateRestored = false;
|
|
65
|
-
private scopeId: string;
|
|
66
65
|
private conversationId: string;
|
|
67
66
|
private lastInjectedBlock: string | null = null;
|
|
68
67
|
private lastInjectedNodeIds: string[] = [];
|
|
69
68
|
private lastInjectedImages: Map<string, ResolvedImage> = new Map();
|
|
70
69
|
|
|
71
|
-
constructor(
|
|
72
|
-
this.scopeId = scopeId;
|
|
70
|
+
constructor(conversationId: string) {
|
|
73
71
|
this.conversationId = conversationId;
|
|
74
72
|
}
|
|
75
73
|
|
|
@@ -147,7 +145,6 @@ export class ConversationGraphMemory {
|
|
|
147
145
|
const db = getDb();
|
|
148
146
|
const baseWhere = and(
|
|
149
147
|
eq(memorySummaries.scope, "conversation"),
|
|
150
|
-
eq(memorySummaries.scopeId, this.scopeId),
|
|
151
148
|
ne(memorySummaries.scopeKey, this.conversationId),
|
|
152
149
|
);
|
|
153
150
|
|
|
@@ -385,29 +382,11 @@ export class ConversationGraphMemory {
|
|
|
385
382
|
signal: AbortSignal,
|
|
386
383
|
onEvent: (msg: ServerMessage) => void,
|
|
387
384
|
) {
|
|
388
|
-
const result = await loadContextMemory({
|
|
389
|
-
scopeId: this.scopeId,
|
|
390
|
-
recentSummaries,
|
|
391
|
-
userQuery,
|
|
392
|
-
config,
|
|
393
|
-
signal,
|
|
394
|
-
});
|
|
395
|
-
|
|
396
|
-
this.initialized = true;
|
|
397
|
-
this.needsReload = false;
|
|
398
|
-
|
|
399
|
-
// v2 routing: when the feature flag and workspace config are both on,
|
|
400
|
-
// replace v1's injection with the activation-pipeline output. v1
|
|
401
|
-
// retrieval still runs above so its tracker stays warm — keeps the
|
|
402
|
-
// off→on→off flag flip cheap and avoids invalidating cached metrics.
|
|
403
|
-
// assistantMessage is empty: context-load fires on turn 1 / post-
|
|
404
|
-
// compaction, so there is no immediately-prior assistant turn to
|
|
405
|
-
// weight the activation against.
|
|
406
|
-
//
|
|
407
385
|
// Use the raw user text (no >10-char filter) so even short greetings
|
|
408
386
|
// ("hi") get a fresh top-K activation dump on the first user message.
|
|
409
|
-
// The activation pipeline is robust to weak ANN signal — it
|
|
410
|
-
//
|
|
387
|
+
// The activation pipeline is robust to weak ANN signal — it falls back
|
|
388
|
+
// to spreading + nowText to surface candidates.
|
|
389
|
+
const startedAt = Date.now();
|
|
411
390
|
const rawUserText = readRawUserText(messages[messages.length - 1]);
|
|
412
391
|
const v2 = await this.maybeRouteV2Injection(
|
|
413
392
|
messages,
|
|
@@ -415,7 +394,11 @@ export class ConversationGraphMemory {
|
|
|
415
394
|
"context-load",
|
|
416
395
|
rawUserText ?? userQuery ?? "",
|
|
417
396
|
"",
|
|
397
|
+
signal,
|
|
418
398
|
);
|
|
399
|
+
this.initialized = true;
|
|
400
|
+
this.needsReload = false;
|
|
401
|
+
|
|
419
402
|
if (v2.routed) {
|
|
420
403
|
this.lastInjectedBlock = v2.injectedBlockText;
|
|
421
404
|
this.lastInjectedNodeIds = [];
|
|
@@ -425,17 +408,22 @@ export class ConversationGraphMemory {
|
|
|
425
408
|
injectedTokens: v2.injectedBlockText
|
|
426
409
|
? estimateTextTokens(v2.injectedBlockText)
|
|
427
410
|
: 0,
|
|
428
|
-
latencyMs:
|
|
411
|
+
latencyMs: Date.now() - startedAt,
|
|
429
412
|
mode: "context-load" as const,
|
|
430
413
|
injectedBlockText: v2.injectedBlockText,
|
|
431
|
-
metrics:
|
|
432
|
-
queryVector: result.queryVector,
|
|
433
|
-
sparseVector: result.sparseVector,
|
|
434
|
-
userQueryVector: result.userQueryVector,
|
|
435
|
-
userQuerySparseVector: result.userQuerySparseVector,
|
|
414
|
+
metrics: null,
|
|
436
415
|
};
|
|
437
416
|
}
|
|
438
417
|
|
|
418
|
+
// v1 fallback — only reached when the v2 flag or workspace config is off.
|
|
419
|
+
const result = await loadContextMemory({
|
|
420
|
+
scopeId: "default",
|
|
421
|
+
recentSummaries,
|
|
422
|
+
userQuery,
|
|
423
|
+
config,
|
|
424
|
+
signal,
|
|
425
|
+
});
|
|
426
|
+
|
|
439
427
|
if (result.nodes.length === 0) {
|
|
440
428
|
this.lastInjectedBlock = null;
|
|
441
429
|
this.lastInjectedNodeIds = [];
|
|
@@ -543,27 +531,16 @@ export class ConversationGraphMemory {
|
|
|
543
531
|
if (userLastBlocks.length > 0 && assistantLast) break;
|
|
544
532
|
}
|
|
545
533
|
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
userLastMessageBlocks: userLastBlocks,
|
|
550
|
-
scopeId: this.scopeId,
|
|
551
|
-
config,
|
|
552
|
-
tracker: this.tracker,
|
|
553
|
-
signal,
|
|
554
|
-
});
|
|
555
|
-
|
|
556
|
-
// v2 routing: same gating as `runContextLoad` — when the flag and config
|
|
557
|
-
// are both on, the v2 activation pipeline produces the injection block
|
|
558
|
-
// (or `null` for the cache-stable empty path). v1 retrieval above runs
|
|
559
|
-
// unconditionally so the tracker stays in sync with the v1 nodes —
|
|
560
|
-
// cheap insurance for an off→on→off flag flip mid-conversation.
|
|
534
|
+
// v2 path — skip v1 retrieval entirely when v2 is enabled. See the
|
|
535
|
+
// matching comment in `runContextLoad` for rationale.
|
|
536
|
+
const startedAt = Date.now();
|
|
561
537
|
const v2 = await this.maybeRouteV2Injection(
|
|
562
538
|
messages,
|
|
563
539
|
config,
|
|
564
540
|
"per-turn",
|
|
565
541
|
userLast,
|
|
566
542
|
assistantLast,
|
|
543
|
+
signal,
|
|
567
544
|
);
|
|
568
545
|
if (v2.routed) {
|
|
569
546
|
this.lastInjectedBlock = v2.injectedBlockText;
|
|
@@ -574,15 +551,24 @@ export class ConversationGraphMemory {
|
|
|
574
551
|
injectedTokens: v2.injectedBlockText
|
|
575
552
|
? estimateTextTokens(v2.injectedBlockText)
|
|
576
553
|
: 0,
|
|
577
|
-
latencyMs:
|
|
554
|
+
latencyMs: Date.now() - startedAt,
|
|
578
555
|
mode: "per-turn" as const,
|
|
579
556
|
injectedBlockText: v2.injectedBlockText,
|
|
580
|
-
metrics:
|
|
581
|
-
queryVector: result.queryVector,
|
|
582
|
-
sparseVector: result.sparseVector,
|
|
557
|
+
metrics: null,
|
|
583
558
|
};
|
|
584
559
|
}
|
|
585
560
|
|
|
561
|
+
// v1 path (only reached when the v2 flag or workspace config is off).
|
|
562
|
+
const result = await retrieveForTurn({
|
|
563
|
+
assistantLastMessage: assistantLast,
|
|
564
|
+
userLastMessage: userLast,
|
|
565
|
+
userLastMessageBlocks: userLastBlocks,
|
|
566
|
+
scopeId: "default",
|
|
567
|
+
config,
|
|
568
|
+
tracker: this.tracker,
|
|
569
|
+
signal,
|
|
570
|
+
});
|
|
571
|
+
|
|
586
572
|
if (result.nodes.length === 0) {
|
|
587
573
|
this.lastInjectedBlock = null;
|
|
588
574
|
this.lastInjectedNodeIds = [];
|
|
@@ -641,12 +627,12 @@ export class ConversationGraphMemory {
|
|
|
641
627
|
}
|
|
642
628
|
|
|
643
629
|
/**
|
|
644
|
-
*
|
|
645
|
-
*
|
|
646
|
-
* config (`memory.v2.enabled`) are both on.
|
|
630
|
+
* Run the v2 activation pipeline when the `memory-v2-enabled` feature flag
|
|
631
|
+
* *and* the workspace config (`memory.v2.enabled`) are both on.
|
|
647
632
|
*
|
|
648
633
|
* The two outcomes the caller distinguishes via `routed`:
|
|
649
|
-
* - `routed: false` — v2 disabled; caller
|
|
634
|
+
* - `routed: false` — v2 disabled; caller falls through to the legacy v1
|
|
635
|
+
* retrieval path.
|
|
650
636
|
* - `routed: true` — v2 ran. `runMessages` is either the v2-prepended
|
|
651
637
|
* message list (block was non-null) or the input
|
|
652
638
|
* messages unchanged (cache-stable empty path).
|
|
@@ -658,6 +644,7 @@ export class ConversationGraphMemory {
|
|
|
658
644
|
mode: InjectMemoryV2Mode,
|
|
659
645
|
userMessage: string,
|
|
660
646
|
assistantMessage: string,
|
|
647
|
+
signal: AbortSignal,
|
|
661
648
|
): Promise<{
|
|
662
649
|
routed: boolean;
|
|
663
650
|
runMessages: Message[];
|
|
@@ -683,6 +670,7 @@ export class ConversationGraphMemory {
|
|
|
683
670
|
messageId: `${this.conversationId}:turn:${currentTurn}`,
|
|
684
671
|
mode,
|
|
685
672
|
config,
|
|
673
|
+
signal,
|
|
686
674
|
});
|
|
687
675
|
|
|
688
676
|
if (!result.block) {
|
|
@@ -691,7 +679,7 @@ export class ConversationGraphMemory {
|
|
|
691
679
|
|
|
692
680
|
return {
|
|
693
681
|
routed: true,
|
|
694
|
-
runMessages:
|
|
682
|
+
runMessages: injectTextBlock(messages, result.block),
|
|
695
683
|
injectedBlockText: result.block,
|
|
696
684
|
};
|
|
697
685
|
}
|
|
@@ -881,26 +869,3 @@ function readRawUserText(message: Message | undefined): string | null {
|
|
|
881
869
|
if (texts.length === 0) return null;
|
|
882
870
|
return texts.join(" ");
|
|
883
871
|
}
|
|
884
|
-
|
|
885
|
-
/**
|
|
886
|
-
* Prepend a pre-rendered `<memory>` block (produced by
|
|
887
|
-
* `injectMemoryV2Block`) to the last user message. Unlike v1's
|
|
888
|
-
* {@link injectMemoryBlock}, the input here is already wrapped — we
|
|
889
|
-
* just need to attach it as a leading text block. We still strip any
|
|
890
|
-
* pre-existing memory injections first so the layer is idempotent
|
|
891
|
-
* across compaction-driven re-injection.
|
|
892
|
-
*/
|
|
893
|
-
function prependMemoryV2Block(messages: Message[], block: string): Message[] {
|
|
894
|
-
if (block.trim().length === 0) return messages;
|
|
895
|
-
if (messages.length === 0) return messages;
|
|
896
|
-
const cleaned = stripExistingMemoryInjections(messages);
|
|
897
|
-
const userTail = cleaned[cleaned.length - 1];
|
|
898
|
-
if (!userTail || userTail.role !== "user") return messages;
|
|
899
|
-
return [
|
|
900
|
-
...cleaned.slice(0, -1),
|
|
901
|
-
{
|
|
902
|
-
...userTail,
|
|
903
|
-
content: [{ type: "text" as const, text: block }, ...userTail.content],
|
|
904
|
-
},
|
|
905
|
-
];
|
|
906
|
-
}
|
|
@@ -1443,9 +1443,7 @@ async function findCandidateNodes(
|
|
|
1443
1443
|
const embedding = await embedWithRetry(config, [searchText]);
|
|
1444
1444
|
const queryVector = embedding.vectors[0];
|
|
1445
1445
|
if (queryVector) {
|
|
1446
|
-
const searchResults = await searchGraphNodes(queryVector, 100
|
|
1447
|
-
scopeId,
|
|
1448
|
-
]);
|
|
1446
|
+
const searchResults = await searchGraphNodes(queryVector, 100);
|
|
1449
1447
|
for (const r of searchResults) allNodeIds.add(r.nodeId);
|
|
1450
1448
|
}
|
|
1451
1449
|
} catch (err) {
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
2
2
|
|
|
3
3
|
import { makeMockLogger } from "../../__tests__/helpers/mock-logger.js";
|
|
4
|
+
import { _setOverridesForTesting } from "../../config/assistant-feature-flags.js";
|
|
5
|
+
|
|
6
|
+
// This test exercises the v1 graph search path. The `memory-v2-enabled` flag
|
|
7
|
+
// (registry default `true`) makes graph-search short-circuit to keep traffic
|
|
8
|
+
// off the legacy collection — disable it so the v1 path stays under test.
|
|
9
|
+
_setOverridesForTesting({ "memory-v2-enabled": false });
|
|
4
10
|
|
|
5
11
|
mock.module("../../util/logger.js", () => ({
|
|
6
12
|
getLogger: () => makeMockLogger(),
|
|
@@ -64,7 +70,7 @@ describe("searchGraphNodes — _meta filter parity", () => {
|
|
|
64
70
|
});
|
|
65
71
|
|
|
66
72
|
test("hybrid path excludes _meta sentinel points", async () => {
|
|
67
|
-
await searchGraphNodes([0.1], 5,
|
|
73
|
+
await searchGraphNodes([0.1], 5, {
|
|
68
74
|
indices: [1],
|
|
69
75
|
values: [1],
|
|
70
76
|
});
|
|
@@ -80,7 +86,7 @@ describe("searchGraphNodes — _meta filter parity", () => {
|
|
|
80
86
|
});
|
|
81
87
|
|
|
82
88
|
test("dense-only path also excludes _meta sentinel points", async () => {
|
|
83
|
-
await searchGraphNodes([0.1], 5
|
|
89
|
+
await searchGraphNodes([0.1], 5);
|
|
84
90
|
|
|
85
91
|
expect(searchCalls).toHaveLength(1);
|
|
86
92
|
const filter = searchCalls[0]?.filter as {
|
|
@@ -93,69 +99,6 @@ describe("searchGraphNodes — _meta filter parity", () => {
|
|
|
93
99
|
});
|
|
94
100
|
});
|
|
95
101
|
|
|
96
|
-
describe("searchGraphNodes — excludeScopeIds", () => {
|
|
97
|
-
beforeEach(() => {
|
|
98
|
-
breakerOpen = false;
|
|
99
|
-
hybridSearchCalls.length = 0;
|
|
100
|
-
searchCalls.length = 0;
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
test("hybrid path adds memory_scope_id must_not when excludeScopeIds provided", async () => {
|
|
104
|
-
await searchGraphNodes(
|
|
105
|
-
[0.1],
|
|
106
|
-
5,
|
|
107
|
-
undefined,
|
|
108
|
-
{ indices: [1], values: [1] },
|
|
109
|
-
undefined,
|
|
110
|
-
["scope:abc", "scope:xyz"],
|
|
111
|
-
);
|
|
112
|
-
|
|
113
|
-
expect(hybridSearchCalls).toHaveLength(1);
|
|
114
|
-
const filter = hybridSearchCalls[0]?.filter as {
|
|
115
|
-
must_not: Array<Record<string, unknown>>;
|
|
116
|
-
};
|
|
117
|
-
const scopeExclude = filter.must_not.find(
|
|
118
|
-
(c) => c.key === "memory_scope_id",
|
|
119
|
-
) as { match: { any: string[] } } | undefined;
|
|
120
|
-
expect(scopeExclude?.match.any).toEqual(["scope:abc", "scope:xyz"]);
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
test("dense-only path adds memory_scope_id must_not when excludeScopeIds provided", async () => {
|
|
124
|
-
await searchGraphNodes([0.1], 5, undefined, undefined, undefined, [
|
|
125
|
-
"scope:abc",
|
|
126
|
-
]);
|
|
127
|
-
|
|
128
|
-
expect(searchCalls).toHaveLength(1);
|
|
129
|
-
const filter = searchCalls[0]?.filter as {
|
|
130
|
-
must_not: Array<Record<string, unknown>>;
|
|
131
|
-
};
|
|
132
|
-
const scopeExclude = filter.must_not.find(
|
|
133
|
-
(c) => c.key === "memory_scope_id",
|
|
134
|
-
) as { match: { any: string[] } } | undefined;
|
|
135
|
-
expect(scopeExclude?.match.any).toEqual(["scope:abc"]);
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
test("hybrid path omits memory_scope_id must_not when excludeScopeIds is empty", async () => {
|
|
139
|
-
await searchGraphNodes(
|
|
140
|
-
[0.1],
|
|
141
|
-
5,
|
|
142
|
-
undefined,
|
|
143
|
-
{ indices: [1], values: [1] },
|
|
144
|
-
undefined,
|
|
145
|
-
[],
|
|
146
|
-
);
|
|
147
|
-
|
|
148
|
-
expect(hybridSearchCalls).toHaveLength(1);
|
|
149
|
-
const filter = hybridSearchCalls[0]?.filter as {
|
|
150
|
-
must_not: Array<Record<string, unknown>>;
|
|
151
|
-
};
|
|
152
|
-
const scopeExclude = filter.must_not.find(
|
|
153
|
-
(c) => c.key === "memory_scope_id",
|
|
154
|
-
);
|
|
155
|
-
expect(scopeExclude).toBeUndefined();
|
|
156
|
-
});
|
|
157
|
-
});
|
|
158
|
-
|
|
159
102
|
describe("searchGraphNodes — prefetch floor", () => {
|
|
160
103
|
beforeEach(() => {
|
|
161
104
|
breakerOpen = false;
|
|
@@ -164,7 +107,7 @@ describe("searchGraphNodes — prefetch floor", () => {
|
|
|
164
107
|
});
|
|
165
108
|
|
|
166
109
|
test("hybrid prefetchLimit floors at 200 for small limits", async () => {
|
|
167
|
-
await searchGraphNodes([0.1], 10,
|
|
110
|
+
await searchGraphNodes([0.1], 10, {
|
|
168
111
|
indices: [1],
|
|
169
112
|
values: [1],
|
|
170
113
|
});
|
|
@@ -174,7 +117,7 @@ describe("searchGraphNodes — prefetch floor", () => {
|
|
|
174
117
|
});
|
|
175
118
|
|
|
176
119
|
test("hybrid prefetchLimit scales with limit when limit*10 exceeds floor", async () => {
|
|
177
|
-
await searchGraphNodes([0.1], 50,
|
|
120
|
+
await searchGraphNodes([0.1], 50, {
|
|
178
121
|
indices: [1],
|
|
179
122
|
values: [1],
|
|
180
123
|
});
|
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
// Memory Graph — Qdrant vector search for graph nodes
|
|
3
3
|
// ---------------------------------------------------------------------------
|
|
4
4
|
|
|
5
|
+
import { getConfig } from "../../config/loader.js";
|
|
5
6
|
import type { AssistantConfig } from "../../config/types.js";
|
|
6
7
|
import { getLogger } from "../../util/logger.js";
|
|
8
|
+
import { isMemoryV2ReadActive } from "../context-search/sources/memory-v2.js";
|
|
7
9
|
import { selectedBackendSupportsMultimodal } from "../embedding-backend.js";
|
|
8
10
|
import type { EmbeddingInput } from "../embedding-types.js";
|
|
9
11
|
import { embedAndUpsert } from "../job-utils.js";
|
|
@@ -36,18 +38,20 @@ export interface GraphSearchResult {
|
|
|
36
38
|
* Semantic search across graph nodes in Qdrant. Returns scored node IDs
|
|
37
39
|
* that the caller can hydrate from the graph store.
|
|
38
40
|
*
|
|
39
|
-
* Filters to `target_type: "graph_node"
|
|
40
|
-
* `excludeScopeIds` adds a `must_not` against `memory_scope_id` for callers
|
|
41
|
-
* that need to omit specific scopes from a broader recall search.
|
|
41
|
+
* Filters to `target_type: "graph_node"`.
|
|
42
42
|
*/
|
|
43
43
|
export async function searchGraphNodes(
|
|
44
44
|
queryVector: number[],
|
|
45
45
|
limit: number,
|
|
46
|
-
scopeIds?: string[],
|
|
47
46
|
sparseVector?: QdrantSparseVector,
|
|
48
47
|
dateRange?: { afterMs?: number; beforeMs?: number },
|
|
49
|
-
excludeScopeIds?: string[],
|
|
50
48
|
): Promise<GraphSearchResult[]> {
|
|
49
|
+
// v2 owns the read path when both gates are on. The v1 `memory` collection
|
|
50
|
+
// is in active retirement and a corrupted sparse segment can OOM-crash the
|
|
51
|
+
// shared Qdrant process — short-circuiting here keeps v1 background work
|
|
52
|
+
// and stale callers from taking v2 down with them.
|
|
53
|
+
if (isMemoryV2ReadActive(getConfig())) return [];
|
|
54
|
+
|
|
51
55
|
if (isQdrantBreakerOpen()) {
|
|
52
56
|
log.warn("Qdrant circuit breaker open, skipping graph search");
|
|
53
57
|
return [];
|
|
@@ -58,21 +62,12 @@ export async function searchGraphNodes(
|
|
|
58
62
|
const mustNot: Record<string, unknown>[] = [
|
|
59
63
|
{ key: "_meta", match: { value: true } },
|
|
60
64
|
];
|
|
61
|
-
if (excludeScopeIds && excludeScopeIds.length > 0) {
|
|
62
|
-
mustNot.push({
|
|
63
|
-
key: "memory_scope_id",
|
|
64
|
-
match: { any: excludeScopeIds },
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
65
|
|
|
68
66
|
// Use hybrid search (dense + sparse with RRF fusion) when a non-empty
|
|
69
67
|
// sparse vector is available; otherwise fall back to dense-only search.
|
|
70
68
|
if (sparseVector && sparseVector.indices.length > 0) {
|
|
71
69
|
const must: Record<string, unknown>[] = [
|
|
72
70
|
{ key: "target_type", match: { value: "graph_node" } },
|
|
73
|
-
...(scopeIds && scopeIds.length > 0
|
|
74
|
-
? [{ key: "memory_scope_id", match: { any: scopeIds } }]
|
|
75
|
-
: []),
|
|
76
71
|
];
|
|
77
72
|
if (dateRange?.afterMs != null) {
|
|
78
73
|
must.push({ key: "created_at", range: { gte: dateRange.afterMs } });
|
|
@@ -112,12 +107,6 @@ export async function searchGraphNodes(
|
|
|
112
107
|
},
|
|
113
108
|
];
|
|
114
109
|
|
|
115
|
-
if (scopeIds && scopeIds.length > 0) {
|
|
116
|
-
denseMusts.push({
|
|
117
|
-
key: "memory_scope_id",
|
|
118
|
-
match: { any: scopeIds },
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
110
|
if (dateRange?.afterMs != null) {
|
|
122
111
|
denseMusts.push({ key: "created_at", range: { gte: dateRange.afterMs } });
|
|
123
112
|
}
|
|
@@ -71,6 +71,7 @@ mock.module("../../providers/provider-send-message.js", () => ({
|
|
|
71
71
|
extractToolUse: () => null,
|
|
72
72
|
}));
|
|
73
73
|
|
|
74
|
+
import { _setOverridesForTesting } from "../../config/assistant-feature-flags.js";
|
|
74
75
|
import { DEFAULT_CONFIG } from "../../config/defaults.js";
|
|
75
76
|
import type { AssistantConfig } from "../../config/types.js";
|
|
76
77
|
import { resetDb } from "../db-connection.js";
|
|
@@ -81,6 +82,11 @@ import { loadContextMemory, retrieveForTurn } from "./retriever.js";
|
|
|
81
82
|
import { createNode } from "./store.js";
|
|
82
83
|
import type { NewNode } from "./types.js";
|
|
83
84
|
|
|
85
|
+
// These tests exercise v1 retrieval. v2 takeover (both `memory-v2-enabled`
|
|
86
|
+
// flag *and* `memory.v2.enabled` schema field) makes `loadContextMemory`
|
|
87
|
+
// short-circuit, so disable the flag here to keep the v1 path under test.
|
|
88
|
+
_setOverridesForTesting({ "memory-v2-enabled": false });
|
|
89
|
+
|
|
84
90
|
const TEST_CONFIG: AssistantConfig = { ...DEFAULT_CONFIG };
|
|
85
91
|
|
|
86
92
|
function makeCapabilityNode(content: string, capId: string): NewNode {
|