@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
|
@@ -117,6 +117,7 @@ function slackResult(
|
|
|
117
117
|
|
|
118
118
|
type PromptResponse = {
|
|
119
119
|
ok: boolean;
|
|
120
|
+
cancelled?: boolean;
|
|
120
121
|
error?: string;
|
|
121
122
|
service?: string;
|
|
122
123
|
field?: string;
|
|
@@ -388,6 +389,74 @@ describe("credentials/prompt route", () => {
|
|
|
388
389
|
expect(capturedMetadata!.allowedDomains).toBeUndefined();
|
|
389
390
|
});
|
|
390
391
|
|
|
392
|
+
test("flags an explicit user cancel distinctly from a failure", async () => {
|
|
393
|
+
/**
|
|
394
|
+
* A user dismissing the secure prompt is a valid flow, not an error. The
|
|
395
|
+
* route must mark it `cancelled: true` (so the CLI can exit with the
|
|
396
|
+
* user-interrupt convention) and must not persist anything.
|
|
397
|
+
*/
|
|
398
|
+
// GIVEN the prompt resolves with no value because the user cancelled
|
|
399
|
+
secretResult = { value: null, delivery: "store", reason: "cancelled" };
|
|
400
|
+
|
|
401
|
+
// WHEN the route handles the prompt
|
|
402
|
+
const result = (await promptRoute!.handler({
|
|
403
|
+
body: { service: "stripe", field: "api_key", label: "Stripe API Key" },
|
|
404
|
+
})) as PromptResponse;
|
|
405
|
+
|
|
406
|
+
// THEN the outcome is flagged as a cancel, not a generic error
|
|
407
|
+
expect(result.ok).toBe(false);
|
|
408
|
+
expect(result.cancelled).toBe(true);
|
|
409
|
+
expect(result.error).toBe("Cancelled by the user");
|
|
410
|
+
|
|
411
|
+
// AND nothing was written to secure storage
|
|
412
|
+
expect(secureKeyWrites).toEqual([]);
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
test("reports a timeout as a failure, not a cancel", async () => {
|
|
416
|
+
/**
|
|
417
|
+
* A prompt that times out (no response in the permission window) is a real
|
|
418
|
+
* failure — it must NOT be flagged as a user cancel, so the CLI keeps the
|
|
419
|
+
* error exit code for it.
|
|
420
|
+
*/
|
|
421
|
+
// GIVEN the prompt resolves with no value because it timed out
|
|
422
|
+
secretResult = { value: null, delivery: "store", reason: "timed_out" };
|
|
423
|
+
|
|
424
|
+
// WHEN the route handles the prompt
|
|
425
|
+
const result = (await promptRoute!.handler({
|
|
426
|
+
body: { service: "stripe", field: "api_key", label: "Stripe API Key" },
|
|
427
|
+
})) as PromptResponse;
|
|
428
|
+
|
|
429
|
+
// THEN it is a plain failure with no cancel flag
|
|
430
|
+
expect(result.ok).toBe(false);
|
|
431
|
+
expect(result.cancelled).toBeUndefined();
|
|
432
|
+
expect(result.error).toBe("The credential prompt timed out");
|
|
433
|
+
});
|
|
434
|
+
|
|
435
|
+
test("reports an undeliverable prompt as a failure, not a cancel", async () => {
|
|
436
|
+
/**
|
|
437
|
+
* When no connected client can render a secure prompt the value is null due
|
|
438
|
+
* to a delivery failure — this stays a hard error and is never a cancel.
|
|
439
|
+
*/
|
|
440
|
+
// GIVEN the prompt could not be delivered to any client
|
|
441
|
+
secretResult = {
|
|
442
|
+
value: null,
|
|
443
|
+
delivery: "store",
|
|
444
|
+
error: "unsupported_channel",
|
|
445
|
+
};
|
|
446
|
+
|
|
447
|
+
// WHEN the route handles the prompt
|
|
448
|
+
const result = (await promptRoute!.handler({
|
|
449
|
+
body: { service: "stripe", field: "api_key", label: "Stripe API Key" },
|
|
450
|
+
})) as PromptResponse;
|
|
451
|
+
|
|
452
|
+
// THEN it is a plain failure with no cancel flag
|
|
453
|
+
expect(result.ok).toBe(false);
|
|
454
|
+
expect(result.cancelled).toBeUndefined();
|
|
455
|
+
expect(result.error).toBe(
|
|
456
|
+
"No connected client supports secure credential entry",
|
|
457
|
+
);
|
|
458
|
+
});
|
|
459
|
+
|
|
391
460
|
test("forwards provided allowed-tools/-domains to credential metadata", async () => {
|
|
392
461
|
/**
|
|
393
462
|
* When the caller does supply policy flags they must reach the metadata
|
|
@@ -215,19 +215,17 @@ describe("Invariant 2: no generic plaintext secret read API", () => {
|
|
|
215
215
|
"daemon/conversation-process.ts", // masked provider key display
|
|
216
216
|
"daemon/handlers/config-model.ts", // masked provider key display
|
|
217
217
|
"providers/speech-to-text/resolve.ts", // STT provider API key lookup
|
|
218
|
+
"calls/telephony-tts-capability.ts", // TTS provider API key availability check (presence only)
|
|
218
219
|
"credential-execution/ces-runtime.ts", // CES runtime owns the daemon CES connection (setCesClient/onCesClientChanged/reconnect wiring at startup)
|
|
219
|
-
"daemon/daemon-skill-host.ts", // SkillHost secureKeys facet adapter (delegates to getProviderKeyAsync)
|
|
220
220
|
"runtime/routes/credential-prompt-routes.ts", // Route for secure credential prompt (stores secret via setSecureKeyAsync)
|
|
221
221
|
"runtime/routes/credential-routes.ts", // CLI credential management routes (CLI-migrated to IPC)
|
|
222
222
|
"runtime/routes/sanity-routes.ts", // Sanity connect/discover routes (reads stored api_token from credential store)
|
|
223
223
|
"runtime/routes/platform-routes.ts", // CLI platform connect/disconnect/status routes (CLI-migrated to IPC)
|
|
224
|
-
"ipc/skill-routes/providers.ts", // host.providers.secureKeys.getProviderKey IPC route (out-of-process SkillHost companion)
|
|
225
224
|
"inbound/platform-callback-registration.ts", // managed credential lookup for platform base URL, assistant ID, and API key
|
|
226
225
|
"tts/providers/elevenlabs-provider.ts", // ElevenLabs TTS API key lookup
|
|
227
226
|
"tts/providers/deepgram-provider.ts", // Deepgram TTS API key lookup
|
|
228
227
|
"tts/providers/xai-provider.ts", // xAI TTS API key lookup
|
|
229
228
|
"credential-health/credential-health-service.ts", // credential health check reads access tokens for liveness pings
|
|
230
|
-
"ipc/skill-routes/providers.ts", // skill IPC route exposes provider key lookup to hosted skills
|
|
231
229
|
"runtime/routes/avatar-routes.ts", // avatar generate route reads platform_base_url from credential store
|
|
232
230
|
"cli/commands/keys.ts", // CLI provider key management
|
|
233
231
|
"cli/commands/oauth/connect.ts", // CLI OAuth connect stored-secret verification
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { Database } from "bun:sqlite";
|
|
2
|
+
import { describe, expect, test } from "bun:test";
|
|
3
|
+
|
|
4
|
+
import { drizzle } from "drizzle-orm/bun-sqlite";
|
|
5
|
+
|
|
6
|
+
import { getSqliteFrom } from "../persistence/db-connection.js";
|
|
7
|
+
import { createMessagesFts } from "../persistence/migrations/116-messages-fts.js";
|
|
8
|
+
import { migrateDropMessagesFts } from "../persistence/migrations/313-drop-messages-fts.js";
|
|
9
|
+
import * as schema from "../persistence/schema/index.js";
|
|
10
|
+
|
|
11
|
+
function createTestDb() {
|
|
12
|
+
const sqlite = new Database(":memory:");
|
|
13
|
+
sqlite.exec("PRAGMA journal_mode=WAL");
|
|
14
|
+
sqlite.exec("PRAGMA foreign_keys = ON");
|
|
15
|
+
return drizzle(sqlite, { schema });
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function bootstrapMessagesTables(raw: Database): void {
|
|
19
|
+
raw.exec(/*sql*/ `
|
|
20
|
+
CREATE TABLE conversations (
|
|
21
|
+
id TEXT PRIMARY KEY,
|
|
22
|
+
title TEXT,
|
|
23
|
+
created_at INTEGER NOT NULL,
|
|
24
|
+
updated_at INTEGER NOT NULL
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
CREATE TABLE messages (
|
|
28
|
+
id TEXT PRIMARY KEY,
|
|
29
|
+
conversation_id TEXT NOT NULL REFERENCES conversations(id) ON DELETE CASCADE,
|
|
30
|
+
role TEXT NOT NULL,
|
|
31
|
+
content TEXT NOT NULL,
|
|
32
|
+
created_at INTEGER NOT NULL,
|
|
33
|
+
metadata TEXT
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
INSERT INTO conversations (id, title, created_at, updated_at)
|
|
37
|
+
VALUES ('conv-1', 'Notes', 1000, 1000);
|
|
38
|
+
`);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Every `messages_fts`-prefixed entry in sqlite_schema: the vtable, its FTS5
|
|
43
|
+
* shadow tables (_config/_docsize/_content/_idx/_data), and the per-row
|
|
44
|
+
* triggers (_ai/_ad/_au) all share the prefix.
|
|
45
|
+
*/
|
|
46
|
+
function ftsSchemaObjects(raw: Database): string[] {
|
|
47
|
+
const rows = raw
|
|
48
|
+
.query(
|
|
49
|
+
`SELECT name FROM sqlite_schema WHERE name LIKE 'messages\\_fts%' ESCAPE '\\' ORDER BY name`,
|
|
50
|
+
)
|
|
51
|
+
.all() as Array<{ name: string }>;
|
|
52
|
+
return rows.map((row) => row.name);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function insertMessage(raw: Database, id: string, content: string): void {
|
|
56
|
+
raw
|
|
57
|
+
.query(
|
|
58
|
+
`INSERT INTO messages (id, conversation_id, role, content, created_at) VALUES (?, 'conv-1', 'user', ?, 1000)`,
|
|
59
|
+
)
|
|
60
|
+
.run(id, content);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
describe("migrateDropMessagesFts", () => {
|
|
64
|
+
test("drops the FTS vtable, shadow tables, and per-row triggers", () => {
|
|
65
|
+
const db = createTestDb();
|
|
66
|
+
const raw = getSqliteFrom(db);
|
|
67
|
+
bootstrapMessagesTables(raw);
|
|
68
|
+
createMessagesFts(db);
|
|
69
|
+
insertMessage(raw, "m-1", "the flux capacitor needs recalibration");
|
|
70
|
+
expect(ftsSchemaObjects(raw).length).toBeGreaterThan(0);
|
|
71
|
+
|
|
72
|
+
migrateDropMessagesFts(db);
|
|
73
|
+
|
|
74
|
+
expect(ftsSchemaObjects(raw)).toEqual([]);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
test("message writes perform no FTS work after the drop", () => {
|
|
78
|
+
const db = createTestDb();
|
|
79
|
+
const raw = getSqliteFrom(db);
|
|
80
|
+
bootstrapMessagesTables(raw);
|
|
81
|
+
createMessagesFts(db);
|
|
82
|
+
insertMessage(raw, "m-1", "indexed before the drop");
|
|
83
|
+
|
|
84
|
+
migrateDropMessagesFts(db);
|
|
85
|
+
|
|
86
|
+
// Insert, update, and delete must all succeed as plain row operations —
|
|
87
|
+
// a leftover trigger would throw against the missing vtable.
|
|
88
|
+
insertMessage(raw, "m-2", "written after the drop");
|
|
89
|
+
raw
|
|
90
|
+
.query(`UPDATE messages SET content = ? WHERE id = ?`)
|
|
91
|
+
.run("updated after the drop", "m-2");
|
|
92
|
+
raw.query(`DELETE FROM messages WHERE id = ?`).run("m-1");
|
|
93
|
+
|
|
94
|
+
const rows = raw
|
|
95
|
+
.query(`SELECT id, content FROM messages ORDER BY id`)
|
|
96
|
+
.all() as Array<{ id: string; content: string }>;
|
|
97
|
+
expect(rows).toEqual([{ id: "m-2", content: "updated after the drop" }]);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
test("is idempotent, including on a database that never had messages_fts", () => {
|
|
101
|
+
const db = createTestDb();
|
|
102
|
+
const raw = getSqliteFrom(db);
|
|
103
|
+
bootstrapMessagesTables(raw);
|
|
104
|
+
createMessagesFts(db);
|
|
105
|
+
|
|
106
|
+
migrateDropMessagesFts(db);
|
|
107
|
+
migrateDropMessagesFts(db);
|
|
108
|
+
expect(ftsSchemaObjects(raw)).toEqual([]);
|
|
109
|
+
|
|
110
|
+
const fresh = createTestDb();
|
|
111
|
+
bootstrapMessagesTables(getSqliteFrom(fresh));
|
|
112
|
+
migrateDropMessagesFts(fresh);
|
|
113
|
+
expect(ftsSchemaObjects(getSqliteFrom(fresh))).toEqual([]);
|
|
114
|
+
});
|
|
115
|
+
});
|
|
@@ -5,8 +5,7 @@
|
|
|
5
5
|
* 1. Verification control messages (code replies, /start gv_<token>) never invoke
|
|
6
6
|
* the normal message pipeline — they produce only template-driven copy.
|
|
7
7
|
* 2. Call session mode metadata is persisted correctly for guardian verification calls.
|
|
8
|
-
* 3.
|
|
9
|
-
* 4. Channel verification reply templates are non-empty and deterministic.
|
|
8
|
+
* 3. Channel verification reply templates are non-empty and deterministic.
|
|
10
9
|
*/
|
|
11
10
|
|
|
12
11
|
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
@@ -54,8 +53,6 @@ mock.module("../daemon/process-message.js", () => ({
|
|
|
54
53
|
// Imports (after mocks)
|
|
55
54
|
// ---------------------------------------------------------------------------
|
|
56
55
|
|
|
57
|
-
import type { TwilioRelaySpeechConfig } from "../calls/twilio-routes.js";
|
|
58
|
-
import { generateTwiML } from "../calls/twilio-routes.js";
|
|
59
56
|
import { initializeDb } from "../persistence/db-init.js";
|
|
60
57
|
import { handleChannelInbound } from "../runtime/routes/inbound-message-handler.js";
|
|
61
58
|
import {
|
|
@@ -110,64 +107,6 @@ describe("Channel verification reply templates", () => {
|
|
|
110
107
|
});
|
|
111
108
|
});
|
|
112
109
|
|
|
113
|
-
// ---------------------------------------------------------------------------
|
|
114
|
-
// TwiML generation: parameter propagation
|
|
115
|
-
// ---------------------------------------------------------------------------
|
|
116
|
-
|
|
117
|
-
describe("TwiML parameter propagation", () => {
|
|
118
|
-
const defaultProfile = {
|
|
119
|
-
language: "en-US",
|
|
120
|
-
ttsProvider: "google",
|
|
121
|
-
voice: "en-US-Standard-A",
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
const defaultSpeechConfig: TwilioRelaySpeechConfig = {
|
|
125
|
-
transcriptionProvider: "deepgram",
|
|
126
|
-
speechModel: undefined,
|
|
127
|
-
hints: undefined,
|
|
128
|
-
interruptSensitivity: "low",
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
test("includes verificationSessionId as Parameter when provided", () => {
|
|
132
|
-
const twiml = generateTwiML(
|
|
133
|
-
"session-123",
|
|
134
|
-
"wss://example.com/v1/calls/relay",
|
|
135
|
-
null,
|
|
136
|
-
defaultProfile,
|
|
137
|
-
defaultSpeechConfig,
|
|
138
|
-
undefined,
|
|
139
|
-
{ verificationSessionId: "gv-session-456" },
|
|
140
|
-
);
|
|
141
|
-
expect(twiml).toContain('name="verificationSessionId"');
|
|
142
|
-
expect(twiml).toContain('value="gv-session-456"');
|
|
143
|
-
expect(twiml).toContain("<Parameter");
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
test("omits Parameter elements when no custom parameters", () => {
|
|
147
|
-
const twiml = generateTwiML(
|
|
148
|
-
"session-123",
|
|
149
|
-
"wss://example.com/v1/calls/relay",
|
|
150
|
-
null,
|
|
151
|
-
defaultProfile,
|
|
152
|
-
defaultSpeechConfig,
|
|
153
|
-
);
|
|
154
|
-
expect(twiml).not.toContain("<Parameter");
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
test("omits Parameter elements when custom parameters is undefined", () => {
|
|
158
|
-
const twiml = generateTwiML(
|
|
159
|
-
"session-123",
|
|
160
|
-
"wss://example.com/v1/calls/relay",
|
|
161
|
-
null,
|
|
162
|
-
defaultProfile,
|
|
163
|
-
defaultSpeechConfig,
|
|
164
|
-
"token123",
|
|
165
|
-
undefined,
|
|
166
|
-
);
|
|
167
|
-
expect(twiml).not.toContain("<Parameter");
|
|
168
|
-
});
|
|
169
|
-
});
|
|
170
|
-
|
|
171
110
|
// ---------------------------------------------------------------------------
|
|
172
111
|
// Call session mode metadata: createCallSession persists callMode
|
|
173
112
|
// ---------------------------------------------------------------------------
|
|
@@ -21,10 +21,10 @@ mock.module("../util/logger.js", () => ({
|
|
|
21
21
|
import { readSlackMetadata } from "../messaging/providers/slack/message-metadata.js";
|
|
22
22
|
import { addMessage } from "../persistence/conversation-crud.js";
|
|
23
23
|
import { getConversationByKey } from "../persistence/conversation-key-store.js";
|
|
24
|
-
import { getDb } from "../persistence/db-connection.js";
|
|
24
|
+
import { getDb, getMemoryDb } from "../persistence/db-connection.js";
|
|
25
25
|
import { initializeDb } from "../persistence/db-init.js";
|
|
26
26
|
import { linkMessage, recordInbound } from "../persistence/delivery-crud.js";
|
|
27
|
-
import { messages } from "../persistence/schema/index.js";
|
|
27
|
+
import { memoryJobs, messages } from "../persistence/schema/index.js";
|
|
28
28
|
import { handleEditIntercept } from "../runtime/routes/inbound-stages/edit-intercept.js";
|
|
29
29
|
|
|
30
30
|
await initializeDb();
|
|
@@ -35,6 +35,25 @@ function resetTables(): void {
|
|
|
35
35
|
db.run("DELETE FROM messages");
|
|
36
36
|
db.run("DELETE FROM conversation_keys");
|
|
37
37
|
db.run("DELETE FROM conversations");
|
|
38
|
+
// memory_jobs lives in the dedicated memory connection.
|
|
39
|
+
getMemoryDb()!.run("DELETE FROM memory_jobs");
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function lexicalIndexJobMessageIds(): string[] {
|
|
43
|
+
return getMemoryDb()!
|
|
44
|
+
.select({ payload: memoryJobs.payload })
|
|
45
|
+
.from(memoryJobs)
|
|
46
|
+
.where(eq(memoryJobs.type, "index_message_lexical"))
|
|
47
|
+
.all()
|
|
48
|
+
.map((r) => {
|
|
49
|
+
try {
|
|
50
|
+
return (
|
|
51
|
+
(JSON.parse(r.payload) as { messageId?: string }).messageId ?? ""
|
|
52
|
+
);
|
|
53
|
+
} catch {
|
|
54
|
+
return "";
|
|
55
|
+
}
|
|
56
|
+
});
|
|
38
57
|
}
|
|
39
58
|
|
|
40
59
|
interface SeededFixture {
|
|
@@ -276,6 +295,41 @@ describe("Slack edit propagation", () => {
|
|
|
276
295
|
expect(after.content).toBe(before.content);
|
|
277
296
|
// No metadata mutation either -- the write is fully skipped.
|
|
278
297
|
expect(after.metadata).toBe(before.metadata);
|
|
298
|
+
|
|
299
|
+
// A no-op edit changes no searchable text, so it must NOT enqueue a lexical
|
|
300
|
+
// reindex.
|
|
301
|
+
expect(lexicalIndexJobMessageIds()).not.toContain(seeded.messageId);
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
test("a content-changing edit enqueues a lexical reindex for the message", async () => {
|
|
305
|
+
// Regression: channel edits update the row in-place via
|
|
306
|
+
// updateMessageContentAndMetadata / updateMessageContent, bypassing
|
|
307
|
+
// onMessagePersisted. The lexical index must be refreshed so the old Qdrant
|
|
308
|
+
// point does not go stale against the edited (FTS-updated) content.
|
|
309
|
+
const seeded = await seedSlackMessage({
|
|
310
|
+
conversationExternalId: "C0123CHANNEL",
|
|
311
|
+
channelTs: "1234.5678",
|
|
312
|
+
initialContent: "original text",
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
// The seed used skipIndexing, so no lexical job exists yet.
|
|
316
|
+
expect(lexicalIndexJobMessageIds()).not.toContain(seeded.messageId);
|
|
317
|
+
|
|
318
|
+
await handleEditIntercept({
|
|
319
|
+
sourceChannel: "slack",
|
|
320
|
+
conversationExternalId: seeded.conversationExternalId,
|
|
321
|
+
externalMessageId: nextEditEventId(),
|
|
322
|
+
sourceMessageId: seeded.channelTs,
|
|
323
|
+
canonicalAssistantId: "self",
|
|
324
|
+
assistantId: "self",
|
|
325
|
+
content: "edited searchable text",
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
expect(readMessageRow(seeded.messageId).content).toBe(
|
|
329
|
+
"edited searchable text",
|
|
330
|
+
);
|
|
331
|
+
// The edit reindexed the message into the lexical index.
|
|
332
|
+
expect(lexicalIndexJobMessageIds()).toContain(seeded.messageId);
|
|
279
333
|
});
|
|
280
334
|
|
|
281
335
|
// The lookup retries 5 times with 2s backoff (~10s total) before giving up,
|
|
@@ -56,6 +56,15 @@ describe("empty-state greeting cache", () => {
|
|
|
56
56
|
expect(getCachedEmptyStateGreeting()).toBe("hey there");
|
|
57
57
|
});
|
|
58
58
|
|
|
59
|
+
test("keeps cached greetings separate by timezone scope", () => {
|
|
60
|
+
setCachedEmptyStateGreeting("hey eastern", "America/New_York");
|
|
61
|
+
setCachedEmptyStateGreeting("hey central", "America/Chicago");
|
|
62
|
+
|
|
63
|
+
expect(getCachedEmptyStateGreeting("America/New_York")).toBe("hey eastern");
|
|
64
|
+
expect(getCachedEmptyStateGreeting("America/Chicago")).toBe("hey central");
|
|
65
|
+
expect(getCachedEmptyStateGreeting("Europe/Skopje")).toBeNull();
|
|
66
|
+
});
|
|
67
|
+
|
|
59
68
|
test("returns null once the TTL is exceeded", () => {
|
|
60
69
|
setCachedEmptyStateGreeting("stale");
|
|
61
70
|
checkpointStore.set(
|
|
@@ -75,21 +75,22 @@ mock.module("../config/loader.js", () => ({
|
|
|
75
75
|
}));
|
|
76
76
|
|
|
77
77
|
// Mock Twilio provider
|
|
78
|
+
class MockTwilioVoiceProvider {
|
|
79
|
+
static getAuthToken() {
|
|
80
|
+
return "mock-auth-token";
|
|
81
|
+
}
|
|
82
|
+
static verifyWebhookSignature() {
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
async initiateCall() {
|
|
86
|
+
return { callSid: "CA_mock_sid" };
|
|
87
|
+
}
|
|
88
|
+
async endCall() {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
78
92
|
mock.module("../calls/twilio-provider.js", () => ({
|
|
79
|
-
|
|
80
|
-
static getAuthToken() {
|
|
81
|
-
return "mock-auth-token";
|
|
82
|
-
}
|
|
83
|
-
static verifyWebhookSignature() {
|
|
84
|
-
return true;
|
|
85
|
-
}
|
|
86
|
-
async initiateCall() {
|
|
87
|
-
return { callSid: "CA_mock_sid" };
|
|
88
|
-
}
|
|
89
|
-
async endCall() {
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
},
|
|
93
|
+
TwilioVoiceProvider: MockTwilioVoiceProvider,
|
|
93
94
|
}));
|
|
94
95
|
|
|
95
96
|
mock.module("../security/secure-keys.js", () => ({
|
|
@@ -268,22 +269,6 @@ describe("gateway-only ingress enforcement", () => {
|
|
|
268
269
|
expect(body.error.code).toBe("GONE");
|
|
269
270
|
});
|
|
270
271
|
|
|
271
|
-
test("POST /webhooks/twilio/connect-action returns 410", async () => {
|
|
272
|
-
const res = await fetch(
|
|
273
|
-
`http://127.0.0.1:${port}/webhooks/twilio/connect-action`,
|
|
274
|
-
{
|
|
275
|
-
method: "POST",
|
|
276
|
-
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
277
|
-
body: makeFormBody({ CallSid: "CA123" }),
|
|
278
|
-
},
|
|
279
|
-
);
|
|
280
|
-
expect(res.status).toBe(410);
|
|
281
|
-
const body = (await res.json()) as {
|
|
282
|
-
error: { code: string; message: string };
|
|
283
|
-
};
|
|
284
|
-
expect(body.error.code).toBe("GONE");
|
|
285
|
-
});
|
|
286
|
-
|
|
287
272
|
test("POST /v1/calls/twilio/voice-webhook returns 410", async () => {
|
|
288
273
|
const res = await fetch(
|
|
289
274
|
`http://127.0.0.1:${port}/v1/calls/twilio/voice-webhook`,
|
|
@@ -357,23 +342,6 @@ describe("gateway-only ingress enforcement", () => {
|
|
|
357
342
|
expect(res.status).not.toBe(410);
|
|
358
343
|
});
|
|
359
344
|
|
|
360
|
-
test("POST /v1/internal/twilio/connect-action is NOT blocked", async () => {
|
|
361
|
-
const res = await fetch(
|
|
362
|
-
`http://127.0.0.1:${port}/v1/internal/twilio/connect-action`,
|
|
363
|
-
{
|
|
364
|
-
method: "POST",
|
|
365
|
-
headers: {
|
|
366
|
-
...GATEWAY_AUTH_HEADERS,
|
|
367
|
-
"Content-Type": "application/json",
|
|
368
|
-
},
|
|
369
|
-
body: JSON.stringify({
|
|
370
|
-
params: { CallSid: "CA123" },
|
|
371
|
-
}),
|
|
372
|
-
},
|
|
373
|
-
);
|
|
374
|
-
expect(res.status).not.toBe(410);
|
|
375
|
-
});
|
|
376
|
-
|
|
377
345
|
test("POST /v1/internal/oauth/callback is NOT blocked", async () => {
|
|
378
346
|
const res = await fetch(
|
|
379
347
|
`http://127.0.0.1:${port}/v1/internal/oauth/callback`,
|
|
@@ -394,69 +362,6 @@ describe("gateway-only ingress enforcement", () => {
|
|
|
394
362
|
});
|
|
395
363
|
});
|
|
396
364
|
|
|
397
|
-
// ── Relay WebSocket upgrade ───────────────────
|
|
398
|
-
|
|
399
|
-
describe("relay WebSocket upgrade", () => {
|
|
400
|
-
test("blocks non-private-network origin", async () => {
|
|
401
|
-
// The peer address (127.0.0.1) passes the private network check,
|
|
402
|
-
// but the external Origin header triggers the secondary defense-in-depth block.
|
|
403
|
-
const res = await fetch(
|
|
404
|
-
`http://127.0.0.1:${port}/v1/calls/relay?callSessionId=sess-123`,
|
|
405
|
-
{
|
|
406
|
-
headers: {
|
|
407
|
-
Upgrade: "websocket",
|
|
408
|
-
Connection: "Upgrade",
|
|
409
|
-
Origin: "https://external.example.com",
|
|
410
|
-
"Sec-WebSocket-Key": "dGhlIHNhbXBsZSBub25jZQ==",
|
|
411
|
-
"Sec-WebSocket-Version": "13",
|
|
412
|
-
},
|
|
413
|
-
},
|
|
414
|
-
);
|
|
415
|
-
expect(res.status).toBe(403);
|
|
416
|
-
const body = (await res.json()) as {
|
|
417
|
-
error: { code: string; message: string };
|
|
418
|
-
};
|
|
419
|
-
expect(body.error.code).toBe("FORBIDDEN");
|
|
420
|
-
expect(body.error.message).toContain("Direct relay access disabled");
|
|
421
|
-
});
|
|
422
|
-
|
|
423
|
-
test("allows request with no origin header (private network peer)", async () => {
|
|
424
|
-
// Without an origin header, isPrivateNetworkOrigin returns true.
|
|
425
|
-
// The peer address (127.0.0.1) passes the private network peer check.
|
|
426
|
-
const res = await fetch(
|
|
427
|
-
`http://127.0.0.1:${port}/v1/calls/relay?callSessionId=sess-123`,
|
|
428
|
-
{
|
|
429
|
-
headers: {
|
|
430
|
-
Upgrade: "websocket",
|
|
431
|
-
Connection: "Upgrade",
|
|
432
|
-
"Sec-WebSocket-Key": "dGhlIHNhbXBsZSBub25jZQ==",
|
|
433
|
-
"Sec-WebSocket-Version": "13",
|
|
434
|
-
},
|
|
435
|
-
},
|
|
436
|
-
);
|
|
437
|
-
// Should NOT be 403 — WebSocket upgrade may or may not succeed
|
|
438
|
-
// depending on test environment, but the gateway guard should pass.
|
|
439
|
-
expect(res.status).not.toBe(403);
|
|
440
|
-
});
|
|
441
|
-
|
|
442
|
-
test("allows localhost origin from loopback peer", async () => {
|
|
443
|
-
const res = await fetch(
|
|
444
|
-
`http://127.0.0.1:${port}/v1/calls/relay?callSessionId=sess-123`,
|
|
445
|
-
{
|
|
446
|
-
headers: {
|
|
447
|
-
Upgrade: "websocket",
|
|
448
|
-
Connection: "Upgrade",
|
|
449
|
-
Origin: "http://127.0.0.1:3000",
|
|
450
|
-
"Sec-WebSocket-Key": "dGhlIHNhbXBsZSBub25jZQ==",
|
|
451
|
-
"Sec-WebSocket-Version": "13",
|
|
452
|
-
},
|
|
453
|
-
},
|
|
454
|
-
);
|
|
455
|
-
// Should NOT be 403
|
|
456
|
-
expect(res.status).not.toBe(403);
|
|
457
|
-
});
|
|
458
|
-
});
|
|
459
|
-
|
|
460
365
|
// ── Media-stream WebSocket upgrade ─────────────────────────────────
|
|
461
366
|
|
|
462
367
|
describe("media-stream WebSocket upgrade", () => {
|
|
@@ -9,10 +9,12 @@ import {
|
|
|
9
9
|
buildGuardianRequestCodeInstruction,
|
|
10
10
|
hasGuardianRequestCodeInstruction,
|
|
11
11
|
parseGuardianQuestionPayload,
|
|
12
|
+
parseInteractiveApprovalPayload,
|
|
12
13
|
resolveGuardianInstructionModeForRequest,
|
|
13
14
|
resolveGuardianInstructionModeFromFields,
|
|
14
15
|
resolveGuardianQuestionInstructionMode,
|
|
15
16
|
stripConflictingGuardianRequestInstructions,
|
|
17
|
+
stripGuardianRequestCodeInstructions,
|
|
16
18
|
} from "../notifications/guardian-question-mode.js";
|
|
17
19
|
|
|
18
20
|
describe("guardian-question-mode", () => {
|
|
@@ -228,4 +230,59 @@ describe("guardian-question-mode", () => {
|
|
|
228
230
|
),
|
|
229
231
|
).toBe("");
|
|
230
232
|
});
|
|
233
|
+
|
|
234
|
+
test("stripGuardianRequestCodeInstructions removes both-mode directives and bare code mentions", () => {
|
|
235
|
+
const text = [
|
|
236
|
+
"Alice is asking to run ls /tmp.",
|
|
237
|
+
"Approval code: A1B2C3",
|
|
238
|
+
'Reference code: A1B2C3. Reply "A1B2C3 approve" or "A1B2C3 reject".',
|
|
239
|
+
'Reply "A1B2C3 <your answer>".',
|
|
240
|
+
].join("\n");
|
|
241
|
+
|
|
242
|
+
expect(stripGuardianRequestCodeInstructions(text, "A1B2C3")).toBe(
|
|
243
|
+
"Alice is asking to run ls /tmp.",
|
|
244
|
+
);
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
test("stripGuardianRequestCodeInstructions leaves unrelated text and other codes intact", () => {
|
|
248
|
+
const text = 'Approval code: ZZZZZZ. Reply "A1B2C3 approve" if you agree.';
|
|
249
|
+
expect(stripGuardianRequestCodeInstructions(text, "A1B2C3")).toBe(text);
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
test("parseInteractiveApprovalPayload accepts approval-mode payloads with a requestId", () => {
|
|
253
|
+
expect(
|
|
254
|
+
parseInteractiveApprovalPayload({
|
|
255
|
+
requestKind: "tool_grant_request",
|
|
256
|
+
requestId: "req-1",
|
|
257
|
+
requestCode: "A1B2C3",
|
|
258
|
+
questionText: "Allow host bash?",
|
|
259
|
+
toolName: "host_bash",
|
|
260
|
+
}),
|
|
261
|
+
).not.toBeNull();
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
test("parseInteractiveApprovalPayload rejects answer-mode and unparseable payloads", () => {
|
|
265
|
+
// Answer mode: free-text questions get no Approve/Reject buttons.
|
|
266
|
+
expect(
|
|
267
|
+
parseInteractiveApprovalPayload({
|
|
268
|
+
requestKind: "pending_question",
|
|
269
|
+
requestId: "req-2",
|
|
270
|
+
requestCode: "A1B2C3",
|
|
271
|
+
questionText: "What time works?",
|
|
272
|
+
callSessionId: "call-1",
|
|
273
|
+
activeGuardianRequestCount: 1,
|
|
274
|
+
}),
|
|
275
|
+
).toBeNull();
|
|
276
|
+
|
|
277
|
+
// Strict-parse failure: missing required pending_question fields.
|
|
278
|
+
expect(
|
|
279
|
+
parseInteractiveApprovalPayload({
|
|
280
|
+
requestKind: "pending_question",
|
|
281
|
+
requestId: "req-3",
|
|
282
|
+
requestCode: "A1B2C3",
|
|
283
|
+
questionText: "Allow send_email?",
|
|
284
|
+
toolName: "send_email",
|
|
285
|
+
}),
|
|
286
|
+
).toBeNull();
|
|
287
|
+
});
|
|
231
288
|
});
|
|
@@ -20,7 +20,7 @@ mock.module("../calls/twilio-config.js", () => ({
|
|
|
20
20
|
}));
|
|
21
21
|
|
|
22
22
|
mock.module("../calls/twilio-provider.js", () => ({
|
|
23
|
-
|
|
23
|
+
TwilioVoiceProvider: class {
|
|
24
24
|
async checkCallerIdEligibility() {
|
|
25
25
|
return { eligible: true };
|
|
26
26
|
}
|