@vellumai/assistant 0.10.4 → 0.10.5-dev.202607022329.d89bf2f
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 +94 -91
- package/Dockerfile +5 -16
- package/README.md +7 -10
- package/bun.lock +0 -4
- package/docs/architecture/security.md +20 -20
- package/docs/stt-provider-onboarding.md +4 -5
- package/docs/trusted-contact-access.md +7 -7
- package/eslint-rules/cli-no-daemon-internals.js +4 -0
- package/eslint.config.mjs +7 -1
- package/knip.json +0 -1
- package/node_modules/@vellumai/gateway-client/src/__tests__/contact-read-contracts.test.ts +36 -0
- package/node_modules/@vellumai/gateway-client/src/__tests__/invite-contract.test.ts +233 -0
- package/node_modules/@vellumai/gateway-client/src/__tests__/trust-verdict-contract.test.ts +40 -0
- package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +20 -8
- package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +10 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +33 -0
- package/node_modules/@vellumai/gateway-client/src/invite-contract.ts +216 -0
- package/node_modules/@vellumai/gateway-client/src/outbound-contract.ts +91 -0
- package/node_modules/@vellumai/gateway-client/src/trust-verdict-contract.ts +39 -3
- package/node_modules/@vellumai/service-contracts/src/__tests__/ingress.test.ts +0 -8
- package/node_modules/@vellumai/service-contracts/src/__tests__/package-boundary.test.ts +1 -5
- package/node_modules/@vellumai/service-contracts/src/twilio-ingress.ts +3 -14
- package/openapi.yaml +1073 -225
- package/package.json +1 -4
- package/scripts/test.sh +35 -13
- package/src/__tests__/access-request-seed-content-blocks.test.ts +60 -4
- package/src/__tests__/acp-session.test.ts +4 -1
- package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +0 -6
- package/src/__tests__/add-message-preassigned-id.test.ts +56 -0
- package/src/__tests__/agent-loop-set-system-prompt.test.ts +139 -0
- package/src/__tests__/app-conversation-ids-backfill.test.ts +3 -0
- package/src/__tests__/app-source-watcher.test.ts +11 -0
- package/src/__tests__/approval-interception-trust-gates.test.ts +148 -3
- package/src/__tests__/assistant-attachments.test.ts +62 -4
- package/src/__tests__/assistant-id-boundary-guard.test.ts +0 -1
- package/src/__tests__/attachments-store-heic-normalize.test.ts +230 -0
- package/src/__tests__/attachments-store.test.ts +3 -0
- package/src/__tests__/background-shell-bash.test.ts +34 -0
- package/src/__tests__/background-shell-host-bash.test.ts +12 -0
- package/src/__tests__/background-tool-registry.test.ts +97 -0
- package/src/__tests__/background-tool-routes.test.ts +72 -1
- package/src/__tests__/background-workers-disk-pressure.test.ts +2 -1
- package/src/__tests__/btw-routes.test.ts +57 -3
- package/src/__tests__/call-controller.test.ts +474 -84
- package/src/__tests__/call-domain.test.ts +48 -1
- package/src/__tests__/call-pointer-messages.test.ts +57 -19
- package/src/__tests__/call-pointer-no-hardcoded-copy.guard.test.ts +2 -6
- package/src/__tests__/call-routes-http.test.ts +15 -14
- package/src/__tests__/call-setup-flow-invite.test.ts +568 -0
- package/src/__tests__/call-setup-flow-midcall-trust.test.ts +231 -0
- package/src/__tests__/call-setup-flow-name-capture.test.ts +754 -0
- package/src/__tests__/call-setup-flow-verification.test.ts +925 -0
- package/src/__tests__/call-setup-flow.test.ts +311 -0
- package/src/__tests__/cancel-resolves-conversation-key.test.ts +0 -1
- package/src/__tests__/channel-guardian.test.ts +4 -7
- package/src/__tests__/channel-readiness-service.test.ts +0 -6
- package/src/__tests__/channel-readiness-slack-remote.test.ts +0 -4
- package/src/__tests__/channel-retry-sweep.test.ts +76 -64
- package/src/__tests__/channel-setup-panel-ack.test.ts +184 -0
- package/src/__tests__/clear-all-lexical.test.ts +90 -0
- package/src/__tests__/compactor-media-strip.test.ts +177 -0
- package/src/__tests__/config-loader-backfill.test.ts +5 -5
- package/src/__tests__/config-schema.test.ts +17 -0
- package/src/__tests__/contact-store-interaction-info.test.ts +27 -70
- package/src/__tests__/contacts-relay-reads.test.ts +188 -23
- package/src/__tests__/contacts-tools.test.ts +42 -1
- package/src/__tests__/contacts-write.test.ts +181 -0
- package/src/__tests__/context-search-conversations-source.test.ts +220 -81
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +1 -0
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -0
- package/src/__tests__/conversation-agent-loop.test.ts +39 -0
- package/src/__tests__/conversation-analysis-routes.test.ts +1 -1
- package/src/__tests__/conversation-app-control-instantiation.test.ts +2 -0
- package/src/__tests__/conversation-clear-safety.test.ts +0 -1
- package/src/__tests__/conversation-crud-enabled-plugins.test.ts +60 -0
- package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +0 -1
- package/src/__tests__/conversation-disk-view.test.ts +1 -0
- package/src/__tests__/conversation-enabledplugins-route.test.ts +184 -0
- package/src/__tests__/conversation-error.test.ts +0 -18
- package/src/__tests__/conversation-fork-crud.test.ts +67 -0
- package/src/__tests__/conversation-history-web-search.test.ts +7 -137
- package/src/__tests__/conversation-initial-prompt.test.ts +110 -0
- package/src/__tests__/conversation-loop-db-lock-resilience.test.ts +191 -0
- package/src/__tests__/conversation-process-callsite.test.ts +37 -0
- package/src/__tests__/conversation-queue.test.ts +149 -0
- package/src/__tests__/conversation-routes-enabled-plugins.test.ts +392 -0
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +84 -0
- package/src/__tests__/conversation-routes-hidden-queue.test.ts +407 -0
- package/src/__tests__/conversation-runtime-assembly.test.ts +36 -16
- package/src/__tests__/conversation-skill-tools.test.ts +73 -0
- package/src/__tests__/conversation-wipe.test.ts +20 -5
- package/src/__tests__/credential-prompt-route.test.ts +69 -0
- package/src/__tests__/credential-security-invariants.test.ts +1 -3
- package/src/__tests__/db-drop-messages-fts.test.ts +115 -0
- package/src/__tests__/deterministic-verification-control-plane.test.ts +1 -62
- package/src/__tests__/edit-propagation.test.ts +56 -2
- package/src/__tests__/empty-state-greeting-cache.test.ts +9 -0
- package/src/__tests__/gateway-only-enforcement.test.ts +15 -110
- package/src/__tests__/guardian-expiry-notifier.test.ts +1 -0
- package/src/__tests__/guardian-question-mode.test.ts +57 -0
- package/src/__tests__/guardian-verification-voice-binding.test.ts +1 -1
- package/src/__tests__/guardian-wait-controller.test.ts +619 -0
- package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +33 -2
- package/src/__tests__/heic-fixture.ts +55 -0
- package/src/__tests__/helpers/seed-contact-channel.ts +0 -2
- package/src/__tests__/http-conversation-lineage.test.ts +6 -1
- package/src/__tests__/image-conversion.test.ts +170 -0
- package/src/__tests__/inbound-invite-redemption.test.ts +72 -341
- package/src/__tests__/introduction-card-resolver.test.ts +354 -0
- package/src/__tests__/invite-redeemed-ipc.test.ts +97 -0
- package/src/__tests__/invite-routes-http.test.ts +246 -420
- package/src/__tests__/job-handler-registration-guard.test.ts +104 -0
- package/src/__tests__/lexical-index-dual-write.test.ts +426 -0
- package/src/__tests__/lifecycle-memory-v2-seed.test.ts +2 -2
- package/src/__tests__/list-messages-attachments.test.ts +159 -0
- package/src/__tests__/list-messages-background-tool-completion.test.ts +141 -0
- package/src/__tests__/list-messages-queued.test.ts +25 -0
- package/src/__tests__/managed-store.test.ts +129 -1
- package/src/__tests__/media-stream-audio-transcode.test.ts +113 -0
- package/src/__tests__/media-stream-output.test.ts +350 -19
- package/src/__tests__/media-stream-server-integration.test.ts +943 -169
- package/src/__tests__/media-stream-stt-session.test.ts +498 -1
- package/src/__tests__/memory-jobs-worker-lanes.test.ts +2 -2
- package/src/__tests__/model-intents.test.ts +1 -1
- package/src/__tests__/mtime-cache.test.ts +19 -0
- package/src/__tests__/non-member-access-request.test.ts +349 -3
- package/src/__tests__/notification-decision-fallback.test.ts +104 -8
- package/src/__tests__/notification-decision-strategy.test.ts +57 -8
- package/src/__tests__/onboarding-template-contract.test.ts +27 -43
- package/src/__tests__/openai-provider.test.ts +33 -0
- package/src/__tests__/openai-responses-provider.test.ts +40 -0
- package/src/__tests__/persistence-layering-guard.test.ts +29 -20
- package/src/__tests__/persona-resolver.test.ts +56 -2
- package/src/__tests__/personal-memory-auth-bypass.test.ts +62 -0
- package/src/__tests__/phone.test.ts +1 -15
- package/src/__tests__/plugin-bootstrap.test.ts +25 -196
- package/src/__tests__/plugin-disabled-state.test.ts +33 -0
- package/src/__tests__/plugin-effective-enabled-set.test.ts +227 -0
- package/src/__tests__/plugin-event-hub-facade.test.ts +323 -0
- package/src/__tests__/plugin-import-boundary-guard.test.ts +156 -42
- package/src/__tests__/plugin-injector-contribution.test.ts +4 -20
- package/src/__tests__/plugin-pipeline.test.ts +63 -1
- package/src/__tests__/plugin-route-contribution.test.ts +62 -115
- package/src/__tests__/plugin-tool-contribution.test.ts +0 -22
- package/src/__tests__/plugin-types.test.ts +0 -1
- package/src/__tests__/pointer-conversation-trust.test.ts +38 -6
- package/src/__tests__/pre-model-call-sanitize.test.ts +1 -1
- package/src/__tests__/prune-old-tool-invocations-job.test.ts +97 -0
- package/src/__tests__/public-ingress-urls.test.ts +0 -48
- package/src/__tests__/qdrant-collection-migration.test.ts +145 -2
- package/src/__tests__/reaction-intercept-member-verdict-warm.test.ts +0 -1
- package/src/__tests__/resolve-trust-class.test.ts +28 -10
- package/src/__tests__/scaffold-managed-skill-tool.test.ts +137 -0
- package/src/__tests__/schedule-retry.test.ts +38 -14
- package/src/__tests__/schedule-routes-workflow-validation.test.ts +3 -3
- package/src/__tests__/schedule-routes.test.ts +14 -6
- package/src/__tests__/schedule-store.test.ts +3 -1
- package/src/__tests__/scheduler-disk-pressure.test.ts +17 -6
- package/src/__tests__/scheduler-recurrence.test.ts +57 -107
- package/src/__tests__/scheduler-reuse-conversation.test.ts +51 -46
- package/src/__tests__/scheduler-wake.test.ts +13 -23
- package/src/__tests__/scheduler-worker-standdown.test.ts +220 -0
- package/src/__tests__/secret-routes-platform-proxy.test.ts +1 -1
- package/src/__tests__/shell-observability.test.ts +1 -0
- package/src/__tests__/skill-boundary-guard.test.ts +3 -4
- package/src/__tests__/skill-load-plugin-scope.test.ts +238 -0
- package/src/__tests__/skill-projection-feature-flag.test.ts +2 -0
- package/src/__tests__/skill-script-runner-host.test.ts +53 -0
- package/src/__tests__/skill-script-runner-sandbox.test.ts +5 -2
- package/src/__tests__/skill-tool-factory.test.ts +73 -1
- package/src/__tests__/slack-app-setup-skill-regression.test.ts +37 -14
- package/src/__tests__/slack-inbound-verification.test.ts +36 -0
- package/src/__tests__/slack-notification-approval-card.test.ts +89 -2
- package/src/__tests__/slack-reaction-canonical-approval.test.ts +51 -1
- package/src/__tests__/stt-hints.test.ts +2 -256
- package/src/__tests__/subagent-allowlist-validation.test.ts +47 -0
- package/src/__tests__/subagent-call-site-routing.test.ts +72 -0
- package/src/__tests__/subagent-fork-notifications.test.ts +14 -2
- package/src/__tests__/subagent-persistence.test.ts +122 -0
- package/src/__tests__/subagent-spawn-and-await.test.ts +1 -0
- package/src/__tests__/subagent-terminal-message.test.ts +99 -0
- package/src/__tests__/subagent-tool-gate-mode.test.ts +78 -1
- package/src/__tests__/system-prompt.test.ts +17 -118
- package/src/__tests__/task-scheduler.test.ts +68 -89
- package/src/__tests__/telephony-credential-preflight.test.ts +312 -0
- package/src/__tests__/telephony-tts-guard.test.ts +538 -0
- package/src/__tests__/title-generate-hook.test.ts +16 -0
- package/src/__tests__/tool-approval-handler.test.ts +87 -1
- package/src/__tests__/tool-approval-seed-content-blocks.test.ts +45 -20
- package/src/__tests__/tool-grant-request-escalation.test.ts +39 -0
- package/src/__tests__/trust-context-guards.test.ts +21 -10
- package/src/__tests__/trusted-contact-multichannel.test.ts +4 -0
- package/src/__tests__/twilio-provider.test.ts +17 -17
- package/src/__tests__/twilio-routes-twiml.test.ts +6 -543
- package/src/__tests__/twilio-routes.test.ts +257 -387
- package/src/__tests__/twilio-validation.test.ts +1 -1
- package/src/__tests__/unified-turn-context-client-os.test.ts +45 -0
- package/src/__tests__/usage-cache-backfill-migration.test.ts +5 -0
- package/src/__tests__/voice-approval-resolver-relay.test.ts +150 -0
- package/src/__tests__/voice-ingress-preflight.test.ts +61 -0
- package/src/__tests__/voice-quality.test.ts +2 -2
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +1 -7
- package/src/__tests__/voice-session-bridge-processing-wait.test.ts +27 -0
- package/src/__tests__/voice-session-bridge.test.ts +1 -10
- package/src/__tests__/workspace-git-service.test.ts +1 -1
- package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +1 -0
- package/src/__tests__/workspace-migration-118-seed-now-md.test.ts +120 -0
- package/src/__tests__/workspace-migration-120-revise-onboarding-threads.test.ts +175 -0
- package/src/__tests__/workspace-migration-121-seed-default-user-guardrails.test.ts +118 -0
- package/src/__tests__/workspace-migration-122-relocate-default-user-boundary.test.ts +119 -0
- package/src/__tests__/workspace-migration-123-swap-quality-profile-to-fable.test.ts +191 -0
- package/src/__tests__/workspace-migration-backfill-installation-id.test.ts +235 -241
- package/src/acp/__tests__/prepare-agent-env.test.ts +0 -97
- package/src/acp/__tests__/session-manager-persistence.test.ts +2 -0
- package/src/acp/__tests__/session-manager-resume.test.ts +8 -0
- package/src/acp/__tests__/session-manager-usage.test.ts +6 -0
- package/src/acp/__tests__/session-manager.test.ts +6 -0
- package/src/acp/agent-process.test.ts +116 -0
- package/src/acp/agent-process.ts +71 -0
- package/src/acp/auto-install.ts +12 -8
- package/src/acp/failure-error.test.ts +109 -0
- package/src/acp/failure-error.ts +111 -0
- package/src/acp/prepare-agent-env.ts +0 -12
- package/src/acp/resolve-agent.test.ts +6 -45
- package/src/acp/resolve-agent.ts +2 -4
- package/src/acp/session-manager.test.ts +312 -0
- package/src/acp/session-manager.ts +102 -46
- package/src/agent/ax-tree-compaction.test.ts +4 -1
- package/src/agent/image-optimize.ts +17 -127
- package/src/agent/loop.ts +45 -192
- package/src/api/events/background-tool-completed.test.ts +51 -0
- package/src/api/events/background-tool-completed.ts +29 -0
- package/src/api/events/background-tool-started.test.ts +36 -0
- package/src/api/events/background-tool-started.ts +28 -0
- package/src/api/events/conversation-error.ts +0 -1
- package/src/api/events/open-panel.ts +33 -0
- package/src/api/events/subagent-status-changed.ts +4 -1
- package/src/api/index.ts +19 -0
- package/src/api/responses/conversation-message.ts +34 -0
- package/src/approvals/guardian-decision-primitive.ts +74 -24
- package/src/approvals/guardian-request-resolvers.ts +450 -122
- package/src/apps/app-store.ts +1 -0
- package/src/apps/shared-app-links-store.ts +1 -0
- package/src/avatar/identity-avatar.ts +3 -7
- package/src/background-wake/wake-intent-hooks.test.ts +1 -1
- package/src/calls/__tests__/fish-audio-client.test.ts +73 -0
- package/src/calls/__tests__/gateway-invite-reader.test.ts +170 -0
- package/src/calls/__tests__/relay-setup-router.test.ts +126 -102
- package/src/calls/call-controller.ts +134 -48
- package/src/calls/call-domain.ts +18 -42
- package/src/calls/call-pointer-messages.ts +51 -67
- package/src/calls/call-setup-flow-types.ts +76 -0
- package/src/calls/call-setup-flow.ts +1743 -0
- package/src/calls/call-speech-output.ts +87 -23
- package/src/calls/call-store.ts +4 -0
- package/src/calls/call-transport.ts +22 -36
- package/src/calls/fish-audio-client.ts +3 -0
- package/src/calls/gateway-invite-reader.ts +98 -0
- package/src/calls/guardian-wait-controller.ts +451 -0
- package/src/calls/media-stream-audio-transcode.ts +82 -2
- package/src/calls/media-stream-output.ts +142 -36
- package/src/calls/media-stream-server.ts +297 -178
- package/src/calls/media-stream-stt-session.ts +393 -50
- package/src/calls/media-turn-detector.ts +4 -6
- package/src/calls/relay-access-wait.ts +3 -4
- package/src/calls/relay-setup-router.ts +22 -43
- package/src/calls/relay-verification.ts +17 -24
- package/src/calls/resolve-call-tts-provider.ts +96 -29
- package/src/calls/stt-hints.ts +24 -87
- package/src/calls/telephony-credential-preflight.ts +159 -0
- package/src/calls/telephony-tts-capability.ts +183 -0
- package/src/calls/tts-call-strategy.ts +18 -20
- package/src/calls/twilio-provider.ts +3 -2
- package/src/calls/twilio-routes.ts +47 -351
- package/src/calls/types.ts +5 -3
- package/src/calls/voice-ingress-preflight.ts +9 -0
- package/src/calls/voice-quality.ts +13 -18
- package/src/calls/voice-session-bridge.ts +25 -35
- package/src/channels/__tests__/types.test.ts +28 -0
- package/src/channels/channel-verification-sessions.ts +7 -2
- package/src/channels/config.ts +0 -42
- package/src/channels/slack-thread-store.ts +12 -0
- package/src/channels/types.ts +23 -0
- package/src/cli/commands/__tests__/conversations-slack.test.ts +1 -1
- package/src/cli/commands/__tests__/schedules.test.ts +83 -34
- package/src/cli/commands/__tests__/status.test.ts +42 -2
- package/src/cli/commands/contacts.ts +2 -2
- package/src/cli/commands/credentials.ts +17 -0
- package/src/cli/commands/monitoring.ts +191 -0
- package/src/cli/commands/schedules-worker.ts +175 -0
- package/src/cli/commands/schedules.ts +169 -43
- package/src/cli/commands/status.ts +12 -1
- package/src/cli/commands/tools.ts +5 -1
- package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +1 -0
- package/src/cli/lib/__tests__/search-plugins.test.ts +29 -1
- package/src/cli/lib/__tests__/toggle-plugin.test.ts +7 -0
- package/src/cli/lib/search-plugins.ts +6 -0
- package/src/cli/lib/toggle-plugin.ts +21 -2
- package/src/cli/program.ts +3 -1
- package/src/config/__tests__/deployment-context-defaults.test.ts +23 -0
- package/src/config/acp-defaults.test.ts +0 -10
- package/src/config/acp-defaults.ts +0 -6
- package/src/config/bundled-skills/acp/SKILL.md +13 -45
- package/src/config/bundled-skills/acp/TOOLS.json +3 -3
- package/src/config/bundled-skills/app-builder/SKILL.md +3 -3
- package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +9 -9
- package/src/config/bundled-skills/contacts/tools/contact-merge.ts +1 -1
- package/src/config/bundled-skills/contacts/tools/contact-search.ts +1 -1
- package/src/config/bundled-skills/phone-calls/SKILL.md +1 -1
- package/src/config/bundled-skills/phone-calls/references/CONFIG.md +9 -9
- package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +10 -7
- package/src/config/bundled-skills/skill-management/TOOLS.json +10 -0
- package/src/config/call-site-defaults.ts +0 -2
- package/src/config/feature-flag-registry.json +16 -8
- package/src/config/loader.ts +11 -0
- package/src/config/schema.ts +9 -1
- package/src/config/schemas/__tests__/memory-v2.test.ts +2 -2
- package/src/config/schemas/__tests__/memory-v3.test.ts +64 -0
- package/src/config/schemas/call-site-catalog.ts +0 -12
- package/src/config/schemas/calls.ts +8 -0
- package/src/config/schemas/elevenlabs.ts +1 -1
- package/src/config/schemas/llm.ts +0 -2
- package/src/config/schemas/memory-v2.ts +1 -1
- package/src/config/schemas/memory-v3.ts +82 -0
- package/src/config/schemas/monitoring.ts +61 -0
- package/src/config/schemas/schedules.ts +35 -0
- package/src/config/seed-inference-profiles.ts +2 -2
- package/src/config/skills-plugin-filter.test.ts +96 -0
- package/src/config/skills.ts +26 -0
- package/src/contacts/__tests__/member-write-relay.test.ts +156 -4
- package/src/contacts/canonical-guardian-store.ts +5 -0
- package/src/contacts/contact-store.ts +81 -35
- package/src/contacts/contacts-write.ts +50 -25
- package/src/contacts/member-write-relay.ts +115 -31
- package/src/contacts/types.ts +0 -8
- package/src/context/compactor.ts +29 -15
- package/src/context/outbound-sanitize.ts +202 -0
- package/src/daemon/__tests__/abort-null-controller.test.ts +167 -0
- package/src/daemon/__tests__/conversation-tool-setup-plugin-scope.test.ts +122 -0
- package/src/daemon/__tests__/embedding-reconcile.test.ts +99 -16
- package/src/daemon/__tests__/wake-conversation-ops-completion.test.ts +107 -0
- package/src/daemon/abort-watchdog.ts +7 -0
- package/src/daemon/app-source-watcher.ts +9 -0
- package/src/daemon/assistant-attachments.ts +42 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +256 -147
- package/src/daemon/conversation-agent-loop.ts +61 -68
- package/src/daemon/conversation-error.ts +1 -15
- package/src/daemon/conversation-history.ts +32 -236
- package/src/daemon/conversation-initial-prompt.ts +77 -0
- package/src/daemon/conversation-lifecycle.ts +25 -1
- package/src/daemon/conversation-messaging.ts +2 -2
- package/src/daemon/conversation-plugin-scope.ts +38 -0
- package/src/daemon/conversation-process.ts +50 -14
- package/src/daemon/conversation-runtime-assembly.ts +36 -6
- package/src/daemon/conversation-skill-tools.ts +19 -3
- package/src/daemon/conversation-store.ts +3 -3
- package/src/daemon/conversation-surfaces.ts +171 -0
- package/src/daemon/conversation-tool-setup.test.ts +95 -0
- package/src/daemon/conversation-tool-setup.ts +116 -1
- package/src/daemon/conversation-turn-finalize.ts +211 -0
- package/src/daemon/conversation.ts +92 -1
- package/src/daemon/disk-pressure-policy.ts +2 -1
- package/src/daemon/event-loop-watchdog.ts +22 -6
- package/src/daemon/external-plugins-bootstrap.ts +47 -134
- package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +1 -1
- package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +26 -14
- package/src/daemon/handlers/__tests__/config-a2a-invite.test.ts +27 -14
- package/src/daemon/handlers/__tests__/config-channels.test.ts +0 -5
- package/src/daemon/handlers/config-a2a.ts +7 -14
- package/src/daemon/handlers/config-channels.ts +2 -10
- package/src/daemon/handlers/conversation-history.ts +3 -1
- package/src/daemon/handlers/conversations.ts +0 -52
- package/src/daemon/handlers/shared.ts +4 -24
- package/src/daemon/handlers/skills.ts +4 -1
- package/src/daemon/host-cu-proxy.ts +1 -1
- package/src/daemon/lifecycle.ts +59 -472
- package/src/daemon/message-protocol.ts +3 -3
- package/src/daemon/message-provenance.ts +12 -14
- package/src/daemon/message-types/background-tools.ts +28 -0
- package/src/daemon/message-types/contacts.ts +2 -10
- package/src/daemon/message-types/conversations.ts +10 -0
- package/src/daemon/message-types/integrations.ts +2 -0
- package/src/daemon/message-types/surfaces.ts +1 -0
- package/src/daemon/message-types/sync.ts +1 -0
- package/src/daemon/pointer-conversation-trust.ts +23 -9
- package/src/daemon/pointer-turn-runner.ts +174 -0
- package/src/daemon/providers-setup.ts +16 -0
- package/src/daemon/shutdown-handlers.ts +139 -47
- package/src/daemon/skill-memory-refresh.ts +2 -2
- package/src/daemon/sqlite-corruption-watchdog.test.ts +217 -0
- package/src/daemon/sqlite-corruption-watchdog.ts +155 -0
- package/src/daemon/tool-setup-types.ts +8 -0
- package/src/daemon/trust-context.ts +21 -6
- package/src/daemon/turn-latency-tracker.test.ts +93 -0
- package/src/daemon/turn-latency-tracker.ts +38 -0
- package/src/daemon/wake-conversation-ops.ts +10 -8
- package/src/documents/document-comments-store.test.ts +7 -1
- package/src/documents/document-comments-store.ts +8 -0
- package/src/documents/document-store.ts +15 -0
- package/src/export/__tests__/transcript-formatter.test.ts +11 -0
- package/src/export/transcript-formatter.ts +49 -67
- package/src/home/__tests__/feed-writer.test.ts +247 -1
- package/src/home/conversation-starter-checkpoints.ts +1 -0
- package/src/home/feed-writer.ts +61 -0
- package/src/home/job-handlers/conversation-starters.ts +1 -0
- package/src/hooks/hook-loader.ts +12 -0
- package/src/hooks/registry.ts +32 -4
- package/src/inbound/public-ingress-urls.ts +0 -17
- package/src/ipc/__tests__/contacts-info-ipc.test.ts +285 -0
- package/src/ipc/assistant-server.ts +28 -7
- package/src/ipc/routes/__tests__/contacts-mirror-apply-atomicity.test.ts +62 -0
- package/src/ipc/routes/__tests__/contacts-mirror-apply.test.ts +272 -0
- package/src/ipc/routes/__tests__/contacts-mirror-ipc-routes.test.ts +322 -0
- package/src/ipc/routes/__tests__/invite-ipc-routes.test.ts +60 -4
- package/src/ipc/routes/contacts-info-ipc-routes.ts +239 -0
- package/src/ipc/routes/contacts-mirror-ipc-routes.ts +202 -0
- package/src/ipc/routes/db-proxy.ts +5 -2
- package/src/ipc/routes/invite-ipc-routes.ts +53 -39
- package/src/jobs/worker.ts +9 -2
- package/src/live-voice/__tests__/live-voice-archive.test.ts +10 -1
- package/src/live-voice/live-voice-archive.ts +5 -0
- package/src/messaging/providers/__tests__/transport-dispatch.test.ts +22 -6
- package/src/messaging/providers/channel-transport.ts +6 -0
- package/src/messaging/providers/index.ts +3 -0
- package/src/messaging/providers/slack/api.test.ts +49 -1
- package/src/messaging/providers/slack/api.ts +110 -0
- package/src/messaging/providers/slack/send.test.ts +85 -0
- package/src/messaging/providers/slack/send.ts +100 -28
- package/src/messaging/providers/slack/transport.ts +7 -13
- package/src/messaging/providers/whatsapp/send.ts +29 -9
- package/src/monitoring/__tests__/control.test.ts +235 -0
- package/src/monitoring/__tests__/sample-ring-buffer.test.ts +96 -0
- package/src/monitoring/control.ts +105 -0
- package/src/monitoring/resource-sampler.ts +258 -0
- package/src/monitoring/sample-ring-buffer.ts +108 -0
- package/src/monitoring/worker.ts +94 -0
- package/src/notifications/README.md +1 -1
- package/src/notifications/access-request-copy.ts +94 -23
- package/src/notifications/adapters/slack.ts +89 -21
- package/src/notifications/approval-card-builder.ts +33 -18
- package/src/notifications/approval-card-data.ts +48 -15
- package/src/notifications/broadcaster.ts +25 -16
- package/src/notifications/decision-engine.ts +131 -32
- package/src/notifications/guardian-question-mode.ts +58 -10
- package/src/permissions/approval-policy.ts +8 -1
- package/src/permissions/checker.ts +2 -0
- package/src/permissions/gateway-threshold-reader.ts +7 -6
- package/src/permissions/ipc-risk-types.ts +1 -0
- package/src/permissions/secret-prompter.ts +11 -3
- package/src/permissions/types.ts +2 -2
- package/src/persistence/__tests__/conversation-queries-search.test.ts +397 -0
- package/src/persistence/__tests__/conversation-search-lexical.test.ts +103 -0
- package/src/persistence/__tests__/jobs-worker-memory-disabled.test.ts +95 -0
- package/src/persistence/__tests__/slow-query-log.test.ts +266 -0
- package/src/persistence/__tests__/slow-sync-log.test.ts +155 -0
- package/src/persistence/a2a-invite-store.ts +205 -0
- package/src/persistence/attachments-store.ts +94 -10
- package/src/persistence/checkpoints.ts +45 -0
- package/src/persistence/conversation-crud.ts +453 -260
- package/src/persistence/conversation-display-order-migration.ts +8 -2
- package/src/persistence/conversation-group-migration.test.ts +8 -0
- package/src/persistence/conversation-group-migration.ts +9 -0
- package/src/persistence/conversation-queries.ts +244 -125
- package/src/persistence/conversation-row-batch-delete.ts +9 -5
- package/src/persistence/conversation-search-lexical.ts +49 -0
- package/src/persistence/db-async-query.ts +42 -0
- package/src/persistence/db-connection.ts +13 -0
- package/src/persistence/delivery-channels.ts +0 -82
- package/src/persistence/delivery-crud.ts +27 -6
- package/src/persistence/embeddings/__tests__/embedding-identity.test.ts +18 -5
- package/src/persistence/embeddings/__tests__/messages-lexical-index.test.ts +334 -0
- package/src/persistence/embeddings/embedding-identity.ts +17 -5
- package/src/persistence/embeddings/embedding-runtime-manager.ts +31 -0
- package/src/persistence/embeddings/messages-lexical-index.ts +396 -0
- package/src/persistence/embeddings/qdrant-client.ts +81 -5
- package/src/persistence/group-crud.ts +13 -1
- package/src/persistence/job-handlers/__tests__/message-lexical-backfill.test.ts +506 -0
- package/src/persistence/job-handlers/__tests__/message-lexical-enqueue.test.ts +164 -0
- package/src/persistence/job-handlers/__tests__/message-lexical.test.ts +259 -0
- package/src/persistence/job-handlers/cleanup.ts +57 -9
- package/src/persistence/job-handlers/message-lexical-backfill.ts +187 -0
- package/src/persistence/job-handlers/message-lexical.ts +251 -0
- package/src/persistence/jobs-store.ts +102 -8
- package/src/persistence/jobs-worker.ts +68 -28
- package/src/persistence/llm-request-log-store.ts +35 -19
- package/src/persistence/llm-usage-store.ts +11 -0
- package/src/persistence/memory-lifecycle-hooks.test.ts +65 -0
- package/src/persistence/memory-lifecycle-hooks.ts +55 -1
- package/src/persistence/migrations/028-call-session-mode.ts +1 -1
- package/src/persistence/migrations/116-messages-fts.ts +8 -1
- package/src/persistence/migrations/311-create-subagents-table.ts +50 -0
- package/src/persistence/migrations/312-drop-inbox-conversation-state-table.ts +15 -0
- package/src/persistence/migrations/313-drop-messages-fts.ts +17 -0
- package/src/persistence/migrations/314-add-conversation-enabled-plugins.ts +25 -0
- package/src/persistence/migrations/315-create-a2a-invites.ts +58 -0
- package/src/persistence/migrations/316-drop-contact-channels-invite-id.ts +28 -0
- package/src/persistence/migrations/317-canonical-guardian-requester-signals.ts +24 -0
- package/src/persistence/migrations/318-drop-contact-channel-telemetry.ts +32 -0
- package/src/persistence/migrations/__tests__/315-create-a2a-invites.test.ts +161 -0
- package/src/persistence/migrations/__tests__/316-drop-contact-channels-invite-id.test.ts +156 -0
- package/src/persistence/migrations/__tests__/318-drop-contact-channel-telemetry.test.ts +134 -0
- package/src/persistence/migrations/__tests__/migration-prefix-guard.test.ts +99 -0
- package/src/persistence/raw-query.ts +50 -11
- package/src/persistence/schema/a2a.ts +14 -0
- package/src/persistence/schema/contacts.ts +0 -62
- package/src/persistence/schema/conversation-groups.ts +12 -0
- package/src/persistence/schema/conversations.ts +2 -0
- package/src/persistence/schema/documents.ts +65 -0
- package/src/persistence/schema/guardian.ts +4 -0
- package/src/persistence/schema/index.ts +4 -0
- package/src/persistence/schema/memory-injection.ts +62 -0
- package/src/persistence/schema/workflows.ts +55 -0
- package/src/persistence/slow-query-log.ts +437 -0
- package/src/persistence/slow-sync-log.ts +204 -0
- package/src/persistence/steps.ts +16 -0
- package/src/persistence/subagent-store.ts +125 -0
- package/src/persistence/worker-control.ts +45 -238
- package/src/plugin-api/event-hub-facade.ts +172 -0
- package/src/plugin-api/index.ts +9 -1
- package/src/plugin-api/types.ts +40 -9
- package/src/plugins/defaults/default-plugin-names.ts +60 -0
- package/src/plugins/defaults/index.ts +19 -29
- package/src/plugins/defaults/memory/__tests__/conversation-queries.test.ts +46 -67
- package/src/plugins/defaults/memory/__tests__/db-async-query.test.ts +36 -1
- package/src/plugins/defaults/memory/__tests__/find-most-recent-retrospective-for.test.ts +2 -4
- package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +2 -2
- package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-schedule.test.ts +9 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +7 -4
- package/src/plugins/defaults/memory/config.ts +11 -0
- package/src/plugins/defaults/memory/context-search/agent-runner.ts +1 -1
- package/src/plugins/defaults/memory/context-search/sources/conversations.ts +124 -113
- package/src/plugins/defaults/memory/embeddings.ts +77 -0
- package/src/plugins/defaults/memory/find-most-recent-retrospective-for.ts +66 -0
- package/src/plugins/defaults/memory/frontmatter.ts +50 -0
- package/src/plugins/defaults/memory/graph/bootstrap.test.ts +36 -10
- package/src/plugins/defaults/memory/graph/bootstrap.ts +6 -5
- package/src/plugins/defaults/memory/graph/consolidation.ts +3 -5
- package/src/plugins/defaults/memory/graph/extraction.ts +3 -6
- package/src/plugins/defaults/memory/graph/graph-search.ts +12 -23
- package/src/plugins/defaults/memory/graph/narrative.ts +3 -5
- package/src/plugins/defaults/memory/graph/pattern-scan.ts +3 -5
- package/src/plugins/defaults/memory/graph/retriever.test.ts +1 -6
- package/src/plugins/defaults/memory/graph/retriever.ts +5 -10
- package/src/plugins/defaults/memory/graph/tools.ts +1 -1
- package/src/plugins/defaults/memory/hooks/init.ts +31 -5
- package/src/plugins/defaults/memory/indexer.ts +2 -3
- package/src/plugins/defaults/memory/injectors.ts +2 -2
- package/src/plugins/defaults/memory/job-handler-registration.ts +96 -0
- package/src/plugins/defaults/memory/job-handlers/backfill.ts +4 -26
- package/src/plugins/defaults/memory/job-handlers/embedding.test.ts +6 -19
- package/src/plugins/defaults/memory/job-handlers/embedding.ts +9 -22
- package/src/plugins/defaults/memory/job-handlers/index-maintenance.ts +2 -3
- package/src/plugins/defaults/memory/job-handlers.ts +13 -12
- package/src/plugins/defaults/memory/jobs/embed-concept-page.ts +1 -1
- package/src/plugins/defaults/memory/llm-helpers.ts +76 -0
- package/src/plugins/defaults/memory/memory-retrospective-job.ts +8 -5
- package/src/plugins/defaults/memory/memory-retrospective-startup-cleanup.ts +2 -2
- package/src/plugins/defaults/memory/memory-v2-concept-frequency.ts +2 -0
- package/src/plugins/defaults/memory/persistence-hooks.ts +46 -1
- package/src/plugins/defaults/memory/pkb/pkb-index.ts +1 -5
- package/src/plugins/defaults/memory/pkb/pkb-search.ts +2 -2
- package/src/plugins/defaults/memory/routes/__tests__/memory-v2-simulate-route.test.ts +4 -6
- package/src/plugins/defaults/memory/routes/memory-item-routes.ts +1 -1
- package/src/plugins/defaults/memory/search/semantic.ts +2 -2
- package/src/plugins/defaults/memory/startup.ts +244 -0
- package/src/plugins/defaults/memory/task-memory-cleanup.ts +8 -0
- package/src/{daemon → plugins/defaults/memory/v2}/__tests__/memory-v2-startup.test.ts +6 -6
- package/src/plugins/defaults/memory/v2/__tests__/migration.test.ts +2 -13
- package/src/plugins/defaults/memory/v2/__tests__/router.test.ts +4 -5
- package/src/plugins/defaults/memory/v2/__tests__/sweep-job.test.ts +1 -8
- package/src/plugins/defaults/memory/v2/activation.ts +2 -4
- package/src/plugins/defaults/memory/v2/cli-command-store.ts +2 -4
- package/src/plugins/defaults/memory/v2/frontmatter-sweep.ts +1 -1
- package/src/{daemon → plugins/defaults/memory/v2}/memory-v2-startup.test.ts +8 -8
- package/src/{daemon → plugins/defaults/memory/v2}/memory-v2-startup.ts +20 -22
- package/src/plugins/defaults/memory/v2/migration.ts +2 -5
- package/src/plugins/defaults/memory/v2/page-store.ts +1 -1
- package/src/plugins/defaults/memory/v2/qdrant.ts +2 -3
- package/src/plugins/defaults/memory/v2/router.ts +5 -5
- package/src/plugins/defaults/memory/v2/sim.ts +2 -4
- package/src/plugins/defaults/memory/v2/skill-store.ts +2 -4
- package/src/plugins/defaults/memory/v2/sweep-job.ts +6 -6
- package/src/plugins/defaults/memory/v3/__tests__/carry-integration.test.ts +11 -9
- package/src/plugins/defaults/memory/v3/__tests__/dense.test.ts +107 -2
- package/src/plugins/defaults/memory/v3/__tests__/gate-flag.test.ts +69 -0
- package/src/plugins/defaults/memory/v3/__tests__/gate.test.ts +181 -0
- package/src/plugins/defaults/memory/v3/__tests__/live-integration.test.ts +7 -3
- package/src/plugins/defaults/memory/v3/__tests__/orchestrate.test.ts +345 -8
- package/src/plugins/defaults/memory/v3/__tests__/pool-select.test.ts +1 -4
- package/src/plugins/defaults/memory/v3/__tests__/section-needle.test.ts +64 -0
- package/src/plugins/defaults/memory/v3/__tests__/shadow-integration.test.ts +18 -13
- package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +62 -1
- package/src/plugins/defaults/memory/v3/card.ts +1 -4
- package/src/plugins/defaults/memory/v3/dense.ts +60 -25
- package/src/plugins/defaults/memory/v3/edge.ts +1 -1
- package/src/plugins/defaults/memory/v3/gate-flag.ts +20 -0
- package/src/plugins/defaults/memory/v3/gate.ts +158 -0
- package/src/plugins/defaults/memory/v3/maintain-job.ts +2 -4
- package/src/plugins/defaults/memory/v3/orchestrate.ts +186 -25
- package/src/plugins/defaults/memory/v3/pool-select.test.ts +7 -9
- package/src/plugins/defaults/memory/v3/pool-select.ts +6 -6
- package/src/plugins/defaults/memory/v3/prune.ts +2 -2
- package/src/plugins/defaults/memory/v3/section-dense-store.ts +8 -11
- package/src/plugins/defaults/memory/v3/section-needle.ts +27 -7
- package/src/plugins/defaults/memory/v3/shadow-plugin.ts +10 -0
- package/src/plugins/defaults/memory/v3-eval/eval-packets.ts +1 -4
- package/src/plugins/defaults/title-generate/hooks/user-prompt-submit.ts +5 -0
- package/src/plugins/defaults/turn-context/injectors.ts +1 -0
- package/src/plugins/defaults/turn-context/unified-turn-context.ts +12 -0
- package/src/plugins/injector-registry.ts +13 -2
- package/src/plugins/mtime-cache.ts +36 -47
- package/src/plugins/pipeline.ts +15 -1
- package/src/plugins/types.ts +14 -23
- package/src/prompts/__tests__/system-prompt.test.ts +170 -32
- package/src/prompts/persona-resolver.ts +13 -9
- package/src/prompts/system-prompt.ts +30 -9
- package/src/prompts/templates/BOOTSTRAP.md +16 -119
- package/src/prompts/templates/SOUL.md +43 -13
- package/src/prompts/templates/system-sections.ts +32 -27
- package/src/prompts/templates/users/default.md +19 -0
- package/src/providers/__tests__/placeholder-sentinels.test.ts +56 -0
- package/src/providers/inference/__tests__/base-url-route-validation.test.ts +96 -1
- package/src/providers/model-intents.ts +2 -2
- package/src/providers/openai/chat-completions-provider.ts +14 -1
- package/src/providers/openai/responses-provider.ts +18 -0
- package/src/providers/placeholder-sentinels.ts +18 -8
- package/src/providers/retry.ts +1 -0
- package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +0 -64
- package/src/providers/speech-to-text/__tests__/resolve.test.ts +92 -79
- package/src/providers/speech-to-text/deepgram-realtime.test.ts +98 -0
- package/src/providers/speech-to-text/deepgram-realtime.ts +62 -3
- package/src/providers/speech-to-text/provider-catalog.ts +0 -89
- package/src/providers/speech-to-text/resolve.ts +55 -0
- package/src/providers/tool-progress-events.test.ts +50 -0
- package/src/providers/tool-progress-events.ts +99 -0
- package/src/providers/types.ts +1 -1
- package/src/providers/vellum-model-routing.test.ts +51 -0
- package/src/providers/vellum-model-routing.ts +84 -0
- package/src/runtime/AGENTS.md +5 -4
- package/src/runtime/__tests__/agent-wake.test.ts +158 -1
- package/src/runtime/__tests__/channel-verification-service.test.ts +2 -2
- package/src/runtime/__tests__/trust-verdict-consumer.test.ts +37 -8
- package/src/runtime/access-request-helper.ts +154 -3
- package/src/runtime/actor-trust-resolver.ts +7 -21
- package/src/runtime/agent-wake.ts +41 -1
- package/src/runtime/assistant-event.ts +86 -12
- package/src/runtime/auth/__tests__/route-policy.test.ts +31 -0
- package/src/runtime/channel-approval-types.ts +52 -2
- package/src/runtime/channel-approvals.ts +23 -8
- package/src/runtime/channel-invite-transport.ts +2 -2
- package/src/runtime/channel-invite-transports/voice.ts +1 -1
- package/src/runtime/channel-readiness-service.ts +3 -5
- package/src/runtime/channel-retry-sweep.ts +18 -24
- package/src/runtime/channel-verification-service.ts +9 -11
- package/src/runtime/finalize-event-delivery.ts +30 -16
- package/src/runtime/guardian-action-service.ts +10 -11
- package/src/runtime/guardian-reply-router.ts +122 -21
- package/src/runtime/http-server.ts +44 -101
- package/src/runtime/introduction-policy.test.ts +214 -0
- package/src/runtime/introduction-policy.ts +284 -0
- package/src/runtime/invite-service.ts +104 -361
- package/src/runtime/local-actor-identity.test.ts +38 -0
- package/src/runtime/local-actor-identity.ts +14 -0
- package/src/runtime/middleware/__tests__/rate-limiter.test.ts +22 -0
- package/src/runtime/middleware/rate-limiter.ts +30 -0
- package/src/runtime/middleware/twilio-validation.ts +5 -7
- package/src/runtime/migrations/__tests__/gcs-signed-url.test.ts +28 -0
- package/src/runtime/migrations/origin-mode.ts +6 -6
- package/src/runtime/pre-first-message-gate.ts +1 -0
- package/src/runtime/routes/__tests__/channel-verification-revoke.test.ts +6 -35
- package/src/runtime/routes/__tests__/consolidation-routes.test.ts +24 -3
- package/src/runtime/routes/__tests__/contact-routes.test.ts +80 -15
- package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +7 -1
- package/src/runtime/routes/__tests__/global-search-routes.test.ts +0 -3
- package/src/runtime/routes/__tests__/home-feed-routes.test.ts +142 -1
- package/src/runtime/routes/__tests__/invite-relay-routes.test.ts +119 -30
- package/src/runtime/routes/__tests__/migration-import-allowed-hosts-env.test.ts +70 -0
- package/src/runtime/routes/__tests__/monitoring-routes.test.ts +194 -0
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +755 -29
- package/src/runtime/routes/__tests__/retrospective-routes.test.ts +4 -0
- package/src/runtime/routes/__tests__/schedule-routes-create.test.ts +70 -0
- package/src/runtime/routes/__tests__/schedule-worker-routes.test.ts +161 -0
- package/src/runtime/routes/__tests__/surface-action-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/surface-content-routes.test.ts +1 -1
- package/src/runtime/routes/acp-routes.ts +15 -3
- package/src/runtime/routes/app-management-routes.ts +4 -7
- package/src/runtime/routes/approval-routes.ts +4 -0
- package/src/runtime/routes/attachment-routes.ts +54 -3
- package/src/runtime/routes/avatar-routes.ts +0 -4
- package/src/runtime/routes/background-tool-routes.ts +34 -5
- package/src/runtime/routes/btw-routes.ts +32 -4
- package/src/runtime/routes/channel-route-shared.ts +18 -14
- package/src/runtime/routes/channel-verification-routes.ts +0 -3
- package/src/runtime/routes/contact-routes.ts +298 -117
- package/src/runtime/routes/conversation-list-routes.ts +6 -0
- package/src/runtime/routes/conversation-management-routes.ts +74 -37
- package/src/runtime/routes/conversation-query-routes.ts +5 -2
- package/src/runtime/routes/conversation-routes.ts +222 -82
- package/src/runtime/routes/conversations-import-routes.ts +8 -1
- package/src/runtime/routes/credential-prompt-routes.ts +20 -5
- package/src/runtime/routes/debug-routes.ts +1 -0
- package/src/runtime/routes/documents-routes.ts +5 -2
- package/src/runtime/routes/empty-state-greeting-cache.ts +37 -10
- package/src/runtime/routes/global-search-routes.ts +2 -1
- package/src/runtime/routes/guardian-approval-interception.ts +51 -0
- package/src/runtime/routes/home-feed-routes.ts +60 -1
- package/src/runtime/routes/identity-routes.ts +4 -87
- package/src/runtime/routes/inbound-message-handler.ts +82 -41
- package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +430 -57
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +302 -572
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +76 -270
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +21 -116
- package/src/runtime/routes/inbound-stages/edit-intercept.ts +9 -1
- package/src/runtime/routes/inbound-stages/escalation-intercept.test.ts +158 -0
- package/src/runtime/routes/inbound-stages/escalation-intercept.ts +22 -1
- package/src/runtime/routes/index.ts +6 -0
- package/src/runtime/routes/inference-provider-connection-routes.ts +22 -16
- package/src/runtime/routes/internal-twilio-routes.ts +0 -15
- package/src/runtime/routes/messages-lexical-routes.ts +75 -0
- package/src/runtime/routes/migration-routes.ts +69 -6
- package/src/runtime/routes/monitoring-routes.ts +237 -0
- package/src/runtime/routes/plugins-routes.ts +329 -8
- package/src/runtime/routes/schedule-routes.ts +49 -8
- package/src/runtime/routes/schedule-worker-routes.ts +210 -0
- package/src/runtime/routes/secret-routes.ts +1 -1
- package/src/runtime/routes/surface-conversation-resolver.ts +1 -0
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +54 -9
- package/src/runtime/services/__tests__/auto-analysis-enqueue.test.ts +30 -6
- package/src/runtime/services/__tests__/conversation-analyze-job.test.ts +43 -8
- package/src/runtime/services/__tests__/conversation-serializer.test.ts +20 -0
- package/src/runtime/services/analyze-conversation.ts +14 -4
- package/src/runtime/services/conversation-serializer.ts +5 -0
- package/src/runtime/slack-no-response.ts +47 -0
- package/src/runtime/slack-reply-session.test.ts +633 -0
- package/src/runtime/slack-reply-session.ts +382 -0
- package/src/runtime/slack-task-progress.ts +95 -0
- package/src/runtime/sync/resource-sync-events.ts +25 -0
- package/src/runtime/tool-grant-request-helper.ts +17 -1
- package/src/runtime/trust-class.test.ts +141 -0
- package/src/runtime/trust-class.ts +121 -0
- package/src/runtime/trust-verdict-consumer.ts +7 -6
- package/src/schedule/__tests__/run-script.test.ts +21 -0
- package/src/schedule/__tests__/worker-control.test.ts +241 -0
- package/src/schedule/run-script.ts +13 -6
- package/src/schedule/schedule-usage-store.ts +1 -0
- package/src/schedule/scheduler.ts +178 -127
- package/src/schedule/worker-control.ts +118 -0
- package/src/schedule/worker.ts +131 -0
- package/src/skills/__tests__/categories-cache.test.ts +38 -0
- package/src/skills/categories-cache.ts +40 -5
- package/src/skills/managed-store.ts +41 -6
- package/src/skills/validate-input.ts +47 -0
- package/src/stt/types.ts +5 -9
- package/src/subagent/manager.ts +267 -39
- package/src/subagent/types.ts +6 -2
- package/src/subagent/validate-allowlists.ts +65 -0
- package/src/telemetry/watchdog-direct-emit.test.ts +109 -0
- package/src/telemetry/watchdog-direct-emit.ts +89 -0
- package/src/tools/acp/list-agents.test.ts +0 -6
- package/src/tools/background-tool-registry.ts +61 -0
- package/src/tools/document/document-comment-tool.test.ts +4 -0
- package/src/tools/host-terminal/host-shell.test.ts +397 -0
- package/src/tools/host-terminal/host-shell.ts +203 -14
- package/src/tools/skills/find-similar-skills.test.ts +152 -1
- package/src/tools/skills/find-similar-skills.ts +30 -4
- package/src/tools/skills/load.ts +36 -0
- package/src/tools/skills/scaffold-managed.ts +66 -34
- package/src/tools/skills/skill-script-runner.ts +17 -0
- package/src/tools/skills/skill-tool-factory.ts +5 -1
- package/src/tools/terminal/safe-env.ts +3 -0
- package/src/tools/terminal/shell.test.ts +177 -0
- package/src/tools/terminal/shell.ts +98 -4
- package/src/tools/tool-approval-handler.ts +106 -29
- package/{node_modules/@vellumai/skill-host-contracts/src → src/tools}/tool-types.ts +16 -17
- package/src/tools/types.ts +29 -17
- package/src/tools/ui-surface/definitions.ts +3 -1
- package/src/tts/__tests__/provider-adapters.test.ts +37 -0
- package/src/tts/__tests__/provider-catalog.test.ts +21 -0
- package/src/tts/provider-catalog.ts +40 -9
- package/src/tts/providers/fish-audio-provider.ts +19 -10
- package/src/tts/types.ts +3 -4
- package/src/util/__tests__/process-tree.test.ts +10 -2
- package/src/util/__tests__/text-spacing.test.ts +53 -0
- package/src/util/cgroup-memory.ts +142 -0
- package/src/util/image-conversion.ts +281 -0
- package/src/util/phone.ts +1 -8
- package/src/util/platform.ts +33 -0
- package/src/util/process-tree.ts +10 -2
- package/src/util/text-spacing.ts +53 -0
- package/src/util/worker-process.ts +271 -0
- package/src/workflows/journal-store.ts +16 -1
- package/src/workflows/library.test.ts +35 -20
- package/src/workflows/library.ts +105 -66
- package/src/workspace/git-service.ts +1 -0
- package/src/workspace/migrations/011-backfill-installation-id.ts +83 -31
- package/src/workspace/migrations/041-backfill-google-gmail-settings-scope.ts +41 -22
- package/src/workspace/migrations/070-memory-v2-summary-schema-rebuild.ts +1 -1
- package/src/workspace/migrations/118-seed-now-md.ts +64 -0
- package/src/workspace/migrations/119-strip-persisted-memory-v3-tuning-defaults.ts +169 -0
- package/src/workspace/migrations/120-revise-onboarding-threads.ts +47 -0
- package/src/workspace/migrations/121-seed-default-user-guardrails.ts +82 -0
- package/src/workspace/migrations/122-relocate-default-user-boundary.ts +111 -0
- package/src/workspace/migrations/123-swap-quality-profile-to-fable.ts +85 -0
- package/src/workspace/migrations/__tests__/119-strip-persisted-memory-v3-tuning-defaults.test.ts +181 -0
- package/src/workspace/migrations/registry.ts +12 -0
- package/drizzle/0000_dizzy_maggott.sql +0 -301
- package/drizzle/meta/0000_snapshot.json +0 -1933
- package/drizzle/meta/_journal.json +0 -13
- package/node_modules/@vellumai/skill-host-contracts/__tests__/client.test.ts +0 -887
- package/node_modules/@vellumai/skill-host-contracts/bun.lock +0 -24
- package/node_modules/@vellumai/skill-host-contracts/package.json +0 -18
- package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +0 -97
- package/node_modules/@vellumai/skill-host-contracts/src/client.ts +0 -1349
- package/node_modules/@vellumai/skill-host-contracts/src/index.ts +0 -6
- package/node_modules/@vellumai/skill-host-contracts/src/runtime-mode.ts +0 -11
- package/node_modules/@vellumai/skill-host-contracts/src/server-message.ts +0 -32
- package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +0 -333
- package/node_modules/@vellumai/skill-host-contracts/tsconfig.json +0 -20
- package/node_modules/@vellumai/skill-host-contracts/tsconfig.test.json +0 -12
- package/src/__tests__/invite-redemption-service.test.ts +0 -1180
- package/src/__tests__/invite-service-ipc.test.ts +0 -350
- package/src/__tests__/job-handler-registry-guard.test.ts +0 -125
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +0 -203
- package/src/__tests__/relay-server.test.ts +0 -6153
- package/src/__tests__/telephony-stt-routing.test.ts +0 -329
- package/src/__tests__/voice-invite-redemption.test.ts +0 -702
- package/src/calls/relay-server.ts +0 -2463
- package/src/calls/telephony-stt-routing.ts +0 -145
- package/src/contacts/__tests__/contacts-write-revoke-relay.test.ts +0 -128
- package/src/daemon/__tests__/daemon-skill-host.test.ts +0 -273
- package/src/daemon/daemon-skill-host.ts +0 -262
- package/src/daemon/message-types/meet.ts +0 -143
- package/src/daemon/shutdown-registry.ts +0 -40
- package/src/ipc/__tests__/skill-server-bidirectional.test.ts +0 -253
- package/src/ipc/__tests__/skill-server.test.ts +0 -182
- package/src/ipc/skill-ipc-types.ts +0 -54
- package/src/ipc/skill-routes/__tests__/config.test.ts +0 -146
- package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +0 -448
- package/src/ipc/skill-routes/__tests__/identity.test.ts +0 -62
- package/src/ipc/skill-routes/__tests__/log.test.ts +0 -133
- package/src/ipc/skill-routes/__tests__/memory.test.ts +0 -203
- package/src/ipc/skill-routes/__tests__/platform.test.ts +0 -111
- package/src/ipc/skill-routes/__tests__/providers.test.ts +0 -265
- package/src/ipc/skill-routes/__tests__/registries.test.ts +0 -400
- package/src/ipc/skill-routes/config.ts +0 -47
- package/src/ipc/skill-routes/events.ts +0 -147
- package/src/ipc/skill-routes/identity.ts +0 -21
- package/src/ipc/skill-routes/index.ts +0 -37
- package/src/ipc/skill-routes/log.ts +0 -40
- package/src/ipc/skill-routes/memory.ts +0 -92
- package/src/ipc/skill-routes/platform.ts +0 -39
- package/src/ipc/skill-routes/providers.ts +0 -162
- package/src/ipc/skill-routes/registries.ts +0 -338
- package/src/ipc/skill-server.ts +0 -831
- package/src/ipc/skill-socket-path.ts +0 -20
- package/src/jobs/register-job-handlers.ts +0 -74
- package/src/persistence/invite-store.ts +0 -481
- package/src/plugins/job-handler-registry.ts +0 -94
- package/src/providers/cache-control.ts +0 -26
- package/src/runtime/__tests__/runtime-mode.test.ts +0 -62
- package/src/runtime/invite-redemption-service.ts +0 -828
- package/src/runtime/invite-redemption-templates.ts +0 -46
- package/src/runtime/runtime-mode.ts +0 -40
- package/src/runtime/slack-dm-text-delivery.ts +0 -177
- package/src/util/voice-code.ts +0 -31
|
@@ -133,3 +133,67 @@ describe("buildSectionNeedle", () => {
|
|
|
133
133
|
expect(results.map((r) => r.article)).toEqual(["page-a", "page-b"]);
|
|
134
134
|
});
|
|
135
135
|
});
|
|
136
|
+
|
|
137
|
+
describe("queryScored", () => {
|
|
138
|
+
/** Drop the score, leaving the shape `query` returns. */
|
|
139
|
+
const strip = ({ article, section }: { article: Slug; section: number }) => ({
|
|
140
|
+
article,
|
|
141
|
+
section,
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
test("scores are non-increasing in rank order", async () => {
|
|
145
|
+
const idx = await index({
|
|
146
|
+
"page-a": "## S\nshared keyword apple here",
|
|
147
|
+
"page-b": "## S\nshared keyword apple here too with extra apple apple",
|
|
148
|
+
"page-c": "## S\nshared keyword apple again",
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
const needle = buildSectionNeedle(idx);
|
|
152
|
+
const hits = needle.queryScored("apple", 5);
|
|
153
|
+
|
|
154
|
+
expect(hits.length).toBeGreaterThan(1);
|
|
155
|
+
for (let i = 1; i < hits.length; i++) {
|
|
156
|
+
expect(hits[i]!.score).toBeLessThanOrEqual(hits[i - 1]!.score);
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
test("parity with query (scores stripped)", async () => {
|
|
161
|
+
const idx = await index({
|
|
162
|
+
"page-a": "## S\nshared keyword apple here",
|
|
163
|
+
"page-b": "## S\nshared keyword apple here too",
|
|
164
|
+
"page-c": "## S\nshared keyword apple again",
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
const needle = buildSectionNeedle(idx);
|
|
168
|
+
for (const k of [1, 2, 5]) {
|
|
169
|
+
expect(needle.queryScored("apple", k).map(strip)).toEqual(
|
|
170
|
+
needle.query("apple", k),
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
test("top score is positive and discriminates between hits", async () => {
|
|
176
|
+
const idx = await index({
|
|
177
|
+
"page-a":
|
|
178
|
+
"## Intro\ngeneral background prose\n\n## Details\nthe elephant appears only here",
|
|
179
|
+
"topic-x": "## Notes\nunrelated material about gardens",
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
const needle = buildSectionNeedle(idx);
|
|
183
|
+
const hits = needle.queryScored("elephant", 5);
|
|
184
|
+
|
|
185
|
+
expect(hits.length).toBeGreaterThan(0);
|
|
186
|
+
expect(hits[0]!.score).toBeGreaterThan(0);
|
|
187
|
+
if (hits.length >= 2) {
|
|
188
|
+
expect(hits[0]!.score).toBeGreaterThan(hits[1]!.score);
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
test("empty for no match and for k <= 0", async () => {
|
|
193
|
+
const idx = await index({ "page-a": "## S\nshared keyword apple here" });
|
|
194
|
+
const needle = buildSectionNeedle(idx);
|
|
195
|
+
|
|
196
|
+
expect(needle.queryScored("zzzznomatch", 5)).toEqual([]);
|
|
197
|
+
expect(needle.queryScored("apple", 0)).toEqual([]);
|
|
198
|
+
});
|
|
199
|
+
});
|
|
@@ -56,21 +56,17 @@ let mockActive = false;
|
|
|
56
56
|
|
|
57
57
|
let providerStub: Provider | null = null;
|
|
58
58
|
|
|
59
|
-
//
|
|
60
|
-
//
|
|
61
|
-
//
|
|
62
|
-
//
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
mock.module("../../../../../providers/provider-send-message.js", () => ({
|
|
67
|
-
...realProvider,
|
|
59
|
+
// The select pool imports `getConfiguredProvider` from `@vellumai/plugin-api`.
|
|
60
|
+
// Spread the real contract module so unrelated exports stay present; override
|
|
61
|
+
// only `getConfiguredProvider`, and only while this file is active so the stub
|
|
62
|
+
// cannot leak into sibling tests.
|
|
63
|
+
const realPluginApi = await import("@vellumai/plugin-api");
|
|
64
|
+
mock.module("@vellumai/plugin-api", () => ({
|
|
65
|
+
...realPluginApi,
|
|
68
66
|
getConfiguredProvider: async (
|
|
69
|
-
...args: Parameters<typeof
|
|
67
|
+
...args: Parameters<typeof realPluginApi.getConfiguredProvider>
|
|
70
68
|
) =>
|
|
71
|
-
mockActive ? providerStub :
|
|
72
|
-
extractToolUse: (response: ProviderResponse) =>
|
|
73
|
-
response.content.find((b) => b.type === "tool_use"),
|
|
69
|
+
mockActive ? providerStub : realPluginApi.getConfiguredProvider(...args),
|
|
74
70
|
}));
|
|
75
71
|
|
|
76
72
|
mock.module("../../../../../util/logger.js", () => ({
|
|
@@ -89,6 +85,15 @@ mock.module("../dense.js", () => ({
|
|
|
89
85
|
...realDense,
|
|
90
86
|
denseLane: async (...args: Parameters<typeof realDense.denseLane>) =>
|
|
91
87
|
mockActive ? denseHits : realDense.denseLane(...args),
|
|
88
|
+
// Orchestrate calls the SCORED variant; intercept it under the same
|
|
89
|
+
// `mockActive` guard (the gate is disabled in these tests, so the score is
|
|
90
|
+
// arbitrary — a constant 1) so the swap can't leak through to real Qdrant.
|
|
91
|
+
denseLaneScored: async (
|
|
92
|
+
...args: Parameters<typeof realDense.denseLaneScored>
|
|
93
|
+
) =>
|
|
94
|
+
mockActive
|
|
95
|
+
? denseHits.map((h) => ({ ...h, score: 1 }))
|
|
96
|
+
: realDense.denseLaneScored(...args),
|
|
92
97
|
}));
|
|
93
98
|
|
|
94
99
|
// In-memory selections DB. `summarizeSelections` reads via getDb/getSqliteFrom;
|
|
@@ -25,6 +25,7 @@ import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
|
|
|
25
25
|
|
|
26
26
|
import { drizzle } from "drizzle-orm/bun-sqlite";
|
|
27
27
|
|
|
28
|
+
import { MemoryV3GateSchema } from "../../../../../config/schemas/memory-v3.js";
|
|
28
29
|
import { migrateAddMemoryV3Selections } from "../../../../../persistence/migrations/268-add-memory-v3-selections.js";
|
|
29
30
|
import { migrateAddMemoryV3EverInjected } from "../../../../../persistence/migrations/277-add-memory-v3-ever-injected.js";
|
|
30
31
|
import { migrateMemoryV3SelectionsMessageIdAndSections } from "../../../../../persistence/migrations/283-memory-v3-selections-message-id-and-sections.js";
|
|
@@ -88,8 +89,20 @@ let extraRealConceptPages = 0;
|
|
|
88
89
|
// Mutable mocked config knob (orchestrate-only) for asserting per-turn tuning
|
|
89
90
|
// re-resolution from a live config edit.
|
|
90
91
|
let selectorEnabledCfg = false;
|
|
92
|
+
// Drives the `memory-v3-injection-gate` feature flag through the shared
|
|
93
|
+
// assistant-feature-flags mock below (default off).
|
|
94
|
+
let gateFlagEnabled = false;
|
|
95
|
+
// Mutable `memory.v3.gate.enabled` config kill-switch carried by the mocked
|
|
96
|
+
// config (default on, mirroring the schema default).
|
|
97
|
+
let gateEnabledCfg = true;
|
|
91
98
|
let messages: Array<{ role: string; content: string }> = [];
|
|
92
99
|
|
|
100
|
+
// Schema defaults for `memory.v3.gate` (the tuning the mocked config carries
|
|
101
|
+
// and the gate-config threading test asserts against). Includes the default-on
|
|
102
|
+
// `enabled` kill-switch; `observeTurn` overwrites `enabled` with the effective
|
|
103
|
+
// flag AND config value.
|
|
104
|
+
const GATE_DEFAULTS = MemoryV3GateSchema.parse({});
|
|
105
|
+
|
|
93
106
|
// A synthetic skill capability slug the page index carries. Its rendered
|
|
94
107
|
// content holds a distinctive term ("kumquat") so the real needle, built over
|
|
95
108
|
// the section index `initLanes` feeds, ranks it. Generic placeholder only.
|
|
@@ -185,7 +198,11 @@ const FAKE_SECTION_INDEX: SectionIndex = {
|
|
|
185
198
|
|
|
186
199
|
mock.module("../../../../../config/assistant-feature-flags.js", () => ({
|
|
187
200
|
isAssistantFeatureFlagEnabled: (key: string) =>
|
|
188
|
-
key === "memory-v3-live"
|
|
201
|
+
key === "memory-v3-live"
|
|
202
|
+
? liveEnabled
|
|
203
|
+
: key === "memory-v3-injection-gate"
|
|
204
|
+
? gateFlagEnabled
|
|
205
|
+
: false,
|
|
189
206
|
}));
|
|
190
207
|
|
|
191
208
|
mock.module("../../../../../config/loader.js", () => ({
|
|
@@ -211,6 +228,10 @@ mock.module("../../../../../config/loader.js", () => ({
|
|
|
211
228
|
},
|
|
212
229
|
edge: { hubDegree: 30, seedCount: 6, perSeed: 1, cap: 6 },
|
|
213
230
|
entity: { enabled: true, idfFloor: 4, cap: 8 },
|
|
231
|
+
// Gate tuning (schema defaults) with the mutable `enabled` kill-switch;
|
|
232
|
+
// `observeTurn` spreads this and overwrites `enabled` with the effective
|
|
233
|
+
// flag AND config value before passing to orchestrate.
|
|
234
|
+
gate: { ...GATE_DEFAULTS, enabled: gateEnabledCfg },
|
|
214
235
|
},
|
|
215
236
|
qdrant: { vectorSize: 8, onDisk: false },
|
|
216
237
|
},
|
|
@@ -438,6 +459,8 @@ beforeEach(() => {
|
|
|
438
459
|
learnedEdgesCap = 0;
|
|
439
460
|
extraRealConceptPages = 0;
|
|
440
461
|
selectorEnabledCfg = false;
|
|
462
|
+
gateFlagEnabled = false;
|
|
463
|
+
gateEnabledCfg = true;
|
|
441
464
|
messages = [
|
|
442
465
|
{
|
|
443
466
|
role: "user",
|
|
@@ -662,6 +685,44 @@ describe("memory-v3 engine", () => {
|
|
|
662
685
|
expect(secondDeps.selectorEnabled).toBe(true);
|
|
663
686
|
});
|
|
664
687
|
|
|
688
|
+
test("flag on → threads the gate tuning plus enabled:true into orchestrate", async () => {
|
|
689
|
+
gateFlagEnabled = true;
|
|
690
|
+
await observeTurn("conv-1", 0);
|
|
691
|
+
|
|
692
|
+
const deps = (
|
|
693
|
+
orchestrateSpy.mock.calls as unknown as unknown[][]
|
|
694
|
+
)[0]![1] as { gateConfig?: unknown };
|
|
695
|
+
// The spread is the live gate config: the `memory.v3.gate` tuning with the
|
|
696
|
+
// flag-derived `enabled` folded in.
|
|
697
|
+
expect(deps.gateConfig).toEqual({ ...GATE_DEFAULTS, enabled: true });
|
|
698
|
+
});
|
|
699
|
+
|
|
700
|
+
test("flag off (default) → gate config threads inert (enabled:false, schema-default tuning)", async () => {
|
|
701
|
+
// gateFlagEnabled defaults to false in beforeEach.
|
|
702
|
+
await observeTurn("conv-1", 0);
|
|
703
|
+
|
|
704
|
+
const deps = (
|
|
705
|
+
orchestrateSpy.mock.calls as unknown as unknown[][]
|
|
706
|
+
)[0]![1] as { gateConfig?: { enabled?: boolean } };
|
|
707
|
+
// Flag off → the gate is wired in but inert, and the tuning fields are the
|
|
708
|
+
// schema defaults the config carries.
|
|
709
|
+
expect(deps.gateConfig?.enabled).toBe(false);
|
|
710
|
+
expect(deps.gateConfig).toEqual({ ...GATE_DEFAULTS, enabled: false });
|
|
711
|
+
});
|
|
712
|
+
|
|
713
|
+
test("flag on + gate.enabled:false config kill-switch → gate threads inert", async () => {
|
|
714
|
+
gateFlagEnabled = true;
|
|
715
|
+
gateEnabledCfg = false;
|
|
716
|
+
await observeTurn("conv-1", 0);
|
|
717
|
+
|
|
718
|
+
const deps = (
|
|
719
|
+
orchestrateSpy.mock.calls as unknown as unknown[][]
|
|
720
|
+
)[0]![1] as { gateConfig?: unknown };
|
|
721
|
+
// The config kill-switch wins over the flag: the effective `enabled` is
|
|
722
|
+
// false, so selection always runs.
|
|
723
|
+
expect(deps.gateConfig).toEqual({ ...GATE_DEFAULTS, enabled: false });
|
|
724
|
+
});
|
|
725
|
+
|
|
665
726
|
test("initLanes filters core to existing pages and excludes core from the hot set", async () => {
|
|
666
727
|
// The core file lists a live page and a dangling slug; the hot set returns
|
|
667
728
|
// a live page and a deleted one (selection rows can outlive their pages).
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
FRONTMATTER_REGEX,
|
|
3
|
-
parseFrontmatterFields,
|
|
4
|
-
} from "../../../../skills/frontmatter.js";
|
|
1
|
+
import { FRONTMATTER_REGEX, parseFrontmatterFields } from "../frontmatter.js";
|
|
5
2
|
import { injectedConceptHeader } from "../v2/injected-block-slugs.js";
|
|
6
3
|
import type { Slug } from "./types.js";
|
|
7
4
|
|
|
@@ -16,11 +16,9 @@
|
|
|
16
16
|
// forward regardless, so a dense outage narrows recall but never breaks a turn.
|
|
17
17
|
|
|
18
18
|
import type { AssistantConfig } from "../../../../config/types.js";
|
|
19
|
-
import {
|
|
20
|
-
embedWithBackend,
|
|
21
|
-
isEmbeddingDimensionAvailable,
|
|
22
|
-
} from "../../../../persistence/embeddings/embedding-backend.js";
|
|
19
|
+
import { isEmbeddingDimensionAvailable } from "../../../../persistence/embeddings/embedding-backend.js";
|
|
23
20
|
import { getLogger } from "../../../../util/logger.js";
|
|
21
|
+
import { embedWithBackend } from "../embeddings.js";
|
|
24
22
|
import {
|
|
25
23
|
getSectionDenseClient,
|
|
26
24
|
SECTION_COLLECTION,
|
|
@@ -42,12 +40,21 @@ export interface DenseHit {
|
|
|
42
40
|
section: number;
|
|
43
41
|
}
|
|
44
42
|
|
|
43
|
+
/** A dense-lane hit plus the raw cosine similarity Qdrant returned. */
|
|
44
|
+
export interface DenseHitScored {
|
|
45
|
+
article: Slug;
|
|
46
|
+
section: number;
|
|
47
|
+
score: number;
|
|
48
|
+
}
|
|
49
|
+
|
|
45
50
|
/**
|
|
46
|
-
* Run the dense lane: embed `query`, search
|
|
47
|
-
* `k * OVERSAMPLE` section points, then dedupe
|
|
48
|
-
* — each with its best-scoring section ordinal
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
+
* Run the dense lane and keep each hit's raw cosine score: embed `query`, search
|
|
52
|
+
* the section collection for the top `k * OVERSAMPLE` section points, then dedupe
|
|
53
|
+
* to the top-`k` distinct articles — each with its best-scoring section ordinal
|
|
54
|
+
* and that section's cosine score. Section points are returned by Qdrant in
|
|
55
|
+
* descending score order, so the first time an article is seen is its best
|
|
56
|
+
* section; subsequent sections of the same article are ignored. A point that
|
|
57
|
+
* arrives without a `score` is recorded as `0`.
|
|
51
58
|
*
|
|
52
59
|
* Returns `[]` on any embedding or Qdrant failure (logged at warn level), and
|
|
53
60
|
* short-circuits to `[]` when the reachable backend cannot produce vectors of
|
|
@@ -55,31 +62,33 @@ export interface DenseHit {
|
|
|
55
62
|
* so a 3072-dim collection committed while only a 384-dim backend is reachable
|
|
56
63
|
* narrows recall cleanly rather than failing the dimension assertion every turn.
|
|
57
64
|
*/
|
|
58
|
-
export async function
|
|
65
|
+
export async function denseLaneScored(
|
|
59
66
|
config: AssistantConfig,
|
|
60
67
|
query: string,
|
|
61
68
|
k: number,
|
|
62
|
-
): Promise<
|
|
69
|
+
): Promise<DenseHitScored[]> {
|
|
63
70
|
if (k <= 0) return [];
|
|
64
71
|
|
|
65
|
-
if (!(await isEmbeddingDimensionAvailable(config))) {
|
|
66
|
-
return [];
|
|
67
|
-
}
|
|
68
|
-
|
|
69
72
|
let points: Array<{ payload?: unknown; score?: number }>;
|
|
70
73
|
try {
|
|
74
|
+
// Inside the try so a rejecting probe (e.g. a transient credential-store
|
|
75
|
+
// error surfacing through getProviderKeyAsync) degrades to `[]` instead of
|
|
76
|
+
// throwing — the orchestrator calls this lane in an unguarded Promise.all
|
|
77
|
+
// that relies on the `[]` contract, so one throw would discard the sibling
|
|
78
|
+
// lanes too. The check itself skips the embed on a dimension mismatch.
|
|
79
|
+
if (!(await isEmbeddingDimensionAvailable(config))) {
|
|
80
|
+
return [];
|
|
81
|
+
}
|
|
82
|
+
|
|
71
83
|
const { vectors } = await embedWithBackend(config, [query]);
|
|
72
84
|
const vector = vectors[0];
|
|
73
85
|
if (!vector || vector.length === 0) return [];
|
|
74
86
|
|
|
75
|
-
const result = await getSectionDenseClient(
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
with_payload: true,
|
|
81
|
-
},
|
|
82
|
-
);
|
|
87
|
+
const result = await getSectionDenseClient().query(SECTION_COLLECTION, {
|
|
88
|
+
query: vector,
|
|
89
|
+
limit: k * OVERSAMPLE,
|
|
90
|
+
with_payload: true,
|
|
91
|
+
});
|
|
83
92
|
points = result.points;
|
|
84
93
|
} catch (err) {
|
|
85
94
|
log.warn({ err }, "memory v3 dense lane failed; degrading to no hits");
|
|
@@ -89,7 +98,7 @@ export async function denseLane(
|
|
|
89
98
|
// Walk hits in score order, keeping the first (best) section per article and
|
|
90
99
|
// stopping once we have `k` distinct articles.
|
|
91
100
|
const seen = new Set<Slug>();
|
|
92
|
-
const hits:
|
|
101
|
+
const hits: DenseHitScored[] = [];
|
|
93
102
|
for (const point of points) {
|
|
94
103
|
const payload = point.payload as
|
|
95
104
|
| { article?: unknown; ordinal?: unknown }
|
|
@@ -100,9 +109,35 @@ export async function denseLane(
|
|
|
100
109
|
if (typeof article !== "string" || typeof ordinal !== "number") continue;
|
|
101
110
|
if (seen.has(article)) continue;
|
|
102
111
|
seen.add(article);
|
|
103
|
-
hits.push({ article, section: ordinal });
|
|
112
|
+
hits.push({ article, section: ordinal, score: point.score ?? 0 });
|
|
104
113
|
if (hits.length >= k) break;
|
|
105
114
|
}
|
|
106
115
|
|
|
107
116
|
return hits;
|
|
108
117
|
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Run the dense lane: embed `query`, search the section collection for the top
|
|
121
|
+
* `k * OVERSAMPLE` section points, then dedupe to the top-`k` distinct articles
|
|
122
|
+
* — each with its best-scoring section ordinal. Section points are returned by
|
|
123
|
+
* Qdrant in descending score order, so the first time an article is seen is its
|
|
124
|
+
* best section; subsequent sections of the same article are ignored.
|
|
125
|
+
*
|
|
126
|
+
* Returns `[]` on any embedding or Qdrant failure (logged at warn level), and
|
|
127
|
+
* short-circuits to `[]` when the reachable backend cannot produce vectors of
|
|
128
|
+
* the committed collection dimension (degraded backend or dimension mismatch) —
|
|
129
|
+
* so a 3072-dim collection committed while only a 384-dim backend is reachable
|
|
130
|
+
* narrows recall cleanly rather than failing the dimension assertion every turn.
|
|
131
|
+
*
|
|
132
|
+
* Thin wrapper over {@link denseLaneScored} that drops the raw cosine score for
|
|
133
|
+
* callers that only need the matched article and section.
|
|
134
|
+
*/
|
|
135
|
+
export async function denseLane(
|
|
136
|
+
config: AssistantConfig,
|
|
137
|
+
query: string,
|
|
138
|
+
k: number,
|
|
139
|
+
): Promise<DenseHit[]> {
|
|
140
|
+
return (await denseLaneScored(config, query, k)).map(
|
|
141
|
+
({ article, section }) => ({ article, section }),
|
|
142
|
+
);
|
|
143
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { isAssistantFeatureFlagEnabled } from "../../../../config/assistant-feature-flags.js";
|
|
2
|
+
import type { AssistantConfig } from "../../../../config/schema.js";
|
|
3
|
+
|
|
4
|
+
/** Feature-flag id (kebab-case) gating the memory-v3 per-turn injection gate. */
|
|
5
|
+
export const MEMORY_V3_INJECTION_GATE_FLAG =
|
|
6
|
+
"memory-v3-injection-gate" as const;
|
|
7
|
+
|
|
8
|
+
/** Whether the memory-v3 injection gate is enabled for this config: the
|
|
9
|
+
* feature flag (resolved via the standard assistant flag resolver — gateway
|
|
10
|
+
* override → registry default → false) AND the `memory.v3.gate.enabled`
|
|
11
|
+
* config kill-switch. `enabled: false` forces the full selection process
|
|
12
|
+
* every turn even with the flag on. Thresholds live in `memory.v3.gate`. */
|
|
13
|
+
export function isMemoryV3InjectionGateEnabled(
|
|
14
|
+
config: AssistantConfig,
|
|
15
|
+
): boolean {
|
|
16
|
+
return (
|
|
17
|
+
isAssistantFeatureFlagEnabled(MEMORY_V3_INJECTION_GATE_FLAG, config) &&
|
|
18
|
+
config.memory.v3.gate.enabled
|
|
19
|
+
);
|
|
20
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Memory v3 — per-turn injection gate (pure score check)
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
//
|
|
5
|
+
// Decides whether the finder-lane retrieval scores clear the injection
|
|
6
|
+
// thresholds for this turn. Three ways to pass:
|
|
7
|
+
// - dense_pass: top-1 dense cosine clears `denseThreshold`.
|
|
8
|
+
// - dense_cluster: dense top-1 falls short but the whole top-3 dense
|
|
9
|
+
// cluster sits above `denseClusterThreshold` within a
|
|
10
|
+
// tight `denseClusterMaxDelta` spread (a coherent-but-
|
|
11
|
+
// borderline neighbourhood).
|
|
12
|
+
// - sparse_only_strong: dense fails outright but normalized top-1 BM25F clears
|
|
13
|
+
// the higher `sparseOnlyThreshold` bar.
|
|
14
|
+
//
|
|
15
|
+
// A zero-overlap hard floor keeps sparse signal honest: a raw BM25F of `0` means
|
|
16
|
+
// no query term matched any section, so the sparse lane can never open the gate
|
|
17
|
+
// regardless of how the thresholds are tuned.
|
|
18
|
+
//
|
|
19
|
+
// This module is intentionally PURE — no async, no I/O, no logging, and no
|
|
20
|
+
// imports beyond the two scored-hit types. `config.enabled` is the resolved
|
|
21
|
+
// effective enable (feature flag AND `memory.v3.gate.enabled`) supplied by the
|
|
22
|
+
// caller, which also feeds in the finder-lane hits.
|
|
23
|
+
|
|
24
|
+
import type { DenseHitScored } from "./dense.js";
|
|
25
|
+
import type { SectionNeedleScoredHit } from "./section-needle.js";
|
|
26
|
+
|
|
27
|
+
/** BM25F normalization constant when config.bm25NormK is null.
|
|
28
|
+
* TODO(memory-v3): replace with per-corpus auto-calibration. */
|
|
29
|
+
export const DEFAULT_BM25_NORM_K = 9.0;
|
|
30
|
+
|
|
31
|
+
export type V3GateReason =
|
|
32
|
+
| "dense_pass"
|
|
33
|
+
| "dense_cluster"
|
|
34
|
+
| "sparse_only_strong"
|
|
35
|
+
| "fail_no_signal"
|
|
36
|
+
| "fail_dense_below_and_sparse_weak"
|
|
37
|
+
| "disabled";
|
|
38
|
+
|
|
39
|
+
export interface V3GateConfig {
|
|
40
|
+
enabled: boolean; // effective enable — flag AND config kill-switch, resolved in observeTurn
|
|
41
|
+
denseThreshold: number;
|
|
42
|
+
sparseThreshold: number;
|
|
43
|
+
sparseOnlyThreshold: number;
|
|
44
|
+
denseClusterThreshold: number;
|
|
45
|
+
denseClusterMaxDelta: number;
|
|
46
|
+
topK: number;
|
|
47
|
+
bm25NormK: number | null;
|
|
48
|
+
bypassForCore: boolean; // consumed by orchestrate, not by checkV3Gate
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface V3GateResult {
|
|
52
|
+
pass: boolean;
|
|
53
|
+
reason: V3GateReason;
|
|
54
|
+
topDenseScore: number | null;
|
|
55
|
+
topSparseScore: number | null; // raw BM25F
|
|
56
|
+
topNormSparseScore: number | null; // normalized BM25F
|
|
57
|
+
denseScores: number[]; // top-K cosine, desc
|
|
58
|
+
sparseScores: number[]; // top-K raw BM25F, desc
|
|
59
|
+
checkedArticles: number;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface V3CheckGateParams {
|
|
63
|
+
needleHits: SectionNeedleScoredHit[];
|
|
64
|
+
denseHits: DenseHitScored[];
|
|
65
|
+
config: V3GateConfig;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Pure injection-gate score check. Given the finder-lane hits and the gate
|
|
70
|
+
* tuning, decides whether retrieval is confident enough to run the selector.
|
|
71
|
+
*
|
|
72
|
+
* `config.bypassForCore` is intentionally NOT read here: whether a closed gate
|
|
73
|
+
* skips entirely versus selecting only the stable core prefix is an
|
|
74
|
+
* orchestrate-level decision, not part of the score check.
|
|
75
|
+
*/
|
|
76
|
+
export function checkV3Gate(params: V3CheckGateParams): V3GateResult {
|
|
77
|
+
const { needleHits, denseHits, config } = params;
|
|
78
|
+
|
|
79
|
+
if (!config.enabled) {
|
|
80
|
+
return {
|
|
81
|
+
pass: true,
|
|
82
|
+
reason: "disabled",
|
|
83
|
+
topDenseScore: null,
|
|
84
|
+
topSparseScore: null,
|
|
85
|
+
topNormSparseScore: null,
|
|
86
|
+
denseScores: [],
|
|
87
|
+
sparseScores: [],
|
|
88
|
+
checkedArticles: 0,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const k = Math.max(1, config.topK);
|
|
93
|
+
const denseScores = denseHits
|
|
94
|
+
.map((h) => h.score)
|
|
95
|
+
.sort((a, b) => b - a)
|
|
96
|
+
.slice(0, k);
|
|
97
|
+
const sparseScores = needleHits
|
|
98
|
+
.map((h) => h.score)
|
|
99
|
+
.sort((a, b) => b - a)
|
|
100
|
+
.slice(0, k);
|
|
101
|
+
|
|
102
|
+
const topDense = denseScores[0] ?? null;
|
|
103
|
+
const topSparseRaw = sparseScores[0] ?? null;
|
|
104
|
+
|
|
105
|
+
const normK = config.bm25NormK ?? DEFAULT_BM25_NORM_K;
|
|
106
|
+
const topNorm =
|
|
107
|
+
topSparseRaw === null ? null : topSparseRaw / (topSparseRaw + normK);
|
|
108
|
+
|
|
109
|
+
const checkedArticles = new Set(
|
|
110
|
+
[...denseHits, ...needleHits].map((h) => h.article),
|
|
111
|
+
).size;
|
|
112
|
+
|
|
113
|
+
const densePass = topDense !== null && topDense >= config.denseThreshold;
|
|
114
|
+
|
|
115
|
+
const top3 = denseScores.slice(0, 3);
|
|
116
|
+
const denseCluster =
|
|
117
|
+
!densePass &&
|
|
118
|
+
top3.length === 3 &&
|
|
119
|
+
top3.every((s) => s >= config.denseClusterThreshold) &&
|
|
120
|
+
top3[0]! - top3[2]! <= config.denseClusterMaxDelta;
|
|
121
|
+
|
|
122
|
+
// Hard floor: a raw BM25F of 0 means no query term matched any section, so the
|
|
123
|
+
// sparse lane is treated as carrying no usable signal no matter the thresholds.
|
|
124
|
+
const sparseUsable = topSparseRaw !== null && topSparseRaw > 0;
|
|
125
|
+
const normSparse = sparseUsable ? topNorm! : 0;
|
|
126
|
+
|
|
127
|
+
const sparsePass = sparseUsable && normSparse >= config.sparseThreshold;
|
|
128
|
+
const sparseOnlyStrong =
|
|
129
|
+
!(densePass || denseCluster) &&
|
|
130
|
+
sparseUsable &&
|
|
131
|
+
normSparse >= config.sparseOnlyThreshold;
|
|
132
|
+
|
|
133
|
+
const pass = densePass || denseCluster || sparseOnlyStrong;
|
|
134
|
+
|
|
135
|
+
let reason: V3GateReason;
|
|
136
|
+
if (densePass) {
|
|
137
|
+
reason = "dense_pass";
|
|
138
|
+
} else if (denseCluster) {
|
|
139
|
+
reason = "dense_cluster";
|
|
140
|
+
} else if (sparseOnlyStrong) {
|
|
141
|
+
reason = "sparse_only_strong";
|
|
142
|
+
} else if (sparsePass) {
|
|
143
|
+
reason = "fail_dense_below_and_sparse_weak";
|
|
144
|
+
} else {
|
|
145
|
+
reason = "fail_no_signal";
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return {
|
|
149
|
+
pass,
|
|
150
|
+
reason,
|
|
151
|
+
topDenseScore: topDense,
|
|
152
|
+
topSparseScore: topSparseRaw,
|
|
153
|
+
topNormSparseScore: topNorm, // null only when no sparse hits; 0 when raw is 0
|
|
154
|
+
denseScores,
|
|
155
|
+
sparseScores,
|
|
156
|
+
checkedArticles,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
@@ -68,10 +68,7 @@ import {
|
|
|
68
68
|
getMemoryCheckpoint,
|
|
69
69
|
setMemoryCheckpoint,
|
|
70
70
|
} from "../../../../persistence/checkpoints.js";
|
|
71
|
-
import {
|
|
72
|
-
EmbeddingBackendUnavailableError,
|
|
73
|
-
embedWithBackend,
|
|
74
|
-
} from "../../../../persistence/embeddings/embedding-backend.js";
|
|
71
|
+
import { EmbeddingBackendUnavailableError } from "../../../../persistence/embeddings/embedding-backend.js";
|
|
75
72
|
import { EmbeddingBillingBlockError } from "../../../../persistence/embeddings/embedding-billing-breaker.js";
|
|
76
73
|
import type { MemoryJob } from "../../../../persistence/jobs-store.js";
|
|
77
74
|
import {
|
|
@@ -81,6 +78,7 @@ import {
|
|
|
81
78
|
import { executeDeleteManagedSkill } from "../../../../tools/skills/delete-managed.js";
|
|
82
79
|
import { getLogger } from "../../../../util/logger.js";
|
|
83
80
|
import { getWorkspaceDir } from "../../../../util/platform.js";
|
|
81
|
+
import { embedWithBackend } from "../embeddings.js";
|
|
84
82
|
import { getPageIndex } from "../v2/page-index.js";
|
|
85
83
|
import { readPage } from "../v2/page-store.js";
|
|
86
84
|
import { skillSlugFor } from "../v2/skill-store.js";
|