@vellumai/assistant 0.7.1 → 0.7.2
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 +32 -49
- 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/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 +39 -1
- 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/skill-host-contracts/src/assistant-event.ts +9 -0
- 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 +565 -12
- 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 +374 -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 +109 -2
- package/src/__tests__/assistant-event.test.ts +10 -0
- package/src/__tests__/assistant-events-sse-hardening.test.ts +7 -2
- package/src/__tests__/assistant-feature-flags-integration.test.ts +11 -7
- package/src/__tests__/background-shell-host-bash.test.ts +14 -15
- 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-domain.test.ts +0 -2
- package/src/__tests__/call-routes-http.test.ts +0 -2
- package/src/__tests__/channel-readiness-service.test.ts +59 -1
- package/src/__tests__/checker.test.ts +3 -4
- package/src/__tests__/config-loader-backfill.test.ts +90 -155
- 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-set-platform-guard.test.ts +48 -4
- package/src/__tests__/config-watcher-cleanup-throttle.test.ts +2 -2
- package/src/__tests__/config-watcher.test.ts +2 -2
- 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-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-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-slash-commands.test.ts +0 -4
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +202 -0
- package/src/__tests__/conversation-surfaces-app-control.test.ts +317 -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 +5 -12
- package/src/__tests__/cu-unified-flow.test.ts +185 -23
- package/src/__tests__/daemon-credential-client.test.ts +101 -19
- package/src/__tests__/db-schedule-syntax-migration.test.ts +2 -0
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
- 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-service.test.ts +718 -1
- package/src/__tests__/helpers/call-route-handler.ts +7 -1
- package/src/__tests__/host-app-control-proxy.test.ts +602 -0
- package/src/__tests__/host-app-control-routes.test.ts +263 -0
- package/src/__tests__/host-bash-proxy.test.ts +246 -47
- package/src/__tests__/host-bash-routes.test.ts +294 -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 +41 -52
- package/src/__tests__/host-cu-routes-targeted.test.ts +300 -0
- package/src/__tests__/host-file-edit-tool.test.ts +47 -1
- package/src/__tests__/host-file-proxy-targeted.test.ts +339 -0
- package/src/__tests__/host-file-proxy.test.ts +37 -43
- package/src/__tests__/host-file-read-tool.test.ts +17 -0
- package/src/__tests__/host-file-routes-targeted.test.ts +262 -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 +583 -0
- package/src/__tests__/host-transfer-proxy.test.ts +121 -22
- package/src/__tests__/host-transfer-routes-targeted.test.ts +447 -0
- package/src/__tests__/http-user-message-parity.test.ts +1 -0
- 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__/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-skill-lifecycle.test.ts +0 -1
- package/src/__tests__/mcp-auth-routes.test.ts +197 -0
- package/src/__tests__/mcp-cli.test.ts +338 -2
- package/src/__tests__/memory-jobs-worker-lanes.test.ts +188 -0
- package/src/__tests__/migration-import-commit-http.test.ts +108 -2
- package/src/__tests__/mock-gateway-ipc.ts +1 -0
- package/src/__tests__/oauth-cli.test.ts +0 -2
- package/src/__tests__/oauth2-gateway-transport.test.ts +0 -1
- package/src/__tests__/persistence-secret-redaction.test.ts +299 -0
- package/src/__tests__/platform-bash-auto-approve.test.ts +5 -9
- package/src/__tests__/prechat-onboarding-contract.test.ts +3 -1
- 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__/public-ingress-urls.test.ts +97 -0
- 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 +10 -6
- package/src/__tests__/sanitize-config-for-transfer.test.ts +24 -2
- package/src/__tests__/schedule-retry.test.ts +715 -0
- package/src/__tests__/script-proxy-mitm-handler.test.ts +1 -1
- package/src/__tests__/secret-ingress-http.test.ts +1 -0
- 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__/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-backfill-installation-id.test.ts +1 -5
- package/src/__tests__/workspace-migration-down-functions.test.ts +8 -8
- package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +10 -6
- 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/bundler/app-bundler.ts +51 -3
- 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 -1
- package/src/cli/commands/backup.ts +6 -331
- package/src/cli/commands/clients.ts +36 -37
- package/src/cli/commands/contacts.ts +73 -0
- package/src/cli/commands/conversations.ts +2 -5
- package/src/cli/commands/credentials.ts +15 -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 +296 -1
- package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +0 -1
- package/src/cli/commands/platform/__tests__/connect.test.ts +0 -2
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +0 -2
- package/src/cli/commands/platform/__tests__/status.test.ts +13 -15
- package/src/cli/commands/platform/disconnect.ts +5 -4
- package/src/cli/commands/platform/index.ts +0 -18
- package/src/cli/lib/daemon-credential-client.ts +110 -28
- package/src/cli/program.ts +2 -0
- package/src/config/assistant-feature-flags.ts +67 -10
- 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/phone-calls/TOOLS.json +0 -12
- package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +19 -4
- package/src/config/bundled-skills/playbooks/TOOLS.json +0 -16
- 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 -12
- package/src/config/feature-flag-registry.json +21 -133
- package/src/config/loader.ts +73 -99
- 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 +7 -4
- package/src/config/schemas/calls.ts +0 -9
- package/src/config/schemas/heartbeat.ts +63 -0
- package/src/config/schemas/ingress.ts +10 -6
- package/src/config/schemas/llm.ts +5 -10
- package/src/config/schemas/memory-lifecycle.ts +77 -24
- package/src/config/schemas/memory-v2.ts +48 -4
- package/src/config/schemas/platform.ts +6 -0
- package/src/config/schemas/services.ts +1 -15
- package/src/config/schemas/skills.ts +0 -6
- package/src/config/seed-inference-profiles.ts +1 -1
- package/src/contacts/contact-store.ts +0 -30
- 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 +126 -5
- package/src/daemon/bootstrap-turn-cleanup.ts +45 -0
- package/src/daemon/config-watcher.ts +4 -3
- package/src/daemon/conversation-agent-loop-handlers.ts +21 -3
- package/src/daemon/conversation-agent-loop.ts +32 -28
- package/src/daemon/conversation-lifecycle.ts +8 -1
- package/src/daemon/conversation-process.ts +16 -11
- package/src/daemon/conversation-runtime-assembly.ts +2 -2
- package/src/daemon/conversation-surfaces.ts +125 -4
- package/src/daemon/conversation-tool-setup.ts +16 -55
- package/src/daemon/conversation.ts +21 -2
- package/src/daemon/doordash-steps.ts +1 -1
- package/src/daemon/handlers/shared.ts +4 -1
- package/src/daemon/host-app-control-proxy.ts +293 -0
- package/src/daemon/host-bash-proxy.ts +84 -74
- package/src/daemon/host-browser-proxy.ts +67 -82
- package/src/daemon/host-cu-proxy.ts +81 -86
- package/src/daemon/host-file-proxy.ts +93 -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 +247 -129
- package/src/daemon/lifecycle.ts +115 -117
- package/src/daemon/message-protocol.ts +3 -8
- package/src/daemon/message-types/contacts.ts +23 -1
- package/src/daemon/message-types/conversations.ts +11 -8
- 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/schedules.ts +8 -3
- package/src/daemon/message-types/skills.ts +2 -2
- package/src/daemon/process-message.ts +18 -1
- 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/events/tool-audit-listener.ts +2 -1
- package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +15 -7
- package/src/heartbeat/__tests__/heartbeat-run-store.test.ts +216 -0
- package/src/heartbeat/heartbeat-run-store.ts +236 -0
- package/src/heartbeat/heartbeat-service.ts +280 -49
- 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/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/public-ingress-urls.ts +32 -34
- package/src/ipc/__tests__/route-error-envelope.test.ts +80 -0
- package/src/ipc/assistant-server.ts +14 -1
- package/src/ipc/cli-client.ts +32 -1
- package/src/live-voice/live-voice-metrics.ts +10 -10
- 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/memory/__tests__/jobs-store-job-classes.test.ts +24 -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/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 +32 -7
- package/src/memory/context-search/sources/memory-v2.ts +17 -5
- package/src/memory/conversation-crud.ts +1 -1
- package/src/memory/conversation-key-store.ts +2 -15
- package/src/memory/db-init.ts +4 -0
- package/src/memory/embedding-backend.ts +9 -21
- package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +49 -4
- package/src/memory/graph/conversation-graph-memory.ts +1 -24
- package/src/memory/graph/graph-search.ts +8 -0
- package/src/memory/graph/retriever.ts +28 -0
- package/src/memory/graph/tools.ts +1 -1
- 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 +66 -22
- package/src/memory/jobs-worker.ts +112 -63
- package/src/memory/memory-v2-activation-log-store.ts +1 -1
- 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/index.ts +5 -0
- package/src/memory/migrations/registry.ts +8 -0
- package/src/memory/pkb/pkb-search.ts +7 -0
- package/src/memory/qdrant-client.ts +50 -20
- package/src/memory/schema/infrastructure.ts +15 -0
- package/src/memory/search/semantic.ts +7 -0
- package/src/memory/sparse-tokenize.ts +49 -0
- package/src/memory/v2/__tests__/activation.test.ts +77 -95
- package/src/memory/v2/__tests__/injection.test.ts +43 -21
- package/src/memory/v2/__tests__/sim.test.ts +166 -6
- package/src/memory/v2/__tests__/sparse-bm25.test.ts +292 -0
- package/src/memory/v2/__tests__/static-context.test.ts +0 -1
- package/src/memory/v2/activation.ts +69 -88
- package/src/memory/v2/consolidation-job.ts +3 -5
- package/src/memory/v2/constants.ts +7 -0
- package/src/memory/v2/injection.ts +86 -53
- package/src/memory/v2/prompts/consolidation.ts +312 -91
- package/src/memory/v2/qdrant.ts +99 -1
- package/src/memory/v2/sim.ts +126 -16
- package/src/memory/v2/skill-qdrant.ts +12 -3
- package/src/memory/v2/skill-store.ts +16 -1
- package/src/memory/v2/sparse-bm25.ts +245 -0
- package/src/memory/v2/static-context.ts +6 -5
- 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/guardian-question-mode.ts +5 -5
- package/src/oauth/connect-orchestrator.ts +4 -0
- package/src/oauth/credential-token-resolver.ts +1 -3
- package/src/oauth/manual-token-connection.ts +0 -4
- 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/prompts/bootstrap-cleanup.ts +27 -0
- package/src/prompts/system-prompt.ts +3 -18
- package/src/prompts/templates/SOUL.md +13 -1
- package/src/providers/speech-to-text/provider-catalog.ts +7 -8
- package/src/runtime/assistant-event-hub.ts +118 -96
- package/src/runtime/assistant-event.ts +1 -0
- package/src/runtime/auth/__tests__/middleware.test.ts +11 -56
- package/src/runtime/auth/middleware.ts +0 -96
- package/src/runtime/auth/route-policy.ts +19 -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/http-server.ts +3 -329
- package/src/runtime/http-types.ts +0 -5
- 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 +35 -9
- package/src/runtime/routes/__tests__/backup-routes.test.ts +22 -150
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +98 -0
- 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 +1 -0
- package/src/runtime/routes/contact-prompt-routes.ts +183 -0
- package/src/runtime/routes/conversation-query-routes.ts +36 -1
- package/src/runtime/routes/conversation-routes.ts +30 -13
- package/src/runtime/routes/document-pdf-renderer.ts +165 -0
- package/src/runtime/routes/documents-routes.ts +30 -0
- package/src/runtime/routes/errors.ts +19 -4
- package/src/runtime/routes/events-routes.ts +12 -6
- 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 +36 -6
- package/src/runtime/routes/host-browser-routes.ts +108 -13
- package/src/runtime/routes/host-cu-routes.ts +44 -14
- package/src/runtime/routes/host-file-routes.ts +33 -10
- package/src/runtime/routes/host-transfer-routes.ts +64 -24
- 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 +15 -43
- package/src/runtime/routes/inbound-message-handler.ts +1 -9
- 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/transcribe-audio.test.ts +0 -20
- package/src/runtime/routes/inbound-stages/transcribe-audio.ts +5 -13
- package/src/runtime/routes/index.ts +8 -0
- package/src/runtime/routes/mcp-auth-routes.ts +132 -0
- package/src/runtime/routes/memory-item-routes.ts +10 -12
- package/src/runtime/routes/memory-v2-routes.ts +441 -1
- package/src/runtime/routes/migration-routes.ts +96 -0
- package/src/runtime/routes/schedule-routes.ts +7 -0
- 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/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 +63 -38
- package/src/security/oauth-callback-registry.ts +8 -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 +5 -5
- 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/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/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.ts +26 -0
- package/src/tools/host-filesystem/read.ts +26 -0
- package/src/tools/host-filesystem/transfer.ts +31 -1
- package/src/tools/host-filesystem/write.ts +26 -0
- package/src/tools/host-terminal/host-shell.ts +58 -0
- 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/tool-approval-handler.ts +1 -5
- package/src/tools/types.ts +4 -0
- package/src/usage/pricing.ts +1 -1
- package/src/workspace/hatched-date.ts +86 -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/AGENTS.md +1 -1
- package/src/workspace/migrations/migrate-to-workspace-volume.ts +4 -10
- package/src/workspace/migrations/utils.ts +21 -0
- 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/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/mcp-reload.ts +0 -18
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
// for the next turn and drop below `epsilon` if no longer relevant.
|
|
33
33
|
|
|
34
34
|
import type { AssistantConfig } from "../../config/types.js";
|
|
35
|
+
import { applyCorrectionIfCalibrated } from "../anisotropy.js";
|
|
35
36
|
import {
|
|
36
37
|
embedWithBackend,
|
|
37
38
|
generateSparseEmbedding,
|
|
@@ -40,22 +41,29 @@ import { clampUnitInterval } from "../validation.js";
|
|
|
40
41
|
import type { EdgeIndex } from "./edge-index.js";
|
|
41
42
|
import { hybridQueryConceptPages } from "./qdrant.js";
|
|
42
43
|
import { simBatch, simSkillBatch } from "./sim.js";
|
|
43
|
-
import { hybridQuerySkills } from "./skill-qdrant.js";
|
|
44
44
|
import type { ActivationState, EverInjectedEntry } from "./types.js";
|
|
45
45
|
|
|
46
46
|
/**
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
47
|
+
* Sentinel passed to Qdrant when `config.memory.v2.ann_candidate_limit` is
|
|
48
|
+
* `null` (unlimited). Qdrant's query API requires an explicit numeric
|
|
49
|
+
* `limit`, so unlimited is represented as a number large enough that any
|
|
50
|
+
* realistic concept-page collection is returned in full.
|
|
51
|
+
*
|
|
52
|
+
* Why not `Number.MAX_SAFE_INTEGER`: Qdrant's sparse-vector `SearchContext`
|
|
53
|
+
* pre-allocates `limit * 16` bytes per query, so passing `MAX_SAFE_INTEGER`
|
|
54
|
+
* triggers a ~144 PB allocation and SIGABRTs the Qdrant process. 1_000_000
|
|
55
|
+
* is ~16 MB of pre-allocation in Qdrant — generous headroom over realistic
|
|
56
|
+
* concept-page counts (low thousands today) while staying well clear of
|
|
57
|
+
* the OOM cliff. Bump explicitly via `ann_candidate_limit` if you ever
|
|
58
|
+
* outgrow it.
|
|
51
59
|
*/
|
|
52
|
-
const
|
|
60
|
+
const UNLIMITED_ANN_CANDIDATE_LIMIT = 1_000_000;
|
|
53
61
|
|
|
54
62
|
// ---------------------------------------------------------------------------
|
|
55
63
|
// Candidate selection
|
|
56
64
|
// ---------------------------------------------------------------------------
|
|
57
65
|
|
|
58
|
-
|
|
66
|
+
interface SelectCandidatesParams {
|
|
59
67
|
/**
|
|
60
68
|
* Prior-turn activation snapshot. Slugs with activation strictly greater
|
|
61
69
|
* than `config.memory.v2.epsilon` are carried forward as candidates so the
|
|
@@ -71,7 +79,7 @@ export interface SelectCandidatesParams {
|
|
|
71
79
|
config: AssistantConfig;
|
|
72
80
|
}
|
|
73
81
|
|
|
74
|
-
|
|
82
|
+
interface SelectCandidatesResult {
|
|
75
83
|
/** Union of `fromPrior` and `fromAnn` — the per-turn candidate set. */
|
|
76
84
|
candidates: Set<string>;
|
|
77
85
|
/** Slugs carried forward from `priorState` because their activation > epsilon. */
|
|
@@ -118,13 +126,15 @@ export async function selectCandidates(
|
|
|
118
126
|
|
|
119
127
|
if (annQueryText.length > 0) {
|
|
120
128
|
const denseResult = await embedWithBackend(config, [annQueryText]);
|
|
121
|
-
const dense =
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
sparse,
|
|
126
|
-
ANN_CANDIDATE_LIMIT,
|
|
129
|
+
const dense = await applyCorrectionIfCalibrated(
|
|
130
|
+
denseResult.vectors[0],
|
|
131
|
+
denseResult.provider,
|
|
132
|
+
denseResult.model,
|
|
127
133
|
);
|
|
134
|
+
const sparse = generateSparseEmbedding(annQueryText);
|
|
135
|
+
const limit =
|
|
136
|
+
config.memory.v2.ann_candidate_limit ?? UNLIMITED_ANN_CANDIDATE_LIMIT;
|
|
137
|
+
const hits = await hybridQueryConceptPages(dense, sparse, limit);
|
|
128
138
|
for (const hit of hits) fromAnn.add(hit.slug);
|
|
129
139
|
}
|
|
130
140
|
|
|
@@ -137,7 +147,7 @@ export async function selectCandidates(
|
|
|
137
147
|
// Own activation
|
|
138
148
|
// ---------------------------------------------------------------------------
|
|
139
149
|
|
|
140
|
-
|
|
150
|
+
interface ComputeOwnActivationParams {
|
|
141
151
|
candidates: ReadonlySet<string>;
|
|
142
152
|
priorState: ActivationState | null;
|
|
143
153
|
userText: string;
|
|
@@ -151,7 +161,7 @@ export interface ComputeOwnActivationParams {
|
|
|
151
161
|
* coefficient weighting is applied. Surfaced for telemetry / inspector views
|
|
152
162
|
* so the UI can show how each term contributed to the final value.
|
|
153
163
|
*/
|
|
154
|
-
|
|
164
|
+
interface OwnActivationBreakdown {
|
|
155
165
|
/** `d * prev(slug)` — the decayed prior-turn activation contribution. */
|
|
156
166
|
priorContribution: number;
|
|
157
167
|
/** Raw `sim(user, slug)` similarity, before `c_user` weighting. */
|
|
@@ -162,7 +172,7 @@ export interface OwnActivationBreakdown {
|
|
|
162
172
|
simNow: number;
|
|
163
173
|
}
|
|
164
174
|
|
|
165
|
-
|
|
175
|
+
interface ComputeOwnActivationResult {
|
|
166
176
|
/** Final clamped own-activation value per slug. */
|
|
167
177
|
activation: Map<string, number>;
|
|
168
178
|
/** Per-slug breakdown of the inputs that fed into `activation`. */
|
|
@@ -222,7 +232,7 @@ export async function computeOwnActivation(
|
|
|
222
232
|
// Spreading activation
|
|
223
233
|
// ---------------------------------------------------------------------------
|
|
224
234
|
|
|
225
|
-
|
|
235
|
+
interface SpreadActivationResult {
|
|
226
236
|
/** Final activation value per slug after spreading. */
|
|
227
237
|
final: Map<string, number>;
|
|
228
238
|
/**
|
|
@@ -239,20 +249,25 @@ export interface SpreadActivationResult {
|
|
|
239
249
|
* Apply 2-hop spreading activation with neighborhood normalization. Edges are
|
|
240
250
|
* directed: an edge A→B means A's activation contributes to B's final value.
|
|
241
251
|
*
|
|
242
|
-
* A(n) = [ A_o(n) +
|
|
243
|
-
* /
|
|
252
|
+
* A(n) = [ A_o(n) + Σ_{r: |active_inR(n)| > 0} k^r · L2(active_inR(n)) ]
|
|
253
|
+
* / [ 1 + Σ_{r: |active_inR(n)| > 0} k^r ]
|
|
254
|
+
*
|
|
255
|
+
* `active_inR(n)` is the subset of structural predecessors at hop `r` that
|
|
256
|
+
* also appear in `ownActivation` (i.e. made the candidate set). `L2(.)` is
|
|
257
|
+
* the quadratic mean √(mean(A_o²)) — a mild bias toward strong outliers
|
|
258
|
+
* compared to the arithmetic mean, without letting a single high-cosine
|
|
259
|
+
* predecessor dominate the way `max` would.
|
|
244
260
|
*
|
|
245
|
-
*
|
|
246
|
-
*
|
|
247
|
-
*
|
|
248
|
-
*
|
|
249
|
-
*
|
|
250
|
-
* predecessors contribute 0 to the numerator.
|
|
261
|
+
* Hops with **no** active predecessors are dropped from BOTH numerator and
|
|
262
|
+
* denominator so a high-in-degree hub with mostly-inactive neighbors stays
|
|
263
|
+
* near `A_o` instead of being crushed by the structural count. A pure
|
|
264
|
+
* source (no incoming edges, or every edge points at a non-candidate)
|
|
265
|
+
* collapses to `A == A_o`.
|
|
251
266
|
*
|
|
252
|
-
* Bounded in [0, 1]:
|
|
253
|
-
* at most `1 +
|
|
254
|
-
*
|
|
255
|
-
*
|
|
267
|
+
* Bounded in [0, 1]: every `L2` term ≤ max active A_o ≤ 1, so the numerator
|
|
268
|
+
* is at most `1 + Σ k^r` — exactly the denominator — so the ratio is at most
|
|
269
|
+
* 1. `clampUnitInterval` guards against numerical drift and out-of-range
|
|
270
|
+
* inputs.
|
|
256
271
|
*
|
|
257
272
|
* Pure function — no I/O. Reads the precomputed `incoming` map from
|
|
258
273
|
* `edgeIndex` and runs a per-source BFS bounded by `hops`.
|
|
@@ -282,22 +297,28 @@ export function spreadActivation(
|
|
|
282
297
|
// hop-0 only via `numerator = ownValue`.
|
|
283
298
|
const distance = bfsPredecessorDistances(edgeIndex.incoming, slug, hops);
|
|
284
299
|
|
|
300
|
+
// Bucket only predecessors that are in `ownActivation` (the candidate
|
|
301
|
+
// set). Structural predecessors that didn't make the cut contribute
|
|
302
|
+
// nothing — neither to the numerator nor the denominator — so hub
|
|
303
|
+
// in-degree alone never penalizes a node.
|
|
304
|
+
const ringActiveCounts: number[] = new Array(hops + 1).fill(0);
|
|
305
|
+
const ringSquareSums: number[] = new Array(hops + 1).fill(0);
|
|
306
|
+
for (const [predecessor, hop] of distance) {
|
|
307
|
+
const predValue = ownActivation.get(predecessor);
|
|
308
|
+
if (predValue === undefined) continue;
|
|
309
|
+
ringActiveCounts[hop] += 1;
|
|
310
|
+
ringSquareSums[hop] += predValue * predValue;
|
|
311
|
+
}
|
|
312
|
+
|
|
285
313
|
let numerator = ownValue;
|
|
286
314
|
let denominator = 1;
|
|
287
315
|
let kPow = 1;
|
|
288
|
-
// Accumulate per-hop contributions in a single pass. We need per-hop
|
|
289
|
-
// counts to weight by k^r, so bucket as we go.
|
|
290
|
-
const ringCounts: number[] = new Array(hops + 1).fill(0);
|
|
291
|
-
const ringSums: number[] = new Array(hops + 1).fill(0);
|
|
292
|
-
for (const [predecessor, hop] of distance) {
|
|
293
|
-
ringCounts[hop] += 1;
|
|
294
|
-
ringSums[hop] += ownActivation.get(predecessor) ?? 0;
|
|
295
|
-
}
|
|
296
316
|
for (let r = 1; r <= hops; r++) {
|
|
297
317
|
kPow *= k;
|
|
298
|
-
if (
|
|
299
|
-
|
|
300
|
-
|
|
318
|
+
if (ringActiveCounts[r] === 0) continue;
|
|
319
|
+
const rms = Math.sqrt(ringSquareSums[r] / ringActiveCounts[r]);
|
|
320
|
+
numerator += kPow * rms;
|
|
321
|
+
denominator += kPow;
|
|
301
322
|
}
|
|
302
323
|
|
|
303
324
|
const finalValue = clampUnitInterval(numerator / denominator);
|
|
@@ -347,7 +368,7 @@ function bfsPredecessorDistances(
|
|
|
347
368
|
// Injection selection
|
|
348
369
|
// ---------------------------------------------------------------------------
|
|
349
370
|
|
|
350
|
-
|
|
371
|
+
interface SelectInjectionsParams {
|
|
351
372
|
/** Final activation map after spread. */
|
|
352
373
|
A: ReadonlyMap<string, number>;
|
|
353
374
|
/** Slugs already attached to a prior user message (with their turn). */
|
|
@@ -356,7 +377,7 @@ export interface SelectInjectionsParams {
|
|
|
356
377
|
topK: number;
|
|
357
378
|
}
|
|
358
379
|
|
|
359
|
-
|
|
380
|
+
interface SelectInjectionsResult {
|
|
360
381
|
/** Top-K slugs by activation (descending), used for the cached top-now view. */
|
|
361
382
|
topNow: string[];
|
|
362
383
|
/**
|
|
@@ -408,47 +429,7 @@ export function selectInjections(
|
|
|
408
429
|
// c_assistant, c_now}` — the design doc (§9) deliberately shares them with
|
|
409
430
|
// concept-page activation rather than introducing parallel knobs.
|
|
410
431
|
|
|
411
|
-
|
|
412
|
-
userText: string;
|
|
413
|
-
assistantText: string;
|
|
414
|
-
nowText: string;
|
|
415
|
-
config: AssistantConfig;
|
|
416
|
-
/** Top-K size for the ANN query against `memory_v2_skills`. */
|
|
417
|
-
topK: number;
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
/**
|
|
421
|
-
* ANN top-K against the skills collection using the concatenated turn text.
|
|
422
|
-
* Runs a single embedding pass over `concat(user, assistant, now)` and a
|
|
423
|
-
* single hybrid Qdrant query — there is no prior-state carry-forward (skills
|
|
424
|
-
* are stateless).
|
|
425
|
-
*
|
|
426
|
-
* Returns a `Set<string>` of skill ids that hit either channel. Empty when
|
|
427
|
-
* the joined text is empty or `topK <= 0`.
|
|
428
|
-
*/
|
|
429
|
-
export async function selectSkillCandidates(
|
|
430
|
-
params: SelectSkillCandidatesParams,
|
|
431
|
-
): Promise<Set<string>> {
|
|
432
|
-
const { userText, assistantText, nowText, config, topK } = params;
|
|
433
|
-
|
|
434
|
-
const candidates = new Set<string>();
|
|
435
|
-
if (topK <= 0) return candidates;
|
|
436
|
-
|
|
437
|
-
const annQueryText = [userText, assistantText, nowText]
|
|
438
|
-
.filter((s) => s.length > 0)
|
|
439
|
-
.join("\n");
|
|
440
|
-
if (annQueryText.length === 0) return candidates;
|
|
441
|
-
|
|
442
|
-
const denseResult = await embedWithBackend(config, [annQueryText]);
|
|
443
|
-
const dense = denseResult.vectors[0];
|
|
444
|
-
const sparse = generateSparseEmbedding(annQueryText);
|
|
445
|
-
const hits = await hybridQuerySkills(dense, sparse, topK);
|
|
446
|
-
for (const hit of hits) candidates.add(hit.id);
|
|
447
|
-
|
|
448
|
-
return candidates;
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
export interface ComputeSkillActivationParams {
|
|
432
|
+
interface ComputeSkillActivationParams {
|
|
452
433
|
candidates: ReadonlySet<string>;
|
|
453
434
|
userText: string;
|
|
454
435
|
assistantText: string;
|
|
@@ -461,7 +442,7 @@ export interface ComputeSkillActivationParams {
|
|
|
461
442
|
* coefficient weighting. Skills have no decay term, so the breakdown is just
|
|
462
443
|
* the three raw sims. Surfaced for telemetry / inspector views.
|
|
463
444
|
*/
|
|
464
|
-
|
|
445
|
+
interface SkillActivationBreakdown {
|
|
465
446
|
/** Raw `sim(user, skill)` similarity, before `c_user` weighting. */
|
|
466
447
|
simUser: number;
|
|
467
448
|
/** Raw `sim(assistant, skill)` similarity, before `c_assistant` weighting. */
|
|
@@ -470,7 +451,7 @@ export interface SkillActivationBreakdown {
|
|
|
470
451
|
simNow: number;
|
|
471
452
|
}
|
|
472
453
|
|
|
473
|
-
|
|
454
|
+
interface ComputeSkillActivationResult {
|
|
474
455
|
/** Final clamped skill-activation value per id. */
|
|
475
456
|
activation: Map<string, number>;
|
|
476
457
|
/** Per-skill breakdown of the raw sim inputs that fed into `activation`. */
|
|
@@ -520,14 +501,14 @@ export async function computeSkillActivation(
|
|
|
520
501
|
return { activation, breakdown };
|
|
521
502
|
}
|
|
522
503
|
|
|
523
|
-
|
|
504
|
+
interface SelectSkillInjectionsParams {
|
|
524
505
|
/** Final skill activation map. */
|
|
525
506
|
A: ReadonlyMap<string, number>;
|
|
526
507
|
/** Cap on the per-turn skill slate, e.g. `config.memory.v2.skills_top_k`. */
|
|
527
508
|
topK: number;
|
|
528
509
|
}
|
|
529
510
|
|
|
530
|
-
|
|
511
|
+
interface SelectSkillInjectionsResult {
|
|
531
512
|
/**
|
|
532
513
|
* Top-K skill ids by activation (descending), tie-broken lexicographically.
|
|
533
514
|
* Skills are re-presented every turn — no `toInject` delta — so the caller
|
|
@@ -66,13 +66,11 @@ import {
|
|
|
66
66
|
type MemoryJob,
|
|
67
67
|
type MemoryJobType,
|
|
68
68
|
} from "../jobs-store.js";
|
|
69
|
+
import { MEMORY_V2_CONSOLIDATION_SOURCE } from "./constants.js";
|
|
69
70
|
import { resolveConsolidationPrompt } from "./prompts/consolidation.js";
|
|
70
71
|
|
|
71
72
|
const log = getLogger("memory-v2-consolidate");
|
|
72
73
|
|
|
73
|
-
/** Source string identifying this wake in `agent-wake` logs and surfaces. */
|
|
74
|
-
const WAKE_SOURCE = "memory_v2_consolidation";
|
|
75
|
-
|
|
76
74
|
/**
|
|
77
75
|
* Follow-up jobs to fan out after a successful consolidation.
|
|
78
76
|
*
|
|
@@ -144,7 +142,7 @@ export async function memoryV2ConsolidateJob(
|
|
|
144
142
|
// writes in the assistant's voice.
|
|
145
143
|
const conversation = bootstrapConversation({
|
|
146
144
|
conversationType: "background",
|
|
147
|
-
source:
|
|
145
|
+
source: MEMORY_V2_CONSOLIDATION_SOURCE,
|
|
148
146
|
origin: "memory_consolidation",
|
|
149
147
|
systemHint: "Running memory consolidation",
|
|
150
148
|
groupId: "system:background",
|
|
@@ -159,7 +157,7 @@ export async function memoryV2ConsolidateJob(
|
|
|
159
157
|
config.memory.v2.consolidation_prompt_path,
|
|
160
158
|
cutoff,
|
|
161
159
|
),
|
|
162
|
-
source:
|
|
160
|
+
source: MEMORY_V2_CONSOLIDATION_SOURCE,
|
|
163
161
|
trustContext: INTERNAL_GUARDIAN_TRUST_CONTEXT,
|
|
164
162
|
});
|
|
165
163
|
wakeInvoked = result.invoked;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical `conversations.source` string for background memory v2
|
|
3
|
+
* consolidation runs. Lives in a tiny constants module so the route layer can
|
|
4
|
+
* recognize consolidation conversations without importing the consolidation
|
|
5
|
+
* job (which pulls in agent-wake + bootstrap dependencies).
|
|
6
|
+
*/
|
|
7
|
+
export const MEMORY_V2_CONSOLIDATION_SOURCE = "memory_v2_consolidation";
|
|
@@ -37,14 +37,13 @@ import {
|
|
|
37
37
|
computeSkillActivation,
|
|
38
38
|
selectCandidates,
|
|
39
39
|
selectInjections,
|
|
40
|
-
selectSkillCandidates,
|
|
41
40
|
selectSkillInjections,
|
|
42
41
|
spreadActivation,
|
|
43
42
|
} from "./activation.js";
|
|
44
43
|
import { hydrate, save } from "./activation-store.js";
|
|
45
44
|
import { getEdgeIndex } from "./edge-index.js";
|
|
46
45
|
import { readPage, renderPageContent } from "./page-store.js";
|
|
47
|
-
import { getSkillCapability } from "./skill-store.js";
|
|
46
|
+
import { getAllSkillIds, getSkillCapability } from "./skill-store.js";
|
|
48
47
|
import type { ActivationState, EverInjectedEntry } from "./types.js";
|
|
49
48
|
|
|
50
49
|
const log = getLogger("memory-v2-injection");
|
|
@@ -89,10 +88,11 @@ export interface InjectMemoryV2BlockParams {
|
|
|
89
88
|
|
|
90
89
|
export interface InjectMemoryV2BlockResult {
|
|
91
90
|
/**
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
* `null` is the cache-stable default: the caller adds
|
|
95
|
-
* user message and prior attachments stay
|
|
91
|
+
* Inner content for the `<memory>` block, ready for the caller to wrap
|
|
92
|
+
* exactly once at injection time — or `null` when nothing new is eligible
|
|
93
|
+
* for injection. `null` is the cache-stable default: the caller adds
|
|
94
|
+
* nothing to the new user message and prior attachments stay
|
|
95
|
+
* byte-identical.
|
|
96
96
|
*/
|
|
97
97
|
block: string | null;
|
|
98
98
|
/**
|
|
@@ -183,16 +183,11 @@ export async function injectMemoryV2Block(
|
|
|
183
183
|
const slugsToRender = mode === "context-load" ? topNow : toInject;
|
|
184
184
|
|
|
185
185
|
// (6b) Skill pipeline — a sibling pipeline to the concept-page one above.
|
|
186
|
-
// Skills are stateless
|
|
187
|
-
//
|
|
188
|
-
//
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
assistantText: assistantMessage,
|
|
192
|
-
nowText,
|
|
193
|
-
config,
|
|
194
|
-
topK: config.memory.v2.top_k_skills,
|
|
195
|
-
});
|
|
186
|
+
// Skills are stateless (no decay, no spread, no `everInjected` dedup) and
|
|
187
|
+
// the catalog is small, so every known skill is scored every turn. The
|
|
188
|
+
// top-K injection slate is re-presented every turn so the agent can drop
|
|
189
|
+
// and pick skills up freely; the inspector renders the full ranked list.
|
|
190
|
+
const skillCandidates = new Set(getAllSkillIds());
|
|
196
191
|
const { activation: skillActivation, breakdown: skillBreakdown } =
|
|
197
192
|
await computeSkillActivation({
|
|
198
193
|
candidates: skillCandidates,
|
|
@@ -241,9 +236,30 @@ export async function injectMemoryV2Block(
|
|
|
241
236
|
|
|
242
237
|
await save(database, conversationId, nextActivationState);
|
|
243
238
|
|
|
244
|
-
//
|
|
245
|
-
//
|
|
246
|
-
//
|
|
239
|
+
// Render before recording telemetry so the activation log can mark slugs
|
|
240
|
+
// whose backing file is gone — those are no-op renders that would otherwise
|
|
241
|
+
// be indistinguishable from successful "injected" rows in the log.
|
|
242
|
+
// `renderInjectionBlock` itself short-circuits on empty inputs.
|
|
243
|
+
const { block, missingSlugs } = await renderInjectionBlock(
|
|
244
|
+
workspaceDir,
|
|
245
|
+
slugsToRender,
|
|
246
|
+
topSkillIds,
|
|
247
|
+
);
|
|
248
|
+
const missingSlugSet = new Set(missingSlugs);
|
|
249
|
+
if (missingSlugs.length > 0) {
|
|
250
|
+
log.warn(
|
|
251
|
+
{
|
|
252
|
+
conversationId,
|
|
253
|
+
turn: currentTurn,
|
|
254
|
+
missingSlugs,
|
|
255
|
+
renderedCount: slugsToRender.length - missingSlugs.length,
|
|
256
|
+
},
|
|
257
|
+
"Memory v2 injection skipped slugs whose page was missing on disk — Qdrant index may be stale; consider reembed",
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Record per-turn activation telemetry. Failures are warn-logged and never
|
|
262
|
+
// block memory injection.
|
|
247
263
|
const toInjectSet = new Set(toInject);
|
|
248
264
|
const renderedSet = new Set(slugsToRender);
|
|
249
265
|
const topSkillIdSet = new Set(topSkillIds);
|
|
@@ -260,6 +276,10 @@ export async function injectMemoryV2Block(
|
|
|
260
276
|
// - per-turn: cached attachments from prior turns are still on the
|
|
261
277
|
// user message, so prior-everInjected slugs are `in_context` and
|
|
262
278
|
// the delta (`toInject`) is `injected`.
|
|
279
|
+
// `page_missing` overrides any "would-have-been-injected" status when
|
|
280
|
+
// `readPage` returned null for the slug — telemetry surfaces stale
|
|
281
|
+
// ANN/edge entries instead of silently masquerading as a successful
|
|
282
|
+
// injection.
|
|
263
283
|
let status: MemoryV2ConceptRowRecord["status"];
|
|
264
284
|
if (mode === "context-load") {
|
|
265
285
|
status = renderedSet.has(slug) ? "injected" : "not_injected";
|
|
@@ -270,6 +290,9 @@ export async function injectMemoryV2Block(
|
|
|
270
290
|
} else {
|
|
271
291
|
status = "not_injected";
|
|
272
292
|
}
|
|
293
|
+
if (status === "injected" && missingSlugSet.has(slug)) {
|
|
294
|
+
status = "page_missing";
|
|
295
|
+
}
|
|
273
296
|
return {
|
|
274
297
|
slug,
|
|
275
298
|
finalActivation: finalActivation.get(slug) ?? 0,
|
|
@@ -327,23 +350,6 @@ export async function injectMemoryV2Block(
|
|
|
327
350
|
);
|
|
328
351
|
}
|
|
329
352
|
|
|
330
|
-
// (7) Cache-stable empty path: nothing to render AND no ranked skills.
|
|
331
|
-
if (slugsToRender.length === 0 && topSkillIds.length === 0) {
|
|
332
|
-
return { block: null, toInject: [] };
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
// (8) Render. Both `topNow` and `toInject` are activation-descending
|
|
336
|
-
// (selectInjections sorts before slicing), so `slugsToRender` doubles as
|
|
337
|
-
// the render order. Per-turn: only the new slugs render (prior turns'
|
|
338
|
-
// attachments stay cached on prior user messages). Context-load: full
|
|
339
|
-
// top-K renders so the fresh user message gets a complete activation dump.
|
|
340
|
-
// Skills are appended after concept-page sections.
|
|
341
|
-
const block = await renderInjectionBlock(
|
|
342
|
-
workspaceDir,
|
|
343
|
-
slugsToRender,
|
|
344
|
-
topSkillIds,
|
|
345
|
-
);
|
|
346
|
-
|
|
347
353
|
return { block, toInject: newlyInjected };
|
|
348
354
|
}
|
|
349
355
|
|
|
@@ -351,14 +357,38 @@ export async function injectMemoryV2Block(
|
|
|
351
357
|
// Internal helpers
|
|
352
358
|
// ---------------------------------------------------------------------------
|
|
353
359
|
|
|
360
|
+
interface RenderInjectionBlockResult {
|
|
361
|
+
/**
|
|
362
|
+
* Inner content for the `<memory>` block (concept-page sections + optional
|
|
363
|
+
* skills suffix), or `null` when both the concept-page list and the skill
|
|
364
|
+
* list collapse to empty after cache misses (no on-disk pages, no
|
|
365
|
+
* resolvable skill ids). Returned unwrapped so the caller can wrap it
|
|
366
|
+
* exactly once at injection time, matching v1's contract: callers that
|
|
367
|
+
* cache the value (`lastInjectedBlock`) or persist it (`memoryInjectedBlock`
|
|
368
|
+
* in message metadata) re-wrap on use, and storing the wrapped form here
|
|
369
|
+
* caused a double wrap on reinject after compaction and on rehydrate from
|
|
370
|
+
* DB.
|
|
371
|
+
*/
|
|
372
|
+
block: string | null;
|
|
373
|
+
/**
|
|
374
|
+
* Slugs that `readPage` returned null for. Surfaced so the caller can
|
|
375
|
+
* mark them in the activation log (`status: "page_missing"`) and emit
|
|
376
|
+
* a warning — silent drops here previously masked stale Qdrant /
|
|
377
|
+
* edge-index entries that pointed at pages no longer on disk.
|
|
378
|
+
*/
|
|
379
|
+
missingSlugs: string[];
|
|
380
|
+
}
|
|
381
|
+
|
|
354
382
|
/**
|
|
355
|
-
* Render the `<memory>` block for a list of slugs and
|
|
356
|
-
* ranked skill ids.
|
|
383
|
+
* Render the inner content of the `<memory>` block for a list of slugs and
|
|
384
|
+
* a list of ranked skill ids. The caller wraps the result in
|
|
385
|
+
* `<memory>...</memory>` exactly once at injection time.
|
|
357
386
|
*
|
|
358
387
|
* Concept pages are read in parallel via `readPage`. Pages whose file has
|
|
359
388
|
* gone missing between selection and render (e.g. consolidation deleted
|
|
360
|
-
* them
|
|
361
|
-
* `
|
|
389
|
+
* them, folder reorg renamed the slug) are dropped from the rendered
|
|
390
|
+
* block but reported back via `missingSlugs` so callers can surface the
|
|
391
|
+
* divergence.
|
|
362
392
|
*
|
|
363
393
|
* Skill ids are looked up via `getSkillCapability`. Ids that the cache no
|
|
364
394
|
* longer knows (e.g. uninstalled mid-run) are silently dropped, mirroring
|
|
@@ -370,7 +400,6 @@ export async function injectMemoryV2Block(
|
|
|
370
400
|
* the agent sees the page's edges and any referenced media paths alongside
|
|
371
401
|
* the prose:
|
|
372
402
|
*
|
|
373
|
-
* <memory>
|
|
374
403
|
* ### <slug-1>
|
|
375
404
|
* ---
|
|
376
405
|
* edges:
|
|
@@ -390,28 +419,29 @@ export async function injectMemoryV2Block(
|
|
|
390
419
|
* ### Skills You Can Use
|
|
391
420
|
* - <skill-1 content>
|
|
392
421
|
* - <skill-2 content>
|
|
393
|
-
* </memory>
|
|
394
|
-
*
|
|
395
|
-
* Returns `null` when both lists collapse to empty after cache misses so
|
|
396
|
-
* the caller can fall through to its empty-block path instead of attaching
|
|
397
|
-
* an empty `<memory>` wrapper.
|
|
398
422
|
*/
|
|
399
423
|
async function renderInjectionBlock(
|
|
400
424
|
workspaceDir: string,
|
|
401
425
|
slugs: string[],
|
|
402
426
|
skillIds: string[],
|
|
403
|
-
): Promise<
|
|
427
|
+
): Promise<RenderInjectionBlockResult> {
|
|
404
428
|
const pages = await Promise.all(
|
|
405
429
|
slugs.map(async (slug) => {
|
|
406
430
|
const page = await readPage(workspaceDir, slug);
|
|
407
|
-
return
|
|
431
|
+
return { slug, page };
|
|
408
432
|
}),
|
|
409
433
|
);
|
|
410
434
|
|
|
411
435
|
const sections: string[] = [];
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
436
|
+
const missingSlugs: string[] = [];
|
|
437
|
+
for (const { slug, page } of pages) {
|
|
438
|
+
if (!page) {
|
|
439
|
+
missingSlugs.push(slug);
|
|
440
|
+
continue;
|
|
441
|
+
}
|
|
442
|
+
const content = renderPageContent(page).trim();
|
|
443
|
+
if (content.length === 0) continue;
|
|
444
|
+
sections.push(`### ${slug}\n${content}`);
|
|
415
445
|
}
|
|
416
446
|
|
|
417
447
|
// v2's skills collection is skills-only, so the activation suffix always applies.
|
|
@@ -425,7 +455,10 @@ async function renderInjectionBlock(
|
|
|
425
455
|
sections.push(`### Skills You Can Use\n${skillLines.join("\n")}`);
|
|
426
456
|
}
|
|
427
457
|
|
|
428
|
-
if (sections.length === 0) return null;
|
|
458
|
+
if (sections.length === 0) return { block: null, missingSlugs };
|
|
429
459
|
|
|
430
|
-
return
|
|
460
|
+
return {
|
|
461
|
+
block: sections.join("\n\n"),
|
|
462
|
+
missingSlugs,
|
|
463
|
+
};
|
|
431
464
|
}
|