@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
|
@@ -40,6 +40,7 @@ import {
|
|
|
40
40
|
import { hydrate, save } from "./activation-store.js";
|
|
41
41
|
import { getEdgeIndex } from "./edge-index.js";
|
|
42
42
|
import { readPage, renderPageContent } from "./page-store.js";
|
|
43
|
+
import { runRouter } from "./router.js";
|
|
43
44
|
import { getSkillCapability, isSkillSlug } from "./skill-store.js";
|
|
44
45
|
import type { ActivationState, EverInjectedEntry } from "./types.js";
|
|
45
46
|
|
|
@@ -58,6 +59,16 @@ const log = getLogger("memory-v2-injection");
|
|
|
58
59
|
*/
|
|
59
60
|
export type InjectMemoryV2Mode = "context-load" | "per-turn";
|
|
60
61
|
|
|
62
|
+
/**
|
|
63
|
+
* Internal mode union for `finalizeInjection`. Extends the public
|
|
64
|
+
* `InjectMemoryV2Mode` with `"router"` (router-driven success path) and
|
|
65
|
+
* `"errored"` (caller-supplied failure path or the helper's own
|
|
66
|
+
* try/catch promotion). The public surface intentionally only carries
|
|
67
|
+
* the caller-facing modes — these two are persistence/telemetry concerns
|
|
68
|
+
* that don't belong on `InjectMemoryV2BlockParams`.
|
|
69
|
+
*/
|
|
70
|
+
type FinalizeInjectionMode = InjectMemoryV2Mode | "router" | "errored";
|
|
71
|
+
|
|
61
72
|
export interface InjectMemoryV2BlockParams {
|
|
62
73
|
/** SQLite database handle for activation_state hydrate/save. */
|
|
63
74
|
database: DrizzleDb;
|
|
@@ -94,8 +105,12 @@ export interface InjectMemoryV2BlockResult {
|
|
|
94
105
|
*/
|
|
95
106
|
block: string | null;
|
|
96
107
|
/**
|
|
97
|
-
* Slugs
|
|
98
|
-
*
|
|
108
|
+
* Slugs we attempted to attach this turn (top-K minus everInjected).
|
|
109
|
+
* Always populated even when `block` is `null` — phantom slugs whose
|
|
110
|
+
* backing page is missing on disk land here and are recorded in
|
|
111
|
+
* `everInjected` so we don't infinite-retry next turn. Callers using
|
|
112
|
+
* this for "we injected N slugs" telemetry should cross-reference
|
|
113
|
+
* `block !== null` (or the activation log's `page_missing` status).
|
|
99
114
|
*/
|
|
100
115
|
toInject: string[];
|
|
101
116
|
}
|
|
@@ -135,6 +150,27 @@ export async function injectMemoryV2Block(
|
|
|
135
150
|
throwIfAborted(signal);
|
|
136
151
|
const priorState = await hydrate(database, conversationId);
|
|
137
152
|
|
|
153
|
+
// Flag-gated router dispatch: when the LLM router is enabled, route the
|
|
154
|
+
// per-turn page selection through `runRouter` and reuse `finalizeInjection`
|
|
155
|
+
// for persistence, render, and telemetry. The activation pipeline below
|
|
156
|
+
// remains the default (flag-off) behavior — every code path past this
|
|
157
|
+
// branch only runs when the router is disabled.
|
|
158
|
+
if (config.memory.v2.router.enabled) {
|
|
159
|
+
return injectViaRouter({
|
|
160
|
+
workspaceDir,
|
|
161
|
+
database,
|
|
162
|
+
conversationId,
|
|
163
|
+
currentTurn,
|
|
164
|
+
userMessage,
|
|
165
|
+
assistantMessage,
|
|
166
|
+
nowText,
|
|
167
|
+
messageId,
|
|
168
|
+
config,
|
|
169
|
+
priorState,
|
|
170
|
+
signal,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
|
|
138
174
|
// (2) Topology. `getEdgeIndex` walks concept-page frontmatter and caches
|
|
139
175
|
// the result module-locally; an empty workspace yields an empty index.
|
|
140
176
|
throwIfAborted(signal);
|
|
@@ -178,7 +214,7 @@ export async function injectMemoryV2Block(
|
|
|
178
214
|
// prior cached attachments don't exist or have been thrown away. The user
|
|
179
215
|
// message gets a complete top-K dump alongside the static
|
|
180
216
|
// essentials/threads/recent block, then per-turn turns just add deltas.
|
|
181
|
-
const mode = params.mode ?? "per-turn";
|
|
217
|
+
const mode: InjectMemoryV2Mode = params.mode ?? "per-turn";
|
|
182
218
|
const priorEverInjected: readonly EverInjectedEntry[] =
|
|
183
219
|
priorState?.everInjected ?? [];
|
|
184
220
|
const { topNow, toInject } = selectInjections({
|
|
@@ -192,11 +228,108 @@ export async function injectMemoryV2Block(
|
|
|
192
228
|
// even on a "no new injection" turn, prior-state activations decay via the
|
|
193
229
|
// candidate-set carry-forward and need to be rewritten so `epsilon`-trimmed
|
|
194
230
|
// slugs drop out of consideration next turn.
|
|
195
|
-
const
|
|
231
|
+
const nextStateMap: Record<string, number> = {};
|
|
196
232
|
for (const [slug, value] of finalActivation) {
|
|
197
|
-
if (value > epsilon)
|
|
233
|
+
if (value > epsilon) nextStateMap[slug] = value;
|
|
198
234
|
}
|
|
199
235
|
|
|
236
|
+
// Build the rich per-candidate telemetry rows up front (status assigned
|
|
237
|
+
// later by `finalizeInjection` once we know what actually rendered).
|
|
238
|
+
const telemetryRows: MemoryV2ConceptRowRecord[] = [...candidates].map(
|
|
239
|
+
(slug) => {
|
|
240
|
+
const breakdown = ownBreakdown.get(slug);
|
|
241
|
+
const inPrior = fromPrior.has(slug);
|
|
242
|
+
const inAnn = fromAnn.has(slug);
|
|
243
|
+
return {
|
|
244
|
+
slug,
|
|
245
|
+
finalActivation: finalActivation.get(slug) ?? 0,
|
|
246
|
+
ownActivation: ownActivation.get(slug) ?? 0,
|
|
247
|
+
priorActivation: breakdown?.priorContribution ?? 0,
|
|
248
|
+
simUser: breakdown?.simUser ?? 0,
|
|
249
|
+
simAssistant: breakdown?.simAssistant ?? 0,
|
|
250
|
+
simNow: breakdown?.simNow ?? 0,
|
|
251
|
+
simUserRerankBoost: breakdown?.simUserRerankBoost ?? 0,
|
|
252
|
+
simAssistantRerankBoost: breakdown?.simAssistantRerankBoost ?? 0,
|
|
253
|
+
inRerankPool: breakdown?.inRerankPool ?? false,
|
|
254
|
+
spreadContribution: spreadContribution.get(slug) ?? 0,
|
|
255
|
+
source:
|
|
256
|
+
inPrior && inAnn ? "both" : inPrior ? "prior_state" : "ann_top50",
|
|
257
|
+
status: "not_injected",
|
|
258
|
+
};
|
|
259
|
+
},
|
|
260
|
+
);
|
|
261
|
+
|
|
262
|
+
return finalizeInjection({
|
|
263
|
+
workspaceDir,
|
|
264
|
+
database,
|
|
265
|
+
conversationId,
|
|
266
|
+
mode,
|
|
267
|
+
currentTurn,
|
|
268
|
+
messageId,
|
|
269
|
+
priorEverInjected,
|
|
270
|
+
slugsToRender,
|
|
271
|
+
telemetryRows,
|
|
272
|
+
config,
|
|
273
|
+
nextStateMap,
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Tail of `injectMemoryV2Block` extracted as a private helper so the
|
|
279
|
+
* router branch (PR 10) can reuse the same persistence + render +
|
|
280
|
+
* telemetry-finalization pipeline. Performs:
|
|
281
|
+
*
|
|
282
|
+
* 1. Build `nextEverInjected` from `slugsToRender`, filtering out skill
|
|
283
|
+
* slugs whose capability cache entry is missing so future turns
|
|
284
|
+
* re-attempt attachment once the cache is populated.
|
|
285
|
+
* 2. Persist the next activation_state row.
|
|
286
|
+
* 3. Render the injection block.
|
|
287
|
+
* 4. Finalize per-row `status` (`injected | in_context | not_injected |
|
|
288
|
+
* page_missing | corrupt`) on the caller-provided telemetry rows
|
|
289
|
+
* using the render result.
|
|
290
|
+
* 5. Sort rows by `finalActivation` descending and flush the activation
|
|
291
|
+
* log — even when an error is thrown partway through, so silent
|
|
292
|
+
* failures remain observable.
|
|
293
|
+
* 6. Return the rendered block plus `toInject = newlyInjected`.
|
|
294
|
+
*
|
|
295
|
+
* The caller pre-builds `telemetryRows` with all per-candidate breakdown
|
|
296
|
+
* fields filled in (router-mode callers can pass zeros where the
|
|
297
|
+
* breakdown doesn't apply) and a placeholder `status: "not_injected"`
|
|
298
|
+
* which this helper overwrites. `nextStateMap` is the activation
|
|
299
|
+
* pipeline's sparse next-state; router-mode callers pass an empty map.
|
|
300
|
+
*/
|
|
301
|
+
async function finalizeInjection(args: {
|
|
302
|
+
workspaceDir: string;
|
|
303
|
+
database: DrizzleDb;
|
|
304
|
+
conversationId: string;
|
|
305
|
+
mode: FinalizeInjectionMode;
|
|
306
|
+
currentTurn: number;
|
|
307
|
+
messageId: string;
|
|
308
|
+
priorEverInjected: readonly EverInjectedEntry[];
|
|
309
|
+
slugsToRender: string[];
|
|
310
|
+
telemetryRows: MemoryV2ConceptRowRecord[];
|
|
311
|
+
config: AssistantConfig;
|
|
312
|
+
nextStateMap: Record<string, number>;
|
|
313
|
+
}): Promise<InjectMemoryV2BlockResult> {
|
|
314
|
+
const {
|
|
315
|
+
workspaceDir,
|
|
316
|
+
database,
|
|
317
|
+
conversationId,
|
|
318
|
+
currentTurn,
|
|
319
|
+
messageId,
|
|
320
|
+
priorEverInjected,
|
|
321
|
+
slugsToRender,
|
|
322
|
+
telemetryRows,
|
|
323
|
+
config,
|
|
324
|
+
nextStateMap,
|
|
325
|
+
} = args;
|
|
326
|
+
|
|
327
|
+
// `mode` is `let` because the trailing try/finally promotes it to "errored"
|
|
328
|
+
// when the render/telemetry path throws — we still want a log row written
|
|
329
|
+
// (with whatever rows we managed to build) so silent failures are
|
|
330
|
+
// observable in the database.
|
|
331
|
+
let mode: FinalizeInjectionMode = args.mode;
|
|
332
|
+
|
|
200
333
|
// Mark every rendered slug as ever-injected so future per-turn deltas don't
|
|
201
334
|
// re-attach the same content. On context-load this is the full top-K (we
|
|
202
335
|
// just rendered all of them); on per-turn it's just the newly added slugs.
|
|
@@ -206,9 +339,21 @@ export async function injectMemoryV2Block(
|
|
|
206
339
|
// like concept slugs — once attached on a turn, the cached attachment lives
|
|
207
340
|
// on that user message and the agent keeps seeing it across subsequent turns
|
|
208
341
|
// until compaction evicts the turn.
|
|
342
|
+
//
|
|
343
|
+
// Skill slugs whose in-process cache entry is missing (e.g. startup race
|
|
344
|
+
// between the skill seed and the first turn, or stale Qdrant index pointing
|
|
345
|
+
// at an uninstalled skill) are excluded from `everInjected` so future
|
|
346
|
+
// per-turn runs re-attempt attachment once the cache is populated. Without
|
|
347
|
+
// this, the slug would be marked injected even though `renderInjectionBlock`
|
|
348
|
+
// silently dropped it.
|
|
349
|
+
const missingSkillSlugs = new Set(
|
|
350
|
+
slugsToRender.filter(
|
|
351
|
+
(slug) => isSkillSlug(slug) && !getSkillCapability(slug),
|
|
352
|
+
),
|
|
353
|
+
);
|
|
209
354
|
const everInjectedSet = new Set(priorEverInjected.map((entry) => entry.slug));
|
|
210
355
|
const newlyInjected = slugsToRender.filter(
|
|
211
|
-
(slug) => !everInjectedSet.has(slug),
|
|
356
|
+
(slug) => !everInjectedSet.has(slug) && !missingSkillSlugs.has(slug),
|
|
212
357
|
);
|
|
213
358
|
const nextEverInjected: EverInjectedEntry[] = [
|
|
214
359
|
...priorEverInjected,
|
|
@@ -217,62 +362,76 @@ export async function injectMemoryV2Block(
|
|
|
217
362
|
|
|
218
363
|
const nextActivationState: ActivationState = {
|
|
219
364
|
messageId,
|
|
220
|
-
state:
|
|
365
|
+
state: nextStateMap,
|
|
221
366
|
everInjected: nextEverInjected,
|
|
222
367
|
currentTurn,
|
|
223
368
|
updatedAt: Date.now(),
|
|
224
369
|
};
|
|
225
370
|
|
|
226
|
-
|
|
371
|
+
// `block` and `conceptRowsForLog` are declared outside the try so the
|
|
372
|
+
// finally block can flush activation telemetry even if rendering, status
|
|
373
|
+
// finalization, or the activation-state save throws partway through.
|
|
374
|
+
// Without this, a Zod failure on a single concept page (e.g. unrecognized
|
|
375
|
+
// frontmatter key) silently dropped the entire turn's activation log row,
|
|
376
|
+
// masking the underlying data-corruption bug.
|
|
377
|
+
//
|
|
378
|
+
// `conceptRowsForLog` only receives the caller-provided `telemetryRows`
|
|
379
|
+
// *after* status finalization succeeds — matching the prior behavior where
|
|
380
|
+
// an early `save()` / `renderInjectionBlock()` throw produced an empty
|
|
381
|
+
// `concepts` array on the log row.
|
|
382
|
+
let block: string | null = null;
|
|
383
|
+
let conceptRowsForLog: MemoryV2ConceptRowRecord[] = [];
|
|
384
|
+
let caughtErr: unknown = undefined;
|
|
227
385
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
386
|
+
try {
|
|
387
|
+
await save(database, conversationId, nextActivationState);
|
|
388
|
+
|
|
389
|
+
// Render before recording telemetry so the activation log can mark slugs
|
|
390
|
+
// whose backing file is gone or failed to load — those are no-op renders
|
|
391
|
+
// that would otherwise be indistinguishable from successful "injected"
|
|
392
|
+
// rows in the log. `renderInjectionBlock` itself short-circuits on empty
|
|
393
|
+
// inputs and emits per-slug `log.warn` for each corrupt page.
|
|
394
|
+
const rendered = await renderInjectionBlock(workspaceDir, slugsToRender);
|
|
395
|
+
block = rendered.block;
|
|
396
|
+
const { missingSlugs, corruptSlugs } = rendered;
|
|
397
|
+
const missingSlugSet = new Set(missingSlugs);
|
|
398
|
+
const corruptSlugSet = new Set(corruptSlugs);
|
|
399
|
+
if (missingSlugs.length > 0) {
|
|
400
|
+
log.warn(
|
|
401
|
+
{
|
|
402
|
+
conversationId,
|
|
403
|
+
turn: currentTurn,
|
|
404
|
+
missingSlugs,
|
|
405
|
+
renderedCount:
|
|
406
|
+
slugsToRender.length - missingSlugs.length - corruptSlugs.length,
|
|
407
|
+
},
|
|
408
|
+
"Memory v2 injection skipped slugs whose page was missing on disk — Qdrant index may be stale; consider reembed",
|
|
409
|
+
);
|
|
410
|
+
}
|
|
248
411
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
// `page_missing` overrides any "would-have-been-injected" status when
|
|
267
|
-
// `readPage` returned null for the slug — telemetry surfaces stale
|
|
268
|
-
// ANN/edge entries instead of silently masquerading as a successful
|
|
269
|
-
// injection.
|
|
412
|
+
// Finalize per-row status onto the caller-provided telemetry rows.
|
|
413
|
+
// - context-load: cache was wiped (turn 1 / post-compaction), so
|
|
414
|
+
// `slugsToRender = topNow` and every rendered slug is freshly
|
|
415
|
+
// injected on this turn. `in_context` is unreachable because there
|
|
416
|
+
// is no prior cached attachment for the inspector to point at.
|
|
417
|
+
// - per-turn: cached attachments from prior turns are still on the
|
|
418
|
+
// user message, so prior-everInjected slugs are `in_context` and
|
|
419
|
+
// the delta (`slugsToRender`, which equals `toInject` in this mode)
|
|
420
|
+
// is `injected`.
|
|
421
|
+
// `page_missing` and `corrupt` override any "would-have-been-injected"
|
|
422
|
+
// status when `readPage` returned null or threw — telemetry surfaces
|
|
423
|
+
// stale ANN/edge entries and malformed pages instead of silently
|
|
424
|
+
// masquerading as successful injections. `corrupt` takes priority over
|
|
425
|
+
// `page_missing` since they're mutually exclusive per slug.
|
|
426
|
+
const renderedSet = new Set(slugsToRender);
|
|
427
|
+
for (const row of telemetryRows) {
|
|
428
|
+
const slug = row.slug;
|
|
270
429
|
let status: MemoryV2ConceptRowRecord["status"];
|
|
271
430
|
if (mode === "context-load") {
|
|
272
431
|
status = renderedSet.has(slug) ? "injected" : "not_injected";
|
|
273
432
|
} else if (everInjectedSet.has(slug)) {
|
|
274
433
|
status = "in_context";
|
|
275
|
-
} else if (
|
|
434
|
+
} else if (renderedSet.has(slug)) {
|
|
276
435
|
status = "injected";
|
|
277
436
|
} else {
|
|
278
437
|
status = "not_injected";
|
|
@@ -280,52 +439,195 @@ export async function injectMemoryV2Block(
|
|
|
280
439
|
if (status === "injected" && missingSlugSet.has(slug)) {
|
|
281
440
|
status = "page_missing";
|
|
282
441
|
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
simNow: breakdown?.simNow ?? 0,
|
|
291
|
-
simUserRerankBoost: breakdown?.simUserRerankBoost ?? 0,
|
|
292
|
-
simAssistantRerankBoost: breakdown?.simAssistantRerankBoost ?? 0,
|
|
293
|
-
inRerankPool: breakdown?.inRerankPool ?? false,
|
|
294
|
-
spreadContribution: spreadContribution.get(slug) ?? 0,
|
|
295
|
-
source:
|
|
296
|
-
inPrior && inAnn ? "both" : inPrior ? "prior_state" : "ann_top50",
|
|
297
|
-
status,
|
|
298
|
-
};
|
|
299
|
-
},
|
|
300
|
-
);
|
|
301
|
-
conceptRows.sort((a, b) => b.finalActivation - a.finalActivation);
|
|
302
|
-
|
|
303
|
-
const v2Cfg = config.memory.v2;
|
|
304
|
-
try {
|
|
305
|
-
recordMemoryV2ActivationLog({
|
|
306
|
-
conversationId,
|
|
307
|
-
turn: currentTurn,
|
|
308
|
-
mode,
|
|
309
|
-
concepts: conceptRows,
|
|
310
|
-
config: {
|
|
311
|
-
d: v2Cfg.d,
|
|
312
|
-
c_user: v2Cfg.c_user,
|
|
313
|
-
c_assistant: v2Cfg.c_assistant,
|
|
314
|
-
c_now: v2Cfg.c_now,
|
|
315
|
-
k: v2Cfg.k,
|
|
316
|
-
hops: v2Cfg.hops,
|
|
317
|
-
top_k: v2Cfg.top_k,
|
|
318
|
-
epsilon: v2Cfg.epsilon,
|
|
319
|
-
},
|
|
320
|
-
});
|
|
442
|
+
if (corruptSlugSet.has(slug)) {
|
|
443
|
+
status = "corrupt";
|
|
444
|
+
}
|
|
445
|
+
row.status = status;
|
|
446
|
+
}
|
|
447
|
+
telemetryRows.sort((a, b) => b.finalActivation - a.finalActivation);
|
|
448
|
+
conceptRowsForLog = telemetryRows;
|
|
321
449
|
} catch (err) {
|
|
450
|
+
// Stash the error and let `finally` flush a best-effort telemetry row
|
|
451
|
+
// before we re-throw to the caller. `mode = "errored"` flags the row
|
|
452
|
+
// for observability dashboards / inspector queries.
|
|
453
|
+
caughtErr = err;
|
|
454
|
+
mode = "errored";
|
|
455
|
+
} finally {
|
|
456
|
+
try {
|
|
457
|
+
recordMemoryV2ActivationLog({
|
|
458
|
+
conversationId,
|
|
459
|
+
turn: currentTurn,
|
|
460
|
+
mode,
|
|
461
|
+
concepts: conceptRowsForLog,
|
|
462
|
+
config: configSnapshot(config),
|
|
463
|
+
});
|
|
464
|
+
} catch (telemetryErr) {
|
|
465
|
+
log.warn(
|
|
466
|
+
{ err: telemetryErr, conversationId, turn: currentTurn },
|
|
467
|
+
"Failed to record memory v2 activation telemetry — continuing",
|
|
468
|
+
);
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
if (caughtErr !== undefined) throw caughtErr;
|
|
473
|
+
return { block, toInject: newlyInjected };
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
* Router-mode dispatch path. Replaces the spreading-activation pipeline with
|
|
478
|
+
* a single LLM call that picks the per-turn concept-page set. On success we
|
|
479
|
+
* reuse `finalizeInjection` so the persistence/render/telemetry contract
|
|
480
|
+
* stays identical to the activation path; on `runRouter` failure we still
|
|
481
|
+
* advance `activation_state` (so `currentTurn` and `messageId` move forward)
|
|
482
|
+
* and emit a `mode: "errored"` telemetry row so the failure is observable.
|
|
483
|
+
*
|
|
484
|
+
* Failure rows are tagged `errored`, not `router`, because router-mode rows
|
|
485
|
+
* are reserved for successful selections — keeping the two visually distinct
|
|
486
|
+
* in inspector queries. `nextStateMap` is always empty in router mode: the
|
|
487
|
+
* router does not compute spreading-activation scores, so there is no sparse
|
|
488
|
+
* activation map to persist.
|
|
489
|
+
*/
|
|
490
|
+
async function injectViaRouter(args: {
|
|
491
|
+
workspaceDir: string;
|
|
492
|
+
database: DrizzleDb;
|
|
493
|
+
conversationId: string;
|
|
494
|
+
currentTurn: number;
|
|
495
|
+
userMessage: string;
|
|
496
|
+
assistantMessage: string;
|
|
497
|
+
nowText: string;
|
|
498
|
+
messageId: string;
|
|
499
|
+
config: AssistantConfig;
|
|
500
|
+
priorState: ActivationState | null;
|
|
501
|
+
signal?: AbortSignal;
|
|
502
|
+
}): Promise<InjectMemoryV2BlockResult> {
|
|
503
|
+
const {
|
|
504
|
+
workspaceDir,
|
|
505
|
+
database,
|
|
506
|
+
conversationId,
|
|
507
|
+
currentTurn,
|
|
508
|
+
userMessage,
|
|
509
|
+
assistantMessage,
|
|
510
|
+
nowText,
|
|
511
|
+
messageId,
|
|
512
|
+
config,
|
|
513
|
+
priorState,
|
|
514
|
+
signal,
|
|
515
|
+
} = args;
|
|
516
|
+
|
|
517
|
+
const priorEverInjected: readonly EverInjectedEntry[] =
|
|
518
|
+
priorState?.everInjected ?? [];
|
|
519
|
+
|
|
520
|
+
const routerResult = await runRouter({
|
|
521
|
+
workspaceDir,
|
|
522
|
+
userMessage,
|
|
523
|
+
assistantMessage,
|
|
524
|
+
nowText,
|
|
525
|
+
priorEverInjected,
|
|
526
|
+
config,
|
|
527
|
+
...(signal ? { signal } : {}),
|
|
528
|
+
});
|
|
529
|
+
|
|
530
|
+
if (routerResult.failureReason !== null) {
|
|
322
531
|
log.warn(
|
|
323
|
-
{
|
|
324
|
-
"
|
|
532
|
+
{ failureReason: routerResult.failureReason },
|
|
533
|
+
"memory v2 router failure; skipping injection",
|
|
325
534
|
);
|
|
535
|
+
// Delegate the failure path to `finalizeInjection` with empty inputs
|
|
536
|
+
// and `mode: "errored"`. The helper persists a stub activation_state
|
|
537
|
+
// (preserving `priorEverInjected` so future turns still subtract
|
|
538
|
+
// previously-attached slugs) and writes the telemetry row through the
|
|
539
|
+
// same code path as the success branch — no inline duplication of
|
|
540
|
+
// `save` + `recordMemoryV2ActivationLog`.
|
|
541
|
+
return finalizeInjection({
|
|
542
|
+
workspaceDir,
|
|
543
|
+
database,
|
|
544
|
+
conversationId,
|
|
545
|
+
mode: "errored",
|
|
546
|
+
currentTurn,
|
|
547
|
+
messageId,
|
|
548
|
+
priorEverInjected,
|
|
549
|
+
slugsToRender: [],
|
|
550
|
+
telemetryRows: [],
|
|
551
|
+
config,
|
|
552
|
+
nextStateMap: {},
|
|
553
|
+
});
|
|
326
554
|
}
|
|
327
555
|
|
|
328
|
-
|
|
556
|
+
// Dedupe router-picked slugs against `priorEverInjected` BEFORE rendering.
|
|
557
|
+
// The router prompt explicitly invites the model to re-pick already-injected
|
|
558
|
+
// pages "to re-anchor"; if we passed those through, `renderInjectionBlock`
|
|
559
|
+
// would re-emit the slug into a fresh `<memory>` block while the prior
|
|
560
|
+
// turn's cached attachment is still on the prior user message — duplicate
|
|
561
|
+
// content. Activation per-turn mode does not have this issue because
|
|
562
|
+
// `selectInjections()` returns `toInject = topNow - everInjected`.
|
|
563
|
+
//
|
|
564
|
+
// Telemetry rows for prior-everInjected slugs are still emitted below,
|
|
565
|
+
// but tagged `source: "carry_over"` (not `"router"`) so inspector queries
|
|
566
|
+
// can attribute selections correctly.
|
|
567
|
+
const everInjectedSet = new Set(priorEverInjected.map((e) => e.slug));
|
|
568
|
+
const slugsToRender = routerResult.selectedSlugs.filter(
|
|
569
|
+
(s) => !everInjectedSet.has(s),
|
|
570
|
+
);
|
|
571
|
+
|
|
572
|
+
// Build minimal telemetry rows for the union of router-selected slugs and
|
|
573
|
+
// prior `everInjected` slugs. Router-mode rows zero out every activation
|
|
574
|
+
// value (no spreading activation runs). Slugs the router picked this turn
|
|
575
|
+
// get `source: "router"`; prior-everInjected slugs the router did NOT
|
|
576
|
+
// re-pick get `source: "carry_over"`. The `status` placeholder is
|
|
577
|
+
// overwritten by `finalizeInjection`.
|
|
578
|
+
const routerPicked = new Set(routerResult.selectedSlugs);
|
|
579
|
+
const telemetrySlugs = new Set<string>(routerPicked);
|
|
580
|
+
for (const entry of priorEverInjected) telemetrySlugs.add(entry.slug);
|
|
581
|
+
const telemetryRows: MemoryV2ConceptRowRecord[] = [...telemetrySlugs].map(
|
|
582
|
+
(slug) => ({
|
|
583
|
+
slug,
|
|
584
|
+
finalActivation: 0,
|
|
585
|
+
ownActivation: 0,
|
|
586
|
+
priorActivation: 0,
|
|
587
|
+
simUser: 0,
|
|
588
|
+
simAssistant: 0,
|
|
589
|
+
simNow: 0,
|
|
590
|
+
simUserRerankBoost: 0,
|
|
591
|
+
simAssistantRerankBoost: 0,
|
|
592
|
+
inRerankPool: false,
|
|
593
|
+
spreadContribution: 0,
|
|
594
|
+
source: routerPicked.has(slug) ? "router" : "carry_over",
|
|
595
|
+
status: "not_injected",
|
|
596
|
+
}),
|
|
597
|
+
);
|
|
598
|
+
|
|
599
|
+
return finalizeInjection({
|
|
600
|
+
workspaceDir,
|
|
601
|
+
database,
|
|
602
|
+
conversationId,
|
|
603
|
+
mode: "router",
|
|
604
|
+
currentTurn,
|
|
605
|
+
messageId,
|
|
606
|
+
priorEverInjected,
|
|
607
|
+
slugsToRender,
|
|
608
|
+
telemetryRows,
|
|
609
|
+
config,
|
|
610
|
+
nextStateMap: {},
|
|
611
|
+
});
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
/**
|
|
615
|
+
* Snapshot the v2 config tunables in the shape `recordMemoryV2ActivationLog`
|
|
616
|
+
* persists. Pulled out so the router-failure path does not duplicate the
|
|
617
|
+
* field list inline.
|
|
618
|
+
*/
|
|
619
|
+
function configSnapshot(config: AssistantConfig) {
|
|
620
|
+
const v2Cfg = config.memory.v2;
|
|
621
|
+
return {
|
|
622
|
+
d: v2Cfg.d,
|
|
623
|
+
c_user: v2Cfg.c_user,
|
|
624
|
+
c_assistant: v2Cfg.c_assistant,
|
|
625
|
+
c_now: v2Cfg.c_now,
|
|
626
|
+
k: v2Cfg.k,
|
|
627
|
+
hops: v2Cfg.hops,
|
|
628
|
+
top_k: v2Cfg.top_k,
|
|
629
|
+
epsilon: v2Cfg.epsilon,
|
|
630
|
+
};
|
|
329
631
|
}
|
|
330
632
|
|
|
331
633
|
function throwIfAborted(signal: AbortSignal | undefined): void {
|
|
@@ -358,14 +660,24 @@ interface RenderInjectionBlockResult {
|
|
|
358
660
|
* edge-index entries that pointed at pages no longer on disk.
|
|
359
661
|
*/
|
|
360
662
|
missingSlugs: string[];
|
|
663
|
+
/**
|
|
664
|
+
* Slugs whose `readPage` call threw (e.g. invalid frontmatter that fails
|
|
665
|
+
* Zod validation, unreadable file). These are reported separately from
|
|
666
|
+
* `missingSlugs` because they're a different failure mode — the file
|
|
667
|
+
* exists but is malformed, not absent — and surfaced so the caller can
|
|
668
|
+
* mark them in the activation log (`status: "corrupt"`). Per-page errors
|
|
669
|
+
* are isolated: one bad page no longer rejects the whole batch.
|
|
670
|
+
*/
|
|
671
|
+
corruptSlugs: string[];
|
|
361
672
|
}
|
|
362
673
|
|
|
363
674
|
/**
|
|
364
|
-
* Leading instruction line emitted at the top of
|
|
365
|
-
*
|
|
366
|
-
*
|
|
367
|
-
*
|
|
368
|
-
*
|
|
675
|
+
* Leading instruction line emitted at the top of an injection block when at
|
|
676
|
+
* least one section was rendered from a page's `summary` field. Tells the
|
|
677
|
+
* agent the truncated entries are summaries and to read the underlying file
|
|
678
|
+
* if relevant. Suppressed when every section is a full-page fallback —
|
|
679
|
+
* claiming "these are summaries" over already-complete content would mislead
|
|
680
|
+
* the agent into wasted reads.
|
|
369
681
|
*/
|
|
370
682
|
const INJECTION_HEADER =
|
|
371
683
|
"**CRITICAL:** These are page summaries. Read the page file if it looks relevant.";
|
|
@@ -380,11 +692,15 @@ const INJECTION_HEADER =
|
|
|
380
692
|
* trailing `### Skills You Can Use` subsection; everything else is read
|
|
381
693
|
* from disk via `readPage` and rendered as a concept-page section.
|
|
382
694
|
*
|
|
383
|
-
* Concept pages are read in parallel via `
|
|
384
|
-
*
|
|
385
|
-
*
|
|
386
|
-
*
|
|
387
|
-
*
|
|
695
|
+
* Concept pages are read in parallel via `Promise.allSettled`. Per-page
|
|
696
|
+
* errors are isolated: a `readPage` rejection (e.g. invalid frontmatter
|
|
697
|
+
* failing Zod validation) collects the slug into `corruptSlugs` and the
|
|
698
|
+
* remaining pages still render normally. Pages whose file has gone missing
|
|
699
|
+
* between selection and render (e.g. consolidation deleted them, folder
|
|
700
|
+
* reorg renamed the slug) are dropped from the rendered block but reported
|
|
701
|
+
* back via `missingSlugs`. The two buckets are kept separate so callers can
|
|
702
|
+
* distinguish "file vanished" (stale index) from "file is malformed"
|
|
703
|
+
* (data-corruption / programmer error).
|
|
388
704
|
*
|
|
389
705
|
* Skill slugs whose entry the cache no longer knows (e.g. uninstalled
|
|
390
706
|
* mid-run) are silently dropped, mirroring the missing-pages behavior but
|
|
@@ -424,16 +740,26 @@ async function renderInjectionBlock(
|
|
|
424
740
|
const conceptSlugs = slugs.filter((s) => !isSkillSlug(s));
|
|
425
741
|
const skillSlugs = slugs.filter((s) => isSkillSlug(s));
|
|
426
742
|
|
|
427
|
-
const
|
|
428
|
-
conceptSlugs.map(
|
|
429
|
-
const page = await readPage(workspaceDir, slug);
|
|
430
|
-
return { slug, page };
|
|
431
|
-
}),
|
|
743
|
+
const settled = await Promise.allSettled(
|
|
744
|
+
conceptSlugs.map((slug) => readPage(workspaceDir, slug)),
|
|
432
745
|
);
|
|
433
746
|
|
|
434
747
|
const sections: string[] = [];
|
|
435
748
|
const missingSlugs: string[] = [];
|
|
436
|
-
|
|
749
|
+
const corruptSlugs: string[] = [];
|
|
750
|
+
let anySummarySection = false;
|
|
751
|
+
for (let i = 0; i < settled.length; i++) {
|
|
752
|
+
const slug = conceptSlugs[i]!;
|
|
753
|
+
const result = settled[i]!;
|
|
754
|
+
if (result.status === "rejected") {
|
|
755
|
+
corruptSlugs.push(slug);
|
|
756
|
+
log.warn(
|
|
757
|
+
{ slug, err: result.reason },
|
|
758
|
+
"Memory v2 injection skipped slug whose page failed to load — frontmatter may be malformed",
|
|
759
|
+
);
|
|
760
|
+
continue;
|
|
761
|
+
}
|
|
762
|
+
const page = result.value;
|
|
437
763
|
if (!page) {
|
|
438
764
|
missingSlugs.push(slug);
|
|
439
765
|
continue;
|
|
@@ -442,6 +768,7 @@ async function renderInjectionBlock(
|
|
|
442
768
|
const path = `memory/concepts/${slug}.md`;
|
|
443
769
|
if (summary && summary.length > 0) {
|
|
444
770
|
sections.push(`# ${path}\n${summary}`);
|
|
771
|
+
anySummarySection = true;
|
|
445
772
|
continue;
|
|
446
773
|
}
|
|
447
774
|
// Fallback: page predates the `summary` field (or the field was set to
|
|
@@ -462,10 +789,14 @@ async function renderInjectionBlock(
|
|
|
462
789
|
sections.push(`### Skills You Can Use\n${skillLines.join("\n")}`);
|
|
463
790
|
}
|
|
464
791
|
|
|
465
|
-
if (sections.length === 0)
|
|
792
|
+
if (sections.length === 0) {
|
|
793
|
+
return { block: null, missingSlugs, corruptSlugs };
|
|
794
|
+
}
|
|
466
795
|
|
|
796
|
+
const body = sections.join("\n\n");
|
|
467
797
|
return {
|
|
468
|
-
block: `${INJECTION_HEADER}\n\n${
|
|
798
|
+
block: anySummarySection ? `${INJECTION_HEADER}\n\n${body}` : body,
|
|
469
799
|
missingSlugs,
|
|
800
|
+
corruptSlugs,
|
|
470
801
|
};
|
|
471
802
|
}
|