@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
|
@@ -1,6 +1,45 @@
|
|
|
1
|
-
import { beforeEach, describe, expect, test } from "bun:test";
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
|
|
2
2
|
|
|
3
3
|
import { writeSlackMetadata } from "../messaging/providers/slack/message-metadata.js";
|
|
4
|
+
import type { MessageLexicalSearchResult } from "../persistence/embeddings/messages-lexical-index.js";
|
|
5
|
+
|
|
6
|
+
// Mutable stand-in for the Qdrant lexical candidate helper. The source treats
|
|
7
|
+
// a thrown lookup as "no candidates" (logged, empty evidence), so the throwing
|
|
8
|
+
// default cannot fail a forgetful test loudly — tests that assert evidence
|
|
9
|
+
// must configure an implementation, and tests that assert the helper is never
|
|
10
|
+
// consulted check `lexicalCalls` instead.
|
|
11
|
+
let lexicalMockImpl: (
|
|
12
|
+
query: string,
|
|
13
|
+
limit: number,
|
|
14
|
+
opts?: { conversationId?: string },
|
|
15
|
+
) => Promise<MessageLexicalSearchResult[]> = () => {
|
|
16
|
+
throw new Error("searchMessageIdsLexical mock not configured for this test");
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
// Records the arguments of every mock invocation so tests can assert the
|
|
20
|
+
// candidate over-fetch count and that gated paths never consult the index.
|
|
21
|
+
let lexicalCalls: Array<{
|
|
22
|
+
query: string;
|
|
23
|
+
limit: number;
|
|
24
|
+
opts?: { conversationId?: string };
|
|
25
|
+
}> = [];
|
|
26
|
+
|
|
27
|
+
mock.module("../persistence/conversation-search-lexical.js", () => ({
|
|
28
|
+
searchMessageIdsLexical: (
|
|
29
|
+
query: string,
|
|
30
|
+
limit: number,
|
|
31
|
+
opts?: { conversationId?: string },
|
|
32
|
+
) => {
|
|
33
|
+
lexicalCalls.push({ query, limit, opts });
|
|
34
|
+
return lexicalMockImpl(query, limit, opts);
|
|
35
|
+
},
|
|
36
|
+
}));
|
|
37
|
+
|
|
38
|
+
import {
|
|
39
|
+
deleteMemoryCheckpoint,
|
|
40
|
+
LEXICAL_BACKFILL_COMPLETE_KEY,
|
|
41
|
+
setMemoryCheckpoint,
|
|
42
|
+
} from "../persistence/checkpoints.js";
|
|
4
43
|
import { getDb } from "../persistence/db-connection.js";
|
|
5
44
|
import { initializeDb } from "../persistence/db-init.js";
|
|
6
45
|
import { rawRun } from "../persistence/raw-query.js";
|
|
@@ -10,18 +49,34 @@ await initializeDb();
|
|
|
10
49
|
|
|
11
50
|
let seedId = 0;
|
|
12
51
|
|
|
13
|
-
describe("searchConversationSource", () => {
|
|
52
|
+
describe("searchConversationSource (qdrant lexical index)", () => {
|
|
14
53
|
beforeEach(() => {
|
|
15
54
|
getDb().run("DELETE FROM messages");
|
|
16
55
|
getDb().run("DELETE FROM conversations");
|
|
56
|
+
lexicalCalls = [];
|
|
57
|
+
// Content evidence is available once the index is populated (backfill
|
|
58
|
+
// complete). Most tests exercise that path, so mark the backfill
|
|
59
|
+
// complete; the gate is covered by its own test.
|
|
60
|
+
setMemoryCheckpoint(LEXICAL_BACKFILL_COMPLETE_KEY, "1");
|
|
17
61
|
});
|
|
18
62
|
|
|
19
|
-
|
|
63
|
+
afterEach(() => {
|
|
64
|
+
deleteMemoryCheckpoint(LEXICAL_BACKFILL_COMPLETE_KEY);
|
|
65
|
+
lexicalMockImpl = () => {
|
|
66
|
+
throw new Error(
|
|
67
|
+
"searchMessageIdsLexical mock not configured for this test",
|
|
68
|
+
);
|
|
69
|
+
};
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
test("returns matching message evidence for lexical candidates", async () => {
|
|
20
73
|
const { conversation, message } = await seedConversation({
|
|
21
74
|
title: "Launch notes",
|
|
22
75
|
content: "The alpha launch checklist includes database backups.",
|
|
23
76
|
});
|
|
24
77
|
|
|
78
|
+
lexicalMockImpl = async () => [{ messageId: message.id, score: 0.9 }];
|
|
79
|
+
|
|
25
80
|
const result = await searchConversationSource(
|
|
26
81
|
"alpha launch",
|
|
27
82
|
makeContext(),
|
|
@@ -43,7 +98,11 @@ describe("searchConversationSource", () => {
|
|
|
43
98
|
});
|
|
44
99
|
});
|
|
45
100
|
|
|
46
|
-
test("
|
|
101
|
+
test("returns no evidence for short and non-ASCII queries (content matching is index-only)", async () => {
|
|
102
|
+
// Short/punctuation-only and CJK queries produce no usable ≥2-char token.
|
|
103
|
+
// There is no content-scan fallback, so such queries yield no conversation
|
|
104
|
+
// evidence even when an exact substring exists — and the index is never
|
|
105
|
+
// consulted (the sparse encoder would emit noisy 1-char tokens).
|
|
47
106
|
await seedConversation({
|
|
48
107
|
title: "C++ notes",
|
|
49
108
|
role: "user",
|
|
@@ -61,107 +120,153 @@ describe("searchConversationSource", () => {
|
|
|
61
120
|
5,
|
|
62
121
|
);
|
|
63
122
|
|
|
64
|
-
expect(
|
|
65
|
-
|
|
66
|
-
]);
|
|
67
|
-
expect(unicodeResult.evidence.map((item) => item.title)).toEqual([
|
|
68
|
-
"Unicode notes",
|
|
69
|
-
]);
|
|
123
|
+
expect(lexicalCalls).toHaveLength(0);
|
|
124
|
+
expect(shortResult.evidence).toEqual([]);
|
|
125
|
+
expect(unicodeResult.evidence).toEqual([]);
|
|
70
126
|
});
|
|
71
127
|
|
|
72
|
-
test("
|
|
73
|
-
const visible = await seedConversation({
|
|
74
|
-
title: "User conversation",
|
|
75
|
-
content: "derivedtoken belongs to a user-authored conversation.",
|
|
76
|
-
});
|
|
128
|
+
test("returns no evidence until the backfill completion checkpoint is set", async () => {
|
|
77
129
|
await seedConversation({
|
|
78
|
-
title: "
|
|
79
|
-
|
|
80
|
-
content: "derivedtoken should not include subagent output.",
|
|
81
|
-
});
|
|
82
|
-
await seedConversation({
|
|
83
|
-
title: "Auto-analysis conversation",
|
|
84
|
-
source: "auto-analysis",
|
|
85
|
-
content: "derivedtoken should not include auto-analysis output.",
|
|
86
|
-
});
|
|
87
|
-
await seedConversation({
|
|
88
|
-
title: "Notification conversation",
|
|
89
|
-
source: "notification",
|
|
90
|
-
content: "derivedtoken should not include notification seed output.",
|
|
130
|
+
title: "Pre-backfill notes",
|
|
131
|
+
content: "The prebackfilltoken decision is recorded here.",
|
|
91
132
|
});
|
|
92
133
|
|
|
134
|
+
// On an upgraded instance the historical messages are still being indexed
|
|
135
|
+
// by the background backfill, so the lexical collection is only partially
|
|
136
|
+
// populated. Until the completion checkpoint is set, the source must
|
|
137
|
+
// yield no evidence without consulting Qdrant.
|
|
138
|
+
deleteMemoryCheckpoint(LEXICAL_BACKFILL_COMPLETE_KEY);
|
|
139
|
+
lexicalMockImpl = async () => {
|
|
140
|
+
throw new Error(
|
|
141
|
+
"searchMessageIdsLexical must not run before the backfill completes",
|
|
142
|
+
);
|
|
143
|
+
};
|
|
144
|
+
|
|
93
145
|
const result = await searchConversationSource(
|
|
94
|
-
"
|
|
146
|
+
"prebackfilltoken",
|
|
95
147
|
makeContext(),
|
|
96
|
-
|
|
148
|
+
5,
|
|
97
149
|
);
|
|
98
150
|
|
|
99
|
-
expect(
|
|
100
|
-
|
|
101
|
-
]);
|
|
151
|
+
expect(lexicalCalls).toHaveLength(0);
|
|
152
|
+
expect(result.evidence).toEqual([]);
|
|
102
153
|
});
|
|
103
154
|
|
|
104
|
-
test("
|
|
105
|
-
const
|
|
106
|
-
title: "
|
|
107
|
-
content: "
|
|
108
|
-
});
|
|
109
|
-
const current = await seedConversation({
|
|
110
|
-
title: "Current conversation",
|
|
111
|
-
content: "currenttoken appears in the active conversation.",
|
|
155
|
+
test("over-fetches a wide candidate pool from Qdrant", async () => {
|
|
156
|
+
const match = await seedConversation({
|
|
157
|
+
title: "Launch notes",
|
|
158
|
+
content: "The widecandidatetoken launch checklist is recorded here.",
|
|
112
159
|
});
|
|
113
160
|
|
|
161
|
+
lexicalMockImpl = async () => [{ messageId: match.message.id, score: 0.9 }];
|
|
162
|
+
|
|
163
|
+
// limit = 5 → the source over-fetches max(5 × 20, 200) = 200 candidates so
|
|
164
|
+
// post-filter yield stays healthy when top lexical hits are excluded by
|
|
165
|
+
// the SQL predicates.
|
|
114
166
|
const result = await searchConversationSource(
|
|
115
|
-
"
|
|
116
|
-
makeContext(
|
|
117
|
-
|
|
167
|
+
"widecandidatetoken",
|
|
168
|
+
makeContext(),
|
|
169
|
+
5,
|
|
118
170
|
);
|
|
119
171
|
|
|
172
|
+
expect(lexicalCalls).toHaveLength(1);
|
|
173
|
+
expect(lexicalCalls[0]?.limit).toBe(200);
|
|
174
|
+
// Filtering still yields the correctly-scored surviving row.
|
|
120
175
|
expect(result.evidence.map((item) => item.locator)).toEqual([
|
|
121
|
-
`${
|
|
176
|
+
`${match.conversation.id}#${match.message.id}`,
|
|
122
177
|
]);
|
|
178
|
+
expect(result.evidence[0]?.score).toBeGreaterThan(0);
|
|
123
179
|
});
|
|
124
180
|
|
|
125
|
-
test("
|
|
126
|
-
const
|
|
127
|
-
title: "
|
|
128
|
-
content: "
|
|
181
|
+
test("returns app-scored evidence for Qdrant-supplied candidates", async () => {
|
|
182
|
+
const match = await seedConversation({
|
|
183
|
+
title: "Launch notes",
|
|
184
|
+
content: "The alpha launch checklist includes database backups.",
|
|
129
185
|
});
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
186
|
+
// A candidate the lexical index also surfaces but that the query does not
|
|
187
|
+
// actually match — proves the app-side scorer, not Qdrant order, ranks.
|
|
188
|
+
const weak = await seedConversation({
|
|
189
|
+
title: "Unrelated",
|
|
190
|
+
content: "Nothing salient in this conversation at all.",
|
|
133
191
|
});
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
192
|
+
|
|
193
|
+
lexicalMockImpl = async () => [
|
|
194
|
+
{ messageId: weak.message.id, score: 0.9 },
|
|
195
|
+
{ messageId: match.message.id, score: 0.1 },
|
|
196
|
+
];
|
|
138
197
|
|
|
139
198
|
const result = await searchConversationSource(
|
|
140
|
-
"
|
|
199
|
+
"alpha launch",
|
|
141
200
|
makeContext(),
|
|
142
|
-
|
|
201
|
+
5,
|
|
143
202
|
);
|
|
144
203
|
|
|
145
|
-
expect(result.evidence
|
|
146
|
-
|
|
147
|
-
|
|
204
|
+
expect(result.evidence[0]).toMatchObject({
|
|
205
|
+
id: `conversations:${match.conversation.id}:${match.message.id}`,
|
|
206
|
+
source: "conversations",
|
|
207
|
+
title: "Launch notes",
|
|
208
|
+
locator: `${match.conversation.id}#${match.message.id}`,
|
|
209
|
+
excerpt: "The alpha launch checklist includes database backups.",
|
|
210
|
+
metadata: {
|
|
211
|
+
role: "assistant",
|
|
212
|
+
conversationId: match.conversation.id,
|
|
213
|
+
},
|
|
214
|
+
});
|
|
215
|
+
expect(result.evidence[0]?.score).toBeGreaterThan(
|
|
216
|
+
result.evidence[1]?.score ?? -1,
|
|
217
|
+
);
|
|
148
218
|
});
|
|
149
219
|
|
|
150
|
-
test("
|
|
220
|
+
test("applies source, type, and excluded-conversation filters to Qdrant candidates", async () => {
|
|
151
221
|
const visible = await seedConversation({
|
|
152
|
-
title: "
|
|
153
|
-
content: "
|
|
222
|
+
title: "User conversation",
|
|
223
|
+
content: "derivedtoken belongs to a user-authored conversation.",
|
|
224
|
+
});
|
|
225
|
+
const subagent = await seedConversation({
|
|
226
|
+
title: "Subagent conversation",
|
|
227
|
+
source: "subagent",
|
|
228
|
+
content: "derivedtoken should not include subagent output.",
|
|
229
|
+
});
|
|
230
|
+
const autoAnalysis = await seedConversation({
|
|
231
|
+
title: "Auto-analysis conversation",
|
|
232
|
+
source: "auto-analysis",
|
|
233
|
+
content: "derivedtoken should not include auto-analysis output.",
|
|
234
|
+
});
|
|
235
|
+
const notification = await seedConversation({
|
|
236
|
+
title: "Notification conversation",
|
|
237
|
+
source: "notification",
|
|
238
|
+
content: "derivedtoken should not include notification output.",
|
|
239
|
+
});
|
|
240
|
+
const current = await seedConversation({
|
|
241
|
+
title: "Current conversation",
|
|
242
|
+
content: "derivedtoken appears in the active conversation.",
|
|
154
243
|
});
|
|
155
244
|
const legacyPrivate = await seedConversation({
|
|
156
|
-
title: "Legacy private
|
|
157
|
-
content: "
|
|
245
|
+
title: "Legacy private conversation",
|
|
246
|
+
content: "derivedtoken belongs to legacy private history.",
|
|
158
247
|
});
|
|
159
248
|
rawRun(
|
|
249
|
+
"test:setPrivateType",
|
|
160
250
|
"UPDATE conversations SET conversation_type = 'private' WHERE id = ?",
|
|
161
251
|
legacyPrivate.conversation.id,
|
|
162
252
|
);
|
|
163
253
|
|
|
164
|
-
|
|
254
|
+
// The lexical index does not filter — it hands back every candidate,
|
|
255
|
+
// including the ones SQL must exclude.
|
|
256
|
+
lexicalMockImpl = async () => [
|
|
257
|
+
{ messageId: visible.message.id, score: 0.9 },
|
|
258
|
+
{ messageId: subagent.message.id, score: 0.85 },
|
|
259
|
+
{ messageId: autoAnalysis.message.id, score: 0.8 },
|
|
260
|
+
{ messageId: notification.message.id, score: 0.75 },
|
|
261
|
+
{ messageId: current.message.id, score: 0.7 },
|
|
262
|
+
{ messageId: legacyPrivate.message.id, score: 0.65 },
|
|
263
|
+
];
|
|
264
|
+
|
|
265
|
+
const result = await searchConversationSource(
|
|
266
|
+
"derivedtoken",
|
|
267
|
+
makeContext({ conversationId: current.conversation.id }),
|
|
268
|
+
10,
|
|
269
|
+
);
|
|
165
270
|
|
|
166
271
|
expect(result.evidence.map((item) => item.locator)).toEqual([
|
|
167
272
|
`${visible.conversation.id}#${visible.message.id}`,
|
|
@@ -174,6 +279,7 @@ describe("searchConversationSource", () => {
|
|
|
174
279
|
content: "includetoken appears in archived history.",
|
|
175
280
|
});
|
|
176
281
|
rawRun(
|
|
282
|
+
"test:archiveConversation",
|
|
177
283
|
"UPDATE conversations SET archived_at = ? WHERE id = ?",
|
|
178
284
|
Date.now(),
|
|
179
285
|
archived.conversation.id,
|
|
@@ -189,6 +295,12 @@ describe("searchConversationSource", () => {
|
|
|
189
295
|
content: "includetoken appears in background history.",
|
|
190
296
|
});
|
|
191
297
|
|
|
298
|
+
lexicalMockImpl = async () => [
|
|
299
|
+
{ messageId: archived.message.id, score: 0.9 },
|
|
300
|
+
{ messageId: scheduled.message.id, score: 0.85 },
|
|
301
|
+
{ messageId: background.message.id, score: 0.8 },
|
|
302
|
+
];
|
|
303
|
+
|
|
192
304
|
const result = await searchConversationSource(
|
|
193
305
|
"includetoken",
|
|
194
306
|
makeContext(),
|
|
@@ -216,6 +328,8 @@ describe("searchConversationSource", () => {
|
|
|
216
328
|
content,
|
|
217
329
|
});
|
|
218
330
|
|
|
331
|
+
lexicalMockImpl = async () => [{ messageId: message.id, score: 0.9 }];
|
|
332
|
+
|
|
219
333
|
const result = await searchConversationSource("needle", makeContext(), 1);
|
|
220
334
|
|
|
221
335
|
expect(result.evidence).toHaveLength(1);
|
|
@@ -233,6 +347,8 @@ describe("searchConversationSource", () => {
|
|
|
233
347
|
'<external_content source="slack" origin="@alice">\nThe recalltoken decision came from Slack.\n</external_content>',
|
|
234
348
|
});
|
|
235
349
|
|
|
350
|
+
lexicalMockImpl = async () => [{ messageId: message.id, score: 0.9 }];
|
|
351
|
+
|
|
236
352
|
const result = await searchConversationSource(
|
|
237
353
|
"recalltoken",
|
|
238
354
|
makeContext(),
|
|
@@ -257,6 +373,8 @@ describe("searchConversationSource", () => {
|
|
|
257
373
|
}),
|
|
258
374
|
});
|
|
259
375
|
|
|
376
|
+
lexicalMockImpl = async () => [{ messageId: message.id, score: 0.9 }];
|
|
377
|
+
|
|
260
378
|
const result = await searchConversationSource(
|
|
261
379
|
"rawrecalltoken",
|
|
262
380
|
makeContext(),
|
|
@@ -282,6 +400,8 @@ describe("searchConversationSource", () => {
|
|
|
282
400
|
}),
|
|
283
401
|
});
|
|
284
402
|
|
|
403
|
+
lexicalMockImpl = async () => [{ messageId: message.id, score: 0.9 }];
|
|
404
|
+
|
|
285
405
|
const result = await searchConversationSource(
|
|
286
406
|
"tagmentionrecalltoken",
|
|
287
407
|
makeContext(),
|
|
@@ -306,6 +426,8 @@ describe("searchConversationSource", () => {
|
|
|
306
426
|
}),
|
|
307
427
|
});
|
|
308
428
|
|
|
429
|
+
lexicalMockImpl = async () => [{ messageId: message.id, score: 0.9 }];
|
|
430
|
+
|
|
309
431
|
const result = await searchConversationSource(
|
|
310
432
|
"guardianrecalltoken",
|
|
311
433
|
makeContext(),
|
|
@@ -319,29 +441,44 @@ describe("searchConversationSource", () => {
|
|
|
319
441
|
});
|
|
320
442
|
});
|
|
321
443
|
|
|
322
|
-
test("
|
|
323
|
-
const specific = await seedConversation({
|
|
324
|
-
title: "Birthday cake plan",
|
|
325
|
-
content:
|
|
326
|
-
"The birthday cake was vanilla with raspberry filling and had the message Happy birthday Alice Love Example Assistant.",
|
|
327
|
-
});
|
|
444
|
+
test("returns no evidence when the Qdrant lookup throws", async () => {
|
|
328
445
|
await seedConversation({
|
|
329
|
-
title: "
|
|
330
|
-
content: "The
|
|
446
|
+
title: "Failure notes",
|
|
447
|
+
content: "The qdranterrortoken decision is recorded here.",
|
|
331
448
|
});
|
|
332
449
|
|
|
450
|
+
lexicalMockImpl = async () => {
|
|
451
|
+
throw new Error("qdrant unavailable");
|
|
452
|
+
};
|
|
453
|
+
|
|
333
454
|
const result = await searchConversationSource(
|
|
334
|
-
"
|
|
455
|
+
"qdranterrortoken",
|
|
335
456
|
makeContext(),
|
|
336
457
|
5,
|
|
337
458
|
);
|
|
338
459
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
460
|
+
// Content matching is index-only: the failure is logged and the source
|
|
461
|
+
// yields no conversation evidence — no content-scan recovery.
|
|
462
|
+
expect(result.evidence).toEqual([]);
|
|
463
|
+
});
|
|
464
|
+
|
|
465
|
+
test("returns no evidence when Qdrant returns no candidates", async () => {
|
|
466
|
+
await seedConversation({
|
|
467
|
+
title: "Empty candidate notes",
|
|
468
|
+
content: "The emptycandidatetoken decision is recorded here.",
|
|
342
469
|
});
|
|
343
|
-
|
|
344
|
-
|
|
470
|
+
|
|
471
|
+
lexicalMockImpl = async () => [];
|
|
472
|
+
|
|
473
|
+
const result = await searchConversationSource(
|
|
474
|
+
"emptycandidatetoken",
|
|
475
|
+
makeContext(),
|
|
476
|
+
5,
|
|
477
|
+
);
|
|
478
|
+
|
|
479
|
+
// The index is authoritative for content matching — an empty candidate
|
|
480
|
+
// set is an empty result, not a trigger for a table-scan fallback.
|
|
481
|
+
expect(result.evidence).toEqual([]);
|
|
345
482
|
});
|
|
346
483
|
});
|
|
347
484
|
|
|
@@ -366,6 +503,7 @@ function seedConversation(opts: {
|
|
|
366
503
|
};
|
|
367
504
|
|
|
368
505
|
rawRun(
|
|
506
|
+
"test:insertConversation",
|
|
369
507
|
`
|
|
370
508
|
INSERT INTO conversations (
|
|
371
509
|
id,
|
|
@@ -386,6 +524,7 @@ function seedConversation(opts: {
|
|
|
386
524
|
opts.memoryScopeId ?? "default",
|
|
387
525
|
);
|
|
388
526
|
rawRun(
|
|
527
|
+
"test:insertMessage",
|
|
389
528
|
`
|
|
390
529
|
INSERT INTO messages (
|
|
391
530
|
id,
|
|
@@ -182,6 +182,7 @@ function makeCtx(overrides: Partial<Context> = {}): Conversation {
|
|
|
182
182
|
getTurnChannelContext: () => null,
|
|
183
183
|
|
|
184
184
|
buildCurrentSystemPrompt: () => "system prompt",
|
|
185
|
+
syncLoopSystemPrompt: () => {},
|
|
185
186
|
modelOverride: undefined,
|
|
186
187
|
graphMemory: {} as Context["graphMemory"],
|
|
187
188
|
...overrides,
|
|
@@ -778,6 +778,7 @@ function makeCtx(
|
|
|
778
778
|
}),
|
|
779
779
|
|
|
780
780
|
buildCurrentSystemPrompt: () => "system prompt",
|
|
781
|
+
syncLoopSystemPrompt: () => {},
|
|
781
782
|
modelOverride: undefined,
|
|
782
783
|
|
|
783
784
|
graphMemory: {
|
|
@@ -2408,6 +2409,44 @@ describe("session-agent-loop", () => {
|
|
|
2408
2409
|
expect(metadataPublishes).toHaveLength(1);
|
|
2409
2410
|
});
|
|
2410
2411
|
|
|
2412
|
+
test("terminal message_complete is emitted before the deferred indexer runs (LUM-2654)", async () => {
|
|
2413
|
+
// Regression guard for LUM-2654 ("long delay between last streaming token
|
|
2414
|
+
// and send-button becoming available"). The terminal `message_complete`
|
|
2415
|
+
// SSE — which the client uses to flip stop→send — is emitted before the
|
|
2416
|
+
// non-critical finalize side-effects (memory segment indexing, lexical
|
|
2417
|
+
// indexing, attention projection), which the orchestrator drains from its
|
|
2418
|
+
// end-of-turn tail. The tail runs within the turn, so the indexer still
|
|
2419
|
+
// fires exactly once; this test pins the ordering by asserting
|
|
2420
|
+
// `message_complete` is already in the client stream when it does.
|
|
2421
|
+
mockMessageById = {
|
|
2422
|
+
id: "msg-reserve",
|
|
2423
|
+
conversationId: "test-conv",
|
|
2424
|
+
createdAt: 1234567,
|
|
2425
|
+
role: "assistant",
|
|
2426
|
+
content: "[]",
|
|
2427
|
+
metadata: null,
|
|
2428
|
+
};
|
|
2429
|
+
|
|
2430
|
+
const events: ServerMessage[] = [];
|
|
2431
|
+
let messageCompleteSeenWhenIndexed: boolean | undefined;
|
|
2432
|
+
indexMessageNowMock.mockImplementationOnce(async () => {
|
|
2433
|
+
messageCompleteSeenWhenIndexed = events.some(
|
|
2434
|
+
(event) => event.type === "message_complete",
|
|
2435
|
+
);
|
|
2436
|
+
return { indexedSegments: 0, enqueuedJobs: 0 };
|
|
2437
|
+
});
|
|
2438
|
+
|
|
2439
|
+
const ctx = makeCtx({
|
|
2440
|
+
providerResponses: [textResponse("indexed reply")],
|
|
2441
|
+
});
|
|
2442
|
+
await runAgentLoopImpl(ctx, "hi", "msg-1", (msg) => events.push(msg));
|
|
2443
|
+
|
|
2444
|
+
// The deferred indexer runs exactly once, within the turn…
|
|
2445
|
+
expect(indexMessageNowMock).toHaveBeenCalledTimes(1);
|
|
2446
|
+
// …and only after the terminal SSE that re-enables the composer.
|
|
2447
|
+
expect(messageCompleteSeenWhenIndexed).toBe(true);
|
|
2448
|
+
});
|
|
2449
|
+
|
|
2411
2450
|
test("handleMessageComplete skips sync invalidation when attention state unchanged", async () => {
|
|
2412
2451
|
// Mirror of the previous test but with the default projector return
|
|
2413
2452
|
// (`false`). The projection still runs every turn, but the sync
|
|
@@ -103,7 +103,7 @@ describe("POST /v1/conversations/:id/analyze", () => {
|
|
|
103
103
|
"analysis-1",
|
|
104
104
|
"user",
|
|
105
105
|
expect.any(String),
|
|
106
|
-
{ metadata: { provenanceTrustClass: "unknown" } },
|
|
106
|
+
{ id: expect.any(String), metadata: { provenanceTrustClass: "unknown" } },
|
|
107
107
|
);
|
|
108
108
|
expect(mockConversation.setTrustContext).toHaveBeenCalledWith({
|
|
109
109
|
trustClass: "unknown",
|
|
@@ -79,6 +79,8 @@ const mockSkillRefCount = new Map<string, number>();
|
|
|
79
79
|
|
|
80
80
|
mock.module("../config/skills.js", () => ({
|
|
81
81
|
loadSkillCatalog: () => mockCatalog,
|
|
82
|
+
// Pass-through: these tests don't exercise per-chat plugin scoping.
|
|
83
|
+
filterSkillsByEnabledPlugins: (skills: unknown) => skills,
|
|
82
84
|
}));
|
|
83
85
|
|
|
84
86
|
mock.module("../skills/active-skill-tools.js", () => ({
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
2
|
+
|
|
3
|
+
import { makeMockLogger } from "./helpers/mock-logger.js";
|
|
4
|
+
|
|
5
|
+
mock.module("../util/logger.js", () => ({
|
|
6
|
+
getLogger: () => makeMockLogger(),
|
|
7
|
+
}));
|
|
8
|
+
|
|
9
|
+
import {
|
|
10
|
+
addMessage,
|
|
11
|
+
createConversation,
|
|
12
|
+
forkConversation,
|
|
13
|
+
getConversation,
|
|
14
|
+
getConversationEnabledPlugins,
|
|
15
|
+
setConversationEnabledPlugins,
|
|
16
|
+
} from "../persistence/conversation-crud.js";
|
|
17
|
+
import { getDb } from "../persistence/db-connection.js";
|
|
18
|
+
import { initializeDb } from "../persistence/db-init.js";
|
|
19
|
+
await initializeDb();
|
|
20
|
+
|
|
21
|
+
describe("getConversationEnabledPlugins / setConversationEnabledPlugins", () => {
|
|
22
|
+
beforeEach(() => {
|
|
23
|
+
const db = getDb();
|
|
24
|
+
db.run(`DELETE FROM messages`);
|
|
25
|
+
db.run(`DELETE FROM conversations`);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test("defaults to null on a fresh conversation", () => {
|
|
29
|
+
const conv = createConversation("enabled-plugins-default");
|
|
30
|
+
expect(getConversationEnabledPlugins(conv.id)).toBeNull();
|
|
31
|
+
expect(getConversation(conv.id)?.enabledPlugins).toBeNull();
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test("round-trips a plugin list and clears it with null", () => {
|
|
35
|
+
const conv = createConversation("enabled-plugins-roundtrip");
|
|
36
|
+
|
|
37
|
+
setConversationEnabledPlugins(conv.id, ["a", "b"]);
|
|
38
|
+
expect(getConversationEnabledPlugins(conv.id)).toEqual(["a", "b"]);
|
|
39
|
+
expect(getConversation(conv.id)?.enabledPlugins).toEqual(["a", "b"]);
|
|
40
|
+
|
|
41
|
+
setConversationEnabledPlugins(conv.id, null);
|
|
42
|
+
expect(getConversationEnabledPlugins(conv.id)).toBeNull();
|
|
43
|
+
expect(getConversation(conv.id)?.enabledPlugins).toBeNull();
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test("stores an empty list distinctly from null", () => {
|
|
47
|
+
const conv = createConversation("enabled-plugins-empty");
|
|
48
|
+
setConversationEnabledPlugins(conv.id, []);
|
|
49
|
+
expect(getConversationEnabledPlugins(conv.id)).toEqual([]);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test("a forked conversation carries the plugin selection", async () => {
|
|
53
|
+
const conv = createConversation("enabled-plugins-fork-source");
|
|
54
|
+
setConversationEnabledPlugins(conv.id, ["x", "y"]);
|
|
55
|
+
await addMessage(conv.id, "user", "hi");
|
|
56
|
+
|
|
57
|
+
const forked = forkConversation({ conversationId: conv.id });
|
|
58
|
+
expect(getConversationEnabledPlugins(forked.id)).toEqual(["x", "y"]);
|
|
59
|
+
});
|
|
60
|
+
});
|
|
@@ -26,7 +26,6 @@ mock.module("../daemon/handlers/conversations.js", () => ({
|
|
|
26
26
|
clearAllConversations: async () => 0,
|
|
27
27
|
switchConversation: async () => null,
|
|
28
28
|
undoLastMessage: async () => null,
|
|
29
|
-
regenerateResponse: async () => null,
|
|
30
29
|
}));
|
|
31
30
|
|
|
32
31
|
import type { Database } from "bun:sqlite";
|
|
@@ -552,6 +552,7 @@ describe("syncMessageToDisk", () => {
|
|
|
552
552
|
});
|
|
553
553
|
const att = uploadAttachment("repair.png", "image/png", "iVBORw0K");
|
|
554
554
|
rawRun(
|
|
555
|
+
"test:linkAttachment",
|
|
555
556
|
`INSERT INTO message_attachments (id, message_id, attachment_id, position, created_at)
|
|
556
557
|
VALUES (?, ?, ?, ?, ?)`,
|
|
557
558
|
`manual-link-${msg.id}`,
|