@vellumai/assistant 0.8.0 → 0.8.1
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/AGENTS.md +11 -0
- package/Dockerfile +5 -4
- package/README.md +2 -2
- package/docker-entrypoint.sh +16 -0
- package/eslint-rules/__tests__/cli-no-daemon-internals.test.ts +420 -0
- package/eslint-rules/cli-no-daemon-internals.js +283 -0
- package/eslint.config.mjs +12 -0
- package/knip.json +2 -1
- package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -1
- package/openapi.yaml +4847 -1698
- package/package.json +3 -1
- package/scripts/generate-openapi.ts +52 -4
- package/scripts/sync-llm-catalog.ts +165 -0
- package/scripts/sync-web-search-catalog.ts +107 -0
- package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +169 -0
- package/src/__tests__/agent-loop-override-profile.test.ts +26 -1
- package/src/__tests__/anthropic-provider.test.ts +92 -2
- package/src/__tests__/app-control-flow.test.ts +7 -0
- package/src/__tests__/assistant-events-sse-shed.test.ts +232 -0
- package/src/__tests__/avatar-identity-sync.test.ts +87 -0
- package/src/__tests__/background-workers-disk-pressure.test.ts +11 -22
- package/src/__tests__/btw-routes.test.ts +1 -0
- package/src/__tests__/call-site-routing-provider.test.ts +172 -45
- package/src/__tests__/cancel-resolves-conversation-key.test.ts +44 -3
- package/src/__tests__/channel-policy.test.ts +12 -0
- package/src/__tests__/checker.test.ts +89 -0
- package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +35 -7
- package/src/__tests__/compact-event-conversation-id-guard.test.ts +33 -5
- package/src/__tests__/compaction-strip-metadata-clear.test.ts +26 -1
- package/src/__tests__/config-loader-backfill.test.ts +526 -102
- package/src/__tests__/config-loader-corrupt.test.ts +68 -0
- package/src/__tests__/config-loader-platform-defaults.test.ts +77 -23
- package/src/__tests__/config-schema-cmd.test.ts +63 -29
- package/src/__tests__/config-schema.test.ts +14 -3
- package/src/__tests__/config-set-platform-guard.test.ts +75 -152
- package/src/__tests__/config-set-route.test.ts +198 -0
- package/src/__tests__/config-watcher.test.ts +6 -0
- package/src/__tests__/contacts-tools.test.ts +51 -199
- package/src/__tests__/context-search-agent-protocol.test.ts +21 -2
- package/src/__tests__/context-search-agent-runner.test.ts +22 -138
- package/src/__tests__/context-search-conversations-source.test.ts +42 -16
- package/src/__tests__/context-search-fanout.test.ts +20 -157
- package/src/__tests__/context-search-memory-v2-source.test.ts +3 -3
- package/src/__tests__/context-search-types.test.ts +7 -2
- package/src/__tests__/context-window-manager.test.ts +389 -1
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -0
- package/src/__tests__/conversation-crud-inference-profile.test.ts +100 -0
- package/src/__tests__/conversation-error.test.ts +38 -0
- package/src/__tests__/conversation-fork-crud.test.ts +241 -1
- package/src/__tests__/conversation-inference-profile-route.test.ts +14 -14
- package/src/__tests__/conversation-init.benchmark.test.ts +1 -0
- package/src/__tests__/conversation-lifecycle.test.ts +124 -0
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +100 -1
- package/src/__tests__/conversation-process-callsite.test.ts +21 -1
- package/src/__tests__/conversation-runtime-assembly.test.ts +4 -4
- package/src/__tests__/conversation-slash-commands.test.ts +194 -2
- package/src/__tests__/conversation-surfaces-app-control.test.ts +323 -3
- package/src/__tests__/credential-security-invariants.test.ts +5 -6
- package/src/__tests__/daemon-credential-client.test.ts +56 -1
- package/src/__tests__/db-activation-state-fk-cascade.test.ts +132 -0
- package/src/__tests__/db-conversation-inference-profile-migration.test.ts +37 -0
- package/src/__tests__/db-memory-graph-event-date-repair.test.ts +43 -20
- package/src/__tests__/db-proxy-transaction.test.ts +206 -0
- package/src/__tests__/external-plugin-loader.test.ts +458 -0
- package/src/__tests__/filing-service.test.ts +23 -3
- package/src/__tests__/fixtures/mock-chrome-extension.ts +5 -0
- package/src/__tests__/gateway-only-guard.test.ts +0 -1
- package/src/__tests__/graph-extraction-event-date.test.ts +34 -0
- package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +0 -8
- package/src/__tests__/heartbeat-disk-pressure.test.ts +21 -8
- package/src/__tests__/heartbeat-service.test.ts +50 -233
- package/src/__tests__/history-repair.test.ts +89 -0
- package/src/__tests__/host-app-control-proxy.test.ts +109 -1
- package/src/__tests__/host-app-control-routes.test.ts +247 -1
- package/src/__tests__/host-browser-proxy.test.ts +416 -20
- package/src/__tests__/host-browser-routes.test.ts +325 -33
- package/src/__tests__/host-proxy-preactivation.test.ts +211 -0
- package/src/__tests__/inference-no-mode-boot-e2e.test.ts +246 -0
- package/src/__tests__/inference-profile-reaper.test.ts +154 -0
- package/src/__tests__/inference-profile-session-handler.test.ts +398 -0
- package/src/__tests__/inference-profile-session-ipc.test.ts +236 -0
- package/src/__tests__/inline-skill-load-permissions.test.ts +6 -1
- package/src/__tests__/install-skill-routing.test.ts +2 -2
- package/src/__tests__/lifecycle-memory-v2-seed.test.ts +15 -0
- package/src/__tests__/llm-callsite-catalog.test.ts +20 -1
- package/src/__tests__/llm-catalog-parity.test.ts +146 -0
- package/src/__tests__/llm-request-log-source-clickhouse.test.ts +188 -0
- package/src/__tests__/llm-request-log-source-factory.test.ts +124 -0
- package/src/__tests__/llm-resolver.test.ts +46 -0
- package/src/__tests__/managed-profile-guard.test.ts +131 -2
- package/src/__tests__/mcp-auth-routes.test.ts +1 -0
- package/src/__tests__/mcp-cli.test.ts +182 -220
- package/src/__tests__/mcp-health-check.test.ts +56 -27
- package/src/__tests__/memory-jobs-worker-lanes.test.ts +18 -11
- package/src/__tests__/message-complete-display-id.test.ts +175 -0
- package/src/__tests__/notification-platform-adapter.test.ts +229 -0
- package/src/__tests__/oauth-cli.test.ts +38 -2009
- package/src/__tests__/oauth-commands-routes.test.ts +711 -0
- package/src/__tests__/oauth-connect-routes.test.ts +174 -11
- package/src/__tests__/oauth-providers-routes.test.ts +14 -10
- package/src/__tests__/openai-responses-cutover-guard.test.ts +33 -12
- package/src/__tests__/openai-responses-provider.test.ts +17 -0
- package/src/__tests__/plugin-bootstrap.test.ts +31 -2
- package/src/__tests__/plugin-route-contribution.test.ts +31 -3
- package/src/__tests__/plugin-tool-contribution.test.ts +31 -3
- package/src/__tests__/plugin-types.test.ts +13 -11
- package/src/__tests__/process-message-background-slack.test.ts +46 -0
- package/src/__tests__/profile-entry-status.test.ts +43 -0
- package/src/__tests__/provider-managed-proxy-integration.test.ts +12 -4
- package/src/__tests__/provider-registry-ollama.test.ts +12 -4
- package/src/__tests__/provider-send-message-override-profile.test.ts +10 -4
- package/src/__tests__/relay-server.test.ts +118 -0
- package/src/__tests__/retry-thinking-tool-choice.test.ts +15 -0
- package/src/__tests__/schedule-retry.test.ts +56 -4
- package/src/__tests__/schedule-routes.test.ts +104 -0
- package/src/__tests__/scheduler-disk-pressure.test.ts +0 -4
- package/src/__tests__/scheduler-recurrence.test.ts +87 -34
- package/src/__tests__/scheduler-reuse-conversation.test.ts +161 -5
- package/src/__tests__/scheduler-wake.test.ts +0 -63
- package/src/__tests__/secret-allowlist.test.ts +1 -0
- package/src/__tests__/secret-routes-managed-proxy.test.ts +12 -4
- package/src/__tests__/shell-credential-ref.test.ts +95 -3
- package/src/__tests__/shell-tool-proxy-mode.test.ts +14 -0
- package/src/__tests__/skill-load-feature-flag.test.ts +1 -0
- package/src/__tests__/skill-load-tool.test.ts +2 -4
- package/src/__tests__/subagent-call-site-routing.test.ts +78 -16
- package/src/__tests__/suggestion-routes.test.ts +3 -3
- package/src/__tests__/sync-message-contract.test.ts +63 -0
- package/src/__tests__/task-scheduler.test.ts +88 -23
- package/src/__tests__/update-bulletin-job.test.ts +96 -193
- package/src/__tests__/usage-cli.test.ts +11 -73
- package/src/__tests__/user-plugin-loader.test.ts +145 -0
- package/src/__tests__/vercel-config.test.ts +168 -0
- package/src/__tests__/web-search-catalog-parity.test.ts +86 -0
- package/src/__tests__/web-search.test.ts +303 -2
- package/src/__tests__/workspace-migration-039-drop-legacy-llm-keys.test.ts +1 -21
- package/src/__tests__/workspace-migration-057-repair-stale-gemini-model-ids.test.ts +58 -0
- package/src/__tests__/workspace-migration-069-seed-onboarding-threads.test.ts +53 -20
- package/src/__tests__/workspace-migration-072-seed-reply-suggestion-callsite.test.ts +191 -0
- package/src/__tests__/workspace-migration-076-drop-services-inference-mode.test.ts +211 -0
- package/src/__tests__/workspace-migration-077-seed-memory-router-callsite.test.ts +174 -0
- package/src/__tests__/workspace-migration-079-home-feed-notification-only.test.ts +323 -0
- package/src/__tests__/workspace-migration-080-restrict-vercel-api-token-metadata.test.ts +299 -0
- package/src/__tests__/workspace-migration-081-backfill-bash-allowed-tools.test.ts +410 -0
- package/src/__tests__/workspace-migration-082-backfill-managed-profile-labels.test.ts +268 -0
- package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +3 -3
- package/src/__tests__/workspace-release-notes-feature-flag-guard.test.ts +115 -0
- package/src/acp/__tests__/helpers/which-stub.ts +4 -2
- package/src/acp/resolve-agent.test.ts +25 -0
- package/src/acp/resolve-agent.ts +13 -2
- package/src/acp/session-manager.ts +14 -0
- package/src/approvals/guardian-request-resolvers.ts +32 -87
- package/src/calls/relay-server.ts +35 -0
- package/src/calls/relay-setup-router.ts +36 -0
- package/src/calls/types.ts +1 -0
- package/src/calls/voice-session-bridge.ts +23 -4
- package/src/channels/config.ts +14 -1
- package/src/channels/types.ts +1 -0
- package/src/cli/AGENTS.md +164 -4
- package/src/cli/__tests__/notifications.test.ts +54 -0
- package/src/cli/commands/__tests__/avatar.test.ts +540 -0
- package/src/cli/commands/__tests__/backup.test.ts +236 -776
- package/src/cli/commands/__tests__/cache.test.ts +1 -1
- package/src/cli/commands/__tests__/changelog.test.ts +593 -0
- package/src/cli/commands/__tests__/channel-verification-sessions.test.ts +503 -0
- package/src/cli/commands/__tests__/conversations-import.test.ts +515 -0
- package/src/cli/commands/__tests__/domain-register.test.ts +140 -167
- package/src/cli/commands/__tests__/domain-status.test.ts +137 -76
- package/src/cli/commands/__tests__/email-attachment.test.ts +314 -337
- package/src/cli/commands/__tests__/email-core.test.ts +579 -0
- package/src/cli/commands/__tests__/image-generation.test.ts +87 -824
- package/src/cli/commands/__tests__/inference-send.test.ts +30 -266
- package/src/cli/commands/__tests__/inference-session.test.ts +423 -0
- package/src/cli/commands/__tests__/memory-v2.test.ts +81 -110
- package/src/cli/commands/__tests__/skills.test.ts +563 -0
- package/src/cli/commands/__tests__/status.test.ts +249 -0
- package/src/cli/commands/__tests__/stt.test.ts +320 -0
- package/src/cli/commands/__tests__/tts-synthesize.test.ts +4 -603
- package/src/cli/commands/__tests__/tts.test.ts +321 -0
- package/src/cli/commands/__tests__/webhooks.test.ts +86 -511
- package/src/cli/commands/attachment.ts +8 -3
- package/src/cli/commands/audit.ts +95 -64
- package/src/cli/commands/auth.ts +61 -58
- package/src/cli/commands/avatar.ts +276 -390
- package/src/cli/commands/backup.ts +409 -505
- package/src/cli/commands/bash.ts +9 -5
- package/src/cli/commands/browser.ts +28 -9
- package/src/cli/commands/cache.ts +9 -4
- package/src/cli/commands/changelog.ts +414 -0
- package/src/cli/commands/channel-verification-sessions.ts +238 -317
- package/src/cli/commands/clients.ts +8 -3
- package/src/cli/commands/completions.ts +9 -9
- package/src/cli/commands/config.ts +102 -72
- package/src/cli/commands/contacts.ts +575 -696
- package/src/cli/commands/conversations-defer.ts +17 -69
- package/src/cli/commands/conversations-import.ts +90 -253
- package/src/cli/commands/conversations.ts +346 -436
- package/src/cli/commands/credential-execution.ts +9 -6
- package/src/cli/commands/credentials.ts +456 -736
- package/src/cli/commands/domain.ts +128 -206
- package/src/cli/commands/email.ts +606 -794
- package/src/cli/commands/gateway.ts +8 -1
- package/src/cli/commands/image-generation.ts +157 -205
- package/src/cli/commands/inference-providers.ts +352 -0
- package/src/cli/commands/inference-session.ts +415 -0
- package/src/cli/commands/inference.ts +87 -65
- package/src/cli/commands/keys.ts +8 -3
- package/src/cli/commands/mcp.ts +103 -287
- package/src/cli/commands/memory-v2.ts +162 -516
- package/src/cli/commands/notifications.ts +33 -7
- package/src/cli/commands/oauth/apps.ts +292 -261
- package/src/cli/commands/oauth/connect.ts +176 -297
- package/src/cli/commands/oauth/disconnect.ts +16 -215
- package/src/cli/commands/oauth/index.ts +49 -45
- package/src/cli/commands/oauth/mode.ts +43 -199
- package/src/cli/commands/oauth/ping.ts +17 -125
- package/src/cli/commands/oauth/providers.ts +732 -921
- package/src/cli/commands/oauth/request.ts +60 -350
- package/src/cli/commands/oauth/shared.ts +11 -121
- package/src/cli/commands/oauth/status.ts +31 -121
- package/src/cli/commands/oauth/token.ts +13 -55
- package/src/cli/commands/pending.ts +19 -10
- package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +133 -183
- package/src/cli/commands/platform/__tests__/connect.test.ts +66 -181
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +71 -227
- package/src/cli/commands/platform/__tests__/status.test.ts +169 -287
- package/src/cli/commands/platform/connect.ts +16 -80
- package/src/cli/commands/platform/disconnect.ts +14 -112
- package/src/cli/commands/platform/index.ts +177 -246
- package/src/cli/commands/routes.ts +153 -336
- package/src/cli/commands/sequence.ts +316 -360
- package/src/cli/commands/skills.ts +449 -671
- package/src/cli/commands/status.ts +58 -37
- package/src/cli/commands/stt.ts +94 -262
- package/src/cli/commands/task.ts +14 -40
- package/src/cli/commands/trust.ts +8 -3
- package/src/cli/commands/tts.ts +162 -167
- package/src/cli/commands/ui.ts +35 -42
- package/src/cli/commands/usage.ts +188 -126
- package/src/cli/commands/watchers.ts +8 -3
- package/src/cli/commands/webhooks.ts +99 -193
- package/src/cli/lib/__tests__/register-command.test.ts +85 -0
- package/src/cli/lib/daemon-credential-client.ts +4 -5
- package/src/cli/lib/nested-value.ts +44 -0
- package/src/cli/lib/open-browser.ts +36 -0
- package/src/cli/lib/register-command.ts +19 -0
- package/src/cli/lib/time-ago.ts +34 -0
- package/src/cli/program.ts +2 -4
- package/src/cli/utils/__tests__/conversation-id.test.ts +66 -0
- package/src/cli/utils/__tests__/parse-duration.test.ts +49 -0
- package/src/cli/utils/conversation-id.ts +30 -0
- package/src/cli/utils/parse-duration.ts +41 -0
- package/src/config/acp-defaults.test.ts +5 -1
- package/src/config/acp-defaults.ts +11 -4
- package/src/config/bundled-skills/acp/TOOLS.json +2 -2
- package/src/config/bundled-skills/app-control/TOOLS.json +32 -0
- package/src/config/bundled-skills/contacts/SKILL.md +12 -45
- package/src/config/bundled-skills/contacts/TOOLS.json +0 -57
- package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +0 -12
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +0 -58
- package/src/config/bundled-tool-registry.ts +0 -2
- package/src/config/feature-flag-registry.json +16 -0
- package/src/config/llm-resolver.ts +16 -1
- package/src/config/loader.ts +76 -14
- package/src/config/raw-config-utils.ts +2 -30
- package/src/config/schema.ts +4 -0
- package/src/config/schemas/__tests__/memory-v2.test.ts +49 -0
- package/src/config/schemas/call-site-catalog.ts +29 -7
- package/src/config/schemas/llm-request-logs.ts +57 -0
- package/src/config/schemas/llm.ts +52 -2
- package/src/config/schemas/memory-retrospective.ts +48 -0
- package/src/config/schemas/memory-v2.ts +32 -1
- package/src/config/schemas/memory.ts +4 -0
- package/src/config/schemas/services.ts +15 -12
- package/src/config/seed-inference-profiles.ts +195 -134
- package/src/contacts/contact-store.ts +0 -61
- package/src/context/window-manager.ts +191 -5
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +79 -0
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +109 -4
- package/src/daemon/__tests__/daemon-skill-host.test.ts +10 -4
- package/src/daemon/approval-generators.ts +23 -29
- package/src/daemon/config-watcher.ts +2 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +24 -0
- package/src/daemon/conversation-agent-loop.ts +127 -97
- package/src/daemon/conversation-error.ts +21 -0
- package/src/daemon/conversation-lifecycle.ts +46 -5
- package/src/daemon/conversation-process.ts +36 -19
- package/src/daemon/conversation-runtime-assembly.ts +14 -5
- package/src/daemon/conversation-slash.ts +175 -23
- package/src/daemon/conversation-store.ts +17 -10
- package/src/daemon/conversation-surfaces.ts +76 -12
- package/src/daemon/conversation-tool-setup.ts +24 -14
- package/src/daemon/conversation.ts +48 -9
- package/src/daemon/external-plugins-bootstrap.ts +18 -8
- package/src/daemon/guardian-action-generators.ts +7 -22
- package/src/daemon/handlers/config-model.ts +8 -126
- package/src/daemon/handlers/config-slack-channel.ts +10 -7
- package/src/daemon/handlers/config-vercel.ts +3 -1
- package/src/daemon/handlers/skills.ts +84 -5
- package/src/daemon/history-repair.ts +33 -6
- package/src/daemon/host-app-control-proxy.ts +44 -19
- package/src/daemon/host-bash-proxy.ts +85 -158
- package/src/daemon/host-browser-proxy.ts +96 -35
- package/src/daemon/host-proxy-base.ts +13 -1
- package/src/daemon/host-proxy-preactivation.ts +25 -1
- package/src/daemon/identity-helpers.ts +19 -0
- package/src/daemon/lifecycle.ts +42 -43
- package/src/daemon/meet-host-supervisor.ts +15 -15
- package/src/daemon/memory-v2-startup.ts +9 -2
- package/src/daemon/message-protocol.ts +6 -0
- package/src/daemon/message-types/bookmarks.ts +18 -0
- package/src/daemon/message-types/conversations.ts +12 -9
- package/src/daemon/message-types/messages.ts +9 -1
- package/src/daemon/message-types/sync.ts +60 -0
- package/src/daemon/pkb-reminder-builder.test.ts +54 -13
- package/src/daemon/pkb-reminder-builder.ts +21 -7
- package/src/daemon/process-message.ts +56 -23
- package/src/daemon/server.ts +23 -18
- package/src/daemon/shutdown-handlers.ts +0 -2
- package/src/daemon/tool-setup-types.ts +9 -0
- package/src/daemon/tool-side-effects.ts +6 -4
- package/src/daemon/wake-target-adapter.ts +11 -0
- package/src/export/transcript-formatter.ts +61 -2
- package/src/filing/filing-service.ts +40 -53
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +359 -0
- package/src/heartbeat/heartbeat-run-store.ts +2 -1
- package/src/heartbeat/heartbeat-service.ts +148 -127
- package/src/home/__tests__/feed-types.test.ts +63 -131
- package/src/home/__tests__/feed-writer.test.ts +77 -278
- package/src/home/__tests__/post-connect-feed.test.ts +9 -12
- package/src/home/feed-types.ts +19 -73
- package/src/home/feed-writer.ts +25 -156
- package/src/home/post-connect-feed.ts +1 -3
- package/src/ipc/__tests__/cli-ipc.test.ts +2 -0
- package/src/ipc/__tests__/email-ipc.test.ts +506 -0
- package/src/ipc/__tests__/exit-helper.test.ts +104 -0
- package/src/ipc/__tests__/streaming-client.test.ts +237 -0
- package/src/ipc/__tests__/streaming-framing.test.ts +142 -0
- package/src/ipc/assistant-server.ts +55 -6
- package/src/ipc/cli-client.ts +370 -50
- package/src/ipc/routes/db-proxy-transaction.ts +151 -0
- package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +60 -0
- package/src/ipc/skill-routes/events.ts +30 -3
- package/src/live-voice/__tests__/live-voice-session-manager.test.ts +46 -0
- package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +1 -0
- package/src/live-voice/live-voice-session-manager.ts +11 -4
- package/src/live-voice/live-voice-session.ts +14 -6
- package/src/memory/__tests__/bookmark-crud.test.ts +258 -0
- package/src/memory/__tests__/bookmark-schema.test.ts +181 -0
- package/src/memory/__tests__/conversation-types.test.ts +36 -0
- package/src/memory/__tests__/find-most-recent-retrospective-for.test.ts +130 -0
- package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +177 -0
- package/src/memory/__tests__/memory-retrospective-job.test.ts +328 -0
- package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +213 -0
- package/src/memory/__tests__/memory-retrospective-trigger-check.test.ts +90 -0
- package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +69 -0
- package/src/memory/__tests__/memory-v2-concept-frequency.test.ts +3 -0
- package/src/memory/bookmark-crud.ts +179 -0
- package/src/memory/context-search/__tests__/agent-runner-redaction.test.ts +31 -9
- package/src/memory/context-search/agent-protocol.ts +5 -1
- package/src/memory/context-search/agent-runner.ts +60 -85
- package/src/memory/context-search/limits.ts +1 -4
- package/src/memory/context-search/search.ts +23 -113
- package/src/memory/context-search/sources/conversations.ts +18 -6
- package/src/memory/context-search/sources/memory-v2.ts +39 -14
- package/src/memory/context-search/sources/memory.ts +7 -0
- package/src/memory/context-search/sources/workspace.ts +13 -10
- package/src/memory/context-search/types.ts +1 -1
- package/src/memory/conversation-bootstrap.ts +11 -0
- package/src/memory/conversation-crud.ts +312 -10
- package/src/memory/conversation-queries.ts +9 -5
- package/src/memory/conversation-title-service.ts +1 -0
- package/src/memory/conversation-types.ts +16 -0
- package/src/memory/db-init.ts +14 -0
- package/src/memory/embedding-backend.ts +2 -1
- package/src/memory/embedding-runtime-manager.ts +1 -2
- package/src/memory/graph/__tests__/remember-description.test.ts +55 -0
- package/src/memory/graph/conversation-graph-memory.ts +76 -5
- package/src/memory/graph/extraction.ts +4 -0
- package/src/memory/graph/graph-memory-state-store.ts +16 -3
- package/src/memory/graph/tool-handlers.ts +17 -7
- package/src/memory/graph/tools.ts +44 -5
- package/src/memory/indexer.ts +17 -0
- package/src/memory/jobs/__tests__/embed-concept-page.test.ts +13 -15
- package/src/memory/jobs/embed-concept-page.ts +45 -9
- package/src/memory/jobs-store.ts +51 -1
- package/src/memory/jobs-worker.ts +52 -3
- package/src/memory/llm-request-log-source-clickhouse.ts +317 -0
- package/src/memory/llm-request-log-source-local.ts +26 -0
- package/src/memory/llm-request-log-source.ts +97 -0
- package/src/memory/llm-request-log-store.ts +1 -1
- package/src/memory/memory-retrospective-constants.ts +13 -0
- package/src/memory/memory-retrospective-enqueue.ts +114 -0
- package/src/memory/memory-retrospective-job.ts +351 -0
- package/src/memory/memory-retrospective-startup-cleanup.ts +108 -0
- package/src/memory/memory-retrospective-state.ts +162 -0
- package/src/memory/memory-retrospective-trigger-check.ts +91 -0
- package/src/memory/memory-v2-activation-log-store.ts +49 -5
- package/src/memory/memory-v2-concept-frequency.ts +4 -0
- package/src/memory/message-content.ts +38 -1
- package/src/memory/migrations/227-add-conversation-inference-profile.ts +6 -1
- package/src/memory/migrations/228-rename-inference-profile-snake-case.ts +20 -7
- package/src/memory/migrations/229-delete-private-conversations.test.ts +70 -1
- package/src/memory/migrations/229-delete-private-conversations.ts +12 -0
- package/src/memory/migrations/231-repair-memory-graph-event-dates.ts +16 -2
- package/src/memory/migrations/240-conversation-inference-profile-session.ts +25 -0
- package/src/memory/migrations/241-activation-state-fk-cascade.ts +50 -0
- package/src/memory/migrations/242-message-bookmarks.ts +38 -0
- package/src/memory/migrations/243-provider-connections.ts +68 -0
- package/src/memory/migrations/244-provider-connection-status-label.ts +23 -0
- package/src/memory/migrations/245-memory-retrospective-state.ts +36 -0
- package/src/memory/migrations/246-backfill-provider-connection-label.ts +81 -0
- package/src/memory/migrations/__tests__/244-provider-connection-status-label.test.ts +84 -0
- package/src/memory/migrations/__tests__/245-memory-retrospective-state.test.ts +125 -0
- package/src/memory/migrations/__tests__/246-backfill-provider-connection-label.test.ts +192 -0
- package/src/memory/migrations/index.ts +7 -0
- package/src/memory/published-pages-store.ts +16 -0
- package/src/memory/schema/bookmarks.ts +38 -0
- package/src/memory/schema/conversations.ts +2 -0
- package/src/memory/schema/index.ts +2 -0
- package/src/memory/schema/inference.ts +29 -0
- package/src/memory/schema/memory-core.ts +9 -0
- package/src/memory/search/semantic.ts +1 -4
- package/src/memory/v2/__tests__/__snapshots__/prompts-router.test.ts.snap +27 -0
- package/src/memory/v2/__tests__/activation-store.test.ts +5 -5
- package/src/memory/v2/__tests__/activation.test.ts +11 -4
- package/src/memory/v2/__tests__/backfill-jobs.test.ts +38 -21
- package/src/memory/v2/__tests__/consolidation-job.test.ts +123 -135
- package/src/memory/v2/__tests__/edge-index.test.ts +1 -1
- package/src/memory/v2/__tests__/frontmatter-sweep.test.ts +111 -0
- package/src/memory/v2/__tests__/injection.test.ts +628 -10
- package/src/memory/v2/__tests__/migration.test.ts +7 -3
- package/src/memory/v2/__tests__/page-index.test.ts +277 -0
- package/src/memory/v2/__tests__/page-store.test.ts +14 -1
- package/src/memory/v2/__tests__/prompts-router.test.ts +257 -0
- package/src/memory/v2/__tests__/qdrant.test.ts +72 -0
- package/src/memory/v2/__tests__/reranker.test.ts +4 -4
- package/src/memory/v2/__tests__/router.test.ts +516 -0
- package/src/memory/v2/__tests__/sim.test.ts +45 -1
- package/src/memory/v2/__tests__/skill-store.test.ts +58 -3
- package/src/memory/v2/__tests__/static-context.test.ts +7 -22
- package/src/memory/v2/__tests__/sweep-job.test.ts +95 -0
- package/src/memory/v2/activation-store.ts +34 -5
- package/src/memory/v2/activation.ts +40 -27
- package/src/memory/v2/backfill-jobs.ts +17 -84
- package/src/memory/v2/consolidation-job.ts +85 -78
- package/src/memory/v2/frontmatter-sweep.ts +91 -0
- package/src/memory/v2/injection.ts +440 -109
- package/src/memory/v2/migration.ts +117 -20
- package/src/memory/v2/page-index.ts +191 -0
- package/src/memory/v2/page-store.ts +3 -0
- package/src/memory/v2/prompts/consolidation.ts +9 -7
- package/src/memory/v2/prompts/router.ts +192 -0
- package/src/memory/v2/qdrant.ts +100 -87
- package/src/memory/v2/reranker.ts +14 -7
- package/src/memory/v2/router.ts +322 -0
- package/src/memory/v2/sim.ts +25 -12
- package/src/memory/v2/skill-store.ts +118 -29
- package/src/memory/v2/static-context.ts +16 -9
- package/src/memory/v2/sweep-job.ts +122 -96
- package/src/memory/v2/types.ts +10 -6
- package/src/memory/validation.ts +13 -0
- package/src/notifications/__tests__/emit-signal-home-feed.test.ts +182 -0
- package/src/notifications/__tests__/home-feed-side-effect.test.ts +199 -0
- package/src/notifications/__tests__/signal-registry.test.ts +17 -0
- package/src/notifications/adapters/platform.ts +171 -0
- package/src/notifications/conversation-pairing.ts +2 -2
- package/src/notifications/copy-composer.ts +15 -0
- package/src/notifications/destination-resolver.ts +21 -0
- package/src/notifications/emit-signal.ts +28 -1
- package/src/notifications/home-feed-side-effect.ts +111 -0
- package/src/notifications/signal.ts +5 -0
- package/src/permissions/checker.ts +12 -0
- package/src/permissions/ipc-risk-types.ts +2 -0
- package/src/plugin-api/index.ts +13 -0
- package/src/plugin-api/package.json +12 -0
- package/src/plugin-api/types.ts +62 -0
- package/src/plugins/defaults/injectors.ts +19 -3
- package/src/plugins/external-plugin-loader.ts +294 -0
- package/src/plugins/types.ts +46 -30
- package/src/plugins/user-loader.ts +64 -41
- package/src/proactive-artifact/job.test.ts +12 -4
- package/src/proactive-artifact/job.ts +4 -0
- package/src/proactive-artifact/trigger-state.test.ts +9 -0
- package/src/proactive-artifact/trigger-state.ts +4 -0
- package/src/prompts/__tests__/system-prompt.test.ts +105 -0
- package/src/prompts/system-prompt.ts +22 -1
- package/src/prompts/update-bulletin-job.ts +61 -73
- package/src/providers/__tests__/dispatch-connection-routing.test.ts +279 -0
- package/src/providers/__tests__/inference.test.ts +288 -0
- package/src/providers/__tests__/provider-env-vars.test.ts +6 -0
- package/src/providers/__tests__/provider-secret-catalog.test.ts +6 -0
- package/src/providers/__tests__/retry-callsite.test.ts +14 -32
- package/src/providers/__tests__/satellite-connection-routing.test.ts +510 -0
- package/src/providers/__tests__/search-provider-catalog.test.ts +80 -0
- package/src/providers/anthropic/client.ts +95 -26
- package/src/providers/call-site-routing.ts +94 -16
- package/src/providers/connection-resolution.ts +163 -0
- package/src/providers/inference/__tests__/connections-status-label.test.ts +250 -0
- package/src/providers/inference/adapter-factory.ts +173 -0
- package/src/providers/inference/auth.ts +112 -0
- package/src/providers/inference/backfill.ts +196 -0
- package/src/providers/inference/connections.ts +356 -0
- package/src/providers/inference/resolve-auth.ts +65 -0
- package/src/providers/model-catalog.ts +104 -6
- package/src/providers/openai/responses-provider.ts +4 -2
- package/src/providers/provider-env-vars.ts +17 -7
- package/src/providers/provider-secret-catalog.ts +49 -30
- package/src/providers/provider-send-message.ts +41 -20
- package/src/providers/registry.ts +143 -159
- package/src/providers/retry.ts +18 -10
- package/src/providers/search-provider-catalog.ts +121 -0
- package/src/runtime/AGENTS.md +18 -5
- package/src/runtime/__tests__/background-job-runner.test.ts +357 -0
- package/src/runtime/__tests__/pre-first-message-gate.test.ts +82 -0
- package/src/runtime/actor-trust-resolver.ts +32 -10
- package/src/runtime/agent-wake.ts +35 -6
- package/src/runtime/assistant-event-hub.ts +3 -85
- package/src/runtime/auth/route-policy.ts +303 -8
- package/src/runtime/auth/same-actor.ts +2 -0
- package/src/runtime/background-job-runner.ts +339 -0
- package/src/runtime/btw-sidechain.ts +1 -0
- package/src/runtime/http-router.ts +36 -1
- package/src/runtime/http-server.ts +31 -5
- package/src/runtime/http-types.ts +2 -0
- package/src/runtime/middleware/__tests__/request-logger.test.ts +162 -0
- package/src/runtime/middleware/request-logger.ts +62 -1
- package/src/runtime/pre-first-message-gate.ts +83 -0
- package/src/runtime/routes/__tests__/backup-routes.test.ts +8 -1
- package/src/runtime/routes/__tests__/bookmark-routes.test.ts +251 -0
- package/src/runtime/routes/__tests__/connection-routes-vs-cli-parity.test.ts +142 -0
- package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +315 -0
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +189 -0
- package/src/runtime/routes/__tests__/home-feed-routes.test.ts +15 -136
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +736 -0
- package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +4 -4
- package/src/runtime/routes/__tests__/stt-routes.test.ts +5 -1
- package/src/runtime/routes/__tests__/surface-action-routes.test.ts +384 -0
- package/src/runtime/routes/__tests__/tts-routes.test.ts +6 -2
- package/src/runtime/routes/acp-routes.ts +10 -8
- package/src/runtime/routes/app-management-routes.ts +228 -3
- package/src/runtime/routes/approval-routes.ts +0 -18
- package/src/runtime/routes/audit-routes.ts +43 -0
- package/src/runtime/routes/auth-routes.ts +72 -0
- package/src/runtime/routes/avatar-routes.ts +273 -20
- package/src/runtime/routes/backup-routes.ts +406 -2
- package/src/runtime/routes/bookmark-routes.ts +154 -0
- package/src/runtime/routes/channel-verification-routes.ts +2 -1
- package/src/runtime/routes/contact-routes.ts +0 -160
- package/src/runtime/routes/conversation-cli-routes.ts +192 -0
- package/src/runtime/routes/conversation-management-routes.ts +30 -43
- package/src/runtime/routes/conversation-query-routes.ts +334 -86
- package/src/runtime/routes/conversation-routes.ts +31 -10
- package/src/runtime/routes/conversations-import-routes.ts +229 -0
- package/src/runtime/routes/credential-routes.ts +540 -0
- package/src/runtime/routes/debug-routes.ts +2 -2
- package/src/runtime/routes/document-pdf-renderer.ts +5 -1
- package/src/runtime/routes/domain-routes.ts +167 -0
- package/src/runtime/routes/email-routes.ts +603 -0
- package/src/runtime/routes/errors.ts +2 -2
- package/src/runtime/routes/events-routes.ts +192 -0
- package/src/runtime/routes/home-feed-routes.ts +6 -78
- package/src/runtime/routes/host-app-control-routes.ts +44 -2
- package/src/runtime/routes/host-browser-routes.ts +103 -22
- package/src/runtime/routes/http-adapter.ts +2 -0
- package/src/runtime/routes/identity-routes.ts +5 -0
- package/src/runtime/routes/image-generation-routes.ts +99 -0
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +137 -1
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +87 -7
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +156 -0
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +22 -4
- package/src/runtime/routes/index.ts +36 -0
- package/src/runtime/routes/inference-profile-session-handler.ts +312 -0
- package/src/runtime/routes/inference-profile-session-reaper.ts +98 -0
- package/src/runtime/routes/inference-profile-session-routes.ts +146 -0
- package/src/runtime/routes/inference-provider-connection-routes.ts +317 -0
- package/src/runtime/routes/inference-send-routes.ts +115 -0
- package/src/runtime/routes/integrations/twilio.ts +1 -0
- package/src/runtime/routes/mcp-auth-routes.ts +283 -9
- package/src/runtime/routes/memory-v2-routes.ts +13 -398
- package/src/runtime/routes/notification-routes.ts +2 -0
- package/src/runtime/routes/oauth-apps.ts +112 -7
- package/src/runtime/routes/oauth-commands-routes.ts +1007 -0
- package/src/runtime/routes/oauth-connect-routes.ts +67 -5
- package/src/runtime/routes/oauth-providers.ts +298 -8
- package/src/runtime/routes/platform-routes.ts +336 -0
- package/src/runtime/routes/playground/inject-failures.ts +2 -1
- package/src/runtime/routes/playground/reset-circuit.ts +2 -1
- package/src/runtime/routes/playground/state.ts +2 -1
- package/src/runtime/routes/publish-routes.ts +221 -0
- package/src/runtime/routes/schedule-routes.ts +82 -0
- package/src/runtime/routes/sequence-routes.ts +291 -0
- package/src/runtime/routes/settings-routes.ts +2 -10
- package/src/runtime/routes/skills-routes.ts +31 -1
- package/src/runtime/routes/stt-routes.ts +240 -3
- package/src/runtime/routes/surface-action-routes.ts +43 -7
- package/src/runtime/routes/tts-routes.ts +67 -0
- package/src/runtime/routes/types.ts +32 -0
- package/src/runtime/routes/user-routes-cli.ts +243 -0
- package/src/runtime/routes/webhook-routes.ts +165 -0
- package/src/runtime/sync/resource-sync-events.ts +25 -0
- package/src/runtime/sync/sync-publisher.test.ts +105 -0
- package/src/runtime/sync/sync-publisher.ts +21 -0
- package/src/schedule/scheduler.ts +200 -123
- package/src/security/__tests__/provider-key-env-fallback.test.ts +12 -6
- package/src/security/secret-patterns.ts +3 -0
- package/src/sequence/engine.ts +38 -40
- package/src/subagent/manager.ts +20 -15
- package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +206 -0
- package/src/tools/browser/browser-execution.ts +15 -4
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +174 -0
- package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +16 -13
- package/src/tools/browser/cdp-client/extension-cdp-client.ts +24 -1
- package/src/tools/browser/cdp-client/factory.ts +66 -5
- package/src/tools/browser/runtime-check.ts +77 -0
- package/src/tools/memory/register.test.ts +3 -3
- package/src/tools/memory/register.ts +9 -1
- package/src/tools/network/__tests__/web-search.test.ts +156 -0
- package/src/tools/network/web-search.ts +280 -37
- package/src/tools/permission-checker.ts +13 -5
- package/src/tools/subagent/spawn.ts +3 -3
- package/src/tools/terminal/shell.ts +44 -0
- package/src/usage/attribution.ts +3 -2
- package/src/util/pricing.ts +86 -160
- package/src/watcher/__tests__/engine.test.ts +301 -0
- package/src/watcher/constants.ts +7 -0
- package/src/watcher/engine.ts +90 -90
- package/src/workspace/migrations/046-seed-conversation-starters-callsite.ts +6 -9
- package/src/workspace/migrations/054-seed-recall-callsite.ts +10 -1
- package/src/workspace/migrations/057-repair-stale-gemini-model-ids.ts +28 -4
- package/src/workspace/migrations/069-seed-onboarding-threads.ts +8 -2
- package/src/workspace/migrations/072-seed-reply-suggestion-callsite.ts +104 -0
- package/src/workspace/migrations/073-repair-recall-callsite-empty-profile.ts +93 -0
- package/src/workspace/migrations/074-drop-deprecated-secret-detection-keys.ts +117 -0
- package/src/workspace/migrations/075-memory-v2-bm25-b-default-reembed.ts +61 -0
- package/src/workspace/migrations/076-drop-services-inference-mode.ts +62 -0
- package/src/workspace/migrations/077-seed-memory-router-callsite.ts +89 -0
- package/src/workspace/migrations/078-release-notes-tavily-web-search.ts +66 -0
- package/src/workspace/migrations/079-home-feed-notification-only.ts +197 -0
- package/src/workspace/migrations/080-restrict-vercel-api-token-metadata.ts +182 -0
- package/src/workspace/migrations/081-backfill-bash-allowed-tools-for-injection-credentials.ts +160 -0
- package/src/workspace/migrations/082-backfill-managed-profile-labels.ts +154 -0
- package/src/workspace/migrations/registry.ts +22 -0
- package/src/workspace/migrations/runner.ts +13 -2
- package/src/workspace/migrations/types.ts +13 -3
- package/src/workspace/provider-commit-message-generator.ts +3 -2
- package/src/__tests__/context-search-pkb-source.test.ts +0 -498
- package/src/__tests__/credentials-cli.test.ts +0 -1225
- package/src/__tests__/memory-admin-recall.test.ts +0 -213
- package/src/approvals/__tests__/guardian-feed-event.test.ts +0 -303
- package/src/cli/commands/__tests__/email-download.test.ts +0 -260
- package/src/cli/commands/__tests__/email-list.test.ts +0 -216
- package/src/cli/commands/__tests__/email-register.test.ts +0 -186
- package/src/cli/commands/__tests__/email-send.test.ts +0 -416
- package/src/cli/commands/__tests__/email-status.test.ts +0 -185
- package/src/cli/commands/__tests__/email-unregister.test.ts +0 -168
- package/src/cli/commands/__tests__/routes.test.ts +0 -562
- package/src/cli/commands/__tests__/stt-transcribe.test.ts +0 -454
- package/src/cli/commands/autonomy.ts +0 -365
- package/src/cli/commands/memory.ts +0 -424
- package/src/cli/commands/oauth/__tests__/connect.test.ts +0 -947
- package/src/cli/commands/oauth/__tests__/disconnect.test.ts +0 -686
- package/src/cli/commands/oauth/__tests__/mode.test.ts +0 -632
- package/src/cli/commands/oauth/__tests__/ping.test.ts +0 -631
- package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +0 -573
- package/src/cli/commands/oauth/__tests__/providers-register.test.ts +0 -330
- package/src/cli/commands/oauth/__tests__/providers-update.test.ts +0 -521
- package/src/cli/commands/oauth/__tests__/status.test.ts +0 -551
- package/src/cli/commands/oauth/__tests__/token.test.ts +0 -420
- package/src/cli/lib/daemon-avatar-client.ts +0 -37
- package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +0 -87
- package/src/config/bundled-skills/messaging/tools/__tests__/messaging-feed-events.test.ts +0 -207
- package/src/daemon/__tests__/conversation-feed-event.test.ts +0 -304
- package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +0 -233
- package/src/home/__tests__/assistant-feed-authoring.test.ts +0 -156
- package/src/home/__tests__/emit-feed-event.test.ts +0 -169
- package/src/home/__tests__/feed-population-integration.test.ts +0 -312
- package/src/home/__tests__/feed-scheduler.test.ts +0 -222
- package/src/home/__tests__/phase5-exit-criteria.test.ts +0 -229
- package/src/home/__tests__/platform-gmail-digest.test.ts +0 -222
- package/src/home/__tests__/rollup-producer.test.ts +0 -507
- package/src/home/assistant-feed-authoring.ts +0 -135
- package/src/home/emit-feed-event.ts +0 -169
- package/src/home/feed-scheduler.ts +0 -281
- package/src/home/platform-gmail-digest.ts +0 -163
- package/src/home/rewrite-command-preview.ts +0 -66
- package/src/home/rewrite-feed-title.ts +0 -58
- package/src/home/rollup-producer.ts +0 -426
- package/src/memory/admin.ts +0 -326
- package/src/memory/context-search/sources/pkb.ts +0 -476
- package/src/memory/graph/compaction.ts +0 -299
- /package/src/cli/{commands → lib}/cache-fs.ts +0 -0
package/src/memory/v2/sim.ts
CHANGED
|
@@ -17,13 +17,20 @@
|
|
|
17
17
|
// channel separately and fuses with the configured `dense_weight` /
|
|
18
18
|
// `sparse_weight` (which the schema validates sum to 1.0).
|
|
19
19
|
//
|
|
20
|
-
//
|
|
21
|
-
//
|
|
22
|
-
//
|
|
23
|
-
//
|
|
24
|
-
//
|
|
25
|
-
//
|
|
26
|
-
//
|
|
20
|
+
// Score normalization:
|
|
21
|
+
// Qdrant returns cosine similarity in [-1, 1]. We clamp negative cosines
|
|
22
|
+
// to 0 before fusion so anti-correlated documents contribute zero, rather
|
|
23
|
+
// than a negative term that subtracts from the sparse channel and can
|
|
24
|
+
// depress the fused score below the sparse-only floor. Positive cosines
|
|
25
|
+
// pass through unchanged — affine-rescaling them into [0, 1] via
|
|
26
|
+
// `(cos + 1) / 2` would halve every pairwise dense difference and shift
|
|
27
|
+
// ranking toward the sparse channel, the opposite of intent. Qdrant's
|
|
28
|
+
// sparse score is on a different, unbounded scale (it depends on query
|
|
29
|
+
// and document term weights), so we divide by the per-batch maximum
|
|
30
|
+
// sparse score to bring it into [0, 1] before fusing. This is the design
|
|
31
|
+
// doc's choice (§4) — batch-relative normalization is sufficient because
|
|
32
|
+
// the score is consumed only as a per-turn ordering signal, not compared
|
|
33
|
+
// across turns.
|
|
27
34
|
|
|
28
35
|
import type { AssistantConfig } from "../../config/types.js";
|
|
29
36
|
import { applyCorrectionIfCalibrated } from "../anisotropy.js";
|
|
@@ -264,11 +271,17 @@ function computeMaxSparse<T>(
|
|
|
264
271
|
|
|
265
272
|
/**
|
|
266
273
|
* Fuse one half of a hit (body or summary) into a normalized [0, 1] score
|
|
267
|
-
* via `clamp01(dense_weight ·
|
|
268
|
-
*
|
|
269
|
-
*
|
|
274
|
+
* via `clamp01(dense_weight · max(0, cosine) + sparse_weight ·
|
|
275
|
+
* sparse/maxSparse)`. Negative cosines clamp to 0 so they don't subtract
|
|
276
|
+
* from sparse; positive cosines pass through unchanged so the
|
|
277
|
+
* operator-configured dense/sparse balance is preserved. Returns
|
|
278
|
+
* `undefined` when neither channel hit — a signal the half had no match
|
|
279
|
+
* at all, so the caller can fall back to the other half cleanly.
|
|
280
|
+
*
|
|
281
|
+
* Exported so the context-search adapter can reuse the same fusion math
|
|
282
|
+
* for its own activation pipeline.
|
|
270
283
|
*/
|
|
271
|
-
function fuseHalf(
|
|
284
|
+
export function fuseHalf(
|
|
272
285
|
denseScore: number | undefined,
|
|
273
286
|
sparseScore: number | undefined,
|
|
274
287
|
maxSparse: number,
|
|
@@ -276,7 +289,7 @@ function fuseHalf(
|
|
|
276
289
|
sparseWeight: number,
|
|
277
290
|
): number | undefined {
|
|
278
291
|
if (denseScore === undefined && sparseScore === undefined) return undefined;
|
|
279
|
-
const dense = denseScore
|
|
292
|
+
const dense = denseScore !== undefined ? Math.max(0, denseScore) : 0;
|
|
280
293
|
const sparseNormalized =
|
|
281
294
|
sparseScore !== undefined && maxSparse > 0 ? sparseScore / maxSparse : 0;
|
|
282
295
|
return clamp01(denseWeight * dense + sparseWeight * sparseNormalized);
|
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
embedWithBackend,
|
|
35
35
|
generateSparseEmbedding,
|
|
36
36
|
} from "../embedding-backend.js";
|
|
37
|
+
import { invalidatePageIndex } from "./page-index.js";
|
|
37
38
|
import {
|
|
38
39
|
pruneSlugsWithPrefixExcept,
|
|
39
40
|
upsertConceptPageEmbedding,
|
|
@@ -42,6 +43,10 @@ import {
|
|
|
42
43
|
augmentMcpSetupDescription,
|
|
43
44
|
buildSkillContent,
|
|
44
45
|
} from "./skill-content.js";
|
|
46
|
+
import {
|
|
47
|
+
generateBm25DocEmbedding,
|
|
48
|
+
getConceptPageCorpusStats,
|
|
49
|
+
} from "./sparse-bm25.js";
|
|
45
50
|
import type { SkillEntry } from "./types.js";
|
|
46
51
|
|
|
47
52
|
const log = getLogger("memory-v2-skill-store");
|
|
@@ -54,6 +59,14 @@ const log = getLogger("memory-v2-skill-store");
|
|
|
54
59
|
*/
|
|
55
60
|
export const SKILL_SLUG_PREFIX = "skills/";
|
|
56
61
|
|
|
62
|
+
/**
|
|
63
|
+
* Payload discriminator written on every skill-seeded Qdrant point. Keeps
|
|
64
|
+
* skill rows distinguishable from user-authored concept pages that happen to
|
|
65
|
+
* be slugged under `skills/...`, so prefix pruning never deletes a hand-
|
|
66
|
+
* authored page sitting in the same namespace.
|
|
67
|
+
*/
|
|
68
|
+
const SKILL_PAYLOAD_KIND = "skill";
|
|
69
|
+
|
|
57
70
|
/** Compose the unified-collection slug for a skill id. */
|
|
58
71
|
export function skillSlugFor(id: string): string {
|
|
59
72
|
return `${SKILL_SLUG_PREFIX}${id}`;
|
|
@@ -68,10 +81,39 @@ let entries: Map<string, SkillEntry> | null = null;
|
|
|
68
81
|
|
|
69
82
|
/**
|
|
70
83
|
* Seed (or re-seed) skill embeddings into the unified concept-page collection.
|
|
71
|
-
* Idempotent
|
|
72
|
-
*
|
|
84
|
+
* Idempotent. Defaults to best-effort (errors are logged but swallowed) for
|
|
85
|
+
* background callers like daemon startup; pass `{ throwOnError: true }` from
|
|
86
|
+
* synchronous CLI-driven paths that need to surface failures to the operator.
|
|
73
87
|
*
|
|
74
|
-
*
|
|
88
|
+
* Single-flight + coalesced: at most one seed runs at a time, and concurrent
|
|
89
|
+
* callers are coalesced into one follow-up re-snapshot that runs after the
|
|
90
|
+
* in-flight seed completes. Without this, an older snapshot can finish after
|
|
91
|
+
* a newer one and overwrite the newer skill state. Strict callers observe
|
|
92
|
+
* the most recent run's outcome via `lastSeedError`.
|
|
93
|
+
*/
|
|
94
|
+
let seedTail: Promise<void> = Promise.resolve();
|
|
95
|
+
let seedPending: Promise<void> | null = null;
|
|
96
|
+
let lastSeedError: unknown = null;
|
|
97
|
+
|
|
98
|
+
export async function seedV2SkillEntries(
|
|
99
|
+
opts: { throwOnError?: boolean } = {},
|
|
100
|
+
): Promise<void> {
|
|
101
|
+
if (!seedPending) {
|
|
102
|
+
const next = seedTail.then(async () => {
|
|
103
|
+
seedPending = null;
|
|
104
|
+
await runSeedOnce();
|
|
105
|
+
});
|
|
106
|
+
seedTail = next.catch(() => {});
|
|
107
|
+
seedPending = next;
|
|
108
|
+
}
|
|
109
|
+
await seedPending;
|
|
110
|
+
if (opts.throwOnError && lastSeedError) {
|
|
111
|
+
throw lastSeedError;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Steps (per run):
|
|
75
117
|
* 1. Enumerate the local skill catalog and resolve each skill's enabled
|
|
76
118
|
* state (`resolveSkillStates`).
|
|
77
119
|
* 2. Build a `SkillEntry` per enabled skill, applying the mcp-setup
|
|
@@ -90,7 +132,7 @@ let entries: Map<string, SkillEntry> | null = null;
|
|
|
90
132
|
* stale points from prior catalog state (e.g. uninstalled skills).
|
|
91
133
|
* 7. Replace the module-level `entries` cache with the freshly built map.
|
|
92
134
|
*/
|
|
93
|
-
|
|
135
|
+
async function runSeedOnce(): Promise<void> {
|
|
94
136
|
try {
|
|
95
137
|
const config = getConfig();
|
|
96
138
|
const catalog = loadSkillCatalog();
|
|
@@ -137,32 +179,53 @@ export async function seedV2SkillEntries(): Promise<void> {
|
|
|
137
179
|
);
|
|
138
180
|
}
|
|
139
181
|
|
|
140
|
-
// Embed all content strings in one batched call
|
|
141
|
-
//
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
seeds.map((s) => s.content),
|
|
145
|
-
);
|
|
146
|
-
const denseVectors = await Promise.all(
|
|
147
|
-
embedded.vectors.map((v) =>
|
|
148
|
-
applyCorrectionIfCalibrated(v, embedded.provider, embedded.model),
|
|
149
|
-
),
|
|
150
|
-
);
|
|
151
|
-
|
|
152
|
-
const now = Date.now();
|
|
182
|
+
// Embed all content strings in one batched call when there is anything to
|
|
183
|
+
// embed. Skipping the call when `seeds` is empty avoids throwing on an
|
|
184
|
+
// unavailable embedding backend in the all-disabled case, so pruning and
|
|
185
|
+
// cache replacement still run and clear stale state.
|
|
153
186
|
const nextEntries = new Map<string, SkillEntry>();
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
187
|
+
if (seeds.length > 0) {
|
|
188
|
+
const embedded = await embedWithBackend(
|
|
189
|
+
config,
|
|
190
|
+
seeds.map((s) => s.content),
|
|
191
|
+
);
|
|
192
|
+
const denseVectors = await Promise.all(
|
|
193
|
+
embedded.vectors.map((v) =>
|
|
194
|
+
applyCorrectionIfCalibrated(v, embedded.provider, embedded.model),
|
|
195
|
+
),
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
// Skills share the concept-page Qdrant collection, so the sparse vector
|
|
199
|
+
// must use the same stemmed BM25 encoding the concept-page documents
|
|
200
|
+
// carry — otherwise the stemmed BM25 query vectors used by callers (see
|
|
201
|
+
// `simBatch`, `activation.selectCandidates`, recall) hash to different
|
|
202
|
+
// buckets than the stored skill vectors and skip the sparse channel
|
|
203
|
+
// entirely. Fall back to the legacy TF encoder only during the cold-start
|
|
204
|
+
// window before corpus stats finish building.
|
|
205
|
+
const corpusStats = getConceptPageCorpusStats();
|
|
206
|
+
const encodeSparse = (input: string) =>
|
|
207
|
+
corpusStats
|
|
208
|
+
? generateBm25DocEmbedding(input, corpusStats, {
|
|
209
|
+
k1: config.memory.v2.bm25_k1,
|
|
210
|
+
b: config.memory.v2.bm25_b,
|
|
211
|
+
})
|
|
212
|
+
: generateSparseEmbedding(input);
|
|
213
|
+
|
|
214
|
+
const now = Date.now();
|
|
215
|
+
await Promise.all(
|
|
216
|
+
seeds.map((seed, i) =>
|
|
217
|
+
upsertConceptPageEmbedding({
|
|
218
|
+
slug: skillSlugFor(seed.id),
|
|
219
|
+
dense: denseVectors[i],
|
|
220
|
+
sparse: encodeSparse(seed.content),
|
|
221
|
+
updatedAt: now,
|
|
222
|
+
kind: SKILL_PAYLOAD_KIND,
|
|
223
|
+
}),
|
|
224
|
+
),
|
|
225
|
+
);
|
|
226
|
+
for (const seed of seeds) {
|
|
227
|
+
nextEntries.set(seed.id, seed);
|
|
228
|
+
}
|
|
166
229
|
}
|
|
167
230
|
|
|
168
231
|
// Prune stale skill slugs. When the catalog is unavailable (empty array
|
|
@@ -173,6 +236,7 @@ export async function seedV2SkillEntries(): Promise<void> {
|
|
|
173
236
|
await pruneSlugsWithPrefixExcept(
|
|
174
237
|
SKILL_SLUG_PREFIX,
|
|
175
238
|
seeds.map((s) => s.id),
|
|
239
|
+
{ kind: SKILL_PAYLOAD_KIND },
|
|
176
240
|
);
|
|
177
241
|
} else {
|
|
178
242
|
log.info(
|
|
@@ -182,7 +246,13 @@ export async function seedV2SkillEntries(): Promise<void> {
|
|
|
182
246
|
|
|
183
247
|
// Atomically replace the cache only after every step above succeeds.
|
|
184
248
|
entries = nextEntries;
|
|
249
|
+
// Drop the page-index cache so the next router invocation observes the
|
|
250
|
+
// freshly seeded skill set (skill entries share the unified concept-page
|
|
251
|
+
// collection and surface in the same index).
|
|
252
|
+
invalidatePageIndex();
|
|
253
|
+
lastSeedError = null;
|
|
185
254
|
} catch (err) {
|
|
255
|
+
lastSeedError = err;
|
|
186
256
|
log.warn({ err }, "Failed to seed v2 skill entries");
|
|
187
257
|
}
|
|
188
258
|
}
|
|
@@ -208,7 +278,26 @@ export function isSkillSlug(slug: string): boolean {
|
|
|
208
278
|
return slug.startsWith(SKILL_SLUG_PREFIX);
|
|
209
279
|
}
|
|
210
280
|
|
|
281
|
+
/**
|
|
282
|
+
* Snapshot of the in-process skill cache, sorted by skill id (ASCII order)
|
|
283
|
+
* for determinism. Returns a freshly allocated array on each call so callers
|
|
284
|
+
* cannot mutate the underlying cache.
|
|
285
|
+
*
|
|
286
|
+
* The cache is replaced atomically by `seedV2SkillEntries`, so a snapshot
|
|
287
|
+
* may be stale once a subsequent seed run completes. Callers that need
|
|
288
|
+
* up-to-the-moment state must re-call this after awaiting the seed.
|
|
289
|
+
*/
|
|
290
|
+
export function listSkillEntries(): SkillEntry[] {
|
|
291
|
+
if (!entries) return [];
|
|
292
|
+
return [...entries.values()].sort((a, b) =>
|
|
293
|
+
a.id < b.id ? -1 : a.id > b.id ? 1 : 0,
|
|
294
|
+
);
|
|
295
|
+
}
|
|
296
|
+
|
|
211
297
|
/** @internal Test-only: clear the module-level cache. */
|
|
212
298
|
export function _resetSkillStoreForTests(): void {
|
|
213
299
|
entries = null;
|
|
300
|
+
seedTail = Promise.resolve();
|
|
301
|
+
seedPending = null;
|
|
302
|
+
lastSeedError = null;
|
|
214
303
|
}
|
|
@@ -60,19 +60,26 @@ export function readMemoryV2StaticContent(): string | null {
|
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
/**
|
|
63
|
-
*
|
|
64
|
-
* (essentials/threads/recent/buffer)
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
63
|
+
* Trust-class predicate for personal-memory injection. Personal memory
|
|
64
|
+
* spans v2 static blocks (essentials/threads/recent/buffer), the PKB
|
|
65
|
+
* context, and NOW.md — all of which can hold private user content. Block
|
|
66
|
+
* injection when a non-guardian actor reaches the assistant over a remote
|
|
67
|
+
* channel — otherwise the model can be prompt-injected into reciting
|
|
68
|
+
* private memory. Internal flows (`sourceChannel: "vellum"`) and turns
|
|
69
|
+
* with no trust context pass through unchanged; this gate exists only to
|
|
70
|
+
* keep remote untrusted actors out.
|
|
71
|
+
*
|
|
72
|
+
* This is the trust-only gate. Cadence (first-turn / post-compaction) is
|
|
73
|
+
* applied separately by the caller so that the freshest content remains
|
|
74
|
+
* available for re-injection after a mid-turn reducer-triggered compaction
|
|
75
|
+
* — the initial-injection turn may not have been a `shouldInjectNowAndPkb`
|
|
76
|
+
* turn, but compaction strips the existing personal-memory blocks and we
|
|
77
|
+
* still need the freshest content to re-inject.
|
|
69
78
|
*/
|
|
70
|
-
export function
|
|
71
|
-
shouldInjectNowAndPkb: boolean;
|
|
79
|
+
export function shouldExposePersonalMemory(args: {
|
|
72
80
|
sourceChannel: ChannelId | undefined;
|
|
73
81
|
isTrustedActor: boolean;
|
|
74
82
|
}): boolean {
|
|
75
|
-
if (!args.shouldInjectNowAndPkb) return false;
|
|
76
83
|
const isRemoteUntrustedActor =
|
|
77
84
|
args.sourceChannel !== undefined &&
|
|
78
85
|
args.sourceChannel !== "vellum" &&
|
|
@@ -22,11 +22,15 @@
|
|
|
22
22
|
import { readFileSync } from "node:fs";
|
|
23
23
|
import { join } from "node:path";
|
|
24
24
|
|
|
25
|
-
import { desc, gt } from "drizzle-orm";
|
|
25
|
+
import { and, desc, eq, gt, notInArray } from "drizzle-orm";
|
|
26
26
|
import { z } from "zod";
|
|
27
27
|
|
|
28
28
|
import type { AssistantConfig } from "../../config/types.js";
|
|
29
|
-
import {
|
|
29
|
+
import {
|
|
30
|
+
getAssistantName,
|
|
31
|
+
resolveUserName,
|
|
32
|
+
} from "../../daemon/identity-helpers.js";
|
|
33
|
+
import { emitNotificationSignal } from "../../notifications/emit-signal.js";
|
|
30
34
|
import {
|
|
31
35
|
extractToolUse,
|
|
32
36
|
getConfiguredProvider,
|
|
@@ -41,11 +45,15 @@ import {
|
|
|
41
45
|
formatRememberEntry,
|
|
42
46
|
} from "../graph/tool-handlers.js";
|
|
43
47
|
import type { MemoryJob } from "../jobs-store.js";
|
|
44
|
-
import {
|
|
48
|
+
import { stringifyMessageContent } from "../message-content.js";
|
|
49
|
+
import { conversations, messages } from "../schema.js";
|
|
45
50
|
import { renderSweepPrompt } from "./prompts/sweep.js";
|
|
46
51
|
|
|
47
52
|
const log = getLogger("memory-v2-sweep");
|
|
48
53
|
|
|
54
|
+
/** Stable job identifier surfaced in `activity.failed` notifications. */
|
|
55
|
+
const JOB_NAME = "memory.v2.sweep";
|
|
56
|
+
|
|
49
57
|
/** Window of conversation history the sweep inspects on each run. */
|
|
50
58
|
const RECENT_MESSAGES_WINDOW_MS = 30 * 60 * 1000;
|
|
51
59
|
|
|
@@ -100,7 +108,7 @@ const SweepResultSchema = z.object({
|
|
|
100
108
|
* progress without inspecting the filesystem.
|
|
101
109
|
*/
|
|
102
110
|
export async function memoryV2SweepJob(
|
|
103
|
-
|
|
111
|
+
job: MemoryJob,
|
|
104
112
|
config: AssistantConfig,
|
|
105
113
|
): Promise<number> {
|
|
106
114
|
if (!config.memory?.v2?.enabled) {
|
|
@@ -115,59 +123,116 @@ export async function memoryV2SweepJob(
|
|
|
115
123
|
|
|
116
124
|
const workspaceDir = getWorkspaceDir();
|
|
117
125
|
const memoryDir = join(workspaceDir, "memory");
|
|
118
|
-
const recentText = loadRecentMessagesText(Date.now());
|
|
119
|
-
if (!recentText) {
|
|
120
|
-
log.debug("No recent messages in window; sweep skipped");
|
|
121
|
-
return 0;
|
|
122
|
-
}
|
|
123
126
|
|
|
124
|
-
|
|
127
|
+
// Once we're committed to running (past the flag/feature gates), any
|
|
128
|
+
// unexpected error is surfaced via an `activity.failed` notification —
|
|
129
|
+
// mirrors v1 filing's post-migration treatment, but hand-rolled because
|
|
130
|
+
// the sweep makes a single forced-tool `provider.sendMessage` call rather
|
|
131
|
+
// than driving a conversation through `runBackgroundJob`. The function
|
|
132
|
+
// continues to return 0 on caught failures (preserving the existing
|
|
133
|
+
// silent-failure contract); only the notification side-effect is new.
|
|
134
|
+
try {
|
|
135
|
+
const recentText = loadRecentMessagesText(Date.now());
|
|
136
|
+
if (!recentText) {
|
|
137
|
+
log.debug("No recent messages in window; sweep skipped");
|
|
138
|
+
return 0;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const existingBuffer = readBufferText(memoryDir);
|
|
125
142
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
143
|
+
const provider = await getConfiguredProvider("memoryV2Sweep");
|
|
144
|
+
if (!provider) {
|
|
145
|
+
log.warn("memoryV2Sweep provider unavailable; sweep skipped");
|
|
146
|
+
return 0;
|
|
147
|
+
}
|
|
131
148
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
149
|
+
const systemPrompt = renderSweepPrompt({
|
|
150
|
+
assistantName: getAssistantName(),
|
|
151
|
+
userName: resolveUserName(workspaceDir),
|
|
152
|
+
});
|
|
153
|
+
const userText =
|
|
154
|
+
`## existingBuffer\n\n${existingBuffer || "(empty)"}\n\n` +
|
|
155
|
+
`## recentMessages\n\n${recentText}`;
|
|
139
156
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
157
|
+
const response = await provider.sendMessage(
|
|
158
|
+
[userMessage(userText)],
|
|
159
|
+
[SWEEP_TOOL],
|
|
160
|
+
systemPrompt,
|
|
161
|
+
{
|
|
162
|
+
config: {
|
|
163
|
+
callSite: "memoryV2Sweep" as const,
|
|
164
|
+
tool_choice: { type: "tool" as const, name: SWEEP_TOOL_NAME },
|
|
165
|
+
},
|
|
148
166
|
},
|
|
149
|
-
|
|
150
|
-
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
const toolBlock = extractToolUse(response);
|
|
170
|
+
if (!toolBlock || toolBlock.name !== SWEEP_TOOL_NAME) {
|
|
171
|
+
log.debug("Sweep model returned no tool_use block");
|
|
172
|
+
return 0;
|
|
173
|
+
}
|
|
174
|
+
const parsed = SweepResultSchema.safeParse(toolBlock.input);
|
|
175
|
+
if (!parsed.success) {
|
|
176
|
+
log.warn(
|
|
177
|
+
{ error: parsed.error.message },
|
|
178
|
+
"Sweep tool input did not match schema",
|
|
179
|
+
);
|
|
180
|
+
return 0;
|
|
181
|
+
}
|
|
151
182
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
183
|
+
const written = appendEntries(memoryDir, parsed.data.entries);
|
|
184
|
+
if (written > 0) {
|
|
185
|
+
log.info({ written }, "Memory v2 sweep wrote new buffer entries");
|
|
186
|
+
}
|
|
187
|
+
return written;
|
|
188
|
+
} catch (err) {
|
|
189
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
190
|
+
log.error({ err }, "memory v2 sweep failed");
|
|
191
|
+
emitSweepActivityFailed({
|
|
192
|
+
jobId: job.id,
|
|
193
|
+
errorMessage,
|
|
194
|
+
});
|
|
155
195
|
return 0;
|
|
156
196
|
}
|
|
157
|
-
|
|
158
|
-
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Emit an `activity.failed` notification for a failed sweep run. Mirrors
|
|
201
|
+
* the shape `runBackgroundJob` produces for its own failures so the home
|
|
202
|
+
* feed and native notifications stay consistent regardless of which code
|
|
203
|
+
* path executed the work. Fire-and-forget — a notification failure must
|
|
204
|
+
* never break sweep operation.
|
|
205
|
+
*/
|
|
206
|
+
function emitSweepActivityFailed(args: {
|
|
207
|
+
jobId: string;
|
|
208
|
+
errorMessage: string;
|
|
209
|
+
}): void {
|
|
210
|
+
const day = new Date().toISOString().slice(0, 10);
|
|
211
|
+
emitNotificationSignal({
|
|
212
|
+
sourceChannel: "scheduler",
|
|
213
|
+
sourceContextId: args.jobId,
|
|
214
|
+
sourceEventName: "activity.failed",
|
|
215
|
+
dedupeKey: `activity-failed:${JOB_NAME}:${day}`,
|
|
216
|
+
contextPayload: {
|
|
217
|
+
jobName: JOB_NAME,
|
|
218
|
+
errorMessage: args.errorMessage,
|
|
219
|
+
errorKind: "exception",
|
|
220
|
+
},
|
|
221
|
+
attentionHints: {
|
|
222
|
+
requiresAction: false,
|
|
223
|
+
urgency: "medium",
|
|
224
|
+
isAsyncBackground: true,
|
|
225
|
+
visibleInSourceNow: false,
|
|
226
|
+
},
|
|
227
|
+
}).catch((emitErr) => {
|
|
159
228
|
log.warn(
|
|
160
|
-
{
|
|
161
|
-
|
|
229
|
+
{
|
|
230
|
+
err: emitErr instanceof Error ? emitErr.message : String(emitErr),
|
|
231
|
+
jobId: args.jobId,
|
|
232
|
+
},
|
|
233
|
+
"Failed to emit activity.failed notification for memory v2 sweep",
|
|
162
234
|
);
|
|
163
|
-
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
const written = appendEntries(memoryDir, parsed.data.entries);
|
|
167
|
-
if (written > 0) {
|
|
168
|
-
log.info({ written }, "Memory v2 sweep wrote new buffer entries");
|
|
169
|
-
}
|
|
170
|
-
return written;
|
|
235
|
+
});
|
|
171
236
|
}
|
|
172
237
|
|
|
173
238
|
/**
|
|
@@ -219,14 +284,22 @@ function loadRecentMessagesText(nowMs: number): string {
|
|
|
219
284
|
const db = getDb();
|
|
220
285
|
// Pull newest-first then reverse for chronological output. Bounding the
|
|
221
286
|
// initial limit (1000) defends against pathological busy windows where a
|
|
222
|
-
// naive scan would touch every recent message.
|
|
287
|
+
// naive scan would touch every recent message. Joining conversations and
|
|
288
|
+
// excluding background/scheduled types keeps automation chatter
|
|
289
|
+
// (heartbeats, filing, update bulletins, scheduled jobs) out of buffer.md.
|
|
223
290
|
const rows = db
|
|
224
291
|
.select({
|
|
225
292
|
role: messages.role,
|
|
226
293
|
content: messages.content,
|
|
227
294
|
})
|
|
228
295
|
.from(messages)
|
|
229
|
-
.
|
|
296
|
+
.innerJoin(conversations, eq(messages.conversationId, conversations.id))
|
|
297
|
+
.where(
|
|
298
|
+
and(
|
|
299
|
+
gt(messages.createdAt, cutoff),
|
|
300
|
+
notInArray(conversations.conversationType, ["background", "scheduled"]),
|
|
301
|
+
),
|
|
302
|
+
)
|
|
230
303
|
.orderBy(desc(messages.createdAt))
|
|
231
304
|
.limit(1000)
|
|
232
305
|
.all();
|
|
@@ -248,50 +321,3 @@ function loadRecentMessagesText(nowMs: number): string {
|
|
|
248
321
|
}
|
|
249
322
|
return joined;
|
|
250
323
|
}
|
|
251
|
-
|
|
252
|
-
/**
|
|
253
|
-
* Coerce stored message content (JSON-serialized `ContentBlock[]` *or* plain
|
|
254
|
-
* string in legacy rows) into a single text string. Image / tool blocks are
|
|
255
|
-
* dropped — the sweep model only needs the spoken context.
|
|
256
|
-
*/
|
|
257
|
-
function stringifyMessageContent(stored: string): string {
|
|
258
|
-
let parsed: unknown;
|
|
259
|
-
try {
|
|
260
|
-
parsed = JSON.parse(stored);
|
|
261
|
-
} catch {
|
|
262
|
-
return stored.trim();
|
|
263
|
-
}
|
|
264
|
-
if (typeof parsed === "string") return parsed.trim();
|
|
265
|
-
if (!Array.isArray(parsed)) return "";
|
|
266
|
-
const parts: string[] = [];
|
|
267
|
-
for (const block of parsed) {
|
|
268
|
-
if (
|
|
269
|
-
block &&
|
|
270
|
-
typeof block === "object" &&
|
|
271
|
-
(block as { type?: string }).type === "text" &&
|
|
272
|
-
typeof (block as { text?: unknown }).text === "string"
|
|
273
|
-
) {
|
|
274
|
-
parts.push((block as { text: string }).text);
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
return parts.join("\n").trim();
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
/**
|
|
281
|
-
* Read the guardian's display name from `users/default.md`. We look for the
|
|
282
|
-
* markdown-bold "Name" label (matching the IDENTITY.md convention) and fall
|
|
283
|
-
* back to `null` on any miss; the prompt template substitutes a generic
|
|
284
|
-
* label.
|
|
285
|
-
*/
|
|
286
|
-
function resolveUserName(workspaceDir: string): string | null {
|
|
287
|
-
try {
|
|
288
|
-
const content = readFileSync(
|
|
289
|
-
join(workspaceDir, "users", "default.md"),
|
|
290
|
-
"utf-8",
|
|
291
|
-
);
|
|
292
|
-
const match = content.match(/\*\*Name:\*\*\s*(.+)/);
|
|
293
|
-
return match?.[1]?.trim() || null;
|
|
294
|
-
} catch {
|
|
295
|
-
return null;
|
|
296
|
-
}
|
|
297
|
-
}
|
package/src/memory/v2/types.ts
CHANGED
|
@@ -25,7 +25,8 @@ import { z } from "zod";
|
|
|
25
25
|
* `edges:` means "activating A pulls in B" — activation flows A → B but not
|
|
26
26
|
* B → A. The full graph is the union of every page's `edges:` list — there
|
|
27
27
|
* is no separate edges-index file. `ref_files` lists paths to attached media
|
|
28
|
-
* (images, audio, etc.).
|
|
28
|
+
* (images, audio, etc.). `ref_urls` lists external URL references (e.g.
|
|
29
|
+
* citations, source links).
|
|
29
30
|
*
|
|
30
31
|
* `summary` is a 1-4 sentence prose description of the page. When present,
|
|
31
32
|
* retrieval injects the path + summary instead of the full page so the agent
|
|
@@ -33,11 +34,14 @@ import { z } from "zod";
|
|
|
33
34
|
* the summary field still parse — those fall back to full-page injection and
|
|
34
35
|
* full-page-only similarity.
|
|
35
36
|
*/
|
|
36
|
-
export const ConceptPageFrontmatterSchema = z
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
export const ConceptPageFrontmatterSchema = z
|
|
38
|
+
.object({
|
|
39
|
+
edges: z.array(z.string()).default([]),
|
|
40
|
+
ref_files: z.array(z.string()).default([]),
|
|
41
|
+
ref_urls: z.array(z.string().url()).default([]),
|
|
42
|
+
summary: z.string().optional(),
|
|
43
|
+
})
|
|
44
|
+
.strict();
|
|
41
45
|
|
|
42
46
|
export type ConceptPageFrontmatter = z.infer<
|
|
43
47
|
typeof ConceptPageFrontmatterSchema
|
package/src/memory/validation.ts
CHANGED
|
@@ -8,3 +8,16 @@
|
|
|
8
8
|
export function clampUnitInterval(value: number): number {
|
|
9
9
|
return Math.min(1, Math.max(0, value));
|
|
10
10
|
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Map cosine similarity [-1, 1] into the unit interval [0, 1] via
|
|
14
|
+
* `(x + 1) / 2`, then clamp. Single-channel display normalization for the
|
|
15
|
+
* legacy v1 semantic-search path; do **not** use before hybrid fusion —
|
|
16
|
+
* the affine rescale halves pairwise dense differences and shifts ranking
|
|
17
|
+
* toward sparse. Hybrid fusion (`v2/sim.ts`) instead clamps negative
|
|
18
|
+
* cosines to 0 with `Math.max(0, x)` and lets positive cosines pass
|
|
19
|
+
* through unchanged.
|
|
20
|
+
*/
|
|
21
|
+
export function mapCosineToUnit(value: number): number {
|
|
22
|
+
return clampUnitInterval((value + 1) / 2);
|
|
23
|
+
}
|