@vellumai/assistant 0.10.12 → 0.11.0-staging.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 +1 -1
- package/ARCHITECTURE.md +4 -5
- package/README.md +1 -1
- package/docs/architecture/memory.md +60 -23
- package/docs/error-handling.md +3 -3
- package/docs/guardian-request-flow.md +112 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/package.json +1 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/__tests__/channels.test.ts +9 -1
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/__tests__/secret-detection.test.ts +449 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/channels.ts +1 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/secret-detection.ts +468 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/app.d.ts +28 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/app.d.ts.map +1 -1
- package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/index.d.ts +2 -2
- package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/index.d.ts.map +1 -1
- package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/index.js.map +1 -1
- package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/message.d.ts +2 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/message.d.ts.map +1 -1
- package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/package.json +1 -1
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/package.json +1 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/__tests__/channels.test.ts +9 -1
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/__tests__/secret-detection.test.ts +449 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/channels.ts +1 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/secret-detection.ts +468 -0
- package/node_modules/@vellumai/gateway-client/package.json +1 -1
- package/node_modules/@vellumai/gateway-client/src/admission-policy-contract.ts +6 -0
- package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +34 -0
- package/node_modules/@vellumai/service-contracts/package.json +1 -0
- package/node_modules/@vellumai/service-contracts/src/__tests__/channels.test.ts +9 -1
- package/node_modules/@vellumai/service-contracts/src/__tests__/secret-detection.test.ts +449 -0
- package/node_modules/@vellumai/service-contracts/src/channels.ts +1 -0
- package/node_modules/@vellumai/service-contracts/src/secret-detection.ts +468 -0
- package/openapi.yaml +246 -10
- package/package.json +2 -2
- package/src/__tests__/acp-session.test.ts +3 -3
- package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +3 -0
- package/src/__tests__/anthropic-provider.test.ts +40 -0
- package/src/__tests__/approval-cascade.test.ts +5 -5
- package/src/__tests__/approval-routes-http.test.ts +3 -3
- package/src/__tests__/ask-question-resolver.test.ts +207 -0
- package/src/__tests__/assistant-event-hub-self-exclusion.test.ts +16 -16
- package/src/__tests__/assistant-event-hub-targeted.test.ts +13 -11
- package/src/__tests__/assistant-event-hub.test.ts +13 -11
- package/src/__tests__/assistant-event.test.ts +12 -9
- package/src/__tests__/assistant-feature-flag-guard.test.ts +3 -3
- package/src/__tests__/assistant-feature-flag-guardrails.test.ts +1 -1
- package/src/__tests__/assistant-id-boundary-guard.test.ts +0 -58
- package/src/__tests__/assistant-stream-state.test.ts +17 -7
- package/src/__tests__/avatar-identity-sync.test.ts +3 -3
- package/src/__tests__/background-workers-disk-pressure.test.ts +1 -0
- package/src/__tests__/call-conversation-messages.test.ts +134 -18
- package/src/__tests__/call-start-guardian-guard.test.ts +27 -0
- package/src/__tests__/channel-approvals.test.ts +0 -27
- package/src/__tests__/channel-guardian.test.ts +85 -512
- package/src/__tests__/channel-readiness-slack-remote.test.ts +151 -3
- package/src/__tests__/channel-retry-sweep.test.ts +88 -1
- package/src/__tests__/channel-setup-panel-ack.test.ts +12 -9
- package/src/__tests__/chat-reveal-guard-priming.test.ts +31 -34
- package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +2 -2
- package/src/__tests__/compaction-events.test.ts +8 -8
- package/src/__tests__/config-loader-platform-defaults.test.ts +54 -28
- package/src/__tests__/config-model-image-provider.test.ts +20 -0
- package/src/__tests__/config-schema-memory-substrate.test.ts +306 -0
- package/src/__tests__/config-schema.test.ts +14 -2
- package/src/__tests__/config-set-platform-guard.test.ts +11 -12
- package/src/__tests__/config-sounds-sync.test.ts +4 -4
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +5 -0
- package/src/__tests__/context-search-memory-source.test.ts +1 -1
- package/src/__tests__/context-search-memory-v2-source.test.ts +6 -6
- package/src/__tests__/context-token-estimator.test.ts +54 -1
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +12 -3
- package/src/__tests__/conversation-agent-loop-fatal-cleanup.test.ts +13 -4
- package/src/__tests__/conversation-agent-loop-handlers-max-tokens.test.ts +4 -4
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +10 -1
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +22 -13
- package/src/__tests__/conversation-agent-loop.test.ts +39 -30
- package/src/__tests__/conversation-confirmation-signals.test.ts +14 -14
- package/src/__tests__/conversation-evictor.test.ts +49 -0
- package/src/__tests__/conversation-fork-crud.test.ts +1 -1
- package/src/__tests__/conversation-history-web-search.test.ts +1 -1
- package/src/__tests__/conversation-key-store-disk-view.test.ts +5 -5
- package/src/__tests__/conversation-loop-db-lock-resilience.test.ts +5 -5
- package/src/__tests__/conversation-message-sync-tags.test.ts +4 -4
- package/src/__tests__/conversation-queue.test.ts +81 -81
- package/src/__tests__/conversation-routes-enabled-plugins.test.ts +8 -1
- package/src/__tests__/conversation-routes-hidden-queue.test.ts +8 -1
- package/src/__tests__/conversation-routes-slash-commands.test.ts +10 -1
- package/src/__tests__/conversation-runtime-assembly.test.ts +29 -2
- package/src/__tests__/conversation-slash-queue.test.ts +11 -11
- package/src/__tests__/conversation-slash-unknown.test.ts +2 -2
- package/src/__tests__/conversation-speed-override.test.ts +2 -2
- package/src/__tests__/conversation-summarize-route.test.ts +9 -0
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +18 -16
- package/src/__tests__/conversation-surfaces-activation-emit.test.ts +17 -17
- package/src/__tests__/conversation-surfaces-app-open.test.ts +7 -4
- package/src/__tests__/conversation-surfaces-data-persist.test.ts +7 -7
- package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +9 -9
- package/src/__tests__/conversation-surfaces-standalone.test.ts +12 -12
- package/src/__tests__/conversation-surfaces-state-update.test.ts +8 -5
- package/src/__tests__/conversation-surfaces-table-action.test.ts +6 -3
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +46 -46
- package/src/__tests__/conversation-sync-tags.test.ts +5 -5
- package/src/__tests__/conversation-wait-for-idle.test.ts +2 -2
- package/src/__tests__/conversation-workspace-cache-state.test.ts +0 -4
- package/src/__tests__/conversation-workspace-injection.test.ts +0 -3
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -3
- package/src/__tests__/copy-composer-tc-templates.test.ts +3 -131
- package/src/__tests__/credential-security-invariants.test.ts +1 -0
- package/src/__tests__/daemon-assistant-events.test.ts +14 -15
- package/src/__tests__/db-test-helpers.ts +13 -27
- package/src/__tests__/disk-pressure-routes.test.ts +12 -3
- package/src/__tests__/document-tool-security.test.ts +95 -0
- package/src/__tests__/drain-kick-guard.test.ts +232 -0
- package/src/__tests__/dynamic-skill-background-guard.test.ts +19 -6
- package/src/__tests__/emit-event-signal.test.ts +5 -6
- package/src/__tests__/encrypted-store-test-helpers.ts +10 -20
- package/src/__tests__/events-tail-route.test.ts +6 -4
- package/src/__tests__/feature-flag-test-helpers.ts +10 -20
- package/src/__tests__/file-edit-tool.test.ts +24 -4
- package/src/__tests__/file-list-tool.test.ts +2 -1
- package/src/__tests__/file-read-tool.test.ts +62 -10
- package/src/__tests__/file-write-tool.test.ts +24 -5
- package/src/__tests__/followup-tools.test.ts +58 -0
- package/src/__tests__/gateway-threshold-reader-mock.ts +99 -0
- package/src/__tests__/graph-extraction-event-date.test.ts +1 -1
- package/src/__tests__/guardian-question-mode.test.ts +42 -3
- package/src/__tests__/guardian-reply-router-answer-mode.test.ts +283 -0
- package/src/__tests__/guardian-vellum-destination-pinning.test.ts +221 -0
- package/src/__tests__/heartbeat-disk-pressure.test.ts +1 -0
- package/src/__tests__/heartbeat-service.test.ts +1 -0
- package/src/__tests__/helpers/native-web-search-harness.ts +10 -10
- package/src/__tests__/host-browser-proxy.test.ts +1 -1
- package/src/__tests__/host-file-edit-tool.test.ts +3 -3
- package/src/__tests__/host-file-read-tool.test.ts +2 -2
- package/src/__tests__/host-file-write-tool.test.ts +7 -3
- package/src/__tests__/host-shell-tool.test.ts +17 -5
- package/src/__tests__/host-transfer-pending-interactions.test.ts +8 -8
- package/src/__tests__/image-credentials.test.ts +65 -8
- package/src/__tests__/injection-block.test.ts +4 -4
- package/src/__tests__/injector-chain.test.ts +1 -1
- package/src/__tests__/injector-pkb-v2-silenced.test.ts +2 -2
- package/src/__tests__/injector-registry-order-guard.test.ts +4 -9
- package/src/__tests__/injector-v3-suppression.test.ts +6 -4
- package/src/__tests__/lifecycle-memory-v2-seed.test.ts +27 -28
- package/src/__tests__/list-messages-page-latest.test.ts +2 -2
- package/src/__tests__/llm-usage-store.test.ts +67 -4
- package/src/__tests__/log-redact.test.ts +18 -0
- package/src/__tests__/managed-profile-guard.test.ts +27 -0
- package/src/__tests__/managed-skill-lifecycle.test.ts +2 -2
- package/src/__tests__/media-generate-image.test.ts +62 -11
- package/src/__tests__/memory-identity-context-parity.test.ts +1 -1
- package/src/__tests__/memory-jobs-worker-lanes.test.ts +9 -1
- package/src/__tests__/memory-retrieval-hook.test.ts +4 -4
- package/src/__tests__/notification-decision-strategy.test.ts +115 -11
- package/src/__tests__/notification-deep-link.test.ts +12 -12
- package/src/__tests__/notification-vellum-adapter.test.ts +8 -8
- package/src/__tests__/outbound-slack-persistence.test.ts +8 -8
- package/src/__tests__/path-policy.test.ts +315 -0
- package/src/__tests__/pending-interactions-resolved-event.test.ts +6 -6
- package/src/__tests__/persistence-layering-guard.test.ts +2 -2
- package/src/__tests__/pkb-autoinject.test.ts +1 -1
- package/src/__tests__/platform-bash-auto-approve.test.ts +1 -0
- package/src/__tests__/plugin-event-hub-facade.test.ts +22 -15
- package/src/__tests__/plugin-import-boundary-guard.test.ts +15 -15
- package/src/__tests__/processing-flag-persist-failure.test.ts +0 -4
- package/src/__tests__/provider-platform-proxy-integration.test.ts +0 -1
- package/src/__tests__/rebuild-index-graph-nodes.test.ts +1 -1
- package/src/__tests__/request-secret-standalone-channel-gate.test.ts +5 -5
- package/src/__tests__/require-fresh-approval.test.ts +38 -38
- package/src/__tests__/run-due-schedules.test.ts +72 -1
- package/src/__tests__/runtime-events-sse-parity.test.ts +11 -10
- package/src/__tests__/runtime-events-sse.test.ts +1 -1
- package/src/__tests__/schedule-routes.test.ts +44 -5
- package/src/__tests__/schedule-store.test.ts +3 -3
- package/src/__tests__/schedule-tools.test.ts +176 -0
- package/src/__tests__/secret-prompt-log-hygiene.test.ts +3 -3
- package/src/__tests__/secret-prompter-channel-fallback.test.ts +3 -3
- package/src/__tests__/secret-response-routing.test.ts +3 -3
- package/src/__tests__/secret-routes-platform-proxy.test.ts +4 -7
- package/src/__tests__/secret-scanner.test.ts +36 -0
- package/src/__tests__/send-endpoint-busy.test.ts +7 -7
- package/src/__tests__/slack-required-scopes-mirror.test.ts +81 -0
- package/src/__tests__/starter-task-flow.test.ts +6 -3
- package/src/__tests__/subagent-call-site-routing.test.ts +2 -2
- package/src/__tests__/subagent-disposal.test.ts +40 -11
- package/src/__tests__/subagent-fork-notifications.test.ts +4 -4
- package/src/__tests__/subagent-fork-prompt-role.test.ts +3 -3
- package/src/__tests__/subagent-fork-spawn.test.ts +4 -4
- package/src/__tests__/subagent-manager-notify.test.ts +73 -14
- package/src/__tests__/subagent-notify-parent.test.ts +48 -4
- package/src/__tests__/subagent-spawn-and-await.test.ts +62 -14
- package/src/__tests__/subagent-tools.test.ts +64 -0
- package/src/__tests__/sync-message-contract.test.ts +3 -3
- package/src/__tests__/terminal-tools.test.ts +12 -3
- package/src/__tests__/test-preload.ts +9 -0
- package/src/__tests__/tool-approval-handler.test.ts +583 -43
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +7 -4
- package/src/__tests__/tool-executor.test.ts +116 -0
- package/src/__tests__/tool-grant-request-escalation.test.ts +5 -0
- package/src/__tests__/tool-preview-lifecycle.test.ts +32 -29
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +5 -5
- package/src/__tests__/tool-start-timestamp.test.ts +4 -4
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +9 -22
- package/src/__tests__/ui-choice-copy-surfaces.test.ts +13 -13
- package/src/__tests__/ui-work-result-surface.test.ts +3 -3
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +6 -6
- package/src/__tests__/voice-session-bridge.test.ts +44 -44
- package/src/__tests__/workspace-migration-134-image-generation-mode-to-provider.test.ts +284 -0
- package/src/__tests__/workspace-policy.test.ts +399 -0
- package/src/acp/__tests__/client-handler.test.ts +3 -3
- package/src/acp/__tests__/session-manager-persistence.test.ts +10 -10
- package/src/acp/__tests__/session-manager-resume.test.ts +7 -7
- package/src/acp/client-handler.ts +3 -3
- package/src/acp/session-manager.ts +8 -8
- package/src/api/events/subagent-event.ts +2 -2
- package/src/api/responses/memory-v2-activation-log.ts +2 -2
- package/src/approvals/AGENTS.md +2 -0
- package/src/approvals/guardian-request-resolvers.ts +118 -24
- package/src/calls/__tests__/voice-control-protocol.test.ts +57 -0
- package/src/calls/__tests__/voice-session-bridge.test.ts +158 -4
- package/src/calls/__tests__/voice-triage-escalate.test.ts +3 -4
- package/src/calls/call-controller.ts +27 -27
- package/src/calls/call-conversation-messages.ts +58 -18
- package/src/calls/voice-control-protocol.ts +56 -0
- package/src/calls/voice-session-bridge.ts +156 -58
- package/src/calls/voice-triage-escalate.ts +2 -3
- package/src/channels/config.ts +8 -0
- package/src/channels/types.ts +1 -0
- package/src/cli/commands/config.ts +49 -13
- package/src/cli/commands/memory/index.help.ts +4 -2
- package/src/cli/commands/memory/memory-retrospective.ts +5 -0
- package/src/cli/lib/bundled-marketplace.json +12 -0
- package/src/cli.ts +2 -109
- package/src/config/__tests__/deployment-context-defaults.test.ts +9 -0
- package/src/config/__tests__/substrate-twin-shadowing.test.ts +191 -0
- package/src/config/assistant-feature-flags.ts +1 -1
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +13 -7
- package/src/config/feature-flag-cache.ts +6 -16
- package/src/config/feature-flag-registry.json +14 -30
- package/src/config/loader.ts +7 -1
- package/src/config/memory-tier.ts +15 -10
- package/src/config/memory-v3-gate.test.ts +278 -1
- package/src/config/memory-v3-gate.ts +88 -26
- package/src/config/raw-config-utils.ts +1 -1
- package/src/config/schemas/__tests__/live-voice.test.ts +27 -16
- package/src/config/schemas/__tests__/memory-v3.test.ts +1 -0
- package/src/config/schemas/live-voice.ts +33 -7
- package/src/config/schemas/llm.ts +1 -0
- package/src/config/schemas/memory-retrospective.ts +13 -0
- package/src/config/schemas/memory-substrate.ts +183 -0
- package/src/config/schemas/memory-v2.ts +3 -2
- package/src/config/schemas/memory-v3.ts +11 -4
- package/src/config/schemas/memory.ts +35 -1
- package/src/config/schemas/services.ts +10 -2
- package/src/config/substrate-twin-shadowing.ts +195 -0
- package/src/config/webhook-routing.ts +67 -0
- package/src/context/compactor.ts +10 -3
- package/src/context/token-estimator.ts +21 -0
- package/src/daemon/__tests__/channel-ui-capability.test.ts +85 -0
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +3 -3
- package/src/daemon/__tests__/embedding-reconcile.test.ts +3 -3
- package/src/daemon/__tests__/inference-profile-notification.test.ts +3 -6
- package/src/daemon/__tests__/native-web-search-metadata.test.ts +5 -5
- package/src/daemon/__tests__/web-search-status-text.test.ts +2 -2
- package/src/daemon/channel-ui-capability.ts +70 -1
- package/src/daemon/conversation-agent-loop-handlers.ts +4 -4
- package/src/daemon/conversation-agent-loop.ts +12 -5
- package/src/daemon/conversation-evictor.ts +26 -4
- package/src/daemon/conversation-launch.ts +11 -14
- package/src/daemon/conversation-messaging.ts +14 -14
- package/src/daemon/conversation-notifiers.ts +2 -2
- package/src/daemon/conversation-process.ts +133 -21
- package/src/daemon/conversation-queue-manager.ts +7 -7
- package/src/daemon/conversation-runtime-assembly.ts +16 -0
- package/src/daemon/conversation-store.ts +11 -3
- package/src/daemon/conversation-surfaces.ts +4 -4
- package/src/daemon/conversation-tool-setup.ts +13 -7
- package/src/daemon/conversation-usage.ts +12 -11
- package/src/daemon/conversation.ts +38 -15
- package/src/daemon/disk-pressure-guard.ts +5 -12
- package/src/daemon/embedding-reconcile.ts +14 -9
- package/src/daemon/handlers/config-channels.ts +40 -134
- package/src/daemon/handlers/config-model.ts +15 -7
- package/src/daemon/handlers/conversations.ts +4 -2
- package/src/daemon/handlers/shared.ts +29 -0
- package/src/daemon/host-proxy-base.ts +4 -4
- package/src/daemon/lifecycle.ts +13 -0
- package/src/daemon/message-protocol.ts +8 -144
- package/src/daemon/message-types/computer-use.ts +0 -12
- package/src/daemon/message-types/conversations.ts +9 -345
- package/src/daemon/message-types/host-app-control.ts +0 -9
- package/src/daemon/message-types/host-browser.ts +0 -7
- package/src/daemon/message-types/host-ui-snapshot.ts +0 -7
- package/src/daemon/message-types/messages.ts +0 -48
- package/src/daemon/message-types/notifications.ts +0 -7
- package/src/daemon/message-types/skills.ts +0 -5
- package/src/daemon/message-types/surfaces.ts +0 -9
- package/src/daemon/message-types/sync.ts +0 -2
- package/src/daemon/process-message.ts +5 -5
- package/src/daemon/skill-memory-refresh.ts +5 -5
- package/src/daemon/tool-side-effects.ts +13 -13
- package/src/daemon/trust-context.ts +1 -1
- package/src/daemon/wake-conversation-ops.ts +4 -4
- package/src/heartbeat/__tests__/heartbeat-run-store.test.ts +100 -7
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +67 -0
- package/src/heartbeat/heartbeat-run-store.ts +81 -4
- package/src/heartbeat/heartbeat-service.ts +32 -1
- package/src/home/__tests__/feed-writer.test.ts +7 -7
- package/src/home/__tests__/home-content-refresh.test.ts +3 -0
- package/src/home/__tests__/suggested-prompts.test.ts +1 -0
- package/src/home/feed-writer.ts +6 -13
- package/src/home/home-content-refresh.ts +6 -9
- package/src/home/relationship-state-writer.ts +5 -12
- package/src/home/suggested-prompts-cache.ts +6 -19
- package/src/ipc/__tests__/events-publish-client.test.ts +67 -0
- package/src/ipc/events-publish-client.ts +44 -0
- package/src/ipc/routes/__tests__/conversation-sync-ipc-routes.test.ts +2 -2
- package/src/ipc/routes/__tests__/events-ipc-routes.test.ts +38 -9
- package/src/ipc/routes/events-ipc-routes.ts +11 -31
- package/src/live-voice/__tests__/front-decision.test.ts +4 -176
- package/src/live-voice/__tests__/live-voice-agent-turn.test.ts +276 -68
- package/src/live-voice/__tests__/live-voice-events.test.ts +6 -3
- package/src/live-voice/__tests__/live-voice-progress.test.ts +185 -46
- package/src/live-voice/__tests__/live-voice-triage-escalate.test.ts +24 -59
- package/src/live-voice/__tests__/live-voice-tts-session.test.ts +38 -54
- package/src/live-voice/__tests__/live-voice-vad.test.ts +218 -422
- package/src/live-voice/front-decision.ts +5 -155
- package/src/live-voice/live-voice-metrics.ts +4 -1
- package/src/live-voice/live-voice-session.ts +650 -333
- package/src/live-voice/progress-phrases.ts +17 -0
- package/src/live-voice/protocol.ts +15 -0
- package/src/media/app-icon-generator.ts +15 -8
- package/src/media/avatar-router.ts +9 -5
- package/src/media/image-credentials.ts +42 -10
- package/src/media/image-service.ts +1 -13
- package/src/media/types.ts +26 -3
- package/src/notifications/AGENTS.md +2 -0
- package/src/notifications/__tests__/broadcaster.test.ts +95 -0
- package/src/notifications/adapters/macos.ts +3 -3
- package/src/notifications/broadcaster.ts +57 -0
- package/src/notifications/copy-composer.ts +0 -15
- package/src/notifications/decision-engine.ts +21 -22
- package/src/notifications/guardian-question-mode.ts +57 -2
- package/src/notifications/home-feed-side-effect.ts +4 -0
- package/src/notifications/signal.ts +6 -4
- package/src/notifications/trusted-contact-payloads.ts +3 -4
- package/src/notifications/vellum-card-affinity.ts +39 -0
- package/src/oauth/AGENTS.md +1 -1
- package/src/permissions/channel-permission-query.test.ts +69 -0
- package/src/permissions/channel-permission-query.ts +73 -1
- package/src/permissions/checker.test.ts +85 -9
- package/src/permissions/checker.ts +17 -22
- package/src/permissions/confirmation-guardian-request.test.ts +2 -2
- package/src/permissions/confirmation-guardian-request.ts +2 -2
- package/src/permissions/gateway-threshold-reader.test.ts +224 -17
- package/src/permissions/gateway-threshold-reader.ts +82 -10
- package/src/permissions/ipc-risk-types.ts +8 -0
- package/src/permissions/prompter.ts +5 -5
- package/src/permissions/question-guardian-request.test.ts +222 -0
- package/src/permissions/question-guardian-request.ts +179 -0
- package/src/permissions/question-prompter.test.ts +8 -8
- package/src/permissions/question-prompter.ts +18 -0
- package/src/permissions/secret-prompter.ts +2 -4
- package/src/permissions/workspace-policy.ts +236 -34
- package/src/persistence/__tests__/lifecycle-quiesce.test.ts +82 -0
- package/src/persistence/__tests__/message-content-file.test.ts +58 -3
- package/src/persistence/conversation-crud.ts +93 -0
- package/src/persistence/conversation-key-store.ts +63 -0
- package/src/persistence/db-async-query.ts +1 -1
- package/src/persistence/db-singleton.ts +14 -27
- package/src/persistence/delivery-crud.ts +45 -0
- package/src/persistence/embeddings/embedding-backend.ts +2 -1
- package/src/persistence/embeddings/embedding-identity.ts +7 -3
- package/src/persistence/job-utils.ts +32 -27
- package/src/persistence/jobs-store.ts +92 -3
- package/src/persistence/lifecycle-quiesce.ts +80 -0
- package/src/persistence/llm-usage-store.ts +45 -8
- package/src/persistence/message-content-file.ts +4 -4
- package/src/persistence/migrations/336-move-memory-v2-activation-logs-to-memory-db.ts +1 -1
- package/src/persistence/migrations/351-schedule-skill-script-handoff.ts +39 -0
- package/src/persistence/migrations/352-drop-schedule-skill-script-handoff.test.ts +83 -0
- package/src/persistence/migrations/352-drop-schedule-skill-script-handoff.ts +36 -0
- package/src/persistence/migrations/353-add-llm-usage-conversation-type.test.ts +110 -0
- package/src/persistence/migrations/353-add-llm-usage-conversation-type.ts +49 -0
- package/src/persistence/schema/infrastructure.ts +11 -0
- package/src/persistence/steps.ts +7 -1
- package/src/plugin-api/__tests__/publish-event-forwarding.test.ts +113 -0
- package/src/plugin-api/__tests__/publish-event.test.ts +57 -0
- package/src/plugin-api/conversation-turn.ts +4 -4
- package/src/plugin-api/event-hub-facade.ts +15 -6
- package/src/plugin-api/index.ts +10 -4
- package/src/plugin-api/publish-event.ts +36 -0
- package/src/plugins/AGENTS.md +2 -0
- package/src/plugins/defaults/compaction/window-manager.ts +9 -0
- package/src/plugins/defaults/index.ts +9 -13
- package/src/plugins/defaults/memory/AGENTS.md +775 -0
- package/src/plugins/defaults/memory/__tests__/capability-seed-embed-gate.test.ts +186 -0
- package/src/plugins/defaults/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +1 -1
- package/src/plugins/defaults/memory/__tests__/indexer-tier-dispatch.test.ts +129 -0
- package/src/plugins/defaults/memory/__tests__/jobs-worker-quiesce-gate.test.ts +91 -0
- package/src/plugins/defaults/memory/__tests__/jobs-worker-v1-graph-substrate-noop.test.ts +342 -0
- package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +9 -1
- package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-schedule.test.ts +36 -1
- package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-sweep-defer.test.ts +9 -1
- package/src/plugins/defaults/memory/__tests__/memory-log-stores-degraded.test.ts +2 -2
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +44 -10
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-sweep.test.ts +151 -10
- package/src/plugins/defaults/memory/__tests__/memory-tier-boundary-guard.test.ts +1155 -0
- package/src/plugins/defaults/memory/__tests__/memory-v2-activation-log-store.test.ts +1 -1
- package/src/plugins/defaults/memory/__tests__/memory-v2-concept-frequency.test.ts +3 -3
- package/src/plugins/defaults/memory/__tests__/tools-delete-memory-page.test.ts +1 -1
- package/src/plugins/defaults/memory/context-search/sources/memory-v2.ts +71 -35
- package/src/plugins/defaults/memory/context-search/sources/memory.ts +5 -1
- package/src/plugins/defaults/memory/fork-conversation-memory.ts +4 -4
- package/src/plugins/defaults/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +80 -10
- package/src/plugins/defaults/memory/graph/__tests__/handle-remember-v2.test.ts +1 -1
- package/src/plugins/defaults/memory/graph/capability-seed.ts +24 -10
- package/src/plugins/defaults/memory/graph/conversation-graph-memory.ts +123 -49
- package/src/plugins/defaults/memory/graph/graph-search.ts +6 -118
- package/src/plugins/defaults/memory/graph/in-context-tracker.test.ts +173 -0
- package/src/plugins/defaults/memory/graph/in-context-tracker.ts +109 -0
- package/src/plugins/defaults/memory/graph/store.ts +1 -0
- package/src/plugins/defaults/memory/graph/tool-handlers.test.ts +1 -1
- package/src/plugins/defaults/memory/graph/tool-handlers.ts +5 -2
- package/src/plugins/defaults/memory/graph-topology/__tests__/build-memory-graph.test.ts +1 -1
- package/src/plugins/defaults/memory/graph-topology/build-memory-graph.ts +6 -9
- package/src/plugins/defaults/memory/hooks/__tests__/user-prompt-submit.test.ts +30 -16
- package/src/plugins/defaults/memory/hooks/user-prompt-submit.ts +18 -14
- package/src/plugins/defaults/memory/indexer.ts +146 -89
- package/src/plugins/defaults/memory/injectors.ts +86 -41
- package/src/plugins/defaults/memory/job-handlers.ts +130 -39
- package/src/plugins/defaults/memory/jobs/__tests__/embed-concept-page.test.ts +2 -2
- package/src/plugins/defaults/memory/jobs/embed-concept-page.ts +22 -10
- package/src/plugins/defaults/memory/jobs-worker.ts +279 -208
- package/src/plugins/defaults/memory/memory-retrospective-enqueue.ts +4 -2
- package/src/plugins/defaults/memory/memory-retrospective-job.ts +40 -3
- package/src/plugins/defaults/memory/memory-retrospective-sweep.ts +99 -11
- package/src/plugins/defaults/memory/src/__tests__/memory-v2-routes.test.ts +5 -3
- package/src/plugins/defaults/memory/src/__tests__/memory-v2-simulate-route.test.ts +3 -4
- package/src/plugins/defaults/memory/src/memory-graph-routes.ts +2 -1
- package/src/plugins/defaults/memory/src/memory-item-routes.test.ts +7 -5
- package/src/plugins/defaults/memory/src/memory-item-routes.ts +51 -19
- package/src/plugins/defaults/memory/src/memory-v2-routes.ts +31 -20
- package/src/plugins/defaults/memory/startup.ts +58 -21
- package/src/plugins/defaults/memory/substrate/__tests__/boot-maintenance.test.ts +335 -0
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/cli-command-store.test.ts +14 -8
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/consolidation-job.test.ts +51 -21
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/edge-index.test.ts +1 -1
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/frontmatter-sweep.test.ts +3 -3
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/page-index.test.ts +1 -1
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/page-store.test.ts +1 -1
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/prompts-consolidation.test.ts +2 -2
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/qdrant.test.ts +23 -14
- package/src/plugins/defaults/memory/substrate/__tests__/reembed-job.test.ts +262 -0
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/sim.test.ts +9 -12
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/skill-content.test.ts +2 -2
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/skill-store.test.ts +9 -9
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/sparse-bm25.test.ts +12 -5
- package/src/plugins/defaults/memory/substrate/__tests__/spread.test.ts +276 -0
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/static-context.test.ts +17 -8
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/sweep-job.test.ts +9 -9
- package/src/plugins/defaults/memory/{v3/substrate/memory-v2-startup.ts → substrate/boot-maintenance.ts} +43 -24
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/cli-command-store.ts +13 -8
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/consolidation-job.ts +51 -27
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/constants.ts +1 -0
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/edge-index.ts +28 -9
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/frontmatter-sweep.ts +14 -7
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/injected-block-slugs.ts +9 -3
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/page-index.ts +29 -10
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/page-store.ts +35 -12
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/prompts/consolidation.ts +14 -8
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/prompts/sweep.ts +4 -1
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/qdrant.ts +96 -36
- package/src/plugins/defaults/memory/substrate/reembed-job.ts +54 -0
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/sim.ts +26 -15
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/skill-content.ts +1 -1
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/skill-store.ts +13 -8
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/sparse-bm25.ts +27 -10
- package/src/plugins/defaults/memory/substrate/spread.ts +165 -0
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/static-context.ts +12 -7
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/sweep-job.ts +20 -15
- package/src/plugins/defaults/memory/substrate/tuning.ts +93 -0
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/types.ts +7 -4
- package/src/plugins/defaults/memory/tools.test.ts +1 -1
- package/src/plugins/defaults/memory/tools.ts +1 -1
- package/src/plugins/defaults/memory/v1/README.md +5 -0
- package/src/plugins/defaults/memory/{__tests__ → v1/__tests__}/filing-jobs.test.ts +4 -4
- package/src/plugins/defaults/memory/{filing-jobs.ts → v1/filing-jobs.ts} +3 -3
- package/src/plugins/defaults/memory/{graph → v1/graph}/bootstrap.test.ts +68 -6
- package/src/plugins/defaults/memory/{graph → v1/graph}/bootstrap.ts +40 -21
- package/src/plugins/defaults/memory/{graph → v1/graph}/consolidation.ts +14 -14
- package/src/plugins/defaults/memory/{graph → v1/graph}/decay.test.ts +1 -1
- package/src/plugins/defaults/memory/{graph → v1/graph}/decay.ts +3 -3
- package/src/plugins/defaults/memory/{graph → v1/graph}/extraction-job.ts +5 -5
- package/src/plugins/defaults/memory/{graph → v1/graph}/extraction.test.ts +1 -1
- package/src/plugins/defaults/memory/{graph → v1/graph}/extraction.ts +20 -14
- package/src/plugins/defaults/memory/{graph → v1/graph}/graph-search.test.ts +3 -3
- package/src/plugins/defaults/memory/v1/graph/graph-search.ts +123 -0
- package/src/plugins/defaults/memory/{graph → v1/graph}/injection.test.ts +1 -118
- package/src/plugins/defaults/memory/{graph → v1/graph}/injection.ts +9 -111
- package/src/plugins/defaults/memory/{graph → v1/graph}/narrative.ts +6 -6
- package/src/plugins/defaults/memory/{graph → v1/graph}/pattern-scan.ts +5 -5
- package/src/plugins/defaults/memory/{graph → v1/graph}/retriever.test.ts +135 -42
- package/src/plugins/defaults/memory/{graph → v1/graph}/retriever.ts +40 -22
- package/src/plugins/defaults/memory/{graph → v1/graph}/scoring.test.ts +1 -1
- package/src/plugins/defaults/memory/{graph → v1/graph}/scoring.ts +1 -1
- package/src/plugins/defaults/memory/{graph → v1/graph}/serendipity.ts +1 -1
- package/src/plugins/defaults/memory/{graph → v1/graph}/triggers.test.ts +1 -1
- package/src/plugins/defaults/memory/{graph → v1/graph}/triggers.ts +1 -1
- package/src/plugins/defaults/memory/{identity-context.ts → v1/identity-context.ts} +4 -4
- package/src/plugins/defaults/memory/{job-handlers → v1/job-handlers}/backfill.ts +6 -6
- package/src/plugins/defaults/memory/{job-handlers → v1/job-handlers}/embedding.test.ts +6 -6
- package/src/plugins/defaults/memory/{job-handlers → v1/job-handlers}/embedding.ts +6 -6
- package/src/plugins/defaults/memory/{job-handlers → v1/job-handlers}/index-maintenance.ts +8 -8
- package/src/plugins/defaults/memory/{jobs → v1/jobs}/embed-pkb-file.test.ts +7 -7
- package/src/plugins/defaults/memory/{jobs → v1/jobs}/embed-pkb-file.ts +5 -5
- package/src/plugins/defaults/memory/{pkb → v1/pkb}/autoinject.ts +1 -1
- package/src/plugins/defaults/memory/{pkb → v1/pkb}/context.ts +2 -2
- package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-index.test.ts +3 -3
- package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-index.ts +2 -2
- package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-reconcile.test.ts +3 -3
- package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-reconcile.ts +2 -2
- package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-search.test.ts +3 -3
- package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-search.ts +6 -6
- package/src/plugins/defaults/memory/{pkb → v1/pkb}/types.ts +3 -5
- package/src/plugins/defaults/memory/{pkb-schedule.ts → v1/pkb-schedule.ts} +2 -2
- package/src/plugins/defaults/memory/{search/semantic.ts → v1/semantic-search.ts} +1 -1
- package/src/plugins/defaults/memory/v2/__tests__/activation-store.test.ts +1 -1
- package/src/plugins/defaults/memory/v2/__tests__/activation.test.ts +11 -274
- package/src/plugins/defaults/memory/v2/__tests__/backfill-jobs.test.ts +9 -131
- package/src/plugins/defaults/memory/v2/__tests__/harness-compare.test.ts +1 -1
- package/src/plugins/defaults/memory/v2/__tests__/harness-oracle.test.ts +1 -1
- package/src/plugins/defaults/memory/v2/__tests__/harness-replay-input.test.ts +1 -1
- package/src/plugins/defaults/memory/v2/__tests__/injection.test.ts +14 -10
- package/src/plugins/defaults/memory/v2/__tests__/reranker.test.ts +7 -5
- package/src/plugins/defaults/memory/v2/__tests__/router.test.ts +12 -6
- package/src/plugins/defaults/memory/{memory-v2-activation-log-store.ts → v2/activation-log-store.ts} +2 -2
- package/src/plugins/defaults/memory/v2/activation-store.ts +22 -8
- package/src/plugins/defaults/memory/v2/activation.ts +30 -163
- package/src/plugins/defaults/memory/v2/backfill-jobs.ts +7 -54
- package/src/plugins/defaults/memory/{memory-v2-concept-frequency.ts → v2/concept-frequency.ts} +3 -3
- package/src/plugins/defaults/memory/v2/harness/oracle.ts +1 -1
- package/src/plugins/defaults/memory/v2/harness/replay-input.ts +2 -2
- package/src/plugins/defaults/memory/v2/harness/retriever.ts +1 -1
- package/src/plugins/defaults/memory/v2/injection.ts +36 -26
- package/src/plugins/defaults/memory/v2/migration.ts +2 -2
- package/src/plugins/defaults/memory/{rerank-local.ts → v2/rerank-local.ts} +44 -18
- package/src/plugins/defaults/memory/v2/reranker.ts +29 -11
- package/src/plugins/defaults/memory/v2/router.ts +38 -15
- package/src/plugins/defaults/memory/v3/__tests__/candidate-match.test.ts +5 -3
- package/src/plugins/defaults/memory/v3/__tests__/carry-integration.test.ts +21 -8
- package/src/plugins/defaults/memory/v3/__tests__/edge.test.ts +1 -1
- package/src/plugins/defaults/memory/v3/__tests__/live-integration.test.ts +1 -1
- package/src/plugins/defaults/memory/v3/__tests__/maintain-job.test.ts +4 -1
- package/src/plugins/defaults/memory/v3/__tests__/orchestrate.test.ts +181 -3
- package/src/plugins/defaults/memory/v3/__tests__/selection-log-store.test.ts +3 -0
- package/src/plugins/defaults/memory/v3/__tests__/shadow-integration.test.ts +14 -5
- package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +40 -50
- package/src/plugins/defaults/memory/v3/__tests__/tuning-profile.test.ts +1 -0
- package/src/plugins/defaults/memory/v3/candidate-match.ts +2 -2
- package/src/plugins/defaults/memory/v3/capabilities.ts +6 -4
- package/src/plugins/defaults/memory/v3/card.ts +25 -9
- package/src/plugins/defaults/memory/v3/edge.ts +52 -18
- package/src/plugins/defaults/memory/v3/gate.ts +4 -4
- package/src/plugins/defaults/memory/v3/injector.ts +10 -3
- package/src/plugins/defaults/memory/v3/maintain-job.ts +3 -3
- package/src/plugins/defaults/memory/v3/orchestrate.ts +100 -18
- package/src/plugins/defaults/memory/v3/page-content.ts +26 -10
- package/src/plugins/defaults/memory/v3/prune.ts +40 -16
- package/src/plugins/defaults/memory/v3/selection-log-store.ts +34 -12
- package/src/plugins/defaults/memory/v3/shadow-plugin.ts +9 -13
- package/src/plugins/defaults/memory/v3/span-query.test.ts +86 -0
- package/src/plugins/defaults/memory/v3/span-query.ts +71 -0
- package/src/plugins/defaults/memory/v3/tuning-profile.ts +3 -0
- package/src/plugins/defaults/memory/v3/types.ts +4 -1
- package/src/plugins/defaults/memory/v3-eval/eval-packets.ts +2 -2
- package/src/plugins/defaults/memory/validation.ts +1 -1
- package/src/plugins/defaults/memory/worker.ts +2 -1
- package/src/plugins/defaults/platform-hosted/__tests__/reengage.test.ts +104 -12
- package/src/plugins/defaults/platform-hosted/routes/reengage.ts +104 -12
- package/src/plugins/types.ts +2 -2
- package/src/providers/__tests__/registry-native-web-search.test.ts +47 -2
- package/src/providers/anthropic/client.ts +15 -6
- package/src/providers/content-block-schema.ts +26 -0
- package/src/providers/inference/__tests__/connections-credential-normalize.test.ts +87 -0
- package/src/providers/inference/adapter-factory.ts +6 -0
- package/src/providers/inference/connections.ts +30 -14
- package/src/providers/model-catalog.ts +77 -0
- package/src/providers/openai/__tests__/chat-completions-input-audio.test.ts +260 -0
- package/src/providers/openai/chat-completions-provider.ts +65 -17
- package/src/providers/openai/input-audio.ts +76 -0
- package/src/providers/openrouter/client.ts +0 -2
- package/src/providers/platform-proxy/constants.ts +4 -0
- package/src/providers/poolside/client.ts +42 -0
- package/src/providers/registry.ts +40 -8
- package/src/providers/retry.ts +2 -0
- package/src/providers/types.ts +39 -1
- package/src/providers/vercel-ai-gateway/client.ts +0 -2
- package/src/runtime/AGENTS.md +7 -5
- package/src/runtime/__tests__/question-request-guardian-bridge.test.ts +173 -0
- package/src/runtime/__tests__/question-resolution.test.ts +111 -0
- package/src/runtime/access-request-helper.ts +7 -15
- package/src/runtime/assistant-event-hub.ts +43 -31
- package/src/runtime/assistant-event-publish-options.ts +31 -0
- package/src/runtime/assistant-event.ts +19 -30
- package/src/runtime/assistant-stream-state.ts +4 -4
- package/src/runtime/channel-approvals.ts +0 -25
- package/src/runtime/channel-readiness-service.ts +99 -40
- package/src/runtime/channel-retry-sweep.ts +38 -15
- package/src/runtime/confirmation-request-guardian-bridge.ts +4 -0
- package/src/runtime/guardian-reply-router.ts +108 -0
- package/src/runtime/http-server.ts +8 -0
- package/src/runtime/http-types.ts +2 -2
- package/src/runtime/process-role.ts +42 -0
- package/src/runtime/question-request-guardian-bridge.ts +184 -0
- package/src/runtime/question-resolution.ts +153 -0
- package/src/runtime/routes/__tests__/bookmark-routes.test.ts +6 -2
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +1 -1
- package/src/runtime/routes/acp-routes.ts +2 -2
- package/src/runtime/routes/bookmark-routes.ts +3 -15
- package/src/runtime/routes/canned-message-complete.ts +2 -2
- package/src/runtime/routes/consolidation-routes.ts +8 -2
- package/src/runtime/routes/conversation-list-routes.ts +3 -19
- package/src/runtime/routes/conversation-management-routes.ts +1 -5
- package/src/runtime/routes/conversation-query-routes.ts +52 -8
- package/src/runtime/routes/conversation-routes.ts +36 -22
- package/src/runtime/routes/credential-request-routes.ts +0 -1
- package/src/runtime/routes/filing-routes.ts +7 -7
- package/src/runtime/routes/global-search-routes.ts +1 -1
- package/src/runtime/routes/guardian-approval-prompt.ts +2 -2
- package/src/runtime/routes/image-generation-routes.ts +12 -9
- package/src/runtime/routes/inbound-message-handler.ts +17 -0
- package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +50 -0
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +19 -0
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +4 -4
- package/src/runtime/routes/inbound-stages/inbound-content-prep.test.ts +129 -0
- package/src/runtime/routes/inbound-stages/inbound-content-prep.ts +141 -9
- package/src/runtime/routes/index.ts +2 -0
- package/src/runtime/routes/lifecycle-routes.ts +199 -0
- package/src/runtime/routes/platform-routes.ts +3 -8
- package/src/runtime/routes/playground/__tests__/inject-failures.test.ts +7 -7
- package/src/runtime/routes/playground/__tests__/reset-circuit.test.ts +5 -5
- package/src/runtime/routes/question-routes.ts +34 -87
- package/src/runtime/routes/secret-routes.ts +11 -1
- package/src/runtime/routes/settings-routes.ts +8 -18
- package/src/runtime/routes/upgrade-broadcast-routes.ts +4 -5
- package/src/runtime/routes/workspace-routes.test.ts +7 -4
- package/src/runtime/slack-reply-session.test.ts +12 -12
- package/src/runtime/slack-reply-session.ts +17 -17
- package/src/runtime/sync/sync-publisher.test.ts +7 -5
- package/src/runtime/tool-grant-request-helper.ts +4 -0
- package/src/schedule/schedule-store.ts +70 -0
- package/src/schedule/scheduler.ts +27 -0
- package/src/security/AGENTS.md +1 -1
- package/src/security/credential-key.ts +17 -0
- package/src/security/secret-ingress.ts +14 -105
- package/src/security/secret-patterns.ts +8 -139
- package/src/security/secret-scanner.ts +8 -3
- package/src/security/store-path-override.ts +6 -16
- package/src/sequence/store.ts +8 -0
- package/src/signals/emit-event.ts +5 -10
- package/src/signals/event-stream.ts +20 -10
- package/src/subagent/manager.ts +76 -25
- package/src/subagent/notify.ts +8 -0
- package/src/subagent/types.ts +13 -3
- package/src/telegram/__tests__/webhook-health.test.ts +442 -0
- package/src/telegram/webhook-health.ts +478 -0
- package/src/telemetry/AGENTS.md +6 -0
- package/src/telemetry/memory-corpus-size.test.ts +129 -0
- package/src/telemetry/memory-corpus-size.ts +184 -0
- package/src/telemetry/memory-tier-reporter.test.ts +67 -2
- package/src/telemetry/memory-tier-reporter.ts +30 -3
- package/src/tools/__tests__/document-tool-input-schemas.test.ts +103 -0
- package/src/tools/__tests__/followup-call-acp-tool-input-schemas.test.ts +125 -0
- package/src/tools/__tests__/schedule-tool-input-schemas.test.ts +83 -0
- package/src/tools/__tests__/subagent-workflow-tool-input-schemas.test.ts +116 -0
- package/src/tools/__tests__/tool-input-schemas.test.ts +192 -0
- package/src/tools/__tests__/tool-schema-drift-harness.ts +142 -0
- package/src/tools/acp/abort.ts +21 -1
- package/src/tools/acp/context.ts +5 -5
- package/src/tools/acp/spawn.test.ts +15 -5
- package/src/tools/acp/spawn.ts +26 -3
- package/src/tools/acp/status.ts +20 -1
- package/src/tools/acp/steer.test.ts +20 -0
- package/src/tools/acp/steer.ts +23 -2
- package/src/tools/ask-question/ask-question-tool.test.ts +65 -0
- package/src/tools/ask-question/ask-question-tool.ts +68 -92
- package/src/tools/browser/browser-screencast.ts +6 -6
- package/src/tools/calls/call-end.ts +24 -3
- package/src/tools/calls/call-start.ts +35 -11
- package/src/tools/calls/call-status.ts +20 -1
- package/src/tools/document/document-comment-tool.test.ts +49 -0
- package/src/tools/document/document-comment-tool.ts +45 -6
- package/src/tools/document/document-tool.ts +142 -24
- package/src/tools/executor.ts +27 -13
- package/src/tools/filesystem/edit.ts +62 -60
- package/src/tools/filesystem/list.ts +36 -29
- package/src/tools/filesystem/read.ts +56 -39
- package/src/tools/filesystem/write.ts +44 -38
- package/src/tools/followups/followup_create.ts +41 -12
- package/src/tools/followups/followup_list.ts +34 -6
- package/src/tools/followups/followup_resolve.ts +26 -4
- package/src/tools/host-filesystem/edit.ts +50 -60
- package/src/tools/host-filesystem/read.ts +45 -39
- package/src/tools/host-filesystem/write.ts +31 -36
- package/src/tools/host-terminal/host-shell.ts +76 -62
- package/src/tools/policy-context.ts +27 -10
- package/src/tools/schedule/create.ts +76 -33
- package/src/tools/schedule/delete.ts +21 -2
- package/src/tools/schedule/list.ts +25 -3
- package/src/tools/schedule/update.ts +105 -48
- package/src/tools/shared/filesystem/path-policy.ts +246 -40
- package/src/tools/shared/zod-tool-schema.ts +117 -0
- package/src/tools/subagent/abort.ts +12 -4
- package/src/tools/subagent/consult-deadline.ts +9 -3
- package/src/tools/subagent/message.ts +21 -5
- package/src/tools/subagent/notify-parent.ts +44 -23
- package/src/tools/subagent/read.ts +15 -4
- package/src/tools/subagent/resolve.ts +26 -4
- package/src/tools/subagent/spawn.ts +37 -13
- package/src/tools/subagent/status.ts +12 -4
- package/src/tools/system/request-permission.ts +35 -26
- package/src/tools/terminal/shell.ts +68 -55
- package/src/tools/tool-approval-handler.ts +327 -53
- package/src/tools/tool-input-schemas.ts +85 -0
- package/src/tools/tool-types.ts +7 -0
- package/src/tools/types.ts +8 -0
- package/src/tools/workflows/manage-workflows.ts +30 -2
- package/src/tools/workflows/run-workflow.test.ts +54 -2
- package/src/tools/workflows/run-workflow.ts +32 -4
- package/src/util/fs-symlinks.ts +30 -0
- package/src/util/log-redact.ts +7 -3
- package/src/vellum-assistant-namespace.d.ts +80 -0
- package/src/watcher/watcher-store.ts +8 -0
- package/src/workflows/leaf-runner.test.ts +104 -2
- package/src/workflows/leaf-runner.ts +31 -6
- package/src/workspace/migrations/070-memory-v2-summary-schema-rebuild.ts +2 -2
- package/src/workspace/migrations/134-image-generation-mode-to-provider.ts +128 -0
- package/src/workspace/migrations/135-copy-substrate-tunables.ts +248 -0
- package/src/workspace/migrations/__tests__/135-copy-substrate-tunables.test.ts +446 -0
- package/src/workspace/migrations/__tests__/backfill-v3-leaves.test.ts +2 -2
- package/src/workspace/migrations/registry.ts +4 -0
- package/src/__tests__/memory-retrieval-budget.test.ts +0 -49
- package/src/__tests__/secret-patterns.test.ts +0 -27
- package/src/config/__tests__/proc-to-skills.test.ts +0 -21
- package/src/config/memory-tier.test.ts +0 -44
- package/src/daemon/message-types/acp.ts +0 -20
- package/src/daemon/message-types/apps.ts +0 -11
- package/src/daemon/message-types/background-tools.ts +0 -14
- package/src/daemon/message-types/bookmarks.ts +0 -13
- package/src/daemon/message-types/contacts.ts +0 -13
- package/src/daemon/message-types/document-comments.ts +0 -14
- package/src/daemon/message-types/documents.ts +0 -13
- package/src/daemon/message-types/home.ts +0 -15
- package/src/daemon/message-types/host-bash.ts +0 -12
- package/src/daemon/message-types/host-cu.ts +0 -10
- package/src/daemon/message-types/host-file.ts +0 -12
- package/src/daemon/message-types/host-transfer.ts +0 -12
- package/src/daemon/message-types/integrations.ts +0 -90
- package/src/daemon/message-types/memory.ts +0 -10
- package/src/daemon/message-types/schedules.ts +0 -14
- package/src/daemon/message-types/settings.ts +0 -17
- package/src/daemon/message-types/subagents.ts +0 -63
- package/src/daemon/message-types/upgrades.ts +0 -14
- package/src/daemon/message-types/workflows.ts +0 -25
- package/src/daemon/message-types/workspace.ts +0 -137
- package/src/live-voice/ack-phrases.ts +0 -58
- package/src/plugins/defaults/memory/retrieval-budget.ts +0 -29
- package/src/plugins/defaults/memory/v3/__tests__/gate-flag.test.ts +0 -69
- package/src/plugins/defaults/memory/v3/gate-flag.ts +0 -20
- package/src/plugins/defaults/memory/v3/substrate/__tests__/memory-v2-startup.test.ts +0 -86
- package/src/plugins/defaults/memory/v3/substrate/memory-v2-startup.test.ts +0 -205
- /package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/concept-page-frontmatter-schema.test.ts +0 -0
- /package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/consolidation-prompt-flag-gating-guard.test.ts +0 -0
- /package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/injected-block-slugs.test.ts +0 -0
- /package/src/plugins/defaults/memory/{v3/substrate → substrate}/cli-command-content.ts +0 -0
|
@@ -1,18 +1,29 @@
|
|
|
1
1
|
// ---------------------------------------------------------------------------
|
|
2
2
|
// Memory Graph — Conversation-level memory integration
|
|
3
3
|
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
4
|
+
// `graph/` is the all-tier legacy-graph store + tier dispatcher: `store.ts`,
|
|
5
|
+
// `capability-seed.ts`, and `tool-handlers.ts` are written on every tier
|
|
6
|
+
// (capability nodes feed `list_memory`), while the read ENGINE lives in
|
|
7
|
+
// `../v1/graph/`. This class manages the InContextTracker lifecycle,
|
|
8
|
+
// dispatches retrieval to the active tier's engine, and owns compaction
|
|
9
|
+
// eviction of v2/v3 per-conversation state.
|
|
7
10
|
// ---------------------------------------------------------------------------
|
|
8
11
|
|
|
9
|
-
import type {
|
|
12
|
+
import type {
|
|
13
|
+
AssistantEvent,
|
|
14
|
+
ContentBlock,
|
|
15
|
+
ImageContent,
|
|
16
|
+
Message,
|
|
17
|
+
} from "@vellumai/plugin-api";
|
|
10
18
|
import { and, desc, eq, inArray, ne, notInArray } from "drizzle-orm";
|
|
11
19
|
import { z } from "zod";
|
|
12
20
|
|
|
21
|
+
import {
|
|
22
|
+
isMemoryEnabled,
|
|
23
|
+
isV2InjectionEngineActive,
|
|
24
|
+
} from "../../../../config/memory-v3-gate.js";
|
|
13
25
|
import type { AssistantConfig } from "../../../../config/types.js";
|
|
14
26
|
import { estimateTextTokens } from "../../../../context/token-estimator.js";
|
|
15
|
-
import type { ServerMessage } from "../../../../daemon/message-protocol.js";
|
|
16
27
|
import { getDb } from "../../../../persistence/db-connection.js";
|
|
17
28
|
import { embedWithRetry } from "../../../../persistence/embeddings/embed.js";
|
|
18
29
|
import { generateSparseEmbedding } from "../../../../persistence/embeddings/embedding-backend.js";
|
|
@@ -22,6 +33,19 @@ import { memorySummaries } from "../../../../persistence/schema/index.js";
|
|
|
22
33
|
import { getLogger } from "../logging.js";
|
|
23
34
|
import { wrapMemoryBlock } from "../memory-marker.js";
|
|
24
35
|
import { getWorkspaceDir } from "../paths.js";
|
|
36
|
+
// V1 — delete with v1. The v1 read engine: legacy-graph retrieval and block
|
|
37
|
+
// assembly, feeding the v1 fallback arms of `loadContextMemory` /
|
|
38
|
+
// `retrieveForTurn` below.
|
|
39
|
+
import {
|
|
40
|
+
assembleContextBlock,
|
|
41
|
+
assembleInjectionBlock,
|
|
42
|
+
MAX_CONTEXT_LOAD_IMAGES,
|
|
43
|
+
MAX_PER_TURN_IMAGES,
|
|
44
|
+
type ResolvedImage,
|
|
45
|
+
resolveInjectionImages,
|
|
46
|
+
} from "../v1/graph/injection.js";
|
|
47
|
+
import { loadContextMemory, retrieveForTurn } from "../v1/graph/retriever.js";
|
|
48
|
+
// v2 injection engine — turn-time selection over the concept-page substrate
|
|
25
49
|
import {
|
|
26
50
|
clearEverInjected as clearV2EverInjected,
|
|
27
51
|
hydrate as hydrateV2State,
|
|
@@ -33,22 +57,16 @@ import {
|
|
|
33
57
|
} from "../v2/injection.js";
|
|
34
58
|
import { loadNowText } from "../v2/now-text.js";
|
|
35
59
|
import type { RouterTurnPair } from "../v2/router.js";
|
|
60
|
+
// v3 per-conversation state — evicted here on compaction
|
|
36
61
|
import { clearConversation as clearV3EverInjected } from "../v3/ever-injected-store.js";
|
|
37
62
|
import {
|
|
38
63
|
loadGraphMemoryState,
|
|
39
64
|
saveGraphMemoryState,
|
|
40
65
|
} from "./graph-memory-state-store.js";
|
|
41
66
|
import {
|
|
42
|
-
assembleContextBlock,
|
|
43
|
-
assembleInjectionBlock,
|
|
44
67
|
InContextTracker,
|
|
45
68
|
type InContextTrackerSnapshot,
|
|
46
|
-
|
|
47
|
-
MAX_PER_TURN_IMAGES,
|
|
48
|
-
type ResolvedImage,
|
|
49
|
-
resolveInjectionImages,
|
|
50
|
-
} from "./injection.js";
|
|
51
|
-
import { loadContextMemory, retrieveForTurn } from "./retriever.js";
|
|
69
|
+
} from "./in-context-tracker.js";
|
|
52
70
|
import type { RetrievalMetrics } from "./types.js";
|
|
53
71
|
|
|
54
72
|
const log = getLogger("graph-conversation-memory");
|
|
@@ -80,7 +98,9 @@ const liveByConversation = new Map<string, ConversationGraphMemory>();
|
|
|
80
98
|
export function getLiveGraphMemory(
|
|
81
99
|
conversationId: string | undefined,
|
|
82
100
|
): ConversationGraphMemory | undefined {
|
|
83
|
-
if (!conversationId)
|
|
101
|
+
if (!conversationId) {
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
84
104
|
return liveByConversation.get(conversationId);
|
|
85
105
|
}
|
|
86
106
|
|
|
@@ -132,7 +152,9 @@ export class ConversationGraphMemory {
|
|
|
132
152
|
* Called during conversation disposal.
|
|
133
153
|
*/
|
|
134
154
|
persistState(): void {
|
|
135
|
-
if (!this.initialized)
|
|
155
|
+
if (!this.initialized) {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
136
158
|
try {
|
|
137
159
|
const snapshot: InContextTrackerSnapshot & {
|
|
138
160
|
initialized: boolean;
|
|
@@ -156,10 +178,14 @@ export class ConversationGraphMemory {
|
|
|
156
178
|
* On failure or missing row, silently falls back to full context-load.
|
|
157
179
|
*/
|
|
158
180
|
restoreState(): void {
|
|
159
|
-
if (this.stateRestored)
|
|
181
|
+
if (this.stateRestored) {
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
160
184
|
try {
|
|
161
185
|
const json = loadGraphMemoryState(this.conversationId);
|
|
162
|
-
if (!json)
|
|
186
|
+
if (!json) {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
163
189
|
|
|
164
190
|
const snapshot = JSON.parse(json) as InContextTrackerSnapshot & {
|
|
165
191
|
initialized: boolean;
|
|
@@ -360,7 +386,9 @@ export class ConversationGraphMemory {
|
|
|
360
386
|
* not the original user message.
|
|
361
387
|
*/
|
|
362
388
|
retrackCachedNodes(): void {
|
|
363
|
-
if (this.lastInjectedNodeIds.length === 0)
|
|
389
|
+
if (this.lastInjectedNodeIds.length === 0) {
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
364
392
|
this.tracker.add(this.lastInjectedNodeIds);
|
|
365
393
|
}
|
|
366
394
|
|
|
@@ -419,7 +447,7 @@ export class ConversationGraphMemory {
|
|
|
419
447
|
messages: Message[],
|
|
420
448
|
config: AssistantConfig,
|
|
421
449
|
abortSignal: AbortSignal,
|
|
422
|
-
onEvent: (msg:
|
|
450
|
+
onEvent: (msg: AssistantEvent) => void,
|
|
423
451
|
): Promise<{
|
|
424
452
|
runMessages: Message[];
|
|
425
453
|
injectedTokens: number;
|
|
@@ -467,7 +495,7 @@ export class ConversationGraphMemory {
|
|
|
467
495
|
metrics: null as RetrievalMetrics | null,
|
|
468
496
|
};
|
|
469
497
|
|
|
470
|
-
if (config
|
|
498
|
+
if (!isMemoryEnabled(config)) {
|
|
471
499
|
// Clear any cached injection so a later overflow-reduction
|
|
472
500
|
// re-injection via `reinjectCachedMemory()` cannot reintroduce a
|
|
473
501
|
// stale <memory> block after the user disables memory.
|
|
@@ -480,12 +508,15 @@ export class ConversationGraphMemory {
|
|
|
480
508
|
// Gate: skip for empty/tool-result-only messages — unless we need to
|
|
481
509
|
// reload after compaction (needsReload) or haven't initialized yet.
|
|
482
510
|
const lastMessage = messages[messages.length - 1];
|
|
483
|
-
if (!lastMessage || lastMessage.role !== "user")
|
|
511
|
+
if (!lastMessage || lastMessage.role !== "user") {
|
|
512
|
+
return noopResult;
|
|
513
|
+
}
|
|
484
514
|
const hasUserContent = lastMessage.content.some(
|
|
485
515
|
(block) => block.type === "text" && block.text.trim().length > 0,
|
|
486
516
|
);
|
|
487
|
-
if (!hasUserContent && this.initialized && !this.needsReload)
|
|
517
|
+
if (!hasUserContent && this.initialized && !this.needsReload) {
|
|
488
518
|
return noopResult;
|
|
519
|
+
}
|
|
489
520
|
|
|
490
521
|
try {
|
|
491
522
|
// Decide which retrieval mode to use
|
|
@@ -530,7 +561,7 @@ export class ConversationGraphMemory {
|
|
|
530
561
|
recentSummaries: string[],
|
|
531
562
|
userQuery: string | undefined,
|
|
532
563
|
signal: AbortSignal,
|
|
533
|
-
onEvent: (msg:
|
|
564
|
+
onEvent: (msg: AssistantEvent) => void,
|
|
534
565
|
) {
|
|
535
566
|
// Use the raw user text (no >10-char filter) so even short greetings
|
|
536
567
|
// ("hi") get a fresh top-K activation dump on the first user message.
|
|
@@ -581,7 +612,9 @@ export class ConversationGraphMemory {
|
|
|
581
612
|
};
|
|
582
613
|
}
|
|
583
614
|
|
|
584
|
-
// v1 fallback — only reached when the v2
|
|
615
|
+
// v1 fallback — only reached when the v2 engine is not the live tier (v2
|
|
616
|
+
// disabled, memory off, or v3 live; under the concept-page substrate the
|
|
617
|
+
// retriever short-circuits to zero nodes).
|
|
585
618
|
const result = await loadContextMemory({
|
|
586
619
|
recentSummaries,
|
|
587
620
|
userQuery,
|
|
@@ -650,7 +683,7 @@ export class ConversationGraphMemory {
|
|
|
650
683
|
type: "memory_status",
|
|
651
684
|
enabled: true,
|
|
652
685
|
degraded: false,
|
|
653
|
-
} as
|
|
686
|
+
} as AssistantEvent);
|
|
654
687
|
|
|
655
688
|
this.lastInjectedBlock = contextBlock;
|
|
656
689
|
this.lastInjectedNodeIds = [
|
|
@@ -700,11 +733,13 @@ export class ConversationGraphMemory {
|
|
|
700
733
|
} else if (msg.role === "assistant" && !assistantLast) {
|
|
701
734
|
assistantLast = text;
|
|
702
735
|
}
|
|
703
|
-
if (userLastBlocks.length > 0 && assistantLast)
|
|
736
|
+
if (userLastBlocks.length > 0 && assistantLast) {
|
|
737
|
+
break;
|
|
738
|
+
}
|
|
704
739
|
}
|
|
705
740
|
|
|
706
|
-
// v2 path — skip v1 retrieval entirely when v2 is
|
|
707
|
-
// matching comment in `runContextLoad` for rationale.
|
|
741
|
+
// v2 path — skip v1 retrieval entirely when the v2 engine is the live
|
|
742
|
+
// tier. See the matching comment in `runContextLoad` for rationale.
|
|
708
743
|
const startedAt = Date.now();
|
|
709
744
|
const v2 = await this.maybeRouteV2Injection(
|
|
710
745
|
messages,
|
|
@@ -747,7 +782,9 @@ export class ConversationGraphMemory {
|
|
|
747
782
|
};
|
|
748
783
|
}
|
|
749
784
|
|
|
750
|
-
// v1 path (only reached when the v2
|
|
785
|
+
// v1 path (only reached when the v2 engine is not the live tier — v2
|
|
786
|
+
// disabled, memory off, or v3 live; under the concept-page substrate the
|
|
787
|
+
// retriever short-circuits to zero nodes).
|
|
751
788
|
const result = await retrieveForTurn({
|
|
752
789
|
assistantLastMessage: assistantLast,
|
|
753
790
|
userLastMessage: userLast,
|
|
@@ -851,11 +888,16 @@ export class ConversationGraphMemory {
|
|
|
851
888
|
}
|
|
852
889
|
|
|
853
890
|
/**
|
|
854
|
-
* Run the v2 activation pipeline when the
|
|
855
|
-
* (`memory.v2.enabled`
|
|
891
|
+
* Run the v2 activation pipeline when the v2 injection engine is the live
|
|
892
|
+
* tier ({@link isV2InjectionEngineActive}) — memory on, `memory.v2.enabled`
|
|
893
|
+
* set, and v3 not live. Every `prepareMemory` entry point shares this gate,
|
|
894
|
+
* including callers without their own v3 guard (e.g. the persona
|
|
895
|
+
* workflow-leaf runner), so a v3-live assistant never runs the v2
|
|
896
|
+
* router/activation pipeline or writes its activation/injection logs.
|
|
856
897
|
*
|
|
857
898
|
* The two outcomes the caller distinguishes via `routed`:
|
|
858
|
-
* - `routed: false` — v2
|
|
899
|
+
* - `routed: false` — v2 engine not active (disabled, memory off, or v3
|
|
900
|
+
* live); caller falls through to the legacy v1
|
|
859
901
|
* retrieval path.
|
|
860
902
|
* - `routed: true` — v2 ran. `runMessages` is either the v2-prepended
|
|
861
903
|
* message list (block was non-null) or the input
|
|
@@ -880,7 +922,7 @@ export class ConversationGraphMemory {
|
|
|
880
922
|
runMessages: Message[];
|
|
881
923
|
injectedBlockText: string | null;
|
|
882
924
|
}> {
|
|
883
|
-
if (!config
|
|
925
|
+
if (!isV2InjectionEngineActive(config)) {
|
|
884
926
|
return { routed: false, runMessages: messages, injectedBlockText: null };
|
|
885
927
|
}
|
|
886
928
|
|
|
@@ -991,12 +1033,18 @@ export function countMemoryPrefixBlocks(content: ContentBlock[]): number {
|
|
|
991
1033
|
* `reinjectCachedMemory` is idempotent — no duplicate images after compaction.
|
|
992
1034
|
*/
|
|
993
1035
|
export function stripExistingMemoryInjections(messages: Message[]): Message[] {
|
|
994
|
-
if (messages.length === 0)
|
|
1036
|
+
if (messages.length === 0) {
|
|
1037
|
+
return messages;
|
|
1038
|
+
}
|
|
995
1039
|
const last = messages[messages.length - 1];
|
|
996
|
-
if (!last || last.role !== "user")
|
|
1040
|
+
if (!last || last.role !== "user") {
|
|
1041
|
+
return messages;
|
|
1042
|
+
}
|
|
997
1043
|
|
|
998
1044
|
const stripped = stripMemoryPrefixFromUserMessage(last);
|
|
999
|
-
if (stripped === last)
|
|
1045
|
+
if (stripped === last) {
|
|
1046
|
+
return messages;
|
|
1047
|
+
}
|
|
1000
1048
|
|
|
1001
1049
|
return [...messages.slice(0, -1), stripped];
|
|
1002
1050
|
}
|
|
@@ -1011,9 +1059,13 @@ export function stripExistingMemoryInjections(messages: Message[]): Message[] {
|
|
|
1011
1059
|
* assembly strips only the TAIL's fresh v2 prefix when v3 supersedes it.
|
|
1012
1060
|
*/
|
|
1013
1061
|
function stripMemoryPrefixFromUserMessage(message: Message): Message {
|
|
1014
|
-
if (message.role !== "user")
|
|
1062
|
+
if (message.role !== "user") {
|
|
1063
|
+
return message;
|
|
1064
|
+
}
|
|
1015
1065
|
const firstNonMemory = countMemoryPrefixBlocks(message.content);
|
|
1016
|
-
if (firstNonMemory === 0)
|
|
1066
|
+
if (firstNonMemory === 0) {
|
|
1067
|
+
return message;
|
|
1068
|
+
}
|
|
1017
1069
|
return { ...message, content: message.content.slice(firstNonMemory) };
|
|
1018
1070
|
}
|
|
1019
1071
|
|
|
@@ -1024,21 +1076,31 @@ function stripMemoryPrefixFromUserMessage(message: Message): Message {
|
|
|
1024
1076
|
* rendering) that otherwise discard the prepended content.
|
|
1025
1077
|
*/
|
|
1026
1078
|
export function extractMemoryPrefixBlocks(messages: Message[]): ContentBlock[] {
|
|
1027
|
-
if (messages.length === 0)
|
|
1079
|
+
if (messages.length === 0) {
|
|
1080
|
+
return [];
|
|
1081
|
+
}
|
|
1028
1082
|
const last = messages[messages.length - 1];
|
|
1029
|
-
if (!last || last.role !== "user")
|
|
1083
|
+
if (!last || last.role !== "user") {
|
|
1084
|
+
return [];
|
|
1085
|
+
}
|
|
1030
1086
|
const count = countMemoryPrefixBlocks(last.content);
|
|
1031
1087
|
return count === 0 ? [] : last.content.slice(0, count);
|
|
1032
1088
|
}
|
|
1033
1089
|
|
|
1034
1090
|
function injectTextBlock(messages: Message[], text: string): Message[] {
|
|
1035
|
-
if (text.trim().length === 0)
|
|
1036
|
-
|
|
1091
|
+
if (text.trim().length === 0) {
|
|
1092
|
+
return messages;
|
|
1093
|
+
}
|
|
1094
|
+
if (messages.length === 0) {
|
|
1095
|
+
return messages;
|
|
1096
|
+
}
|
|
1037
1097
|
// Strip existing memory blocks from the last user message first to prevent
|
|
1038
1098
|
// duplicates when the message was loaded from DB with a persisted block.
|
|
1039
1099
|
const cleaned = stripExistingMemoryInjections(messages);
|
|
1040
1100
|
const userTail = cleaned[cleaned.length - 1];
|
|
1041
|
-
if (!userTail || userTail.role !== "user")
|
|
1101
|
+
if (!userTail || userTail.role !== "user") {
|
|
1102
|
+
return messages;
|
|
1103
|
+
}
|
|
1042
1104
|
return [
|
|
1043
1105
|
...cleaned.slice(0, -1),
|
|
1044
1106
|
{
|
|
@@ -1059,13 +1121,19 @@ function injectMemoryBlock(
|
|
|
1059
1121
|
text: string,
|
|
1060
1122
|
images: Map<string, ResolvedImage>,
|
|
1061
1123
|
): Message[] {
|
|
1062
|
-
if (text.trim().length === 0 && images.size === 0)
|
|
1063
|
-
|
|
1124
|
+
if (text.trim().length === 0 && images.size === 0) {
|
|
1125
|
+
return messages;
|
|
1126
|
+
}
|
|
1127
|
+
if (messages.length === 0) {
|
|
1128
|
+
return messages;
|
|
1129
|
+
}
|
|
1064
1130
|
// Strip existing memory blocks from the last user message first to prevent
|
|
1065
1131
|
// duplicates when the message was loaded from DB with a persisted block.
|
|
1066
1132
|
const cleaned = stripExistingMemoryInjections(messages);
|
|
1067
1133
|
const userTail = cleaned[cleaned.length - 1];
|
|
1068
|
-
if (!userTail || userTail.role !== "user")
|
|
1134
|
+
if (!userTail || userTail.role !== "user") {
|
|
1135
|
+
return messages;
|
|
1136
|
+
}
|
|
1069
1137
|
|
|
1070
1138
|
const blocks: ContentBlock[] = [];
|
|
1071
1139
|
|
|
@@ -1106,7 +1174,9 @@ function injectMemoryBlock(
|
|
|
1106
1174
|
*/
|
|
1107
1175
|
function extractUserText(message: Message): string | null {
|
|
1108
1176
|
const joined = readRawUserText(message);
|
|
1109
|
-
if (!joined)
|
|
1177
|
+
if (!joined) {
|
|
1178
|
+
return null;
|
|
1179
|
+
}
|
|
1110
1180
|
return joined.length > 10 ? joined : null;
|
|
1111
1181
|
}
|
|
1112
1182
|
|
|
@@ -1117,12 +1187,16 @@ function extractUserText(message: Message): string | null {
|
|
|
1117
1187
|
* v1 needs would unnecessarily starve v2 on short greetings.
|
|
1118
1188
|
*/
|
|
1119
1189
|
function readRawUserText(message: Message | undefined): string | null {
|
|
1120
|
-
if (!message)
|
|
1190
|
+
if (!message) {
|
|
1191
|
+
return null;
|
|
1192
|
+
}
|
|
1121
1193
|
const texts = message.content
|
|
1122
1194
|
.filter((b): b is Extract<typeof b, { type: "text" }> => b.type === "text")
|
|
1123
1195
|
.map((b) => b.text.trim())
|
|
1124
1196
|
.filter((t) => t.length > 0);
|
|
1125
|
-
if (texts.length === 0)
|
|
1197
|
+
if (texts.length === 0) {
|
|
1198
|
+
return null;
|
|
1199
|
+
}
|
|
1126
1200
|
return texts.join(" ");
|
|
1127
1201
|
}
|
|
1128
1202
|
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
// ---------------------------------------------------------------------------
|
|
2
|
-
// Memory Graph —
|
|
2
|
+
// Memory Graph — node/trigger embedding plumbing (all tiers)
|
|
3
|
+
//
|
|
4
|
+
// Capability seeding writes graph nodes on every tier, so the
|
|
5
|
+
// `embed_graph_node` and `graph_trigger_embed` jobs handled here run under
|
|
6
|
+
// the substrate too. The v1 hybrid node SEARCH path lives in
|
|
7
|
+
// `../v1/graph/graph-search.ts`.
|
|
3
8
|
// ---------------------------------------------------------------------------
|
|
4
9
|
|
|
5
10
|
import {
|
|
@@ -7,17 +12,8 @@ import {
|
|
|
7
12
|
selectedBackendSupportsMultimodal,
|
|
8
13
|
} from "@vellumai/plugin-api";
|
|
9
14
|
|
|
10
|
-
import { getConfig } from "../../../../config/loader.js";
|
|
11
|
-
import { usesConceptPageMemory } from "../../../../config/memory-v3-gate.js";
|
|
12
15
|
import type { AssistantConfig } from "../../../../config/types.js";
|
|
13
16
|
import type { EmbeddingInput } from "../../../../persistence/embeddings/embedding-types.js";
|
|
14
|
-
import { isQdrantBreakerOpen } from "../../../../persistence/embeddings/qdrant-circuit-breaker.js";
|
|
15
|
-
import { withQdrantBreaker } from "../../../../persistence/embeddings/qdrant-circuit-breaker.js";
|
|
16
|
-
import {
|
|
17
|
-
getQdrantClient,
|
|
18
|
-
type QdrantSearchResult,
|
|
19
|
-
type QdrantSparseVector,
|
|
20
|
-
} from "../../../../persistence/embeddings/qdrant-client.js";
|
|
21
17
|
import { asString } from "../../../../persistence/job-utils.js";
|
|
22
18
|
import {
|
|
23
19
|
enqueueMemoryJob,
|
|
@@ -31,114 +27,6 @@ import type { MemoryNode } from "./types.js";
|
|
|
31
27
|
|
|
32
28
|
const log = getLogger("graph-search");
|
|
33
29
|
|
|
34
|
-
// ---------------------------------------------------------------------------
|
|
35
|
-
// Search
|
|
36
|
-
// ---------------------------------------------------------------------------
|
|
37
|
-
|
|
38
|
-
export interface GraphSearchResult {
|
|
39
|
-
nodeId: string;
|
|
40
|
-
score: number;
|
|
41
|
-
text: string;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Semantic search across graph nodes in Qdrant. Returns scored node IDs
|
|
46
|
-
* that the caller can hydrate from the graph store.
|
|
47
|
-
*
|
|
48
|
-
* Filters to `target_type: "graph_node"`.
|
|
49
|
-
*/
|
|
50
|
-
export async function searchGraphNodes(
|
|
51
|
-
queryVector: number[],
|
|
52
|
-
limit: number,
|
|
53
|
-
sparseVector?: QdrantSparseVector,
|
|
54
|
-
dateRange?: { afterMs?: number; beforeMs?: number },
|
|
55
|
-
): Promise<GraphSearchResult[]> {
|
|
56
|
-
// Concept-page memory owns the read path when active. The v1 `memory`
|
|
57
|
-
// collection is in active retirement and a corrupted sparse segment can
|
|
58
|
-
// OOM-crash the shared Qdrant process — short-circuiting here keeps v1
|
|
59
|
-
// background work and stale callers from taking it down.
|
|
60
|
-
if (usesConceptPageMemory(getConfig().memory)) {
|
|
61
|
-
return [];
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
if (isQdrantBreakerOpen()) {
|
|
65
|
-
log.warn("Qdrant circuit breaker open, skipping graph search");
|
|
66
|
-
return [];
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
const client = getQdrantClient();
|
|
70
|
-
|
|
71
|
-
const mustNot: Record<string, unknown>[] = [
|
|
72
|
-
{ key: "_meta", match: { value: true } },
|
|
73
|
-
];
|
|
74
|
-
|
|
75
|
-
// Use hybrid search (dense + sparse with RRF fusion) when a non-empty
|
|
76
|
-
// sparse vector is available; otherwise fall back to dense-only search.
|
|
77
|
-
if (sparseVector && sparseVector.indices.length > 0) {
|
|
78
|
-
const must: Record<string, unknown>[] = [
|
|
79
|
-
{ key: "target_type", match: { value: "graph_node" } },
|
|
80
|
-
];
|
|
81
|
-
if (dateRange?.afterMs != null) {
|
|
82
|
-
must.push({ key: "created_at", range: { gte: dateRange.afterMs } });
|
|
83
|
-
}
|
|
84
|
-
if (dateRange?.beforeMs != null) {
|
|
85
|
-
must.push({ key: "created_at", range: { lte: dateRange.beforeMs } });
|
|
86
|
-
}
|
|
87
|
-
const filter = { must, must_not: mustNot };
|
|
88
|
-
|
|
89
|
-
// RRF fuses per-modality top-N. A small prefetch (e.g. limit*3) silently
|
|
90
|
-
// truncates good matches when the query is wordy or low-similarity, so
|
|
91
|
-
// give RRF a meaningful candidate window with a generous floor.
|
|
92
|
-
const prefetchLimit = Math.max(limit * 10, 200);
|
|
93
|
-
|
|
94
|
-
const results: QdrantSearchResult[] = await withQdrantBreaker(() =>
|
|
95
|
-
client.hybridSearch({
|
|
96
|
-
denseVector: queryVector,
|
|
97
|
-
sparseVector,
|
|
98
|
-
filter,
|
|
99
|
-
limit,
|
|
100
|
-
prefetchLimit,
|
|
101
|
-
}),
|
|
102
|
-
);
|
|
103
|
-
|
|
104
|
-
return results.map((r) => ({
|
|
105
|
-
nodeId: r.payload.target_id,
|
|
106
|
-
score: r.score,
|
|
107
|
-
text: r.payload.text,
|
|
108
|
-
}));
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// Dense-only fallback
|
|
112
|
-
const denseMusts: Record<string, unknown>[] = [
|
|
113
|
-
{
|
|
114
|
-
key: "target_type",
|
|
115
|
-
match: { value: "graph_node" },
|
|
116
|
-
},
|
|
117
|
-
];
|
|
118
|
-
|
|
119
|
-
if (dateRange?.afterMs != null) {
|
|
120
|
-
denseMusts.push({ key: "created_at", range: { gte: dateRange.afterMs } });
|
|
121
|
-
}
|
|
122
|
-
if (dateRange?.beforeMs != null) {
|
|
123
|
-
denseMusts.push({ key: "created_at", range: { lte: dateRange.beforeMs } });
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
const filter: Record<string, unknown> = {
|
|
127
|
-
must: denseMusts,
|
|
128
|
-
must_not: mustNot,
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
const results: QdrantSearchResult[] = await withQdrantBreaker(async () => {
|
|
132
|
-
return client.search(queryVector, limit, filter);
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
return results.map((r) => ({
|
|
136
|
-
nodeId: r.payload.target_id,
|
|
137
|
-
score: r.score,
|
|
138
|
-
text: r.payload.text,
|
|
139
|
-
}));
|
|
140
|
-
}
|
|
141
|
-
|
|
142
30
|
// ---------------------------------------------------------------------------
|
|
143
31
|
// Embedding job
|
|
144
32
|
// ---------------------------------------------------------------------------
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
|
|
3
|
+
import { InContextTracker } from "./in-context-tracker.js";
|
|
4
|
+
import type { MemoryNode, ScoredNode } from "./types.js";
|
|
5
|
+
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
// Helpers
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
|
|
10
|
+
const DAY_MS = 1000 * 60 * 60 * 24;
|
|
11
|
+
|
|
12
|
+
function makeNode(overrides: Partial<MemoryNode> = {}): MemoryNode {
|
|
13
|
+
return {
|
|
14
|
+
id: "node-1",
|
|
15
|
+
content: "Test memory content.",
|
|
16
|
+
type: "episodic",
|
|
17
|
+
created: Date.now() - 5 * DAY_MS,
|
|
18
|
+
lastAccessed: Date.now(),
|
|
19
|
+
lastConsolidated: Date.now(),
|
|
20
|
+
eventDate: null,
|
|
21
|
+
emotionalCharge: {
|
|
22
|
+
valence: 0,
|
|
23
|
+
intensity: 0,
|
|
24
|
+
decayCurve: "linear",
|
|
25
|
+
decayRate: 0.05,
|
|
26
|
+
originalIntensity: 0,
|
|
27
|
+
},
|
|
28
|
+
fidelity: "vivid",
|
|
29
|
+
confidence: 0.8,
|
|
30
|
+
significance: 0.5,
|
|
31
|
+
stability: 14,
|
|
32
|
+
reinforcementCount: 0,
|
|
33
|
+
lastReinforced: Date.now(),
|
|
34
|
+
sourceConversations: ["conv-1"],
|
|
35
|
+
sourceType: "direct",
|
|
36
|
+
narrativeRole: null,
|
|
37
|
+
partOfStory: null,
|
|
38
|
+
imageRefs: null,
|
|
39
|
+
...overrides,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function makeScored(nodeOverrides: Partial<MemoryNode> = {}): ScoredNode {
|
|
44
|
+
return {
|
|
45
|
+
node: makeNode(nodeOverrides),
|
|
46
|
+
score: 0.5,
|
|
47
|
+
scoreBreakdown: {
|
|
48
|
+
semanticSimilarity: 0.5,
|
|
49
|
+
effectiveSignificance: 0.5,
|
|
50
|
+
emotionalIntensity: 0,
|
|
51
|
+
temporalBoost: 0,
|
|
52
|
+
recencyBoost: 0.5,
|
|
53
|
+
triggerBoost: 0,
|
|
54
|
+
activationBoost: 0,
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// ---------------------------------------------------------------------------
|
|
60
|
+
// InContextTracker
|
|
61
|
+
// ---------------------------------------------------------------------------
|
|
62
|
+
|
|
63
|
+
describe("InContextTracker", () => {
|
|
64
|
+
test("tracks added node IDs", () => {
|
|
65
|
+
const tracker = new InContextTracker();
|
|
66
|
+
tracker.add(["a", "b"]);
|
|
67
|
+
expect(tracker.isInContext("a")).toBe(true);
|
|
68
|
+
expect(tracker.isInContext("b")).toBe(true);
|
|
69
|
+
expect(tracker.isInContext("c")).toBe(false);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
test("filters out nodes already in context", () => {
|
|
73
|
+
const tracker = new InContextTracker();
|
|
74
|
+
tracker.add(["a"]);
|
|
75
|
+
|
|
76
|
+
const candidates: ScoredNode[] = [
|
|
77
|
+
makeScored({ id: "a" }),
|
|
78
|
+
makeScored({ id: "b" }),
|
|
79
|
+
makeScored({ id: "c" }),
|
|
80
|
+
];
|
|
81
|
+
const filtered = tracker.filterNew(candidates);
|
|
82
|
+
expect(filtered).toHaveLength(2);
|
|
83
|
+
expect(filtered.map((c) => c.node.id)).toEqual(["b", "c"]);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
test("advances turn counter", () => {
|
|
87
|
+
const tracker = new InContextTracker();
|
|
88
|
+
expect(tracker.getTurn()).toBe(0);
|
|
89
|
+
tracker.advanceTurn();
|
|
90
|
+
expect(tracker.getTurn()).toBe(1);
|
|
91
|
+
tracker.advanceTurn();
|
|
92
|
+
expect(tracker.getTurn()).toBe(2);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
test("records injection log with turn numbers", () => {
|
|
96
|
+
const tracker = new InContextTracker();
|
|
97
|
+
tracker.add(["a"]);
|
|
98
|
+
tracker.advanceTurn();
|
|
99
|
+
tracker.add(["b"]);
|
|
100
|
+
|
|
101
|
+
const log = tracker.getLog();
|
|
102
|
+
expect(log).toHaveLength(2);
|
|
103
|
+
expect(log[0]).toEqual({ nodeId: "a", turn: 0 });
|
|
104
|
+
expect(log[1]).toEqual({ nodeId: "b", turn: 1 });
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
test("returns all active node IDs", () => {
|
|
108
|
+
const tracker = new InContextTracker();
|
|
109
|
+
tracker.add(["a", "b"]);
|
|
110
|
+
tracker.advanceTurn();
|
|
111
|
+
tracker.add(["c"]);
|
|
112
|
+
|
|
113
|
+
const active = tracker.getActiveNodeIds();
|
|
114
|
+
expect(active.sort()).toEqual(["a", "b", "c"]);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
test("evicts compacted turns", () => {
|
|
118
|
+
const tracker = new InContextTracker();
|
|
119
|
+
tracker.add(["a"]);
|
|
120
|
+
tracker.advanceTurn();
|
|
121
|
+
tracker.add(["b"]);
|
|
122
|
+
tracker.advanceTurn();
|
|
123
|
+
tracker.add(["c"]);
|
|
124
|
+
|
|
125
|
+
// Evict turns 0 and 1
|
|
126
|
+
tracker.evictCompactedTurns(1);
|
|
127
|
+
|
|
128
|
+
expect(tracker.isInContext("a")).toBe(false);
|
|
129
|
+
expect(tracker.isInContext("b")).toBe(false);
|
|
130
|
+
expect(tracker.isInContext("c")).toBe(true);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
test("keeps nodes that appear in both compacted and non-compacted turns", () => {
|
|
134
|
+
const tracker = new InContextTracker();
|
|
135
|
+
tracker.add(["a"]);
|
|
136
|
+
tracker.advanceTurn();
|
|
137
|
+
tracker.add(["a"]); // same node re-injected in turn 1
|
|
138
|
+
|
|
139
|
+
// Evict turn 0 only
|
|
140
|
+
tracker.evictCompactedTurns(0);
|
|
141
|
+
|
|
142
|
+
// "a" should still be in context because it was also injected in turn 1
|
|
143
|
+
expect(tracker.isInContext("a")).toBe(true);
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
test("eviction cleans up log entries", () => {
|
|
147
|
+
const tracker = new InContextTracker();
|
|
148
|
+
tracker.add(["a"]);
|
|
149
|
+
tracker.advanceTurn();
|
|
150
|
+
tracker.add(["b"]);
|
|
151
|
+
|
|
152
|
+
tracker.evictCompactedTurns(0);
|
|
153
|
+
|
|
154
|
+
const log = tracker.getLog();
|
|
155
|
+
expect(log).toHaveLength(1);
|
|
156
|
+
expect(log[0].nodeId).toBe("b");
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
test("evicting with upToTurn=0 only evicts turn 0", () => {
|
|
160
|
+
const tracker = new InContextTracker();
|
|
161
|
+
tracker.add(["a"]);
|
|
162
|
+
tracker.advanceTurn();
|
|
163
|
+
tracker.add(["b"]);
|
|
164
|
+
tracker.advanceTurn();
|
|
165
|
+
tracker.add(["c"]);
|
|
166
|
+
|
|
167
|
+
tracker.evictCompactedTurns(0);
|
|
168
|
+
|
|
169
|
+
expect(tracker.isInContext("a")).toBe(false);
|
|
170
|
+
expect(tracker.isInContext("b")).toBe(true);
|
|
171
|
+
expect(tracker.isInContext("c")).toBe(true);
|
|
172
|
+
});
|
|
173
|
+
});
|