@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
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
/** Local cross-encoder rerank backend — drives the rerank-worker subprocess. */
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
|
|
4
|
+
import type { RerankDtype } from "../config/schemas/memory-v2.js";
|
|
5
|
+
import { getLogger } from "../util/logger.js";
|
|
6
|
+
import { getEmbeddingModelsDir } from "../util/platform.js";
|
|
7
|
+
import { PromiseGuard } from "../util/promise-guard.js";
|
|
8
|
+
import { EmbeddingRuntimeManager } from "./embedding-runtime-manager.js";
|
|
9
|
+
|
|
10
|
+
const log = getLogger("memory-rerank-local");
|
|
11
|
+
|
|
12
|
+
interface WorkerResponse {
|
|
13
|
+
id?: number;
|
|
14
|
+
type?: string;
|
|
15
|
+
scores?: number[];
|
|
16
|
+
error?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export class LocalRerankBackend {
|
|
20
|
+
readonly model: string;
|
|
21
|
+
readonly dtype: RerankDtype;
|
|
22
|
+
|
|
23
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
24
|
+
private workerProc: any = null;
|
|
25
|
+
private stdoutBuffer = "";
|
|
26
|
+
private requestCounter = 0;
|
|
27
|
+
private pendingRequests = new Map<
|
|
28
|
+
number,
|
|
29
|
+
{ resolve: (response: WorkerResponse) => void }
|
|
30
|
+
>();
|
|
31
|
+
private stdoutReaderActive = false;
|
|
32
|
+
private activeRequests = 0;
|
|
33
|
+
private disposeRequested = false;
|
|
34
|
+
|
|
35
|
+
private readyResolve: (() => void) | null = null;
|
|
36
|
+
private readyReject: ((err: Error) => void) | null = null;
|
|
37
|
+
|
|
38
|
+
private readonly initGuard = new PromiseGuard<void>();
|
|
39
|
+
|
|
40
|
+
constructor(model: string, dtype: RerankDtype) {
|
|
41
|
+
this.model = model;
|
|
42
|
+
this.dtype = dtype;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Score paired `(queries[i], passages[i])` tuples in one batched ONNX
|
|
47
|
+
* inference call. Multiple distinct queries can ride in a single batch
|
|
48
|
+
* so callers can score the user-channel and assistant-channel queries
|
|
49
|
+
* against a shared candidate set in one tokenizer + forward pass.
|
|
50
|
+
*/
|
|
51
|
+
async score(queries: string[], passages: string[]): Promise<number[]> {
|
|
52
|
+
if (this.disposeRequested) {
|
|
53
|
+
throw new Error("Local rerank backend is shutting down");
|
|
54
|
+
}
|
|
55
|
+
if (passages.length === 0) return [];
|
|
56
|
+
if (queries.length !== passages.length) {
|
|
57
|
+
throw new Error(
|
|
58
|
+
`Rerank backend got ${queries.length} queries for ${passages.length} passages`,
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
this.activeRequests++;
|
|
63
|
+
try {
|
|
64
|
+
await this.ensureInitialized();
|
|
65
|
+
const response = await this.sendRequest({ queries, passages });
|
|
66
|
+
if (response.error) {
|
|
67
|
+
throw new Error(`Rerank worker error: ${response.error}`);
|
|
68
|
+
}
|
|
69
|
+
if (!response.scores) {
|
|
70
|
+
throw new Error("Rerank worker returned no scores");
|
|
71
|
+
}
|
|
72
|
+
if (response.scores.length !== passages.length) {
|
|
73
|
+
throw new Error(
|
|
74
|
+
`Rerank worker returned ${response.scores.length} scores for ${passages.length} passages`,
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
return response.scores;
|
|
78
|
+
} finally {
|
|
79
|
+
this.activeRequests--;
|
|
80
|
+
this.disposeIfIdle();
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
dispose(): void {
|
|
85
|
+
this.disposeRequested = true;
|
|
86
|
+
this.disposeIfIdle();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
private sendRequest(payload: {
|
|
90
|
+
queries: string[];
|
|
91
|
+
passages: string[];
|
|
92
|
+
}): Promise<WorkerResponse> {
|
|
93
|
+
const id = ++this.requestCounter;
|
|
94
|
+
return new Promise((resolve) => {
|
|
95
|
+
if (!this.workerProc) {
|
|
96
|
+
resolve({ error: "Worker not initialized" });
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
this.pendingRequests.set(id, { resolve });
|
|
100
|
+
this.workerProc.stdin.write(JSON.stringify({ id, ...payload }) + "\n");
|
|
101
|
+
try {
|
|
102
|
+
this.workerProc.stdin.flush();
|
|
103
|
+
} catch {
|
|
104
|
+
// Worker may have exited — stdout reader cleanup resolves pending requests.
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
private async ensureInitialized(): Promise<void> {
|
|
110
|
+
if (this.workerProc) return;
|
|
111
|
+
await this.initGuard.run(() => this.initialize());
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
private async initialize(): Promise<void> {
|
|
115
|
+
log.info({ model: this.model }, "Initializing local rerank backend");
|
|
116
|
+
|
|
117
|
+
const runtimeManager = new EmbeddingRuntimeManager();
|
|
118
|
+
if (!runtimeManager.isReady()) {
|
|
119
|
+
log.info("Embedding runtime not yet available, waiting for download...");
|
|
120
|
+
await runtimeManager.ensureInstalled();
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const bunPath = runtimeManager.getBunPath();
|
|
124
|
+
const workerPath = runtimeManager.getRerankWorkerPath();
|
|
125
|
+
|
|
126
|
+
if (!bunPath) {
|
|
127
|
+
throw new Error("Local rerank backend unavailable: no bun binary found");
|
|
128
|
+
}
|
|
129
|
+
if (!existsSync(workerPath)) {
|
|
130
|
+
throw new Error(
|
|
131
|
+
`Local rerank backend unavailable: worker script not found at ${workerPath}`,
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
await this.startWorker(bunPath, workerPath);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
private async startWorker(
|
|
139
|
+
bunPath: string,
|
|
140
|
+
workerPath: string,
|
|
141
|
+
): Promise<void> {
|
|
142
|
+
const embeddingModelsDir = getEmbeddingModelsDir();
|
|
143
|
+
const modelCacheDir = `${embeddingModelsDir}/model-cache`;
|
|
144
|
+
|
|
145
|
+
log.info(
|
|
146
|
+
{ bunPath, workerPath, model: this.model, dtype: this.dtype },
|
|
147
|
+
"Spawning rerank worker process",
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
const proc = Bun.spawn({
|
|
151
|
+
cmd: [
|
|
152
|
+
bunPath,
|
|
153
|
+
"--smol",
|
|
154
|
+
workerPath,
|
|
155
|
+
this.model,
|
|
156
|
+
modelCacheDir,
|
|
157
|
+
this.dtype,
|
|
158
|
+
],
|
|
159
|
+
stdin: "pipe",
|
|
160
|
+
stdout: "pipe",
|
|
161
|
+
stderr: "pipe",
|
|
162
|
+
cwd: embeddingModelsDir,
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
this.workerProc = proc;
|
|
166
|
+
this.startStdoutReader();
|
|
167
|
+
|
|
168
|
+
try {
|
|
169
|
+
await this.waitForReady();
|
|
170
|
+
} catch (err) {
|
|
171
|
+
this.workerProc = null;
|
|
172
|
+
this.stdoutReaderActive = false;
|
|
173
|
+
try {
|
|
174
|
+
proc.kill();
|
|
175
|
+
} catch {
|
|
176
|
+
/* may already be dead */
|
|
177
|
+
}
|
|
178
|
+
const exitCode = await proc.exited.catch(() => undefined);
|
|
179
|
+
const stderr = await new Response(proc.stderr).text().catch(() => "");
|
|
180
|
+
if (stderr.trim()) {
|
|
181
|
+
log.warn({ stderr: stderr.trim(), exitCode }, "Rerank worker stderr");
|
|
182
|
+
}
|
|
183
|
+
throw new Error(
|
|
184
|
+
`Rerank worker exited (code ${exitCode ?? "unknown"}): ${
|
|
185
|
+
stderr.trim() || (err instanceof Error ? err.message : String(err))
|
|
186
|
+
}`,
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
this.drainStderr(proc.stderr);
|
|
191
|
+
log.info(
|
|
192
|
+
{ pid: proc.pid, model: this.model },
|
|
193
|
+
"Rerank worker process started",
|
|
194
|
+
);
|
|
195
|
+
this.disposeIfIdle();
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
private drainStderr(stderr: ReadableStream<Uint8Array>): void {
|
|
199
|
+
const reader = stderr.getReader();
|
|
200
|
+
const decoder = new TextDecoder();
|
|
201
|
+
(async () => {
|
|
202
|
+
try {
|
|
203
|
+
while (true) {
|
|
204
|
+
const { done, value } = await reader.read();
|
|
205
|
+
if (done) break;
|
|
206
|
+
const text = decoder.decode(value, { stream: true }).trim();
|
|
207
|
+
if (text) log.debug({ workerStderr: text }, "Rerank worker stderr");
|
|
208
|
+
}
|
|
209
|
+
} catch {
|
|
210
|
+
/* expected on shutdown */
|
|
211
|
+
}
|
|
212
|
+
})();
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
private startStdoutReader(): void {
|
|
216
|
+
if (this.stdoutReaderActive || !this.workerProc) return;
|
|
217
|
+
this.stdoutReaderActive = true;
|
|
218
|
+
|
|
219
|
+
const proc = this.workerProc;
|
|
220
|
+
const reader = proc.stdout.getReader();
|
|
221
|
+
const decoder = new TextDecoder();
|
|
222
|
+
|
|
223
|
+
(async () => {
|
|
224
|
+
try {
|
|
225
|
+
while (true) {
|
|
226
|
+
const { done, value } = await reader.read();
|
|
227
|
+
if (done) break;
|
|
228
|
+
this.stdoutBuffer += decoder.decode(value, { stream: true });
|
|
229
|
+
this.processStdoutBuffer();
|
|
230
|
+
}
|
|
231
|
+
} catch {
|
|
232
|
+
/* reader cancelled or stream errored */
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
if (this.workerProc === proc) {
|
|
236
|
+
for (const pending of this.pendingRequests.values()) {
|
|
237
|
+
pending.resolve({
|
|
238
|
+
error: "Rerank worker process exited unexpectedly",
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
this.pendingRequests.clear();
|
|
242
|
+
this.workerProc = null;
|
|
243
|
+
this.stdoutReaderActive = false;
|
|
244
|
+
this.stdoutBuffer = "";
|
|
245
|
+
this.initGuard.reset();
|
|
246
|
+
}
|
|
247
|
+
})();
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
private processStdoutBuffer(): void {
|
|
251
|
+
let idx: number;
|
|
252
|
+
while ((idx = this.stdoutBuffer.indexOf("\n")) !== -1) {
|
|
253
|
+
const line = this.stdoutBuffer.slice(0, idx);
|
|
254
|
+
this.stdoutBuffer = this.stdoutBuffer.slice(idx + 1);
|
|
255
|
+
if (!line.trim()) continue;
|
|
256
|
+
|
|
257
|
+
let msg: WorkerResponse;
|
|
258
|
+
try {
|
|
259
|
+
msg = JSON.parse(line);
|
|
260
|
+
} catch {
|
|
261
|
+
continue;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
if (msg.type === "ready") {
|
|
265
|
+
this.readyResolve?.();
|
|
266
|
+
this.readyResolve = null;
|
|
267
|
+
this.readyReject = null;
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
if (msg.type === "error" && this.readyReject) {
|
|
271
|
+
this.readyReject(
|
|
272
|
+
new Error(msg.error ?? "Worker initialization failed"),
|
|
273
|
+
);
|
|
274
|
+
this.readyResolve = null;
|
|
275
|
+
this.readyReject = null;
|
|
276
|
+
continue;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
if (msg.id !== undefined) {
|
|
280
|
+
const pending = this.pendingRequests.get(msg.id);
|
|
281
|
+
if (pending) {
|
|
282
|
+
this.pendingRequests.delete(msg.id);
|
|
283
|
+
pending.resolve(msg);
|
|
284
|
+
this.disposeIfIdle();
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
private waitForReady(): Promise<void> {
|
|
291
|
+
return new Promise<void>((resolve, reject) => {
|
|
292
|
+
// First-call timeout. Generous because the first run downloads the
|
|
293
|
+
// ONNX weights (~280 MB to ~1 GB depending on model) before loading.
|
|
294
|
+
const timeout = setTimeout(() => {
|
|
295
|
+
this.readyResolve = null;
|
|
296
|
+
this.readyReject = null;
|
|
297
|
+
reject(new Error("Rerank worker timed out waiting for model to load"));
|
|
298
|
+
}, 120_000);
|
|
299
|
+
|
|
300
|
+
this.readyResolve = () => {
|
|
301
|
+
clearTimeout(timeout);
|
|
302
|
+
resolve();
|
|
303
|
+
};
|
|
304
|
+
this.readyReject = (err: Error) => {
|
|
305
|
+
clearTimeout(timeout);
|
|
306
|
+
reject(err);
|
|
307
|
+
};
|
|
308
|
+
|
|
309
|
+
this.workerProc?.exited.then(() => {
|
|
310
|
+
if (this.readyResolve) {
|
|
311
|
+
clearTimeout(timeout);
|
|
312
|
+
this.readyResolve = null;
|
|
313
|
+
this.readyReject = null;
|
|
314
|
+
reject(
|
|
315
|
+
new Error("Rerank worker process exited before becoming ready"),
|
|
316
|
+
);
|
|
317
|
+
}
|
|
318
|
+
});
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
private disposeIfIdle(): void {
|
|
323
|
+
if (!this.disposeRequested) return;
|
|
324
|
+
if (this.activeRequests > 0) return;
|
|
325
|
+
if (this.pendingRequests.size > 0) return;
|
|
326
|
+
if (this.readyResolve || this.readyReject) return;
|
|
327
|
+
|
|
328
|
+
const proc = this.workerProc;
|
|
329
|
+
this.workerProc = null;
|
|
330
|
+
this.stdoutReaderActive = false;
|
|
331
|
+
this.stdoutBuffer = "";
|
|
332
|
+
this.initGuard.reset();
|
|
333
|
+
|
|
334
|
+
if (!proc) return;
|
|
335
|
+
|
|
336
|
+
try {
|
|
337
|
+
proc.kill();
|
|
338
|
+
} catch {
|
|
339
|
+
/* may already be exiting */
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// ── Module-level singleton management ─────────────────────────────────
|
|
345
|
+
|
|
346
|
+
let _backend: LocalRerankBackend | null = null;
|
|
347
|
+
|
|
348
|
+
export function getOrCreateRerankBackend(
|
|
349
|
+
model: string,
|
|
350
|
+
dtype: RerankDtype,
|
|
351
|
+
): LocalRerankBackend {
|
|
352
|
+
if (_backend?.model === model && _backend.dtype === dtype) return _backend;
|
|
353
|
+
if (_backend) {
|
|
354
|
+
try {
|
|
355
|
+
_backend.dispose();
|
|
356
|
+
} catch {
|
|
357
|
+
/* best effort */
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
_backend = new LocalRerankBackend(model, dtype);
|
|
361
|
+
return _backend;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/** @internal Test-only: reset the cached backend. */
|
|
365
|
+
export function _resetRerankBackendForTests(): void {
|
|
366
|
+
if (_backend) {
|
|
367
|
+
try {
|
|
368
|
+
_backend.dispose();
|
|
369
|
+
} catch {
|
|
370
|
+
/* best effort */
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
_backend = null;
|
|
374
|
+
}
|
|
@@ -19,6 +19,8 @@ export const cronJobs = sqliteTable("cron_jobs", {
|
|
|
19
19
|
lastRunAt: integer("last_run_at"),
|
|
20
20
|
lastStatus: text("last_status"), // 'ok' | 'error'
|
|
21
21
|
retryCount: integer("retry_count").notNull().default(0),
|
|
22
|
+
maxRetries: integer("max_retries").notNull().default(3),
|
|
23
|
+
retryBackoffMs: integer("retry_backoff_ms").notNull().default(60000),
|
|
22
24
|
createdBy: text("created_by").notNull(), // 'agent' | 'user'
|
|
23
25
|
mode: text("mode").notNull().default("execute"), // 'notify' | 'execute'
|
|
24
26
|
routingIntent: text("routing_intent").notNull().default("all_channels"), // 'single_channel' | 'multi_channel' | 'all_channels'
|
|
@@ -54,6 +56,19 @@ export const cronRuns = sqliteTable("cron_runs", {
|
|
|
54
56
|
export const scheduleJobs = cronJobs;
|
|
55
57
|
export const scheduleRuns = cronRuns;
|
|
56
58
|
|
|
59
|
+
export const heartbeatRuns = sqliteTable("heartbeat_runs", {
|
|
60
|
+
id: text("id").primaryKey(),
|
|
61
|
+
scheduledFor: integer("scheduled_for").notNull(),
|
|
62
|
+
startedAt: integer("started_at"),
|
|
63
|
+
finishedAt: integer("finished_at"),
|
|
64
|
+
durationMs: integer("duration_ms"),
|
|
65
|
+
status: text("status").notNull(), // 'pending' | 'running' | 'ok' | 'error' | 'timeout' | 'skipped' | 'missed' | 'superseded'
|
|
66
|
+
skipReason: text("skip_reason"), // 'disabled' | 'outside_active_hours' | 'overlap'
|
|
67
|
+
error: text("error"),
|
|
68
|
+
conversationId: text("conversation_id"),
|
|
69
|
+
createdAt: integer("created_at").notNull(),
|
|
70
|
+
});
|
|
71
|
+
|
|
57
72
|
export const sharedAppLinks = sqliteTable("shared_app_links", {
|
|
58
73
|
id: text("id").primaryKey(),
|
|
59
74
|
shareToken: text("share_token").notNull().unique(),
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { inArray } from "drizzle-orm";
|
|
2
2
|
|
|
3
|
+
import { getConfig } from "../../config/loader.js";
|
|
4
|
+
import { isMemoryV2ReadActive } from "../context-search/sources/memory-v2.js";
|
|
3
5
|
import { getDb } from "../db-connection.js";
|
|
4
6
|
import { withQdrantBreaker } from "../qdrant-circuit-breaker.js";
|
|
5
7
|
import type {
|
|
@@ -7,7 +9,7 @@ import type {
|
|
|
7
9
|
QdrantSparseVector,
|
|
8
10
|
} from "../qdrant-client.js";
|
|
9
11
|
import { getQdrantClient } from "../qdrant-client.js";
|
|
10
|
-
import {
|
|
12
|
+
import { memorySegments, memorySummaries } from "../schema.js";
|
|
11
13
|
// ── Types (inlined from deleted types.ts) ──────────────────────────
|
|
12
14
|
|
|
13
15
|
type CandidateType = "segment" | "item" | "summary" | "media";
|
|
@@ -50,11 +52,15 @@ export async function semanticSearch(
|
|
|
50
52
|
_model: string,
|
|
51
53
|
limit: number,
|
|
52
54
|
excludedMessageIds: string[] = [],
|
|
53
|
-
scopeIds?: string[],
|
|
54
55
|
sparseVector?: QdrantSparseVector,
|
|
55
56
|
): Promise<Candidate[]> {
|
|
56
57
|
if (limit <= 0) return [];
|
|
57
58
|
|
|
59
|
+
// v2 owns the read path when both gates are on; the v1 `memory` collection
|
|
60
|
+
// is in active retirement, and routing semantic recall there would re-enter
|
|
61
|
+
// the same corrupted sparse segments that can OOM-crash Qdrant.
|
|
62
|
+
if (isMemoryV2ReadActive(getConfig())) return [];
|
|
63
|
+
|
|
58
64
|
const qdrant = getQdrantClient();
|
|
59
65
|
|
|
60
66
|
// Overfetch to account for items filtered out post-query (invalidated, excluded, etc.)
|
|
@@ -68,7 +74,7 @@ export async function semanticSearch(
|
|
|
68
74
|
let isHybrid = false;
|
|
69
75
|
if (sparseVector && sparseVector.indices.length > 0) {
|
|
70
76
|
isHybrid = true;
|
|
71
|
-
const filter = buildHybridFilter(excludedMessageIds
|
|
77
|
+
const filter = buildHybridFilter(excludedMessageIds);
|
|
72
78
|
results = await withQdrantBreaker(() =>
|
|
73
79
|
qdrant.hybridSearch({
|
|
74
80
|
denseVector: queryVector,
|
|
@@ -85,7 +91,6 @@ export async function semanticSearch(
|
|
|
85
91
|
fetchLimit,
|
|
86
92
|
["summary", "segment", "media"],
|
|
87
93
|
excludedMessageIds,
|
|
88
|
-
scopeIds,
|
|
89
94
|
),
|
|
90
95
|
);
|
|
91
96
|
}
|
|
@@ -95,18 +100,15 @@ export async function semanticSearch(
|
|
|
95
100
|
// Batch-fetch all backing records upfront to avoid N+1 queries per result
|
|
96
101
|
const summaryTargetIds: string[] = [];
|
|
97
102
|
const segmentTargetIds: string[] = [];
|
|
98
|
-
const mediaConversationIds: string[] = [];
|
|
99
103
|
for (const r of results) {
|
|
100
104
|
if (r.payload.target_type === "summary")
|
|
101
105
|
summaryTargetIds.push(r.payload.target_id);
|
|
102
106
|
else if (r.payload.target_type === "segment")
|
|
103
107
|
segmentTargetIds.push(r.payload.target_id);
|
|
104
|
-
else if (r.payload.target_type === "media" && r.payload.conversation_id)
|
|
105
|
-
mediaConversationIds.push(r.payload.conversation_id);
|
|
106
108
|
}
|
|
107
109
|
|
|
108
110
|
const summariesMap = new Map<string, typeof memorySummaries.$inferSelect>();
|
|
109
|
-
if (
|
|
111
|
+
if (summaryTargetIds.length > 0) {
|
|
110
112
|
const allSummaries = db
|
|
111
113
|
.select()
|
|
112
114
|
.from(memorySummaries)
|
|
@@ -116,7 +118,7 @@ export async function semanticSearch(
|
|
|
116
118
|
}
|
|
117
119
|
|
|
118
120
|
const segmentsMap = new Map<string, typeof memorySegments.$inferSelect>();
|
|
119
|
-
if (
|
|
121
|
+
if (segmentTargetIds.length > 0) {
|
|
120
122
|
const allSegments = db
|
|
121
123
|
.select()
|
|
122
124
|
.from(memorySegments)
|
|
@@ -125,23 +127,6 @@ export async function semanticSearch(
|
|
|
125
127
|
for (const seg of allSegments) segmentsMap.set(seg.id, seg);
|
|
126
128
|
}
|
|
127
129
|
|
|
128
|
-
// Batch-fetch conversation scope IDs for media results to avoid N+1 queries.
|
|
129
|
-
// When a conversation is not found (deleted), its media is excluded rather than
|
|
130
|
-
// falling back to "default" scope, which would leak private media.
|
|
131
|
-
const mediaScopeMap = new Map<string, string>();
|
|
132
|
-
if (scopeIds && mediaConversationIds.length > 0) {
|
|
133
|
-
const unique = [...new Set(mediaConversationIds)];
|
|
134
|
-
const rows = db
|
|
135
|
-
.select({
|
|
136
|
-
id: conversations.id,
|
|
137
|
-
memoryScopeId: conversations.memoryScopeId,
|
|
138
|
-
})
|
|
139
|
-
.from(conversations)
|
|
140
|
-
.where(inArray(conversations.id, unique))
|
|
141
|
-
.all();
|
|
142
|
-
for (const row of rows) mediaScopeMap.set(row.id, row.memoryScopeId);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
130
|
const candidates: Candidate[] = [];
|
|
146
131
|
for (const result of results) {
|
|
147
132
|
const { payload, score } = result;
|
|
@@ -153,10 +138,7 @@ export async function semanticSearch(
|
|
|
153
138
|
// Legacy item vectors — skip (table dropped, Qdrant cleanup pending)
|
|
154
139
|
continue;
|
|
155
140
|
} else if (payload.target_type === "summary") {
|
|
156
|
-
if (
|
|
157
|
-
const summary = summariesMap.get(payload.target_id);
|
|
158
|
-
if (!summary || !scopeIds.includes(summary.scopeId)) continue;
|
|
159
|
-
}
|
|
141
|
+
if (!summariesMap.has(payload.target_id)) continue;
|
|
160
142
|
candidates.push({
|
|
161
143
|
key: `summary:${payload.target_id}`,
|
|
162
144
|
type: "summary",
|
|
@@ -173,22 +155,6 @@ export async function semanticSearch(
|
|
|
173
155
|
finalScore: 0,
|
|
174
156
|
});
|
|
175
157
|
} else if (payload.target_type === "media") {
|
|
176
|
-
// Use stored memory_scope_id when available; fall back to deriving
|
|
177
|
-
// scope from conversation_id for legacy media points.
|
|
178
|
-
// If the conversation was deleted, skip the media to avoid leaking
|
|
179
|
-
// private media into the default scope.
|
|
180
|
-
if (scopeIds) {
|
|
181
|
-
let mediaScopeId: string | undefined;
|
|
182
|
-
if (payload.memory_scope_id) {
|
|
183
|
-
mediaScopeId = payload.memory_scope_id;
|
|
184
|
-
} else if (payload.conversation_id) {
|
|
185
|
-
mediaScopeId = mediaScopeMap.get(payload.conversation_id);
|
|
186
|
-
if (!mediaScopeId) continue; // conversation deleted — skip
|
|
187
|
-
} else {
|
|
188
|
-
mediaScopeId = "default";
|
|
189
|
-
}
|
|
190
|
-
if (!scopeIds.includes(mediaScopeId)) continue;
|
|
191
|
-
}
|
|
192
158
|
candidates.push({
|
|
193
159
|
key: `media:${payload.target_id}`,
|
|
194
160
|
type: "media",
|
|
@@ -205,10 +171,7 @@ export async function semanticSearch(
|
|
|
205
171
|
finalScore: 0,
|
|
206
172
|
});
|
|
207
173
|
} else {
|
|
208
|
-
if (
|
|
209
|
-
const segment = segmentsMap.get(payload.target_id);
|
|
210
|
-
if (!segment || !scopeIds.includes(segment.scopeId)) continue;
|
|
211
|
-
}
|
|
174
|
+
if (!segmentsMap.has(payload.target_id)) continue;
|
|
212
175
|
candidates.push({
|
|
213
176
|
key: `segment:${payload.target_id}`,
|
|
214
177
|
type: "segment",
|
|
@@ -247,14 +210,9 @@ export async function semanticSearch(
|
|
|
247
210
|
/**
|
|
248
211
|
* Build a Qdrant filter for hybrid search. Mirrors the logic in
|
|
249
212
|
* `searchWithFilter` but as a standalone object for the query API.
|
|
250
|
-
*
|
|
251
|
-
* Scope filtering: points with a `memory_scope_id` payload field are
|
|
252
|
-
* filtered at the Qdrant level. Legacy points without the field pass
|
|
253
|
-
* through and are caught by post-query DB filtering.
|
|
254
213
|
*/
|
|
255
214
|
function buildHybridFilter(
|
|
256
215
|
excludeMessageIds: string[],
|
|
257
|
-
scopeIds?: string[],
|
|
258
216
|
): Record<string, unknown> {
|
|
259
217
|
const mustConditions: Array<Record<string, unknown>> = [
|
|
260
218
|
{
|
|
@@ -263,18 +221,6 @@ function buildHybridFilter(
|
|
|
263
221
|
},
|
|
264
222
|
];
|
|
265
223
|
|
|
266
|
-
// Scope filtering: accept points whose memory_scope_id matches one of the
|
|
267
|
-
// allowed scopes, OR points that lack the field entirely (legacy data).
|
|
268
|
-
// Post-query DB filtering remains as defense-in-depth for legacy points.
|
|
269
|
-
if (scopeIds && scopeIds.length > 0) {
|
|
270
|
-
mustConditions.push({
|
|
271
|
-
should: [
|
|
272
|
-
{ key: "memory_scope_id", match: { any: scopeIds } },
|
|
273
|
-
{ is_empty: { key: "memory_scope_id" } },
|
|
274
|
-
],
|
|
275
|
-
});
|
|
276
|
-
}
|
|
277
|
-
|
|
278
224
|
const mustNotConditions: Array<Record<string, unknown>> = [
|
|
279
225
|
{ key: "_meta", match: { value: true } },
|
|
280
226
|
];
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Sparse-vector tokenization primitives
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
//
|
|
5
|
+
// Shared by both the legacy TF-only encoder in `embedding-backend.ts`
|
|
6
|
+
// (`generateSparseEmbedding`) and the BM25 encoder in `v2/sparse-bm25.ts`.
|
|
7
|
+
//
|
|
8
|
+
// Lives in its own module so consumers of the BM25 encoder don't transitively
|
|
9
|
+
// depend on `embedding-backend.ts` for these primitives — that matters
|
|
10
|
+
// because many tests mock `embedding-backend.js` wholesale via
|
|
11
|
+
// `mock.module(...)`, and a missing export from the mock would break any
|
|
12
|
+
// transitive importer of these helpers.
|
|
13
|
+
|
|
14
|
+
import { stemmer } from "stemmer";
|
|
15
|
+
|
|
16
|
+
/** Hashed-vocabulary size for sparse encoders. */
|
|
17
|
+
export const SPARSE_VOCAB_SIZE = 30_000;
|
|
18
|
+
|
|
19
|
+
/** Tokenize text into lowercase alphanumeric tokens (Unicode-aware). */
|
|
20
|
+
export function tokenize(text: string): string[] {
|
|
21
|
+
return text.toLowerCase().match(/[\p{L}\p{N}]+/gu) ?? [];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Tokenize and apply Porter stemming so morphological variants collapse to a
|
|
26
|
+
* shared bucket (e.g. `running`/`runs`/`ran` → `run`, `supplements` →
|
|
27
|
+
* `supplement`). Used only by the BM25 sparse channel in
|
|
28
|
+
* `v2/sparse-bm25.ts`; both the document-side and query-side encoders call
|
|
29
|
+
* this so doc and query tokens land in the same hash buckets.
|
|
30
|
+
*
|
|
31
|
+
* Other callers (workspace context-search, the legacy TF-only
|
|
32
|
+
* `generateSparseEmbedding`) intentionally keep the non-stemmed `tokenize()`
|
|
33
|
+
* because they predate this and rebuilding their on-disk indexes is out of
|
|
34
|
+
* scope here.
|
|
35
|
+
*/
|
|
36
|
+
export function tokenizeStemmed(text: string): string[] {
|
|
37
|
+
return tokenize(text).map((token) => stemmer(token));
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** Hash a token to a stable index in [0, vocabSize). */
|
|
41
|
+
export function tokenHash(token: string, vocabSize: number): number {
|
|
42
|
+
// FNV-1a 32-bit hash for speed
|
|
43
|
+
let hash = 0x811c9dc5;
|
|
44
|
+
for (let i = 0; i < token.length; i++) {
|
|
45
|
+
hash ^= token.charCodeAt(i);
|
|
46
|
+
hash = Math.imul(hash, 0x01000193) >>> 0;
|
|
47
|
+
}
|
|
48
|
+
return hash % vocabSize;
|
|
49
|
+
}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import { and, asc, eq, gt,
|
|
1
|
+
import { and, asc, eq, gt, sql } from "drizzle-orm";
|
|
2
2
|
|
|
3
3
|
import type {
|
|
4
4
|
TraceEvent,
|
|
5
5
|
TraceEventKind,
|
|
6
6
|
} from "../daemon/message-types/messages.js";
|
|
7
7
|
import { getDb } from "./db-connection.js";
|
|
8
|
-
import { rawChanges } from "./raw-query.js";
|
|
9
8
|
import { traceEvents } from "./schema.js";
|
|
10
9
|
|
|
11
10
|
// ---------------------------------------------------------------------------
|
|
@@ -115,21 +114,6 @@ export function getTraceEvents(
|
|
|
115
114
|
return rows.map(rowToTraceEventRow);
|
|
116
115
|
}
|
|
117
116
|
|
|
118
|
-
// ---------------------------------------------------------------------------
|
|
119
|
-
// Cleanup
|
|
120
|
-
// ---------------------------------------------------------------------------
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Delete trace events older than `maxAgeDays` based on `created_at`.
|
|
124
|
-
* Returns the count of deleted rows.
|
|
125
|
-
*/
|
|
126
|
-
export function deleteOldTraceEvents(maxAgeDays: number): number {
|
|
127
|
-
const db = getDb();
|
|
128
|
-
const cutoff = Date.now() - maxAgeDays * 24 * 60 * 60 * 1000;
|
|
129
|
-
db.delete(traceEvents).where(lt(traceEvents.createdAt, cutoff)).run();
|
|
130
|
-
return rawChanges();
|
|
131
|
-
}
|
|
132
|
-
|
|
133
117
|
// ---------------------------------------------------------------------------
|
|
134
118
|
// Sequence
|
|
135
119
|
// ---------------------------------------------------------------------------
|