@vellumai/assistant 0.8.3 → 0.8.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +2 -2
- package/docker-entrypoint.sh +0 -1
- package/docs/browser-use-architecture-phase2.md +1 -1
- package/knip.json +2 -1
- package/node_modules/@vellumai/gateway-client/src/types.ts +2 -0
- package/openapi.yaml +1492 -100
- package/package.json +1 -1
- package/src/__tests__/agent-loop-exit-reason.test.ts +4 -5
- package/src/__tests__/agent-loop-override-profile.test.ts +1 -1
- package/src/__tests__/agent-loop.test.ts +88 -3
- package/src/__tests__/anthropic-provider.test.ts +302 -33
- package/src/__tests__/approval-cascade.test.ts +1 -1
- package/src/__tests__/assistant-event-hub-self-exclusion.test.ts +293 -0
- package/src/__tests__/assistant-feature-flags-integration.test.ts +3 -3
- package/src/__tests__/audit-log-rotation.test.ts +70 -16
- package/src/__tests__/background-workers-disk-pressure.test.ts +4 -3
- package/src/__tests__/btw-routes.test.ts +2 -3
- package/src/__tests__/call-controller.test.ts +0 -1
- package/src/__tests__/cancel-resolves-conversation-key.test.ts +1 -1
- package/src/__tests__/channel-delivery-store.test.ts +193 -0
- package/src/__tests__/channel-guardian.test.ts +3 -3
- package/src/__tests__/channel-reply-delivery.test.ts +284 -5
- package/src/__tests__/channel-retry-sweep.test.ts +274 -1
- package/src/__tests__/checker.test.ts +6 -15
- package/src/__tests__/compaction-events.test.ts +2 -1
- package/src/__tests__/compactor-call-site-logging.test.ts +214 -0
- package/src/__tests__/compactor-preserved-tail-count.test.ts +110 -0
- package/src/__tests__/computer-use-skill-manifest-regression.test.ts +5 -11
- package/src/__tests__/computer-use-tools.test.ts +2 -4
- package/src/__tests__/config-watcher.test.ts +1 -1
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +0 -1
- package/src/__tests__/context-token-estimator.test.ts +91 -1
- package/src/__tests__/conversation-abort-tool-results.test.ts +1 -1
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +1 -1
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +55 -4
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +228 -8
- package/src/__tests__/conversation-agent-loop.test.ts +188 -129
- package/src/__tests__/conversation-app-control-instantiation.test.ts +2 -5
- package/src/__tests__/conversation-app-control-lifecycle.test.ts +1 -1
- package/src/__tests__/conversation-clean-command.test.ts +137 -0
- package/src/__tests__/conversation-clear-safety.test.ts +25 -25
- package/src/__tests__/conversation-confirmation-signals.test.ts +1 -1
- package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +1 -1
- package/src/__tests__/conversation-disk-view-integration.test.ts +2 -2
- package/src/__tests__/conversation-error.test.ts +31 -0
- package/src/__tests__/conversation-fork-crud.test.ts +324 -0
- package/src/__tests__/conversation-lifecycle.test.ts +53 -12
- package/src/__tests__/conversation-load-history-repair.test.ts +1 -1
- package/src/__tests__/conversation-load-history-stripped.test.ts +279 -0
- package/src/__tests__/conversation-pairing.test.ts +2 -2
- package/src/__tests__/conversation-process-callsite.test.ts +1 -1
- package/src/__tests__/conversation-provider-retry-repair.test.ts +2 -1
- package/src/__tests__/conversation-queue.test.ts +1 -1
- package/src/__tests__/conversation-routes-disk-view.test.ts +109 -0
- package/src/__tests__/conversation-routes-slash-commands.test.ts +35 -0
- package/src/__tests__/conversation-runtime-assembly.test.ts +264 -81
- package/src/__tests__/conversation-seed-composer.test.ts +66 -4
- package/src/__tests__/conversation-skill-tools.test.ts +2 -5
- package/src/__tests__/conversation-slash-commands.test.ts +36 -8
- package/src/__tests__/conversation-slash-queue.test.ts +1 -1
- package/src/__tests__/conversation-slash-unknown.test.ts +1 -1
- package/src/__tests__/conversation-speed-override.test.ts +1 -1
- package/src/__tests__/conversation-store.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +220 -0
- package/src/__tests__/conversation-sync-tags.test.ts +99 -32
- package/src/__tests__/conversation-workspace-cache-state.test.ts +2 -1
- package/src/__tests__/conversation-workspace-injection.test.ts +5 -1
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +5 -1
- package/src/__tests__/credential-execution-feature-gates.test.ts +9 -7
- package/src/__tests__/credential-execution-tools.test.ts +6 -6
- package/src/__tests__/credential-security-invariants.test.ts +7 -0
- package/src/__tests__/credential-vault-unit.test.ts +2 -2
- package/src/__tests__/cu-unified-flow.test.ts +10 -1
- package/src/__tests__/dm-backfill.test.ts +64 -0
- package/src/__tests__/dm-persistence.test.ts +33 -0
- package/src/__tests__/document-find-replace.test.ts +501 -0
- package/src/__tests__/dynamic-page-surface.test.ts +2 -2
- package/src/__tests__/email-html-renderer.test.ts +12 -0
- package/src/__tests__/first-greeting.test.ts +23 -2
- package/src/__tests__/gateway-flag-listener.test.ts +237 -0
- package/src/__tests__/gemini-provider.test.ts +78 -0
- package/src/__tests__/guardian-dispatch.test.ts +0 -1
- package/src/__tests__/guardian-outbound-http.test.ts +7 -5
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +1 -1
- package/src/__tests__/headless-browser-navigate.test.ts +172 -0
- package/src/__tests__/heartbeat-disk-pressure.test.ts +4 -0
- package/src/__tests__/heartbeat-service.test.ts +4 -0
- package/src/__tests__/host-bash-proxy.test.ts +6 -0
- package/src/__tests__/host-browser-proxy.test.ts +10 -0
- package/src/__tests__/host-cu-proxy.test.ts +8 -1
- package/src/__tests__/host-file-proxy.test.ts +8 -1
- package/src/__tests__/host-shell-tool.test.ts +1 -1
- package/src/__tests__/host-transfer-proxy.test.ts +8 -1
- package/src/__tests__/identity-routes.test.ts +57 -0
- package/src/__tests__/inbound-slack-persistence.test.ts +3 -0
- package/src/__tests__/init-feature-flag-overrides.test.ts +5 -6
- package/src/__tests__/injector-chain.test.ts +2 -0
- package/src/__tests__/injector-document-comments.test.ts +378 -0
- package/src/__tests__/injector-pkb-v2-silenced.test.ts +4 -25
- package/src/__tests__/list-messages-attachments.test.ts +21 -17
- package/src/__tests__/list-messages-hidden-metadata.test.ts +217 -0
- package/src/__tests__/list-messages-page-latest.test.ts +130 -14
- package/src/__tests__/list-messages-tool-merge.test.ts +77 -17
- package/src/__tests__/llm-context-normalization.test.ts +0 -2
- package/src/__tests__/llm-request-log-call-site.test.ts +136 -0
- package/src/__tests__/llm-request-log-source-clickhouse.test.ts +26 -0
- package/src/__tests__/llm-resolver.test.ts +161 -9
- package/src/__tests__/llm-usage-store.test.ts +66 -0
- package/src/__tests__/log-export-routes.test.ts +99 -2
- package/src/__tests__/logger.test.ts +89 -0
- package/src/__tests__/mcp-abort-signal.test.ts +2 -2
- package/src/__tests__/media-generate-image.test.ts +31 -0
- package/src/__tests__/memory-v2-static-injector.test.ts +7 -7
- package/src/__tests__/message-queue-steer.test.ts +114 -0
- package/src/__tests__/model-intents.test.ts +2 -4
- package/src/__tests__/notification-guardian-path.test.ts +0 -1
- package/src/__tests__/onboarding-template-contract.test.ts +1 -1
- package/src/__tests__/openai-provider.test.ts +151 -0
- package/src/__tests__/openai-responses-provider.test.ts +118 -16
- package/src/__tests__/outbound-slack-persistence.test.ts +187 -20
- package/src/__tests__/pending-interactions-resolved-event.test.ts +189 -0
- package/src/__tests__/platform-bash-auto-approve.test.ts +2 -2
- package/src/__tests__/platform.test.ts +2 -5
- package/src/__tests__/plugin-api-tool-definition.test.ts +92 -0
- package/src/__tests__/plugin-bootstrap.test.ts +2 -2
- package/src/__tests__/plugin-source-watcher.test.ts +302 -0
- package/src/__tests__/plugin-tool-contribution.test.ts +13 -6
- package/src/__tests__/plugin-types.test.ts +3 -2
- package/src/__tests__/prechat-onboarding-contract.test.ts +131 -98
- package/src/__tests__/pricing.test.ts +12 -0
- package/src/__tests__/process-message-background-slack.test.ts +1 -51
- package/src/__tests__/process-message-display-content.test.ts +21 -16
- package/src/__tests__/prune-jobs-changes-parser.test.ts +61 -0
- package/src/__tests__/registry.test.ts +2 -8
- package/src/__tests__/require-fresh-approval.test.ts +2 -2
- package/src/__tests__/runtime-events-sse-bilingual.test.ts +154 -0
- package/src/__tests__/server-history-render.test.ts +83 -4
- package/src/__tests__/shell-tool-proxy-mode.test.ts +1 -1
- package/src/__tests__/skill-feature-flags.test.ts +2 -2
- package/src/__tests__/skill-projection-feature-flag.test.ts +4 -7
- package/src/__tests__/skill-projection.benchmark.test.ts +2 -6
- package/src/__tests__/skill-tool-factory.test.ts +1 -1
- package/src/__tests__/steer-tool-repair.test.ts +249 -0
- package/src/__tests__/subagent-notify-parent.test.ts +1 -1
- package/src/__tests__/suggestion-routes.test.ts +1 -0
- package/src/__tests__/sync-message-contract.test.ts +59 -0
- package/src/__tests__/system-prompt.test.ts +161 -124
- package/src/__tests__/terminal-tools.test.ts +12 -2
- package/src/__tests__/thinking-block-replay.test.ts +113 -0
- package/src/__tests__/thread-backfill.test.ts +370 -22
- package/src/__tests__/tool-approval-handler.test.ts +1 -5
- package/src/__tests__/tool-execute-pipeline.test.ts +2 -2
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +2 -5
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +15 -5
- package/src/__tests__/tool-executor.test.ts +89 -53
- package/src/__tests__/tool-grant-request-escalation.test.ts +1 -6
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +167 -0
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +0 -1
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +1 -6
- package/src/__tests__/trusted-contact-multichannel.test.ts +0 -1
- package/src/__tests__/twilio-routes.test.ts +1 -1
- package/src/__tests__/ui-file-upload-surface.test.ts +2 -2
- package/src/__tests__/usage-routes.test.ts +3 -0
- package/src/__tests__/verification-control-plane-policy.test.ts +2 -2
- package/src/__tests__/web-fetch.test.ts +2 -2
- package/src/__tests__/workspace-git-service.test.ts +94 -10
- package/src/__tests__/workspace-migration-088-deprecate-background-conversation-override.test.ts +158 -0
- package/src/__tests__/workspace-migration-089-move-memory-tree-out-of-v3.test.ts +86 -0
- package/src/acp/__tests__/prepare-agent-env.test.ts +146 -0
- package/src/acp/prepare-agent-env.ts +78 -0
- package/src/acp/session-manager.ts +1 -1
- package/src/agent/attachments.ts +1 -0
- package/src/agent/loop.ts +65 -20
- package/src/api/README.md +5 -0
- package/src/api/index.ts +4 -0
- package/src/api/package.json +10 -0
- package/src/background-wake/background-wake-routes.test.ts +233 -0
- package/src/background-wake/next-wake.test.ts +289 -0
- package/src/background-wake/next-wake.ts +172 -0
- package/src/background-wake/runtime-registry.ts +24 -0
- package/src/browser/operations.ts +15 -0
- package/src/cli/commands/__tests__/browser.test.ts +23 -5
- package/src/cli/commands/__tests__/conversations-slack.test.ts +572 -0
- package/src/cli/commands/__tests__/domain-register.test.ts +110 -0
- package/src/cli/commands/__tests__/domain-status.test.ts +33 -33
- package/src/cli/commands/__tests__/inference-send.test.ts +108 -5
- package/src/cli/commands/__tests__/memory-v2-compare-render.test.ts +98 -0
- package/src/cli/commands/__tests__/memory-v2.test.ts +10 -12
- package/src/cli/commands/__tests__/memory-v3-render.test.ts +340 -0
- package/src/cli/commands/browser.ts +247 -0
- package/src/cli/commands/conversations.ts +128 -1
- package/src/cli/commands/domain.ts +91 -41
- package/src/cli/commands/inference-providers.ts +147 -1
- package/src/cli/commands/inference.ts +93 -40
- package/src/cli/commands/memory-v2-compare-render.ts +115 -0
- package/src/cli/commands/memory-v2.ts +483 -0
- package/src/cli/commands/memory-v3-render.ts +344 -0
- package/src/cli/commands/memory-v3.ts +316 -0
- package/src/cli/commands/notifications.ts +24 -2
- package/src/cli/program.ts +2 -0
- package/src/cli/utils/conversation-id.ts +17 -5
- package/src/config/assistant-feature-flags.ts +21 -9
- package/src/config/bundled-skills/app-builder/SKILL.md +2 -2
- package/src/config/bundled-skills/document-editor/SKILL.md +124 -0
- package/src/config/bundled-skills/document-editor/TOOLS.json +258 -0
- package/src/config/bundled-skills/document-editor/tools/comment-list.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/comment-reply.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/comment-resolve.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/document-find.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/document-open.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/document-replace-text.ts +12 -0
- package/src/config/bundled-skills/image-studio/SKILL.md +4 -0
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +2 -2
- package/src/config/bundled-skills/media-processing/SKILL.md +8 -0
- package/src/config/bundled-skills/media-processing/tools/ingest-media.ts +13 -8
- package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +10 -3
- package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +16 -14
- package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +7 -2
- package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +7 -2
- package/src/config/bundled-skills/schedule/SKILL.md +8 -0
- package/src/config/bundled-tool-registry.ts +24 -12
- package/src/config/call-site-defaults.ts +20 -0
- package/src/config/feature-flag-registry.json +115 -3
- package/src/config/llm-resolver.ts +16 -2
- package/src/config/schemas/__tests__/memory-v2.test.ts +217 -1
- package/src/config/schemas/call-site-catalog.ts +35 -0
- package/src/config/schemas/llm.ts +14 -0
- package/src/config/schemas/memory-v2.ts +294 -1
- package/src/config/schemas/memory.ts +2 -1
- package/src/context/compactor.ts +60 -1
- package/src/context/token-estimator.ts +47 -4
- package/src/context/window-manager.ts +25 -0
- package/src/conversations/__tests__/message-consolidation.test.ts +350 -0
- package/src/conversations/message-consolidation.ts +404 -0
- package/src/credential-health/credential-health-service.ts +34 -19
- package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +1 -1
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +66 -6
- package/src/daemon/__tests__/meet-manifest-loader.test.ts +1 -1
- package/src/daemon/__tests__/native-web-search-metadata.test.ts +357 -0
- package/src/daemon/__tests__/web-search-status-text.test.ts +287 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +155 -36
- package/src/daemon/conversation-agent-loop.ts +307 -88
- package/src/daemon/conversation-error.ts +31 -1
- package/src/daemon/conversation-lifecycle.ts +149 -118
- package/src/daemon/conversation-messaging.ts +3 -0
- package/src/daemon/conversation-process.ts +273 -0
- package/src/daemon/conversation-queue-manager.ts +14 -0
- package/src/daemon/conversation-runtime-assembly.ts +145 -84
- package/src/daemon/conversation-slash.ts +37 -5
- package/src/daemon/conversation-surfaces.ts +45 -2
- package/src/daemon/conversation-tool-setup.ts +70 -3
- package/src/daemon/conversation-usage.ts +2 -0
- package/src/daemon/conversation.ts +54 -32
- package/src/daemon/disk-pressure-guard.ts +14 -2
- package/src/daemon/first-greeting.ts +10 -0
- package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +498 -0
- package/src/daemon/handlers/config-a2a.ts +160 -0
- package/src/daemon/handlers/config-model.test.ts +2 -0
- package/src/daemon/handlers/conversations.ts +90 -3
- package/src/daemon/handlers/shared.ts +92 -29
- package/src/daemon/host-bash-proxy.ts +1 -1
- package/src/daemon/host-browser-proxy.ts +5 -5
- package/src/daemon/host-cu-proxy.ts +5 -5
- package/src/daemon/host-file-proxy.ts +5 -5
- package/src/daemon/host-proxy-base.ts +4 -4
- package/src/daemon/host-transfer-proxy.ts +11 -11
- package/src/daemon/lifecycle.ts +40 -23
- package/src/daemon/meet-manifest-loader.ts +1 -7
- package/src/daemon/message-protocol.ts +4 -0
- package/src/daemon/message-types/conversations.ts +14 -9
- package/src/daemon/message-types/document-comments.ts +50 -0
- package/src/daemon/message-types/home.ts +1 -13
- package/src/daemon/message-types/messages.ts +66 -7
- package/src/daemon/message-types/surfaces.ts +3 -1
- package/src/daemon/message-types/sync.ts +14 -0
- package/src/daemon/message-types/web-activity.ts +57 -0
- package/src/daemon/plugin-source-watcher.ts +135 -3
- package/src/daemon/process-message.ts +69 -12
- package/src/daemon/shutdown-handlers.ts +24 -5
- package/src/daemon/switch-inference-profile-tool.ts +52 -0
- package/src/daemon/tool-setup-types.ts +13 -0
- package/src/daemon/trust-context.ts +6 -0
- package/src/documents/document-comments-store.test.ts +338 -0
- package/src/documents/document-comments-store.ts +237 -0
- package/src/documents/document-store.ts +202 -0
- package/src/events/relationship-state-updated.ts +25 -0
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +1 -2
- package/src/heartbeat/heartbeat-service.ts +1 -0
- package/src/home/__tests__/suggested-prompts.test.ts +33 -2
- package/src/home/feed-types.ts +6 -1
- package/src/home/home-content-refresh.ts +52 -0
- package/src/home/home-greeting-cache.ts +69 -0
- package/src/home/home-greeting.ts +85 -0
- package/src/home/suggested-prompts.ts +168 -9
- package/src/ipc/gateway-flag-listener.ts +123 -0
- package/src/ipc/skill-routes/registries.ts +8 -12
- package/src/memory/__tests__/db-async-query.test.ts +165 -0
- package/src/memory/__tests__/db-maintenance.test.ts +115 -0
- package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +241 -0
- package/src/memory/__tests__/jobs-store-job-classes.test.ts +28 -1
- package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +135 -2
- package/src/memory/__tests__/memory-retrospective-job.test.ts +327 -6
- package/src/memory/auto-analysis-enqueue.ts +5 -1
- package/src/memory/conversation-crud.ts +191 -100
- package/src/memory/conversation-starters-cadence.ts +3 -1
- package/src/memory/conversation-title-service.ts +19 -3
- package/src/memory/db-async-query.ts +214 -0
- package/src/memory/db-init.ts +26 -0
- package/src/memory/db-maintenance.ts +30 -21
- package/src/memory/delivery-crud.ts +41 -0
- package/src/memory/delivery-status.ts +141 -15
- package/src/memory/external-conversation-store.ts +32 -1
- package/src/memory/graph/bootstrap.ts +8 -1
- package/src/memory/graph/capability-seed.ts +7 -3
- package/src/memory/graph/conversation-graph-memory.ts +100 -17
- package/src/memory/graph/extraction.ts +1 -5
- package/src/memory/graph/graph-search.ts +7 -1
- package/src/memory/indexer.ts +28 -18
- package/src/memory/job-handlers/cleanup.ts +76 -18
- package/src/memory/job-handlers/conversation-starters.ts +1 -4
- package/src/memory/jobs/embed-pkb-file.ts +6 -1
- package/src/memory/jobs-store.ts +14 -0
- package/src/memory/jobs-worker.ts +68 -15
- package/src/memory/llm-request-log-source-clickhouse.ts +42 -2
- package/src/memory/llm-request-log-source-local.ts +7 -0
- package/src/memory/llm-request-log-source.ts +9 -2
- package/src/memory/llm-request-log-store.ts +43 -1
- package/src/memory/llm-usage-store.ts +24 -0
- package/src/memory/memory-retrospective-constants.ts +28 -0
- package/src/memory/memory-retrospective-enqueue.ts +11 -3
- package/src/memory/memory-retrospective-job.ts +413 -18
- package/src/memory/memory-retrospective-startup-cleanup.ts +3 -3
- package/src/memory/memory-v2-activation-log-store.ts +41 -14
- package/src/memory/migrations/100-core-tables.ts +1 -0
- package/src/memory/migrations/109-external-conversation-bindings.ts +1 -0
- package/src/memory/migrations/253-conversation-last-notified-profile.ts +15 -0
- package/src/memory/migrations/253-document-comments.ts +47 -0
- package/src/memory/migrations/254-external-conversation-binding-chat-name.ts +43 -0
- package/src/memory/migrations/255-channel-inbound-delivery-attempts.ts +24 -0
- package/src/memory/migrations/256-memory-v2-injection-events.ts +113 -0
- package/src/memory/migrations/257-strip-base-url-non-openai-compatible.ts +22 -0
- package/src/memory/migrations/258-onboarding-events-prior-assistants.ts +13 -0
- package/src/memory/migrations/259-conversation-cleaned-at.ts +33 -0
- package/src/memory/migrations/260-rename-cleaned-at.ts +44 -0
- package/src/memory/migrations/261-llm-usage-add-raw-usage.ts +36 -0
- package/src/memory/migrations/262-memory-v3-coactivation.ts +57 -0
- package/src/memory/migrations/263-memory-v3-auto-edges.ts +50 -0
- package/src/memory/migrations/264-llm-request-log-call-site.ts +29 -0
- package/src/memory/migrations/index.ts +34 -0
- package/src/memory/migrations/registry.ts +58 -0
- package/src/memory/onboarding-events-store.ts +7 -0
- package/src/memory/schema/calls.ts +1 -0
- package/src/memory/schema/conversations.ts +3 -0
- package/src/memory/schema/infrastructure.ts +22 -0
- package/src/memory/tool-usage-store.ts +36 -8
- package/src/memory/v2/__tests__/consolidation-job.test.ts +1 -0
- package/src/memory/v2/__tests__/harness-compare.test.ts +186 -0
- package/src/memory/v2/__tests__/harness-metrics.test.ts +74 -0
- package/src/memory/v2/__tests__/harness-oracle.test.ts +257 -0
- package/src/memory/v2/__tests__/harness-replay-input.test.ts +225 -0
- package/src/memory/v2/__tests__/harness-runner.test.ts +109 -0
- package/src/memory/v2/__tests__/injection-events.test.ts +318 -0
- package/src/memory/v2/__tests__/injection.test.ts +158 -112
- package/src/memory/v2/__tests__/page-index.test.ts +365 -1
- package/src/memory/v2/__tests__/qdrant.test.ts +36 -0
- package/src/memory/v2/__tests__/router.test.ts +660 -4
- package/src/memory/v2/consolidation-job.ts +14 -0
- package/src/memory/v2/harness/compare.ts +57 -0
- package/src/memory/v2/harness/metrics.ts +124 -0
- package/src/memory/v2/harness/oracle.ts +145 -0
- package/src/memory/v2/harness/replay-input.ts +224 -0
- package/src/memory/v2/harness/retriever.ts +74 -0
- package/src/memory/v2/harness/router-retriever.ts +43 -0
- package/src/memory/v2/harness/runner.ts +106 -0
- package/src/memory/v2/harness/trace.ts +58 -0
- package/src/memory/v2/injection-events.ts +101 -0
- package/src/memory/v2/injection.ts +42 -25
- package/src/memory/v2/page-index.ts +209 -7
- package/src/memory/v2/page-store.ts +18 -0
- package/src/memory/v2/prompts/router.ts +26 -1
- package/src/memory/v2/qdrant.ts +14 -2
- package/src/memory/v2/router.ts +369 -62
- package/src/memory/v3/__tests__/coactivation-store.test.ts +422 -0
- package/src/memory/v3/__tests__/consolidation-job.test.ts +468 -0
- package/src/memory/v3/__tests__/edge-learning-job.test.ts +324 -0
- package/src/memory/v3/__tests__/edges.test.ts +563 -0
- package/src/memory/v3/__tests__/filter.test.ts +512 -0
- package/src/memory/v3/__tests__/gate.test.ts +574 -0
- package/src/memory/v3/__tests__/index-composition.test.ts +233 -0
- package/src/memory/v3/__tests__/loop.test.ts +530 -0
- package/src/memory/v3/__tests__/retriever.test.ts +226 -0
- package/src/memory/v3/__tests__/scouts.test.ts +440 -0
- package/src/memory/v3/__tests__/shadow-middleware.test.ts +312 -0
- package/src/memory/v3/__tests__/system-prompts.test.ts +154 -0
- package/src/memory/v3/__tests__/traversal.test.ts +469 -0
- package/src/memory/v3/__tests__/tree-index.test.ts +280 -0
- package/src/memory/v3/__tests__/tree-store.test.ts +529 -0
- package/src/memory/v3/__tests__/tree-walk.test.ts +707 -0
- package/src/memory/v3/__tests__/validate.test.ts +245 -0
- package/src/memory/v3/auto-edges.ts +223 -0
- package/src/memory/v3/coactivation-store.ts +124 -0
- package/src/memory/v3/consolidation-job.ts +323 -0
- package/src/memory/v3/edge-learning-job.ts +160 -0
- package/src/memory/v3/edges.ts +249 -0
- package/src/memory/v3/filter.ts +281 -0
- package/src/memory/v3/gate.ts +334 -0
- package/src/memory/v3/index-composition.ts +113 -0
- package/src/memory/v3/llm-capture.ts +46 -0
- package/src/memory/v3/loop.ts +382 -0
- package/src/memory/v3/maintenance.ts +144 -0
- package/src/memory/v3/prompt-context.ts +33 -0
- package/src/memory/v3/prompts/consolidation.ts +458 -0
- package/src/memory/v3/prompts/system-prompts.ts +196 -0
- package/src/memory/v3/retriever.ts +33 -0
- package/src/memory/v3/scouts.ts +420 -0
- package/src/memory/v3/shadow-middleware.ts +305 -0
- package/src/memory/v3/traversal.ts +206 -0
- package/src/memory/v3/tree-index.ts +237 -0
- package/src/memory/v3/tree-store.ts +394 -0
- package/src/memory/v3/tree-walk.ts +351 -0
- package/src/memory/v3/types.ts +65 -0
- package/src/memory/v3/validate.ts +300 -0
- package/src/messaging/providers/index.ts +7 -1
- package/src/messaging/providers/slack/__tests__/adapter-mention-rendering.test.ts +329 -3
- package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +34 -1
- package/src/messaging/providers/slack/adapter.ts +178 -25
- package/src/messaging/providers/slack/api.test.ts +54 -0
- package/src/messaging/providers/slack/api.ts +119 -3
- package/src/messaging/providers/slack/client.ts +12 -0
- package/src/messaging/providers/slack/deep-link.ts +20 -1
- package/src/messaging/providers/slack/message-metadata.test.ts +48 -0
- package/src/messaging/providers/slack/message-metadata.ts +156 -0
- package/src/messaging/providers/slack/render-transcript.test.ts +107 -75
- package/src/messaging/providers/slack/render-transcript.ts +176 -49
- package/src/messaging/providers/slack/send.test.ts +77 -0
- package/src/messaging/providers/slack/send.ts +8 -2
- package/src/messaging/providers/slack/types.ts +14 -0
- package/src/notifications/__tests__/emit-signal-home-feed.test.ts +4 -1
- package/src/notifications/__tests__/home-feed-side-effect.test.ts +116 -54
- package/src/notifications/adapters/macos.ts +18 -1
- package/src/notifications/adapters/platform.ts +1 -1
- package/src/notifications/conversation-seed-composer.ts +14 -2
- package/src/notifications/decision-engine.ts +1 -4
- package/src/notifications/deferred-emit.ts +135 -0
- package/src/notifications/emit-signal.ts +38 -50
- package/src/notifications/home-feed-side-effect.ts +60 -30
- package/src/oauth/connect-orchestrator.ts +3 -0
- package/src/oauth/credential-token-resolver.ts +2 -0
- package/src/oauth/manual-token-connection.ts +19 -0
- package/src/oauth/oauth-store.ts +12 -0
- package/src/oauth/seed-providers.ts +22 -0
- package/src/permissions/prompter.ts +8 -5
- package/src/permissions/question-prompter.ts +5 -2
- package/src/permissions/secret-prompter.ts +6 -3
- package/src/plugin-api/index.ts +4 -0
- package/src/plugin-api/types.ts +7 -33
- package/src/plugins/defaults/index.ts +6 -0
- package/src/plugins/defaults/injectors.ts +100 -20
- package/src/plugins/external-plugin-loader.ts +5 -68
- package/src/plugins/types.ts +11 -16
- package/src/proactive-artifact/aux-message-injector.ts +17 -4
- package/src/prompts/__tests__/system-prompt.test.ts +46 -2
- package/src/prompts/__tests__/task-progress-hint-section.test.ts +3 -9
- package/src/prompts/normalize-onboarding.ts +40 -0
- package/src/prompts/persona-resolver.ts +36 -21
- package/src/prompts/sections.ts +69 -19
- package/src/prompts/system-prompt.ts +118 -216
- package/src/prompts/template-detection.ts +37 -0
- package/src/prompts/templates/BOOTSTRAP-CONTENT-AUTOMATION.md +141 -0
- package/src/prompts/templates/BOOTSTRAP.md +10 -2
- package/src/prompts/templates/VOICE.md +3 -0
- package/src/prompts/templates/system-sections.ts +281 -9
- package/src/providers/__tests__/connection-model-compat.test.ts +234 -0
- package/src/providers/__tests__/retry-callsite.test.ts +85 -5
- package/src/providers/anthropic/client.ts +159 -66
- package/src/providers/call-site-routing.ts +14 -2
- package/src/providers/connection-model-compat.ts +38 -0
- package/src/providers/connection-resolution.ts +16 -2
- package/src/providers/fireworks/client.ts +20 -2
- package/src/providers/gemini/client.ts +49 -6
- package/src/providers/inference/__tests__/base-url-route-validation.test.ts +342 -0
- package/src/providers/inference/__tests__/base-url-security.test.ts +189 -0
- package/src/providers/inference/__tests__/codex-token-refresh.test.ts +254 -0
- package/src/providers/inference/adapter-factory.ts +18 -1
- package/src/providers/inference/auth.ts +3 -3
- package/src/providers/inference/codex-token-refresh.ts +128 -0
- package/src/providers/inference/resolve-auth.ts +49 -6
- package/src/providers/minimax/client.ts +106 -0
- package/src/providers/model-catalog.ts +91 -1
- package/src/providers/model-intents.ts +1 -1
- package/src/providers/openai/chat-completions-provider.ts +63 -23
- package/src/providers/openai/codex-models.ts +18 -0
- package/src/providers/openai/responses-provider.ts +86 -23
- package/src/providers/openrouter/client.ts +5 -1
- package/src/providers/provider-send-message.ts +7 -1
- package/src/providers/retry.ts +34 -3
- package/src/providers/thinking-config.ts +26 -1
- package/src/providers/types.ts +25 -0
- package/src/providers/usage-tracking.ts +2 -0
- package/src/runtime/AGENTS.md +2 -2
- package/src/runtime/__tests__/agent-wake.test.ts +214 -0
- package/src/runtime/__tests__/background-job-runner.test.ts +128 -0
- package/src/runtime/agent-wake.ts +152 -56
- package/src/runtime/assistant-event-hub.ts +76 -6
- package/src/runtime/auth/route-policy.ts +43 -3
- package/src/runtime/background-job-runner.ts +26 -0
- package/src/runtime/btw-sidechain.ts +0 -6
- package/src/runtime/channel-reply-delivery.ts +182 -47
- package/src/runtime/channel-retry-sweep.ts +141 -16
- package/src/runtime/http-types.ts +7 -6
- package/src/runtime/migrations/vbundle-builder.ts +10 -3
- package/src/runtime/pending-interactions.ts +50 -8
- package/src/runtime/routes/__tests__/content-source-routes.test.ts +162 -0
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +161 -1
- package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +14 -0
- package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +290 -0
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +512 -0
- package/src/runtime/routes/__tests__/sanity-routes.test.ts +280 -0
- package/src/runtime/routes/__tests__/slack-channel-routes.test.ts +266 -0
- package/src/runtime/routes/acp-routes.test.ts +255 -6
- package/src/runtime/routes/acp-routes.ts +8 -1
- package/src/runtime/routes/approval-routes.ts +4 -1
- package/src/runtime/routes/avatar-routes.ts +10 -10
- package/src/runtime/routes/background-wake-routes.ts +188 -0
- package/src/runtime/routes/browser-tabs-routes.ts +200 -0
- package/src/runtime/routes/btw-routes.ts +0 -6
- package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +246 -0
- package/src/runtime/routes/content-source-routes.ts +78 -0
- package/src/runtime/routes/conversation-cli-routes.ts +147 -2
- package/src/runtime/routes/conversation-list-routes.ts +12 -4
- package/src/runtime/routes/conversation-management-routes.ts +77 -20
- package/src/runtime/routes/conversation-query-routes.ts +196 -31
- package/src/runtime/routes/conversation-routes.ts +472 -425
- package/src/runtime/routes/conversation-starter-routes.ts +6 -3
- package/src/runtime/routes/disk-pressure-routes.ts +1 -1
- package/src/runtime/routes/document-comments-routes.ts +287 -0
- package/src/runtime/routes/documents-routes.ts +33 -0
- package/src/runtime/routes/domain-routes.ts +60 -10
- package/src/runtime/routes/email-routes.ts +5 -2
- package/src/runtime/routes/events-routes.ts +54 -10
- package/src/runtime/routes/group-routes.ts +24 -8
- package/src/runtime/routes/home-feed-routes.ts +6 -3
- package/src/runtime/routes/host-app-control-routes.ts +1 -1
- package/src/runtime/routes/host-browser-routes.ts +17 -2
- package/src/runtime/routes/host-cu-routes.ts +2 -2
- package/src/runtime/routes/identity-routes.ts +21 -0
- package/src/runtime/routes/inbound-message-handler.ts +288 -58
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +96 -3
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +365 -6
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +283 -82
- package/src/runtime/routes/index.ts +20 -4
- package/src/runtime/routes/inference-profile-session-handler.ts +22 -12
- package/src/runtime/routes/inference-profile-session-routes.ts +7 -1
- package/src/runtime/routes/inference-provider-connection-routes.ts +63 -7
- package/src/runtime/routes/integrations/a2a.ts +60 -1
- package/src/runtime/routes/llm-call-sites-routes.ts +32 -5
- package/src/runtime/routes/log-export-routes.ts +39 -0
- package/src/runtime/routes/memory-item-routes.ts +8 -3
- package/src/runtime/routes/memory-v2-routes.ts +427 -0
- package/src/runtime/routes/memory-v3-routes.ts +316 -0
- package/src/runtime/routes/migration-routes.ts +21 -24
- package/src/runtime/routes/notification-routes.ts +19 -2
- package/src/runtime/routes/plugins-routes.ts +337 -0
- package/src/runtime/routes/question-routes.ts +4 -1
- package/src/runtime/routes/rename-conversation-routes.ts +6 -2
- package/src/runtime/routes/sanity-routes.ts +159 -0
- package/src/runtime/routes/secret-routes.ts +25 -5
- package/src/runtime/routes/settings-routes.ts +12 -11
- package/src/runtime/routes/slack-channel-routes.ts +188 -0
- package/src/runtime/routes/workspace-routes.ts +25 -10
- package/src/runtime/services/conversation-serializer.ts +30 -4
- package/src/runtime/sync/resource-sync-events.ts +106 -38
- package/src/runtime/sync/sync-publisher.test.ts +49 -0
- package/src/runtime/sync/sync-publisher.ts +2 -1
- package/src/runtime/verification-outbound-actions.ts +73 -1
- package/src/schedule/integration-status.ts +3 -1
- package/src/security/__tests__/oauth2-device-code.test.ts +479 -0
- package/src/security/oauth2-device-code.ts +307 -0
- package/src/security/oauth2.ts +26 -9
- package/src/security/secure-keys.ts +5 -0
- package/src/skills/catalog-install.ts +6 -2
- package/src/telemetry/types.ts +12 -0
- package/src/telemetry/usage-telemetry-reporter.test.ts +48 -0
- package/src/telemetry/usage-telemetry-reporter.ts +1 -0
- package/src/tools/acp/spawn.test.ts +119 -0
- package/src/tools/acp/spawn.ts +15 -2
- package/src/tools/apps/definitions.ts +2 -8
- package/src/tools/ask-question/ask-question-tool.test.ts +3 -3
- package/src/tools/ask-question/ask-question-tool.ts +38 -45
- package/src/tools/browser/__tests__/pinned-tabs.test.ts +150 -0
- package/src/tools/browser/browser-execution.ts +106 -0
- package/src/tools/browser/cdp-client/__tests__/browser-tabs-factory.test.ts +402 -0
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +28 -0
- package/src/tools/browser/cdp-client/__tests__/types.test.ts +4 -0
- package/src/tools/browser/cdp-client/cdp-inspect-client.ts +22 -0
- package/src/tools/browser/cdp-client/extension-cdp-client.ts +42 -2
- package/src/tools/browser/cdp-client/factory.ts +171 -4
- package/src/tools/browser/cdp-client/local-cdp-client.ts +21 -0
- package/src/tools/browser/cdp-client/types.ts +101 -0
- package/src/tools/browser/pinned-tabs.ts +146 -0
- package/src/tools/computer-use/definitions.ts +22 -78
- package/src/tools/credential-execution/make-authenticated-request.ts +3 -9
- package/src/tools/credential-execution/manage-secure-command-tool.ts +3 -9
- package/src/tools/credential-execution/run-authenticated-command.ts +3 -9
- package/src/tools/credentials/vault.ts +3 -9
- package/src/tools/document/document-comment-tool.test.ts +379 -0
- package/src/tools/document/document-comment-tool.ts +156 -0
- package/src/tools/document/document-tool.ts +187 -2
- package/src/tools/execution-target.ts +21 -23
- package/src/tools/executor.ts +6 -1
- package/src/tools/filesystem/edit.ts +3 -9
- package/src/tools/filesystem/list.ts +3 -9
- package/src/tools/filesystem/read.ts +3 -9
- package/src/tools/filesystem/write.ts +3 -9
- package/src/tools/host-filesystem/edit.ts +3 -9
- package/src/tools/host-filesystem/read.ts +3 -9
- package/src/tools/host-filesystem/transfer.ts +3 -9
- package/src/tools/host-filesystem/write.ts +3 -9
- package/src/tools/host-terminal/host-shell.ts +3 -9
- package/src/tools/mcp/mcp-tool-factory.ts +1 -8
- package/src/tools/memory/register.test.ts +1 -1
- package/src/tools/memory/register.ts +4 -9
- package/src/tools/network/__tests__/web-fetch-metadata.test.ts +229 -0
- package/src/tools/network/__tests__/web-search-metadata.test.ts +346 -0
- package/src/tools/network/domain-normalize.ts +17 -0
- package/src/tools/network/web-fetch.ts +216 -73
- package/src/tools/network/web-search.ts +216 -98
- package/src/tools/registry.ts +7 -23
- package/src/tools/schema-transforms.ts +1 -1
- package/src/tools/skills/execute.ts +3 -9
- package/src/tools/skills/load.ts +3 -9
- package/src/tools/skills/skill-tool-factory.ts +1 -8
- package/src/tools/subagent/notify-parent.ts +3 -9
- package/src/tools/system/request-permission.ts +3 -9
- package/src/tools/terminal/safe-env.ts +3 -2
- package/src/tools/terminal/shell.ts +3 -9
- package/src/tools/tool-approval-handler.ts +19 -12
- package/src/tools/tool-defaults.ts +94 -0
- package/src/tools/types.ts +31 -98
- package/src/tools/ui-surface/definitions.ts +9 -23
- package/src/types/onboarding-context.ts +4 -0
- package/src/usage/pricing.ts +23 -0
- package/src/usage/types.ts +12 -0
- package/src/util/__tests__/favicon.test.ts +84 -0
- package/src/util/favicon.ts +40 -0
- package/src/util/logger.ts +16 -7
- package/src/util/platform.ts +7 -7
- package/src/util/sqlite3-runtime.ts +65 -0
- package/src/workspace/git-service.ts +75 -4
- package/src/workspace/migrations/086-revert-stale-gemini-mis-rewrites.ts +1 -0
- package/src/workspace/migrations/088-deprecate-background-conversation-override.ts +103 -0
- package/src/workspace/migrations/089-move-memory-tree-out-of-v3.ts +86 -0
- package/src/workspace/migrations/registry.ts +4 -0
- package/src/__tests__/compaction-strip-metadata-clear.test.ts +0 -206
- package/src/__tests__/message-complete-display-id.test.ts +0 -175
- package/src/config/bundled-skills/document/SKILL.md +0 -54
- package/src/config/bundled-skills/document/TOOLS.json +0 -106
- package/src/daemon/seed-files.ts +0 -18
- package/src/prompts/cache-boundary.ts +0 -8
- package/src/runtime/routes/interface-routes.ts +0 -43
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-create.ts +0 -0
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-delete.ts +0 -0
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-list.ts +0 -0
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-read.ts +0 -0
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-update.ts +0 -0
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory v3 — live-shadow `memoryRetrieval` middleware.
|
|
3
|
+
*
|
|
4
|
+
* Registered unconditionally into the `memoryRetrieval` pipeline, but inert
|
|
5
|
+
* unless BOTH `config.memory.v3.enabled` and `config.memory.v3.shadow` are on.
|
|
6
|
+
* When inert it is a byte-for-byte pass-through: it returns `next(args)`
|
|
7
|
+
* verbatim and performs zero extra work (no v3 call, no DB read, no log write).
|
|
8
|
+
*
|
|
9
|
+
* When active, it:
|
|
10
|
+
* 1. Returns the real (v2/default) `MemoryResult` from `next(args)` promptly —
|
|
11
|
+
* the injected context is ALWAYS the v2 result, never v3.
|
|
12
|
+
* 2. Kicks off the v3 retrieval loop DETACHED (not awaited on the path that
|
|
13
|
+
* returns the result), so the shadow run can never block or slow the turn.
|
|
14
|
+
* 3. Logs v3's selection set to `memory_v2_activation_logs` with
|
|
15
|
+
* `mode = "v3_shadow"`. The harness oracle filters `mode='router'`, so
|
|
16
|
+
* shadow rows never pollute it; the inspector can still surface them.
|
|
17
|
+
*
|
|
18
|
+
* The shadow build mirrors the inputs the v2 router receives (recent turn
|
|
19
|
+
* pairs, NOW context, prior-ever-injected slugs, config) so its recall is
|
|
20
|
+
* measured against the same situational context the live path saw. Failures
|
|
21
|
+
* are swallowed with a warn — the shadow is observational only and must never
|
|
22
|
+
* affect the live turn.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import { desc, eq } from "drizzle-orm";
|
|
26
|
+
|
|
27
|
+
import { getConfig } from "../../config/loader.js";
|
|
28
|
+
import { registerPlugin } from "../../plugins/registry.js";
|
|
29
|
+
import {
|
|
30
|
+
type MemoryArgs,
|
|
31
|
+
type MemoryResult,
|
|
32
|
+
type Middleware,
|
|
33
|
+
type Plugin,
|
|
34
|
+
PluginExecutionError,
|
|
35
|
+
} from "../../plugins/types.js";
|
|
36
|
+
import type { ContentBlock } from "../../providers/types.js";
|
|
37
|
+
import { getLogger } from "../../util/logger.js";
|
|
38
|
+
import { getWorkspaceDir } from "../../util/platform.js";
|
|
39
|
+
import type { DrizzleDb } from "../db-connection.js";
|
|
40
|
+
import { getDb } from "../db-connection.js";
|
|
41
|
+
import {
|
|
42
|
+
type MemoryV2ConceptRowRecord,
|
|
43
|
+
type MemoryV2ConfigSnapshot,
|
|
44
|
+
recordMemoryV2ActivationLog,
|
|
45
|
+
} from "../memory-v2-activation-log-store.js";
|
|
46
|
+
import { messages } from "../schema.js";
|
|
47
|
+
import { hydrate } from "../v2/activation-store.js";
|
|
48
|
+
import type { RetrievalInput } from "../v2/harness/retriever.js";
|
|
49
|
+
import { loadNowText } from "../v2/now-text.js";
|
|
50
|
+
import type { RouterTurnPair } from "../v2/router.js";
|
|
51
|
+
import type { EverInjectedEntry } from "../v2/types.js";
|
|
52
|
+
import { runRetrievalLoop } from "./loop.js";
|
|
53
|
+
|
|
54
|
+
const log = getLogger("memory-v3-shadow");
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Extract the recent (assistant, user) turn pairs from a conversation's
|
|
58
|
+
* message list, newest-pair-last, capped at `k`. Mirrors production
|
|
59
|
+
* `extractRecentTurnPairs` in `conversation-graph-memory.ts` (and its harness
|
|
60
|
+
* twin in `replay-input.ts`) so the shadow's `recentTurnPairs` matches what the
|
|
61
|
+
* live router was fed.
|
|
62
|
+
*/
|
|
63
|
+
function extractRecentTurnPairs(
|
|
64
|
+
msgs: ReadonlyArray<{ role: string; content: ContentBlock[] }>,
|
|
65
|
+
k: number,
|
|
66
|
+
): RouterTurnPair[] {
|
|
67
|
+
const messageText = (content: ContentBlock[]): string =>
|
|
68
|
+
content
|
|
69
|
+
.filter(
|
|
70
|
+
(b): b is Extract<ContentBlock, { type: "text" }> => b.type === "text",
|
|
71
|
+
)
|
|
72
|
+
.map((b) => b.text)
|
|
73
|
+
.join(" ");
|
|
74
|
+
|
|
75
|
+
const pairs: RouterTurnPair[] = [];
|
|
76
|
+
let pendingUser: string | null = null;
|
|
77
|
+
for (let i = msgs.length - 1; i >= 0 && pairs.length < k; i--) {
|
|
78
|
+
const msg = msgs[i]!;
|
|
79
|
+
if (msg.role === "user" && pendingUser === null) {
|
|
80
|
+
pendingUser = messageText(msg.content);
|
|
81
|
+
} else if (msg.role === "assistant" && pendingUser !== null) {
|
|
82
|
+
pairs.unshift({
|
|
83
|
+
assistantMessage: messageText(msg.content),
|
|
84
|
+
userMessage: pendingUser,
|
|
85
|
+
});
|
|
86
|
+
pendingUser = null;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
if (pendingUser !== null && pairs.length < k) {
|
|
90
|
+
pairs.unshift({ assistantMessage: "", userMessage: pendingUser });
|
|
91
|
+
}
|
|
92
|
+
if (pairs.length === 0) {
|
|
93
|
+
pairs.push({ assistantMessage: "", userMessage: "" });
|
|
94
|
+
}
|
|
95
|
+
return pairs;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** Parse a persisted JSON content-block string; tolerate malformed rows. */
|
|
99
|
+
function parseContent(raw: string): ContentBlock[] {
|
|
100
|
+
try {
|
|
101
|
+
const parsed = JSON.parse(raw);
|
|
102
|
+
return Array.isArray(parsed) ? (parsed as ContentBlock[]) : [];
|
|
103
|
+
} catch {
|
|
104
|
+
return [];
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Load the most recent messages for a conversation, oldest-first, bounded to a
|
|
110
|
+
* small generous multiple of `historicalPairs`. Pair extraction only needs the
|
|
111
|
+
* tail, so a bounded `LIMIT` query avoids loading an entire (potentially
|
|
112
|
+
* multi-GB) conversation on every shadow turn — mirrors the harness's bounded
|
|
113
|
+
* fetch in `replay-input.ts`.
|
|
114
|
+
*/
|
|
115
|
+
function loadRecentMessages(
|
|
116
|
+
db: DrizzleDb,
|
|
117
|
+
conversationId: string,
|
|
118
|
+
historicalPairs: number,
|
|
119
|
+
): Array<{ role: string; content: ContentBlock[] }> {
|
|
120
|
+
const fetchWindow = Math.max(20, historicalPairs * 12);
|
|
121
|
+
const rows = db
|
|
122
|
+
.select({ role: messages.role, content: messages.content })
|
|
123
|
+
.from(messages)
|
|
124
|
+
.where(eq(messages.conversationId, conversationId))
|
|
125
|
+
.orderBy(desc(messages.createdAt), desc(messages.id))
|
|
126
|
+
.limit(fetchWindow)
|
|
127
|
+
.all();
|
|
128
|
+
return rows
|
|
129
|
+
.reverse()
|
|
130
|
+
.map((r) => ({ role: r.role, content: parseContent(r.content) }));
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Empty config snapshot for shadow log rows. The activation-state values are
|
|
135
|
+
* meaningless for a v3 selection (it computes no spreading-activation scores),
|
|
136
|
+
* so they are zeroed — exactly as the v2 router-mode rows do.
|
|
137
|
+
*/
|
|
138
|
+
const SHADOW_CONFIG_SNAPSHOT: MemoryV2ConfigSnapshot = {
|
|
139
|
+
d: 0,
|
|
140
|
+
c_user: 0,
|
|
141
|
+
c_assistant: 0,
|
|
142
|
+
c_now: 0,
|
|
143
|
+
k: 0,
|
|
144
|
+
hops: 0,
|
|
145
|
+
top_k: 0,
|
|
146
|
+
epsilon: 0,
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Build the concept rows logged for a v3 shadow selection. Each selected slug
|
|
151
|
+
* becomes a zeroed concept row tagged `source: "router"` and
|
|
152
|
+
* `status: "injected"` — the shadow has no activation scores to record, and the
|
|
153
|
+
* `mode='v3_shadow'` row tag (not the concept source) is what distinguishes
|
|
154
|
+
* shadow telemetry from live router selections.
|
|
155
|
+
*/
|
|
156
|
+
function buildShadowConceptRows(
|
|
157
|
+
selectedSlugs: readonly string[],
|
|
158
|
+
): MemoryV2ConceptRowRecord[] {
|
|
159
|
+
return selectedSlugs.map((slug) => ({
|
|
160
|
+
slug,
|
|
161
|
+
finalActivation: 0,
|
|
162
|
+
ownActivation: 0,
|
|
163
|
+
priorActivation: 0,
|
|
164
|
+
simUser: 0,
|
|
165
|
+
simAssistant: 0,
|
|
166
|
+
simNow: 0,
|
|
167
|
+
simUserRerankBoost: 0,
|
|
168
|
+
simAssistantRerankBoost: 0,
|
|
169
|
+
inRerankPool: false,
|
|
170
|
+
spreadContribution: 0,
|
|
171
|
+
source: "router",
|
|
172
|
+
status: "injected",
|
|
173
|
+
}));
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Run the v3 retrieval loop for the shadow and log its selection. Best-effort:
|
|
178
|
+
* any failure is logged and swallowed. Honors `signal` so a cancelled turn
|
|
179
|
+
* stops the shadow's lane work.
|
|
180
|
+
*/
|
|
181
|
+
async function runShadowAndLog(
|
|
182
|
+
args: MemoryArgs,
|
|
183
|
+
signal: AbortSignal,
|
|
184
|
+
): Promise<void> {
|
|
185
|
+
try {
|
|
186
|
+
if (signal.aborted) return;
|
|
187
|
+
|
|
188
|
+
const config = getConfig();
|
|
189
|
+
const workspaceDir = getWorkspaceDir();
|
|
190
|
+
const db = getDb();
|
|
191
|
+
|
|
192
|
+
const historicalPairs = config.memory.v2.router.historical_pairs;
|
|
193
|
+
const recentMessages = loadRecentMessages(
|
|
194
|
+
db,
|
|
195
|
+
args.conversationId,
|
|
196
|
+
historicalPairs,
|
|
197
|
+
);
|
|
198
|
+
const recentTurnPairs = extractRecentTurnPairs(
|
|
199
|
+
recentMessages,
|
|
200
|
+
historicalPairs,
|
|
201
|
+
);
|
|
202
|
+
|
|
203
|
+
const nowText = await loadNowText(workspaceDir);
|
|
204
|
+
|
|
205
|
+
let priorEverInjected: readonly EverInjectedEntry[] = [];
|
|
206
|
+
try {
|
|
207
|
+
const state = await hydrate(db, args.conversationId);
|
|
208
|
+
priorEverInjected = state?.everInjected ?? [];
|
|
209
|
+
} catch (err) {
|
|
210
|
+
log.warn(
|
|
211
|
+
{ err, conversationId: args.conversationId },
|
|
212
|
+
"v3 shadow: failed to hydrate prior-ever-injected; continuing with empty set",
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (signal.aborted) return;
|
|
217
|
+
|
|
218
|
+
const input: RetrievalInput = {
|
|
219
|
+
workspaceDir,
|
|
220
|
+
recentTurnPairs,
|
|
221
|
+
nowText,
|
|
222
|
+
priorEverInjected,
|
|
223
|
+
config,
|
|
224
|
+
signal,
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
const output = await runRetrievalLoop(input, {
|
|
228
|
+
db,
|
|
229
|
+
conversationId: args.conversationId,
|
|
230
|
+
turn: args.turnIndex,
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
if (signal.aborted) return;
|
|
234
|
+
|
|
235
|
+
recordMemoryV2ActivationLog({
|
|
236
|
+
conversationId: args.conversationId,
|
|
237
|
+
turn: args.turnIndex,
|
|
238
|
+
mode: "v3_shadow",
|
|
239
|
+
concepts: buildShadowConceptRows(output.selectedSlugs),
|
|
240
|
+
config: SHADOW_CONFIG_SNAPSHOT,
|
|
241
|
+
});
|
|
242
|
+
} catch (err) {
|
|
243
|
+
log.warn(
|
|
244
|
+
{ err, conversationId: args.conversationId, turn: args.turnIndex },
|
|
245
|
+
"v3 shadow retrieval failed; live turn unaffected",
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Live-shadow `memoryRetrieval` middleware.
|
|
252
|
+
*
|
|
253
|
+
* Flag-gated INSIDE the middleware (per-turn, live-toggle): when v3 shadow is
|
|
254
|
+
* off it is a pure pass-through. When on, it fires the v3 loop detached and
|
|
255
|
+
* returns the unchanged downstream (v2) result immediately.
|
|
256
|
+
*/
|
|
257
|
+
export const memoryV3ShadowMiddleware: Middleware<MemoryArgs, MemoryResult> =
|
|
258
|
+
async function memoryV3Shadow(args, next) {
|
|
259
|
+
const v3 = getConfig().memory.v3;
|
|
260
|
+
if (!v3?.enabled || !v3?.shadow) {
|
|
261
|
+
// Inert: byte-for-byte pass-through, zero extra work.
|
|
262
|
+
return next(args);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// Detached — never awaited on the path that returns the result, so the
|
|
266
|
+
// shadow can neither block nor slow the live turn. Errors are swallowed
|
|
267
|
+
// inside `runShadowAndLog`.
|
|
268
|
+
void runShadowAndLog(args, args.signal);
|
|
269
|
+
|
|
270
|
+
return next(args);
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* First-party plugin contributing the live-shadow `memoryRetrieval`
|
|
275
|
+
* middleware. Registered unconditionally by the plugin bootstrap (it is inert
|
|
276
|
+
* unless both v3 flags are on), so the registration is always present but does
|
|
277
|
+
* zero work in the default (flags-off) configuration.
|
|
278
|
+
*/
|
|
279
|
+
export const memoryV3ShadowPlugin: Plugin = {
|
|
280
|
+
manifest: {
|
|
281
|
+
name: "memory-v3-shadow",
|
|
282
|
+
version: "0.0.1",
|
|
283
|
+
},
|
|
284
|
+
middleware: {
|
|
285
|
+
memoryRetrieval: memoryV3ShadowMiddleware,
|
|
286
|
+
},
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
// Module-load side effect: register the shadow plugin at import time so the
|
|
290
|
+
// registry is populated even in tests that skip `bootstrapPlugins()`, matching
|
|
291
|
+
// the first-party `default-*` plugins. Idempotent via the swallowed
|
|
292
|
+
// duplicate-name check (the defaults aggregator also lists this plugin).
|
|
293
|
+
try {
|
|
294
|
+
registerPlugin(memoryV3ShadowPlugin);
|
|
295
|
+
} catch (err) {
|
|
296
|
+
if (
|
|
297
|
+
err instanceof PluginExecutionError &&
|
|
298
|
+
err.message.includes("already registered")
|
|
299
|
+
) {
|
|
300
|
+
// already registered — expected when both the defaults aggregator and the
|
|
301
|
+
// direct module import run in the same process.
|
|
302
|
+
} else {
|
|
303
|
+
throw err;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory v3 — Tree traversal primitives.
|
|
3
|
+
*
|
|
4
|
+
* The *mechanical* half of the v3 read loop: a deterministic, provider-free
|
|
5
|
+
* walk over the {@link TreeIndex} DAG. The intelligence — *which* child nodes
|
|
6
|
+
* to recurse into at each level — is injected via the `descend` callback so
|
|
7
|
+
* this module stays pure and unit-testable without an LLM. The driver PR wires
|
|
8
|
+
* `descend` to the model's descend/skip decision; here `descend` is just a
|
|
9
|
+
* function `(nodeId, children) => chosen node-children`.
|
|
10
|
+
*
|
|
11
|
+
* `walkTree` fans out from a `start` node and any `seeds`, level by level:
|
|
12
|
+
* - At each node it resolves the ordered child refs, hands them to `descend`,
|
|
13
|
+
* and recurses into the chosen `node:` children (capped by `breadthBudget`).
|
|
14
|
+
* - The `page:` children the `descend` decision chooses to *keep* are collected
|
|
15
|
+
* into the returned `pages` set — pages are leaves, never recursed into. A
|
|
16
|
+
* page the decision does not keep is dropped, so the walk emits a curated
|
|
17
|
+
* selection rather than every page it passes.
|
|
18
|
+
* - A `visited` set keyed by canonical id (`node:<id>`) dedups shared
|
|
19
|
+
* sub-nodes (the DAG case) and terminates cycles (A ↔ B). A node is walked
|
|
20
|
+
* at most once regardless of how many parents reference it.
|
|
21
|
+
* - `maxDepth` bounds how deep the recursion goes; the start/seed level is
|
|
22
|
+
* depth 0.
|
|
23
|
+
*
|
|
24
|
+
* Each walked node emits one {@link TreeLevel} (the `harness/trace.ts` shape)
|
|
25
|
+
* recording what was considered, descended, and skipped. `reasoning` is
|
|
26
|
+
* supplied by the `descend` callback (the driver attaches the model's stated
|
|
27
|
+
* reason); the mechanical walk defaults it to `""`.
|
|
28
|
+
*
|
|
29
|
+
* Processing is strictly level-by-level so `visited` mutations are never raced:
|
|
30
|
+
* within a level the per-node `descend` calls run concurrently (`Promise.all`),
|
|
31
|
+
* but the chosen children for the *next* level are only dedup'd and enqueued
|
|
32
|
+
* after the whole level resolves.
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
import type { TreeLevel } from "../v2/harness/trace.js";
|
|
36
|
+
import type { ChildRef, TreeIndex } from "./tree-index.js";
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* The decision injected into {@link walkTree}. Given a node id and its ordered
|
|
40
|
+
* child refs, return the *node* children to recurse into and the *page* children
|
|
41
|
+
* to keep for the answer. The driver wires this to the LLM; tests pass a
|
|
42
|
+
* deterministic stub.
|
|
43
|
+
*
|
|
44
|
+
* Returning a `reasoning` string is optional — when present it is threaded into
|
|
45
|
+
* the emitted {@link TreeLevel}; absent, the level's `reasoning` defaults to
|
|
46
|
+
* `""`. Returned `descend` refs that are not `node:` children of `nodeId`, and
|
|
47
|
+
* `keep` refs that are not `page:` children of `nodeId`, are ignored by the walk
|
|
48
|
+
* (it only acts on the distinct children it actually offered).
|
|
49
|
+
*/
|
|
50
|
+
export type DescendDecision = (
|
|
51
|
+
nodeId: string,
|
|
52
|
+
children: ReadonlyArray<ChildRef>,
|
|
53
|
+
) => Promise<DescendResult> | DescendResult;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* The result of a {@link DescendDecision}. `descend` lists the `node:` children
|
|
57
|
+
* chosen for recursion; `keep` lists the `page:` children to collect into the
|
|
58
|
+
* walk's result; `reasoning` is the optional model rationale recorded on the
|
|
59
|
+
* level.
|
|
60
|
+
*/
|
|
61
|
+
export interface DescendResult {
|
|
62
|
+
descend: ChildRef[];
|
|
63
|
+
keep: ChildRef[];
|
|
64
|
+
reasoning?: string;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** Options controlling a {@link walkTree} run. */
|
|
68
|
+
export interface WalkOptions {
|
|
69
|
+
/** Entry node id; defaults to `tree.root`. */
|
|
70
|
+
start?: string;
|
|
71
|
+
/** Extra node ids to start from in parallel with `start`. */
|
|
72
|
+
seeds?: string[];
|
|
73
|
+
/** Max `node:` children to descend into per node (after the `descend` pick). */
|
|
74
|
+
breadthBudget: number;
|
|
75
|
+
/** Max recursion depth; the start/seed level is depth 0. */
|
|
76
|
+
maxDepth: number;
|
|
77
|
+
/** Injected descend decision (the LLM hook). */
|
|
78
|
+
descend: DescendDecision;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** The result of a {@link walkTree} run. */
|
|
82
|
+
export interface WalkResult {
|
|
83
|
+
/** Every `page:` slug the descend decision kept across the walk, dedup'd. */
|
|
84
|
+
pages: Set<string>;
|
|
85
|
+
/** One {@link TreeLevel} per walked node, in walk order. */
|
|
86
|
+
levels: TreeLevel[];
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Resolve the ordered child refs for `nodeId`. Thin accessor over
|
|
91
|
+
* `tree.childrenByNode`; returns an empty array for an unknown / leaf node id so
|
|
92
|
+
* callers never branch on `undefined`.
|
|
93
|
+
*/
|
|
94
|
+
export function resolveChildren(
|
|
95
|
+
tree: TreeIndex,
|
|
96
|
+
nodeId: string,
|
|
97
|
+
): ReadonlyArray<ChildRef> {
|
|
98
|
+
return tree.childrenByNode.get(nodeId) ?? [];
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** Canonical visited-set key for a node id. */
|
|
102
|
+
function nodeKey(nodeId: string): string {
|
|
103
|
+
return `node:${nodeId}`;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Walk the {@link TreeIndex} DAG from `start` (default `tree.root`) plus any
|
|
108
|
+
* `seeds`, driven by the injected `descend` decision. Deterministic and
|
|
109
|
+
* provider-free — see the module docstring for the full contract.
|
|
110
|
+
*
|
|
111
|
+
* Returns the collected leaf `pages` and the per-node `levels` trace.
|
|
112
|
+
*/
|
|
113
|
+
export async function walkTree(
|
|
114
|
+
tree: TreeIndex,
|
|
115
|
+
opts: WalkOptions,
|
|
116
|
+
): Promise<WalkResult> {
|
|
117
|
+
const { breadthBudget, maxDepth, descend } = opts;
|
|
118
|
+
const start = opts.start ?? tree.root;
|
|
119
|
+
|
|
120
|
+
const pages = new Set<string>();
|
|
121
|
+
const levels: TreeLevel[] = [];
|
|
122
|
+
const visited = new Set<string>();
|
|
123
|
+
|
|
124
|
+
// Seed the frontier with `start` + `seeds`, dedup'd and marked visited up
|
|
125
|
+
// front so a node that is both the start and a seed is walked once.
|
|
126
|
+
let frontier: string[] = [];
|
|
127
|
+
for (const id of [start, ...(opts.seeds ?? [])]) {
|
|
128
|
+
const key = nodeKey(id);
|
|
129
|
+
if (visited.has(key)) continue;
|
|
130
|
+
visited.add(key);
|
|
131
|
+
frontier.push(id);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Depth 0 is the start/seed level; stop once we'd exceed `maxDepth`.
|
|
135
|
+
for (let depth = 0; depth <= maxDepth && frontier.length > 0; depth++) {
|
|
136
|
+
// Resolve every node on this level concurrently. `visited` is not mutated
|
|
137
|
+
// here — only after the whole level settles — so the concurrency is safe.
|
|
138
|
+
const levelResults = await Promise.all(
|
|
139
|
+
frontier.map(async (nodeId) => {
|
|
140
|
+
const children = resolveChildren(tree, nodeId);
|
|
141
|
+
const result = await descend(nodeId, children);
|
|
142
|
+
return { nodeId, children, result };
|
|
143
|
+
}),
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
const nextFrontier: string[] = [];
|
|
147
|
+
|
|
148
|
+
for (const { nodeId, children, result } of levelResults) {
|
|
149
|
+
// Collect only the page children the decision chose to keep, filtered to
|
|
150
|
+
// the page children this node actually offered — a decision can't keep a
|
|
151
|
+
// page the node never presented.
|
|
152
|
+
const offeredPageRefs = new Set(
|
|
153
|
+
children.filter((c) => c.kind === "page").map((c) => c.ref),
|
|
154
|
+
);
|
|
155
|
+
for (const choice of result.keep) {
|
|
156
|
+
if (choice.kind === "page" && offeredPageRefs.has(choice.ref)) {
|
|
157
|
+
pages.add(choice.ref);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// The set of node children this node legitimately offered, in order. The
|
|
162
|
+
// descend pick is intersected with this so a stub returning bogus or
|
|
163
|
+
// duplicate refs can't make the walk recurse into something not offered.
|
|
164
|
+
const offeredNodes = children.filter((c) => c.kind === "node");
|
|
165
|
+
const offeredRefs = new Set(offeredNodes.map((c) => c.ref));
|
|
166
|
+
|
|
167
|
+
// Honor the descend pick in the order it was returned, dedup'd, filtered
|
|
168
|
+
// to genuinely-offered node children, and capped by `breadthBudget`.
|
|
169
|
+
const descended: string[] = [];
|
|
170
|
+
const descendedSet = new Set<string>();
|
|
171
|
+
for (const choice of result.descend) {
|
|
172
|
+
if (choice.kind !== "node") continue;
|
|
173
|
+
if (!offeredRefs.has(choice.ref)) continue;
|
|
174
|
+
if (descendedSet.has(choice.ref)) continue;
|
|
175
|
+
if (descended.length >= breadthBudget) break;
|
|
176
|
+
descendedSet.add(choice.ref);
|
|
177
|
+
descended.push(choice.ref);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const considered = offeredNodes.map((c) => c.ref);
|
|
181
|
+
const skipped = considered.filter((ref) => !descendedSet.has(ref));
|
|
182
|
+
|
|
183
|
+
levels.push({
|
|
184
|
+
node: nodeId,
|
|
185
|
+
considered,
|
|
186
|
+
descended,
|
|
187
|
+
skipped,
|
|
188
|
+
reasoning: result.reasoning ?? "",
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
// Enqueue chosen node children for the next level. Mark visited now (the
|
|
192
|
+
// level has fully resolved) so a shared sub-node or a cycle is enqueued at
|
|
193
|
+
// most once across the whole walk.
|
|
194
|
+
for (const ref of descended) {
|
|
195
|
+
const key = nodeKey(ref);
|
|
196
|
+
if (visited.has(key)) continue;
|
|
197
|
+
visited.add(key);
|
|
198
|
+
nextFrontier.push(ref);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
frontier = nextFrontier;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return { pages, levels };
|
|
206
|
+
}
|