@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
|
@@ -17,6 +17,14 @@
|
|
|
17
17
|
* associations the authored link graph does not record.
|
|
18
18
|
* Each lane only ever ADDS candidates, so the pool is recall-safe by
|
|
19
19
|
* construction.
|
|
20
|
+
* 1b. OPT-IN injection gate (`deps.gateConfig.enabled`, default off): once the
|
|
21
|
+
* CURRENT-message finder lanes have run, `checkV3Gate` scores the needle +
|
|
22
|
+
* dense hits against the tuned thresholds. A closed gate skips the
|
|
23
|
+
* selectPool LLM call for the turn — returning empty selections (or, when
|
|
24
|
+
* `bypassForCore` is set, selecting over the stable prefix only via the
|
|
25
|
+
* same selector dispatch as the normal path, honoring `selectorEnabled`) —
|
|
26
|
+
* so a low-signal turn pays no selector cost. The gate is pass-open: any
|
|
27
|
+
* throw inside it logs a warning and falls through to normal selection.
|
|
20
28
|
* 2. Build the candidate pool in CACHE ORDER: the stable prefix —
|
|
21
29
|
* `[...core (file order), ...hot (score order), ...fresh (recency order),
|
|
22
30
|
* ...always-candidate (skills pinned every turn)]`, all computed at lane
|
|
@@ -47,12 +55,19 @@
|
|
|
47
55
|
*/
|
|
48
56
|
|
|
49
57
|
import type { AssistantConfig } from "../../../../config/schema.js";
|
|
50
|
-
import {
|
|
58
|
+
import { recordWatchdogEvent } from "../../../../telemetry/watchdog-events-store.js";
|
|
59
|
+
import { getLogger } from "../../../../util/logger.js";
|
|
60
|
+
import { denseLaneScored } from "./dense.js";
|
|
51
61
|
import type { EdgeGraph } from "./edge.js";
|
|
52
62
|
import { edgeExpand } from "./edge.js";
|
|
53
63
|
import type { EntityIndex } from "./entity-lane.js";
|
|
54
64
|
import { entityLane } from "./entity-lane.js";
|
|
55
|
-
import
|
|
65
|
+
import { checkV3Gate, type V3GateConfig, type V3GateResult } from "./gate.js";
|
|
66
|
+
import type {
|
|
67
|
+
PoolCandidate,
|
|
68
|
+
SelectorPool,
|
|
69
|
+
StableCandidate,
|
|
70
|
+
} from "./pool-select.js";
|
|
56
71
|
import { selectAllPoolCandidates, selectPool } from "./pool-select.js";
|
|
57
72
|
import type { SectionNeedle } from "./section-needle.js";
|
|
58
73
|
import type {
|
|
@@ -64,6 +79,32 @@ import type {
|
|
|
64
79
|
Slug,
|
|
65
80
|
} from "./types.js";
|
|
66
81
|
|
|
82
|
+
// Named to disambiguate from the unrelated `src/config/memory-v3-gate.ts`: this
|
|
83
|
+
// logger names the per-turn INJECTION gate wired in below.
|
|
84
|
+
const log = getLogger("memory-v3-injection-gate");
|
|
85
|
+
|
|
86
|
+
/** `check_name` of the `watchdog` telemetry event recorded once per
|
|
87
|
+
* injection-gate run. The platform's memory admin analytics count and filter
|
|
88
|
+
* on this exact string — keep it stable. */
|
|
89
|
+
export const MEMORY_V3_INJECTION_GATE_CHECK_NAME = "memory_v3_injection_gate";
|
|
90
|
+
|
|
91
|
+
/** Record one injection-gate run to usage telemetry. `detail` keys are the
|
|
92
|
+
* platform-side contract (snake_case, scores and reason codes only — never
|
|
93
|
+
* conversation content). Never throws: the gate is pass-open by design, and a
|
|
94
|
+
* telemetry failure must not cost the turn its memory either. */
|
|
95
|
+
function recordGateRun(detail: Record<string, unknown>): void {
|
|
96
|
+
try {
|
|
97
|
+
recordWatchdogEvent({
|
|
98
|
+
checkName: MEMORY_V3_INJECTION_GATE_CHECK_NAME,
|
|
99
|
+
value: 1,
|
|
100
|
+
detail,
|
|
101
|
+
});
|
|
102
|
+
} catch {
|
|
103
|
+
// recordWatchdogEvent already no-ops on opt-out and a missing telemetry
|
|
104
|
+
// DB; anything past that is not worth failing the turn over.
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
67
108
|
/** Default number of BM25 needle articles to fold into the pool. */
|
|
68
109
|
export const DEFAULT_NEEDLE_K = 12;
|
|
69
110
|
/** Default number of dense-lane articles to fold into the pool. */
|
|
@@ -137,6 +178,10 @@ export interface OrchestrateDeps {
|
|
|
137
178
|
/** Whether to run the selector LLM. False passes all pooled candidates
|
|
138
179
|
* straight through as selections, preserving pool-order slug dedup. */
|
|
139
180
|
selectorEnabled?: boolean;
|
|
181
|
+
/** Per-turn injection gate config (`memory.v3.gate` tuning + the flag-derived
|
|
182
|
+
* `enabled`, assembled in observeTurn). Omitted/disabled → the gate never
|
|
183
|
+
* runs and every turn proceeds to selectPool as before. */
|
|
184
|
+
gateConfig?: V3GateConfig;
|
|
140
185
|
}
|
|
141
186
|
|
|
142
187
|
/** A finder-lane candidate: the slug, the descriptor that justified it, and
|
|
@@ -209,6 +254,35 @@ export async function orchestrate(
|
|
|
209
254
|
);
|
|
210
255
|
const stablePrefix = new Set<Slug>([...coreHotFresh, ...always]);
|
|
211
256
|
|
|
257
|
+
// The stable prefix as FULL CARDS, in cache order. Pre-rendered at lane init
|
|
258
|
+
// (`prefixCards`) so the rendered prefix is byte-identical across turns. A
|
|
259
|
+
// missing card is a lane-init bug and throws (silently degrading would violate
|
|
260
|
+
// the byte-stable-prefix contract). Built lazily so the gate's bypass path can
|
|
261
|
+
// reuse the exact same construction as the normal step-2 pool assembly.
|
|
262
|
+
const buildStable = (): StableCandidate[] =>
|
|
263
|
+
[...core, ...hot, ...fresh, ...always].map((slug) => {
|
|
264
|
+
const card = deps.prefixCards.get(slug);
|
|
265
|
+
if (card === undefined) {
|
|
266
|
+
// Lane init renders a card for every core/hot slug; a hole here means
|
|
267
|
+
// the lanes and the card map are out of sync. Throw rather than render
|
|
268
|
+
// a degraded card — the caller (observeTurn) logs and skips the turn,
|
|
269
|
+
// which is better than silently breaking the byte-stable prefix.
|
|
270
|
+
throw new Error(
|
|
271
|
+
`memory-v3: no pre-rendered card for stable-prefix slug "${slug}"`,
|
|
272
|
+
);
|
|
273
|
+
}
|
|
274
|
+
return { slug, card };
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
// Run the selector over a pool, or pass its candidates straight through when
|
|
278
|
+
// the selector LLM is disabled (`selectorEnabled: false`, the new-user
|
|
279
|
+
// profile). Shared by the normal step-3 selection and the gate's
|
|
280
|
+
// bypass-to-stable path so the two cannot diverge.
|
|
281
|
+
const runSelection = async (pool: SelectorPool): Promise<SelectedPage[]> =>
|
|
282
|
+
deps.selectorEnabled === false
|
|
283
|
+
? selectAllPoolCandidates(pool)
|
|
284
|
+
: selectPool(pool, turn, deps.selectorPrompt);
|
|
285
|
+
|
|
212
286
|
// Step 1: needle (sync BM25) and the enabled dense lane (async embed +
|
|
213
287
|
// Qdrant) run in parallel. Both return distinct articles each tagged with
|
|
214
288
|
// their best-scoring section index/ordinal. The reply-query pass re-runs the
|
|
@@ -223,18 +297,27 @@ export async function orchestrate(
|
|
|
223
297
|
replyK > 0 ? (turn.previousAssistantMessage ?? "").trim() : "";
|
|
224
298
|
const denseEnabled = denseK > 0;
|
|
225
299
|
const [needled, densed, replyNeedled, replyDensed] = await Promise.all([
|
|
226
|
-
Promise.resolve(deps.needle.
|
|
300
|
+
Promise.resolve(deps.needle.queryScored(turn.currentMessage, needleK)),
|
|
227
301
|
denseEnabled
|
|
228
|
-
?
|
|
302
|
+
? denseLaneScored(deps.denseConfig, turn.currentMessage, denseK)
|
|
229
303
|
: Promise.resolve([]),
|
|
230
304
|
Promise.resolve(
|
|
231
|
-
replyQuery.length > 0 ? deps.needle.
|
|
305
|
+
replyQuery.length > 0 ? deps.needle.queryScored(replyQuery, replyK) : [],
|
|
232
306
|
),
|
|
233
307
|
replyQuery.length > 0 && denseEnabled
|
|
234
|
-
?
|
|
308
|
+
? denseLaneScored(deps.denseConfig, replyQuery, replyK)
|
|
235
309
|
: Promise.resolve([]),
|
|
236
310
|
]);
|
|
237
311
|
|
|
312
|
+
// Dense hits restricted to pages still in the live section index. A deleted
|
|
313
|
+
// page's points can linger in Qdrant; the candidate pool already drops those
|
|
314
|
+
// (see the dense finder loop), so the gate must score the same live set —
|
|
315
|
+
// stale low-scored hits for deleted pages must neither fake dense availability
|
|
316
|
+
// nor drag the gate closed while the live lanes have candidates.
|
|
317
|
+
const liveDensed = densed.filter((hit) =>
|
|
318
|
+
deps.sectionIndex.byArticle.has(hit.article),
|
|
319
|
+
);
|
|
320
|
+
|
|
238
321
|
// `matchedSections` records the matched `Section` (when one is known) for
|
|
239
322
|
// every finder hit — INCLUDING hits on stable-prefix slugs — for downstream
|
|
240
323
|
// injection/spotlight. `finder` accumulates one entry per distinct
|
|
@@ -337,6 +420,101 @@ export async function orchestrate(
|
|
|
337
420
|
}
|
|
338
421
|
}
|
|
339
422
|
|
|
423
|
+
// Step 1b''': opt-in injection gate. With the CURRENT-message finder lanes in
|
|
424
|
+
// hand (needle + dense — NOT reply/entity/edge, which only add recall), decide
|
|
425
|
+
// whether retrieval is confident enough to spend the selectPool LLM call this
|
|
426
|
+
// turn. Default-off via `?.enabled`; pass-open on any throw (a gate bug must
|
|
427
|
+
// never drop a turn's memory). A closed gate either hard-skips selection
|
|
428
|
+
// (empty selections) or, when `bypassForCore` is set, runs selectPool over the
|
|
429
|
+
// stable prefix only — never the finder tail.
|
|
430
|
+
//
|
|
431
|
+
// The gate is dense-gated: it only runs when the live dense lane produced hits
|
|
432
|
+
// (`liveDensed.length > 0`). In healthy operation dense returns top-k hits for
|
|
433
|
+
// any query, so zero live dense hits means dense is unavailable — denseK=0 (the
|
|
434
|
+
// new-user/small-corpus profile), a degraded embedding backend, a Qdrant error
|
|
435
|
+
// (`denseLaneScored` swallows these to `[]`), or only stale deleted-page points
|
|
436
|
+
// returned — NOT low relevance. checkV3Gate reads only finder scores and cannot
|
|
437
|
+
// tell those apart, so without live dense signal we pass open rather than
|
|
438
|
+
// suppress all memory (not even the core/hot/fresh prefix) on every
|
|
439
|
+
// lexically-weak turn.
|
|
440
|
+
if (deps.gateConfig?.enabled) {
|
|
441
|
+
if (liveDensed.length === 0) {
|
|
442
|
+
// No live dense hits (denseK=0 / degraded backend / Qdrant error swallowed
|
|
443
|
+
// to [] / only stale deleted-page points returned). That means dense is
|
|
444
|
+
// unavailable, not low relevance, so pass open — but record it so rollout
|
|
445
|
+
// telemetry sees these turns instead of silently skipping the gate.
|
|
446
|
+
log.info(
|
|
447
|
+
{
|
|
448
|
+
conversationId: turn.conversationId,
|
|
449
|
+
turnNumber: turn.turnNumber,
|
|
450
|
+
reason: "dense_unavailable",
|
|
451
|
+
pass: true,
|
|
452
|
+
},
|
|
453
|
+
"memory-v3 injection gate: dense lane unavailable, passing open",
|
|
454
|
+
);
|
|
455
|
+
recordGateRun({ pass: true, reason: "dense_unavailable" });
|
|
456
|
+
} else {
|
|
457
|
+
let gate: V3GateResult | null = null;
|
|
458
|
+
try {
|
|
459
|
+
gate = checkV3Gate({
|
|
460
|
+
needleHits: needled,
|
|
461
|
+
denseHits: liveDensed,
|
|
462
|
+
config: deps.gateConfig,
|
|
463
|
+
});
|
|
464
|
+
} catch (err) {
|
|
465
|
+
log.warn(
|
|
466
|
+
{
|
|
467
|
+
err: err instanceof Error ? err.message : String(err),
|
|
468
|
+
conversationId: turn.conversationId,
|
|
469
|
+
},
|
|
470
|
+
"memory-v3 injection gate threw; passing open (proceeding with selection)",
|
|
471
|
+
);
|
|
472
|
+
recordGateRun({ pass: true, reason: "gate_error" });
|
|
473
|
+
}
|
|
474
|
+
if (gate) {
|
|
475
|
+
log.info(
|
|
476
|
+
{
|
|
477
|
+
conversationId: turn.conversationId,
|
|
478
|
+
turnNumber: turn.turnNumber,
|
|
479
|
+
gate,
|
|
480
|
+
},
|
|
481
|
+
"memory-v3 injection gate decision",
|
|
482
|
+
);
|
|
483
|
+
recordGateRun({
|
|
484
|
+
pass: gate.pass,
|
|
485
|
+
reason: gate.reason,
|
|
486
|
+
top_dense_score: gate.topDenseScore,
|
|
487
|
+
top_norm_sparse_score: gate.topNormSparseScore,
|
|
488
|
+
checked_articles: gate.checkedArticles,
|
|
489
|
+
});
|
|
490
|
+
if (!gate.pass) {
|
|
491
|
+
// A closed gate produces no finder lane and no matched sections; only
|
|
492
|
+
// the `selections` differ between bypass (stable prefix) and hard-skip.
|
|
493
|
+
const closed = (selections: SelectedPage[]): OrchestrateResult => ({
|
|
494
|
+
selections,
|
|
495
|
+
matchedSections: new Map(),
|
|
496
|
+
lanes: { core, hot, fresh, finder: [] },
|
|
497
|
+
});
|
|
498
|
+
if (deps.gateConfig.bypassForCore) {
|
|
499
|
+
// Select over the stable prefix only. `runSelection` mirrors the
|
|
500
|
+
// normal path: with the selector off it passes the stable candidates
|
|
501
|
+
// straight through rather than forcing the selectPool LLM call —
|
|
502
|
+
// which a selector-disabled assistant has no provider for, so it
|
|
503
|
+
// throws MemoryV3RetrievalUnavailableError and escapes the gate on a
|
|
504
|
+
// benign low-signal turn. Reaching here means the assistant is
|
|
505
|
+
// explicitly configured with `selectorEnabled: false` AND
|
|
506
|
+
// `denseK > 0` (the dense-gated gate only runs with dense hits; the
|
|
507
|
+
// new-user profile sets `denseK: 0`, so the gate never runs for it).
|
|
508
|
+
return closed(
|
|
509
|
+
await runSelection({ stable: buildStable(), finder: [] }),
|
|
510
|
+
);
|
|
511
|
+
}
|
|
512
|
+
return closed([]);
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
|
|
340
518
|
// Step 1c: edge expansion over the top needle+dense article seeds. `alive`
|
|
341
519
|
// skips slugs already in the pool — finder-surfaced AND stable-prefix slugs
|
|
342
520
|
// (an edge hit carries no matched section, so re-surfacing a core/hot page
|
|
@@ -408,21 +586,7 @@ export async function orchestrate(
|
|
|
408
586
|
// its own snippet line so its CURRENT relevance stays visible; `selectPool`
|
|
409
587
|
// dedupes selections by slug. Finder candidates with no match text fall
|
|
410
588
|
// back to the page's lead-section snippet.
|
|
411
|
-
const stable
|
|
412
|
-
(slug) => {
|
|
413
|
-
const card = deps.prefixCards.get(slug);
|
|
414
|
-
if (card === undefined) {
|
|
415
|
-
// Lane init renders a card for every core/hot slug; a hole here means
|
|
416
|
-
// the lanes and the card map are out of sync. Throw rather than render
|
|
417
|
-
// a degraded card — the caller (observeTurn) logs and skips the turn,
|
|
418
|
-
// which is better than silently breaking the byte-stable prefix.
|
|
419
|
-
throw new Error(
|
|
420
|
-
`memory-v3: no pre-rendered card for stable-prefix slug "${slug}"`,
|
|
421
|
-
);
|
|
422
|
-
}
|
|
423
|
-
return { slug, card };
|
|
424
|
-
},
|
|
425
|
-
);
|
|
589
|
+
const stable = buildStable();
|
|
426
590
|
const finderTail: PoolCandidate[] = finder.map((c) => ({
|
|
427
591
|
slug: c.slug,
|
|
428
592
|
lane: c.lane,
|
|
@@ -437,10 +601,7 @@ export async function orchestrate(
|
|
|
437
601
|
// contract. `selectorPrompt` is the (optionally overridden) instruction
|
|
438
602
|
// scaffold; `undefined` falls through to the bundled default.
|
|
439
603
|
const pool = { stable, finder: finderTail };
|
|
440
|
-
const selections =
|
|
441
|
-
deps.selectorEnabled === false
|
|
442
|
-
? selectAllPoolCandidates(pool)
|
|
443
|
-
: await selectPool(pool, turn, deps.selectorPrompt);
|
|
604
|
+
const selections = await runSelection(pool);
|
|
444
605
|
|
|
445
606
|
return {
|
|
446
607
|
selections,
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
* empty pool → [].
|
|
11
11
|
*
|
|
12
12
|
* `mock.module` is process-global and leaks into sibling files in a directory
|
|
13
|
-
* run, so the
|
|
14
|
-
*
|
|
13
|
+
* run, so the `@vellumai/plugin-api` stub DELEGATES to the real
|
|
14
|
+
* `getConfiguredProvider` unless this test is actively running
|
|
15
15
|
* (`selectMockActive`) — mirrors `prune.test.ts` / `ever-injected-store.test.ts`.
|
|
16
16
|
*/
|
|
17
17
|
|
|
@@ -25,9 +25,7 @@ import type {
|
|
|
25
25
|
|
|
26
26
|
import type { MemoryRoutingTurn, Slug } from "./types.js";
|
|
27
27
|
|
|
28
|
-
const
|
|
29
|
-
...(await import("../../../../providers/provider-send-message.js")),
|
|
30
|
-
};
|
|
28
|
+
const realPluginApi = await import("@vellumai/plugin-api");
|
|
31
29
|
|
|
32
30
|
let selectMockActive = false;
|
|
33
31
|
let sendMessageImpl: (() => Promise<ProviderResponse>) | null = null;
|
|
@@ -40,14 +38,14 @@ const mockProvider = {
|
|
|
40
38
|
},
|
|
41
39
|
} as unknown as Provider;
|
|
42
40
|
|
|
43
|
-
mock.module("
|
|
44
|
-
...
|
|
41
|
+
mock.module("@vellumai/plugin-api", () => ({
|
|
42
|
+
...realPluginApi,
|
|
45
43
|
getConfiguredProvider: (
|
|
46
|
-
...args: Parameters<typeof
|
|
44
|
+
...args: Parameters<typeof realPluginApi.getConfiguredProvider>
|
|
47
45
|
) =>
|
|
48
46
|
selectMockActive
|
|
49
47
|
? Promise.resolve(mockProvider)
|
|
50
|
-
:
|
|
48
|
+
: realPluginApi.getConfiguredProvider(...args),
|
|
51
49
|
}));
|
|
52
50
|
|
|
53
51
|
const { MemoryV3RetrievalUnavailableError, selectPool } =
|
|
@@ -51,19 +51,19 @@ import type {
|
|
|
51
51
|
Message,
|
|
52
52
|
ToolUseContent,
|
|
53
53
|
} from "@vellumai/plugin-api";
|
|
54
|
+
import { getConfiguredProvider } from "@vellumai/plugin-api";
|
|
54
55
|
import { z } from "zod";
|
|
55
56
|
|
|
56
57
|
import { classifyConversationError } from "../../../../daemon/conversation-error.js";
|
|
57
58
|
import type { PendingConversationNotice } from "../../../../daemon/conversation-notices.js";
|
|
58
|
-
import { cachedTextBlock } from "../../../../providers/cache-control.js";
|
|
59
|
-
import {
|
|
60
|
-
extractToolUse,
|
|
61
|
-
getConfiguredProvider,
|
|
62
|
-
} from "../../../../providers/provider-send-message.js";
|
|
63
|
-
import type { ToolDefinition } from "../../../../providers/types.js";
|
|
64
59
|
import { redactLogString } from "../../../../util/log-redact.js";
|
|
65
60
|
import { getLogger } from "../../../../util/logger.js";
|
|
66
61
|
import { truncate } from "../../../../util/truncate.js";
|
|
62
|
+
import {
|
|
63
|
+
cachedTextBlock,
|
|
64
|
+
extractToolUse,
|
|
65
|
+
type ToolDefinition,
|
|
66
|
+
} from "../llm-helpers.js";
|
|
67
67
|
import { loadPromptOverride } from "../prompt-override.js";
|
|
68
68
|
import { retryForResult } from "./llm-retry.js";
|
|
69
69
|
import type { MemoryRoutingTurn, SelectedPage, Slug } from "./types.js";
|
|
@@ -60,9 +60,9 @@
|
|
|
60
60
|
|
|
61
61
|
import type { ContentBlock, Message } from "@vellumai/plugin-api";
|
|
62
62
|
|
|
63
|
-
import { getConfig } from "../../../../config/loader.js";
|
|
64
63
|
import { getDb, getSqliteFrom } from "../../../../persistence/db-connection.js";
|
|
65
64
|
import { getLogger } from "../../../../util/logger.js";
|
|
65
|
+
import { getMemoryConfig } from "../config.js";
|
|
66
66
|
import { unwrapMemoryBlock, wrapMemoryBlock } from "../memory-marker.js";
|
|
67
67
|
import {
|
|
68
68
|
INJECTED_CONCEPT_HEADER_REGEX,
|
|
@@ -393,7 +393,7 @@ export async function runPruneValve(
|
|
|
393
393
|
options: PruneValveOptions,
|
|
394
394
|
): Promise<PrunePlan | null> {
|
|
395
395
|
// Defensive read: test configs may omit the prune block entirely.
|
|
396
|
-
const pruneConfig =
|
|
396
|
+
const pruneConfig = getMemoryConfig()?.v3?.prune;
|
|
397
397
|
if (!pruneConfig) return null;
|
|
398
398
|
|
|
399
399
|
// Planning needs only the store (cheap); the persisted-metadata scan for
|
|
@@ -28,7 +28,6 @@ import type { AssistantConfig } from "../../../../config/types.js";
|
|
|
28
28
|
import { deleteMemoryCheckpoint } from "../../../../persistence/checkpoints.js";
|
|
29
29
|
import { getDb } from "../../../../persistence/db-connection.js";
|
|
30
30
|
import {
|
|
31
|
-
embedWithBackend,
|
|
32
31
|
geminiCacheExtras,
|
|
33
32
|
getMemoryBackendStatus,
|
|
34
33
|
} from "../../../../persistence/embeddings/embedding-backend.js";
|
|
@@ -37,8 +36,8 @@ import {
|
|
|
37
36
|
writeEmbeddingCache,
|
|
38
37
|
} from "../../../../persistence/embeddings/embedding-cache.js";
|
|
39
38
|
import { embeddingInputContentHash } from "../../../../persistence/embeddings/embedding-types.js";
|
|
40
|
-
import { resolveQdrantUrl } from "../../../../persistence/embeddings/qdrant-client.js";
|
|
41
39
|
import { getLogger } from "../../../../util/logger.js";
|
|
40
|
+
import { embedWithBackend, resolveQdrantUrl } from "../embeddings.js";
|
|
42
41
|
import type { Section } from "./types.js";
|
|
43
42
|
|
|
44
43
|
const log = getLogger("memory-v3-section-dense-store");
|
|
@@ -77,12 +76,10 @@ let _collectionReady = false;
|
|
|
77
76
|
* Shared by both section-dense lanes (this store and the dense read lane in
|
|
78
77
|
* `dense.ts`) so they reuse one client instance and one reset hook.
|
|
79
78
|
*/
|
|
80
|
-
export function getSectionDenseClient(
|
|
81
|
-
config: AssistantConfig,
|
|
82
|
-
): QdrantRestClient {
|
|
79
|
+
export function getSectionDenseClient(): QdrantRestClient {
|
|
83
80
|
if (_client) return _client;
|
|
84
81
|
_client = new QdrantRestClient({
|
|
85
|
-
url: resolveQdrantUrl(
|
|
82
|
+
url: resolveQdrantUrl(),
|
|
86
83
|
checkCompatibility: false,
|
|
87
84
|
});
|
|
88
85
|
return _client;
|
|
@@ -108,7 +105,7 @@ export async function ensureSectionCollection(
|
|
|
108
105
|
): Promise<void> {
|
|
109
106
|
if (_collectionReady) return;
|
|
110
107
|
|
|
111
|
-
const client = getSectionDenseClient(
|
|
108
|
+
const client = getSectionDenseClient();
|
|
112
109
|
const vectorSize = config.memory.qdrant.vectorSize;
|
|
113
110
|
const onDisk = config.memory.qdrant.onDisk;
|
|
114
111
|
|
|
@@ -218,7 +215,7 @@ export async function ensureSectionCollection(
|
|
|
218
215
|
export async function recreateSectionCollection(
|
|
219
216
|
config: AssistantConfig,
|
|
220
217
|
): Promise<void> {
|
|
221
|
-
const client = getSectionDenseClient(
|
|
218
|
+
const client = getSectionDenseClient();
|
|
222
219
|
const exists = await client.collectionExists(SECTION_COLLECTION);
|
|
223
220
|
if (exists.exists) {
|
|
224
221
|
await client.deleteCollection(SECTION_COLLECTION);
|
|
@@ -296,7 +293,7 @@ export async function upsertSections(
|
|
|
296
293
|
|
|
297
294
|
if (points.length === 0) return;
|
|
298
295
|
|
|
299
|
-
await getSectionDenseClient(
|
|
296
|
+
await getSectionDenseClient().upsert(SECTION_COLLECTION, {
|
|
300
297
|
wait: true,
|
|
301
298
|
points,
|
|
302
299
|
});
|
|
@@ -418,7 +415,7 @@ export async function deleteSectionsForArticle(
|
|
|
418
415
|
): Promise<void> {
|
|
419
416
|
await ensureSectionCollection(config);
|
|
420
417
|
|
|
421
|
-
await getSectionDenseClient(
|
|
418
|
+
await getSectionDenseClient().delete(SECTION_COLLECTION, {
|
|
422
419
|
wait: true,
|
|
423
420
|
filter: { must: [{ key: "article", match: { value: article } }] },
|
|
424
421
|
});
|
|
@@ -440,7 +437,7 @@ export async function listSectionArticles(
|
|
|
440
437
|
): Promise<string[]> {
|
|
441
438
|
await ensureSectionCollection(config);
|
|
442
439
|
|
|
443
|
-
const client = getSectionDenseClient(
|
|
440
|
+
const client = getSectionDenseClient();
|
|
444
441
|
const articles = new Set<string>();
|
|
445
442
|
let offset: string | number | undefined = undefined;
|
|
446
443
|
const maxIterations = 10_000;
|
|
@@ -25,6 +25,14 @@ const HEAD_WEIGHT = 2.5;
|
|
|
25
25
|
/** `body`-field weight in the BM25F term-frequency blend. */
|
|
26
26
|
const BODY_WEIGHT = 1;
|
|
27
27
|
|
|
28
|
+
/** A scored section-needle hit: the article, its best-scoring section index
|
|
29
|
+
* (into `SectionIndex.sections`), and that section's raw BM25F score. */
|
|
30
|
+
export interface SectionNeedleScoredHit {
|
|
31
|
+
article: Slug;
|
|
32
|
+
section: number;
|
|
33
|
+
score: number;
|
|
34
|
+
}
|
|
35
|
+
|
|
28
36
|
export interface SectionNeedle {
|
|
29
37
|
/**
|
|
30
38
|
* Returns up to `k` distinct articles ranked by BM25F score (descending),
|
|
@@ -32,6 +40,11 @@ export interface SectionNeedle {
|
|
|
32
40
|
* `SectionIndex.sections`). Ties break by `(article, ordinal)`.
|
|
33
41
|
*/
|
|
34
42
|
query(text: string, k: number): { article: Slug; section: number }[];
|
|
43
|
+
/**
|
|
44
|
+
* Like {@link query} but includes the raw BM25F score per hit, in the same
|
|
45
|
+
* rank order (score desc, then (article, ordinal) asc).
|
|
46
|
+
*/
|
|
47
|
+
queryScored(text: string, k: number): SectionNeedleScoredHit[];
|
|
35
48
|
/**
|
|
36
49
|
* Highest-scoring section index (into `SectionIndex.sections`) for `article`
|
|
37
50
|
* against `queryText`. Returns the article's first section index when no term
|
|
@@ -164,10 +177,7 @@ export function buildSectionNeedle(index: SectionIndex): SectionNeedle {
|
|
|
164
177
|
return sa.article.localeCompare(sc.article) || sa.ordinal - sc.ordinal;
|
|
165
178
|
}
|
|
166
179
|
|
|
167
|
-
function
|
|
168
|
-
text: string,
|
|
169
|
-
k: number,
|
|
170
|
-
): { article: Slug; section: number }[] {
|
|
180
|
+
function queryScored(text: string, k: number): SectionNeedleScoredHit[] {
|
|
171
181
|
if (k <= 0 || docCount === 0) return [];
|
|
172
182
|
|
|
173
183
|
const queryTerms = new Set(tokenize(text));
|
|
@@ -179,17 +189,27 @@ export function buildSectionNeedle(index: SectionIndex): SectionNeedle {
|
|
|
179
189
|
// Dedupe to distinct articles, keeping each article's best (first-ranked)
|
|
180
190
|
// section, until we have `k` articles.
|
|
181
191
|
const seen = new Set<Slug>();
|
|
182
|
-
const result:
|
|
192
|
+
const result: SectionNeedleScoredHit[] = [];
|
|
183
193
|
for (const doc of ranked) {
|
|
184
194
|
const article = sections[doc]!.article;
|
|
185
195
|
if (seen.has(article)) continue;
|
|
186
196
|
seen.add(article);
|
|
187
|
-
result.push({ article, section: doc });
|
|
197
|
+
result.push({ article, section: doc, score: scores.get(doc) ?? 0 });
|
|
188
198
|
if (result.length >= k) break;
|
|
189
199
|
}
|
|
190
200
|
return result;
|
|
191
201
|
}
|
|
192
202
|
|
|
203
|
+
function query(
|
|
204
|
+
text: string,
|
|
205
|
+
k: number,
|
|
206
|
+
): { article: Slug; section: number }[] {
|
|
207
|
+
return queryScored(text, k).map(({ article, section }) => ({
|
|
208
|
+
article,
|
|
209
|
+
section,
|
|
210
|
+
}));
|
|
211
|
+
}
|
|
212
|
+
|
|
193
213
|
function bestSection(article: Slug, queryText: string): number {
|
|
194
214
|
const docs = index.byArticle.get(article);
|
|
195
215
|
if (!docs || docs.length === 0) return -1;
|
|
@@ -211,5 +231,5 @@ export function buildSectionNeedle(index: SectionIndex): SectionNeedle {
|
|
|
211
231
|
return best;
|
|
212
232
|
}
|
|
213
233
|
|
|
214
|
-
return { query, bestSection, idf };
|
|
234
|
+
return { query, queryScored, bestSection, idf };
|
|
215
235
|
}
|
|
@@ -44,6 +44,7 @@ import { buildEdgeGraph } from "./edge.js";
|
|
|
44
44
|
import type { EntityIndex } from "./entity-lane.js";
|
|
45
45
|
import { buildEntityIndex } from "./entity-lane.js";
|
|
46
46
|
import { computeFreshSet } from "./fresh-set.js";
|
|
47
|
+
import { isMemoryV3InjectionGateEnabled } from "./gate-flag.js";
|
|
47
48
|
import { computeHotSet } from "./hot-set.js";
|
|
48
49
|
import { computeLearnedEdgeGraph } from "./learned-edges.js";
|
|
49
50
|
import type { OrchestrateResult } from "./orchestrate.js";
|
|
@@ -586,6 +587,10 @@ export async function observeTurn(
|
|
|
586
587
|
if (cfg.memory.enabled === false) return null;
|
|
587
588
|
const lanes = await getLanes(cfg);
|
|
588
589
|
const v3 = cfg.memory.v3;
|
|
590
|
+
// Resolve the effective gate enable once for the turn: the feature flag
|
|
591
|
+
// AND the `memory.v3.gate.enabled` config kill-switch. Tuning lives in
|
|
592
|
+
// `memory.v3.gate`.
|
|
593
|
+
const gateEnabled = isMemoryV3InjectionGateEnabled(cfg);
|
|
589
594
|
// Re-resolve the corpus-adaptive tuning each turn from the CURRENT config
|
|
590
595
|
// (with the lane-build corpus-size signal) so a live config.json edit to a
|
|
591
596
|
// per-turn knob (selectorEnabled, denseK, replyQueryK, edge.*) takes effect
|
|
@@ -619,6 +624,11 @@ export async function observeTurn(
|
|
|
619
624
|
v3.selectorPromptPath,
|
|
620
625
|
getWorkspaceDir(),
|
|
621
626
|
),
|
|
627
|
+
// Per-turn injection gate: the `memory.v3.gate` tuning with the raw
|
|
628
|
+
// config `enabled` overwritten by the effective enable (flag AND config).
|
|
629
|
+
// The spread is the compile-time drift guard — if the gate schema and
|
|
630
|
+
// `V3GateConfig` diverge, this stops typechecking.
|
|
631
|
+
gateConfig: { ...v3.gate, enabled: gateEnabled },
|
|
622
632
|
});
|
|
623
633
|
|
|
624
634
|
// A zero-selection turn over a non-trivial pool is unusual enough to be
|
|
@@ -35,10 +35,7 @@ import {
|
|
|
35
35
|
conversations,
|
|
36
36
|
messages,
|
|
37
37
|
} from "../../../../persistence/schema/index.js";
|
|
38
|
-
import {
|
|
39
|
-
FRONTMATTER_REGEX,
|
|
40
|
-
parseFrontmatterFields,
|
|
41
|
-
} from "../../../../skills/frontmatter.js";
|
|
38
|
+
import { FRONTMATTER_REGEX, parseFrontmatterFields } from "../frontmatter.js";
|
|
42
39
|
import { injectedConceptHeader } from "../v2/injected-block-slugs.js";
|
|
43
40
|
import { slugFromConceptPath } from "../v2/page-store.js";
|
|
44
41
|
import { renderCard } from "../v3/card.js";
|
|
@@ -19,6 +19,11 @@ import { getConversation } from "../../../../persistence/conversation-crud.js";
|
|
|
19
19
|
import { queueGenerateConversationTitle } from "../../../../persistence/conversation-title-service.js";
|
|
20
20
|
|
|
21
21
|
const userPromptSubmit: HookFunction<UserPromptSubmitContext> = async (ctx) => {
|
|
22
|
+
// Hidden machine signals (e.g. the channel-setup wizard-close marker) are
|
|
23
|
+
// not user speech — a title minted from one would surface invisible
|
|
24
|
+
// scaffolding text in the sidebar, and the LLM call is wasted.
|
|
25
|
+
if (ctx.isHiddenPrompt) return;
|
|
26
|
+
|
|
22
27
|
// System conversations (background/scheduled) carry a deterministic title
|
|
23
28
|
// from bootstrap. Their own job prompts arrive as non-interactive turns and
|
|
24
29
|
// must not spend an LLM call on a title nobody reads — only a genuine user
|
|
@@ -32,6 +32,7 @@ const unifiedTurnContextInjector: Injector = {
|
|
|
32
32
|
const text = buildUnifiedTurnContextBlock({
|
|
33
33
|
timestamp,
|
|
34
34
|
interfaceName: ctx.interfaceName,
|
|
35
|
+
clientOs: ctx.clientOs,
|
|
35
36
|
channelName: ctx.channelName,
|
|
36
37
|
actorContext: ctx.actorContext,
|
|
37
38
|
configuredUserTimezone: ctx.configuredUserTimezone,
|
|
@@ -18,6 +18,7 @@ import { resolveCapabilities } from "../../../runtime/capabilities.js";
|
|
|
18
18
|
export interface UnifiedTurnContextOptions {
|
|
19
19
|
timestamp: string;
|
|
20
20
|
interfaceName?: string;
|
|
21
|
+
clientOs?: string;
|
|
21
22
|
channelName?: string;
|
|
22
23
|
actorContext?: InboundActorContext | null;
|
|
23
24
|
configuredUserTimezone?: string | null;
|
|
@@ -100,6 +101,9 @@ export function buildUnifiedTurnContextBlock(
|
|
|
100
101
|
if (options.interfaceName) {
|
|
101
102
|
lines.push(`interface: ${options.interfaceName}`);
|
|
102
103
|
}
|
|
104
|
+
if (options.clientOs) {
|
|
105
|
+
lines.push(`client_os: ${options.clientOs}`);
|
|
106
|
+
}
|
|
103
107
|
|
|
104
108
|
// Actor identity and trust fields — only for non-guardian turns.
|
|
105
109
|
if (options.actorContext) {
|
|
@@ -182,6 +186,14 @@ export function buildUnifiedTurnContextBlock(
|
|
|
182
186
|
|
|
183
187
|
// Behavioral guidance - only for non-guardian actors where social
|
|
184
188
|
// engineering defense matters. Guardian case needs no instruction.
|
|
189
|
+
//
|
|
190
|
+
// Scope: this is identity/verification hygiene (don't infer guardian status
|
|
191
|
+
// from tone, don't self-approve, don't explain the verification system).
|
|
192
|
+
// Its complement — the data-disclosure boundary (never reveal the guardian's
|
|
193
|
+
// private data: schedule, contacts, files, memories) — lives in the
|
|
194
|
+
// `users/default.md` persona guardrail, gated by
|
|
195
|
+
// `derivePersonaTrustFlags()` in `runtime/trust-class.ts`. Keep the two
|
|
196
|
+
// distinct.
|
|
185
197
|
switch (resolveCapabilities(ctx.trustClass).promptTrustGuidance) {
|
|
186
198
|
case "social-engineering-defense": {
|
|
187
199
|
lines.push("");
|
|
@@ -96,8 +96,16 @@ export function unregisterPluginInjectors(pluginName: string): void {
|
|
|
96
96
|
* and tool registries honor. The order-sorted union is memoized across the
|
|
97
97
|
* filter (rebuilt only on a registration change); only the small per-plugin
|
|
98
98
|
* disabled check re-runs each call.
|
|
99
|
+
*
|
|
100
|
+
* `effectiveEnabledPlugins` layers the per-chat plugin scope on top of the
|
|
101
|
+
* global disabled check: when non-null, an injector's contributing plugin must
|
|
102
|
+
* also be a member of the set or the injector is excluded for this turn. `null`
|
|
103
|
+
* (or omitted) means no per-chat restriction — every globally-enabled plugin's
|
|
104
|
+
* injectors run, unchanged.
|
|
99
105
|
*/
|
|
100
|
-
export function getRegisteredInjectors(
|
|
106
|
+
export function getRegisteredInjectors(
|
|
107
|
+
effectiveEnabledPlugins?: Set<string> | null,
|
|
108
|
+
): Injector[] {
|
|
101
109
|
if (cachedChain === null) {
|
|
102
110
|
const pairs: Array<{ plugin: string; injector: Injector }> = [];
|
|
103
111
|
for (const [plugin, injectors] of injectorsByPlugin) {
|
|
@@ -110,7 +118,10 @@ export function getRegisteredInjectors(): Injector[] {
|
|
|
110
118
|
const isEnabled = (plugin: string): boolean => {
|
|
111
119
|
let enabled = enabledByPlugin.get(plugin);
|
|
112
120
|
if (enabled === undefined) {
|
|
113
|
-
enabled =
|
|
121
|
+
enabled =
|
|
122
|
+
!isPluginDisabled(plugin) &&
|
|
123
|
+
(effectiveEnabledPlugins == null ||
|
|
124
|
+
effectiveEnabledPlugins.has(plugin));
|
|
114
125
|
enabledByPlugin.set(plugin, enabled);
|
|
115
126
|
}
|
|
116
127
|
return enabled;
|