@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,34 +1,24 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* HTTP route handlers for Twilio voice webhooks.
|
|
3
3
|
*
|
|
4
|
-
* - handleVoiceWebhook: initial voice webhook; returns
|
|
5
|
-
*
|
|
4
|
+
* - handleVoiceWebhook: initial voice webhook; returns `<Connect><Stream>`
|
|
5
|
+
* TwiML so the daemon receives raw audio over the media-stream transport
|
|
6
|
+
* and performs STT/TTS server-side for every call
|
|
6
7
|
* - handleStatusCallback: call status updates (ringing, in-progress, completed, etc.)
|
|
7
|
-
* - handleConnectAction: called when the ConversationRelay connection ends
|
|
8
8
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* TwiML generation
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* - **`conversation-relay-native`** (deepgram, google-gemini) — emits
|
|
16
|
-
* `<Connect><ConversationRelay>` with Twilio-native `transcriptionProvider`
|
|
17
|
-
* and `speechModel` attributes.
|
|
18
|
-
*
|
|
19
|
-
* - **`media-stream-custom`** (openai-whisper) — emits
|
|
20
|
-
* `<Connect><Stream>` so the daemon receives raw audio and transcribes
|
|
21
|
-
* server-side.
|
|
9
|
+
* Setup-flow routing (verification, invite redemption, name capture, deny,
|
|
10
|
+
* normal) is resolved by the media-stream server when Twilio's `start`
|
|
11
|
+
* frame arrives — TwiML generation performs no routing of its own. Its
|
|
12
|
+
* only gate is the STT+TTS credential-readiness preflight: a call whose
|
|
13
|
+
* daemon cannot transcribe or speak gets audible `<Say>` setup-required
|
|
14
|
+
* TwiML and a `<Hangup/>` instead of a doomed stream.
|
|
22
15
|
*/
|
|
23
16
|
|
|
24
17
|
import {
|
|
25
18
|
buildTwilioMediaStreamUrl,
|
|
26
|
-
buildTwilioRelayUrl,
|
|
27
19
|
TWILIO_PUBLIC_BASE_URL_PLACEHOLDER,
|
|
28
20
|
} from "@vellumai/service-contracts/twilio-ingress";
|
|
29
21
|
|
|
30
|
-
import { loadConfig } from "../config/loader.js";
|
|
31
|
-
import { getProviderEntry } from "../providers/speech-to-text/provider-catalog.js";
|
|
32
22
|
import {
|
|
33
23
|
BadRequestError,
|
|
34
24
|
GoneError,
|
|
@@ -54,13 +44,8 @@ import {
|
|
|
54
44
|
releaseCallbackClaim,
|
|
55
45
|
updateCallSession,
|
|
56
46
|
} from "./call-store.js";
|
|
57
|
-
import {
|
|
58
|
-
import { getPhoneCallerVerdict } from "./inbound-trust-reader.js";
|
|
59
|
-
import { routeSetup } from "./relay-setup-router.js";
|
|
60
|
-
import { resolveCallHints } from "./stt-hints.js";
|
|
61
|
-
import { resolveTelephonySttRouting } from "./telephony-stt-routing.js";
|
|
47
|
+
import { resolveTelephonyCredentialReadiness } from "./telephony-credential-preflight.js";
|
|
62
48
|
import type { CallStatus } from "./types.js";
|
|
63
|
-
import { resolveVoiceQualityProfile } from "./voice-quality.js";
|
|
64
49
|
|
|
65
50
|
const log = getLogger("twilio-routes");
|
|
66
51
|
|
|
@@ -71,26 +56,7 @@ const log = getLogger("twilio-routes");
|
|
|
71
56
|
*/
|
|
72
57
|
const TWILIO_RELAY_TOKEN_PLACEHOLDER = "__VELLUM_RELAY_TOKEN__";
|
|
73
58
|
|
|
74
|
-
// ──
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Twilio ConversationRelay speech-to-text attributes.
|
|
78
|
-
*
|
|
79
|
-
* All values are pre-formatted strings ready for direct insertion into
|
|
80
|
-
* TwiML XML attribute values (XML escaping is the caller's responsibility).
|
|
81
|
-
*/
|
|
82
|
-
export interface TwilioRelaySpeechConfig {
|
|
83
|
-
/** STT provider name (e.g. "Deepgram", "Google"). */
|
|
84
|
-
transcriptionProvider: string;
|
|
85
|
-
/** ASR model identifier, or undefined when the provider default should be used. */
|
|
86
|
-
speechModel: string | undefined;
|
|
87
|
-
/** Comma-separated vocabulary hints for the STT provider, or undefined when no hints are available. */
|
|
88
|
-
hints: string | undefined;
|
|
89
|
-
/** How aggressively the provider detects the start of caller speech. */
|
|
90
|
-
interruptSensitivity: string;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// ── Helpers ──────────────────────────────────────────────────────────
|
|
59
|
+
// ── TwiML generation ─────────────────────────────────────────────────
|
|
94
60
|
|
|
95
61
|
function escapeXml(str: string): string {
|
|
96
62
|
return str
|
|
@@ -101,71 +67,11 @@ function escapeXml(str: string): string {
|
|
|
101
67
|
.replace(/'/g, "'");
|
|
102
68
|
}
|
|
103
69
|
|
|
104
|
-
export function generateTwiML(
|
|
105
|
-
callSessionId: string,
|
|
106
|
-
relayUrl: string,
|
|
107
|
-
welcomeGreeting: string | null,
|
|
108
|
-
profile: {
|
|
109
|
-
language: string;
|
|
110
|
-
ttsProvider: string;
|
|
111
|
-
voice: string;
|
|
112
|
-
},
|
|
113
|
-
speechConfig: TwilioRelaySpeechConfig,
|
|
114
|
-
relayToken?: string,
|
|
115
|
-
customParameters?: Record<string, string>,
|
|
116
|
-
): string {
|
|
117
|
-
const greetingAttr =
|
|
118
|
-
welcomeGreeting && welcomeGreeting.trim().length > 0
|
|
119
|
-
? `\n welcomeGreeting="${escapeXml(welcomeGreeting.trim())}"`
|
|
120
|
-
: "";
|
|
121
|
-
const tokenParam = relayToken
|
|
122
|
-
? `&token=${escapeXml(encodeURIComponent(relayToken))}`
|
|
123
|
-
: "";
|
|
124
|
-
|
|
125
|
-
// Build <Parameter> elements for custom parameters to propagate
|
|
126
|
-
// through the ConversationRelay setup payload for observability.
|
|
127
|
-
let parameterElements = "";
|
|
128
|
-
if (customParameters) {
|
|
129
|
-
for (const [key, value] of Object.entries(customParameters)) {
|
|
130
|
-
parameterElements += `\n <Parameter name="${escapeXml(
|
|
131
|
-
key,
|
|
132
|
-
)}" value="${escapeXml(value)}" />`;
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// When there are no Parameter children, use self-closing tag to preserve
|
|
137
|
-
// the original TwiML format. With children, use open/close tags.
|
|
138
|
-
const hasParameters = parameterElements.length > 0;
|
|
139
|
-
const relayClose = hasParameters
|
|
140
|
-
? `>${parameterElements}\n </ConversationRelay>`
|
|
141
|
-
: "/>";
|
|
142
|
-
|
|
143
|
-
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
144
|
-
<Response>
|
|
145
|
-
<Connect>
|
|
146
|
-
<ConversationRelay
|
|
147
|
-
url="${escapeXml(relayUrl)}?callSessionId=${escapeXml(
|
|
148
|
-
callSessionId,
|
|
149
|
-
)}${tokenParam}"
|
|
150
|
-
${greetingAttr}
|
|
151
|
-
voice="${escapeXml(profile.voice)}"
|
|
152
|
-
language="${escapeXml(profile.language)}"
|
|
153
|
-
transcriptionProvider="${escapeXml(speechConfig.transcriptionProvider)}"${speechConfig.speechModel ? `\n speechModel="${escapeXml(speechConfig.speechModel)}"` : ""}
|
|
154
|
-
ttsProvider="${escapeXml(profile.ttsProvider)}"
|
|
155
|
-
interruptible="true"
|
|
156
|
-
dtmfDetection="true"
|
|
157
|
-
interruptSensitivity="${escapeXml(speechConfig.interruptSensitivity)}"${speechConfig.hints ? `\n hints="${escapeXml(speechConfig.hints)}"` : ""}
|
|
158
|
-
${relayClose}
|
|
159
|
-
</Connect>
|
|
160
|
-
</Response>`;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
70
|
/**
|
|
164
|
-
* Generate `<Connect><Stream>` TwiML for the media-stream
|
|
71
|
+
* Generate `<Connect><Stream>` TwiML for the media-stream transport.
|
|
165
72
|
*
|
|
166
|
-
*
|
|
167
|
-
*
|
|
168
|
-
* raw audio frames; the daemon transcribes server-side.
|
|
73
|
+
* Twilio opens a WebSocket to `streamUrl` and sends raw audio frames; the
|
|
74
|
+
* daemon transcribes and synthesizes speech server-side.
|
|
169
75
|
*
|
|
170
76
|
* `callSessionId` and `token` are encoded as **path segments** on the
|
|
171
77
|
* WebSocket URL so the gateway can validate and route the upgrade request
|
|
@@ -220,19 +126,6 @@ export function generateStreamTwiML(
|
|
|
220
126
|
</Response>`;
|
|
221
127
|
}
|
|
222
128
|
|
|
223
|
-
export function buildWelcomeGreeting(
|
|
224
|
-
task: string | null,
|
|
225
|
-
configuredGreeting?: string,
|
|
226
|
-
): string {
|
|
227
|
-
void task;
|
|
228
|
-
const override = configuredGreeting?.trim();
|
|
229
|
-
if (override) return override;
|
|
230
|
-
// The contextual first opener now comes from the call controller's
|
|
231
|
-
// initial LLM turn via the conversation pipeline. Keep Twilio's relay-level
|
|
232
|
-
// greeting empty by default so we don't speak a deterministic static line first.
|
|
233
|
-
return "";
|
|
234
|
-
}
|
|
235
|
-
|
|
236
129
|
/**
|
|
237
130
|
* Map Twilio call status strings to our internal CallStatus.
|
|
238
131
|
*/
|
|
@@ -305,18 +198,7 @@ async function processVoiceWebhook(
|
|
|
305
198
|
toNumber: callerTo,
|
|
306
199
|
});
|
|
307
200
|
|
|
308
|
-
return buildVoiceWebhookTwiml(
|
|
309
|
-
session.id,
|
|
310
|
-
{
|
|
311
|
-
task: session.task,
|
|
312
|
-
toNumber: callerTo,
|
|
313
|
-
fromNumber: callerFrom,
|
|
314
|
-
direction: "inbound",
|
|
315
|
-
inviteFriendName: null,
|
|
316
|
-
inviteGuardianName: null,
|
|
317
|
-
},
|
|
318
|
-
session.verificationSessionId,
|
|
319
|
-
);
|
|
201
|
+
return buildVoiceWebhookTwiml(session.id, session.verificationSessionId);
|
|
320
202
|
}
|
|
321
203
|
|
|
322
204
|
// ── Outbound mode: callSessionId is present ─────────────────────
|
|
@@ -340,25 +222,14 @@ async function processVoiceWebhook(
|
|
|
340
222
|
log.info({ callSessionId, callSid }, "Stored CallSid from voice webhook");
|
|
341
223
|
}
|
|
342
224
|
|
|
343
|
-
return buildVoiceWebhookTwiml(
|
|
344
|
-
callSessionId,
|
|
345
|
-
{
|
|
346
|
-
task: session.task,
|
|
347
|
-
toNumber: session.toNumber,
|
|
348
|
-
fromNumber: session.fromNumber,
|
|
349
|
-
direction: "outbound",
|
|
350
|
-
inviteFriendName: session.inviteFriendName,
|
|
351
|
-
inviteGuardianName: session.inviteGuardianName,
|
|
352
|
-
},
|
|
353
|
-
session.verificationSessionId,
|
|
354
|
-
);
|
|
225
|
+
return buildVoiceWebhookTwiml(callSessionId, session.verificationSessionId);
|
|
355
226
|
}
|
|
356
227
|
|
|
357
228
|
// ── Route handlers ───────────────────────────────────────────────────
|
|
358
229
|
|
|
359
230
|
/**
|
|
360
231
|
* Receives the initial voice webhook when Twilio connects the call.
|
|
361
|
-
* Returns TwiML XML that tells Twilio to open a
|
|
232
|
+
* Returns TwiML XML that tells Twilio to open a media-stream WebSocket.
|
|
362
233
|
*
|
|
363
234
|
* Supports two flows:
|
|
364
235
|
* - **Outbound** (callSessionId present in query): uses the existing session
|
|
@@ -385,207 +256,57 @@ export async function handleVoiceWebhook(req: Request): Promise<Response> {
|
|
|
385
256
|
/**
|
|
386
257
|
* Shared TwiML generation for both inbound and outbound voice webhooks.
|
|
387
258
|
*
|
|
388
|
-
*
|
|
389
|
-
*
|
|
259
|
+
* Every call connects over the media-stream transport. Setup-flow routing
|
|
260
|
+
* (`routeSetup`) is owned by the media-stream server, which resolves it
|
|
261
|
+
* when Twilio's `start` frame arrives — no routing happens at TwiML time.
|
|
390
262
|
*
|
|
391
|
-
*
|
|
392
|
-
*
|
|
393
|
-
*
|
|
394
|
-
*
|
|
395
|
-
* -
|
|
396
|
-
*
|
|
397
|
-
*
|
|
263
|
+
* The one TwiML-time gate is credential readiness: the daemon performs
|
|
264
|
+
* both STT and TTS on this transport, so when
|
|
265
|
+
* {@link resolveTelephonyCredentialReadiness} reports a gap the webhook
|
|
266
|
+
* returns `<Say>` setup-required copy plus `<Hangup/>` (audible via
|
|
267
|
+
* Twilio-hosted TTS even when the daemon's TTS is the broken half) and
|
|
268
|
+
* records a `telephony_credential_preflight_failed` call event instead of
|
|
269
|
+
* connecting a stream that cannot work.
|
|
398
270
|
*
|
|
399
271
|
* When `verificationSessionId` is provided, it is included as a
|
|
400
272
|
* `<Parameter>` in the TwiML for observability and compatibility with
|
|
401
273
|
* the Twilio setup payload. The persisted call session mode is the
|
|
402
|
-
* primary signal for deterministic flow selection
|
|
274
|
+
* primary signal for deterministic flow selection at stream start.
|
|
403
275
|
*/
|
|
404
276
|
async function buildVoiceWebhookTwiml(
|
|
405
277
|
callSessionId: string,
|
|
406
|
-
sessionContext: {
|
|
407
|
-
task: string | null;
|
|
408
|
-
toNumber: string;
|
|
409
|
-
fromNumber: string;
|
|
410
|
-
direction: "inbound" | "outbound";
|
|
411
|
-
inviteFriendName: string | null;
|
|
412
|
-
inviteGuardianName: string | null;
|
|
413
|
-
} | null,
|
|
414
278
|
verificationSessionId?: string | null,
|
|
415
279
|
): Promise<string> {
|
|
416
|
-
const
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
log.info(
|
|
420
|
-
{ callSessionId, ttsProvider: profile.ttsProvider, voice: profile.voice },
|
|
421
|
-
"Voice quality profile resolved",
|
|
422
|
-
);
|
|
423
|
-
|
|
424
|
-
// Resolve telephony STT strategy from services.stt.provider.
|
|
425
|
-
// The routing resolver handles speech-model defaults internally per provider.
|
|
426
|
-
const routingResult = resolveTelephonySttRouting();
|
|
427
|
-
|
|
428
|
-
// Derive Deepgram fallback values from the provider catalog so they stay
|
|
429
|
-
// in sync with the single source of truth. Hardcoded strings are kept only
|
|
430
|
-
// as a final safety net in case the catalog entry is missing.
|
|
431
|
-
const dgEntry = getProviderEntry("deepgram");
|
|
432
|
-
const fallbackProvider =
|
|
433
|
-
dgEntry?.telephonyRouting.twilioNativeMapping?.provider ?? "Deepgram";
|
|
434
|
-
const fallbackModel =
|
|
435
|
-
dgEntry?.telephonyRouting.twilioNativeMapping?.defaultSpeechModel ??
|
|
436
|
-
"nova-3";
|
|
437
|
-
|
|
438
|
-
if (routingResult.status === "unknown-provider") {
|
|
439
|
-
log.error(
|
|
440
|
-
{
|
|
441
|
-
callSessionId,
|
|
442
|
-
providerId: routingResult.providerId,
|
|
443
|
-
reason: routingResult.reason,
|
|
444
|
-
},
|
|
445
|
-
"Telephony STT routing failed — unknown provider; falling back to ConversationRelay with Deepgram",
|
|
446
|
-
);
|
|
447
|
-
// Graceful degradation: fall back to Deepgram ConversationRelay so
|
|
448
|
-
// calls don't fail entirely on a misconfigured provider.
|
|
449
|
-
return buildConversationRelayTwiml(
|
|
450
|
-
callSessionId,
|
|
451
|
-
profile,
|
|
452
|
-
sessionContext,
|
|
453
|
-
verificationSessionId,
|
|
454
|
-
{ transcriptionProvider: fallbackProvider, speechModel: fallbackModel },
|
|
455
|
-
);
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
const { strategy } = routingResult;
|
|
459
|
-
|
|
460
|
-
if (strategy.strategy === "conversation-relay-native") {
|
|
461
|
-
return buildConversationRelayTwiml(
|
|
462
|
-
callSessionId,
|
|
463
|
-
profile,
|
|
464
|
-
sessionContext,
|
|
465
|
-
verificationSessionId,
|
|
466
|
-
{
|
|
467
|
-
transcriptionProvider: strategy.transcriptionProvider,
|
|
468
|
-
speechModel: strategy.speechModel,
|
|
469
|
-
},
|
|
470
|
-
);
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
// media-stream-custom path — preflight check to reject interactive setup
|
|
474
|
-
// flows that the media-stream transport cannot support. The media-stream
|
|
475
|
-
// server has a defensive fallback for these cases, but catching them here
|
|
476
|
-
// avoids bootstrapping a WebSocket session that will immediately fail.
|
|
477
|
-
const session = getCallSession(callSessionId);
|
|
478
|
-
const from = sessionContext?.fromNumber ?? "";
|
|
479
|
-
const to = sessionContext?.toNumber ?? "";
|
|
480
|
-
|
|
481
|
-
// Resolve the phone channel's inbound admission floor so this preflight
|
|
482
|
-
// classification matches the real enforcement at stream start — a
|
|
483
|
-
// floor-denied caller is recognized as `deny` here, not `normal_call`.
|
|
484
|
-
// The reader fails open to `null` by contract, so a transport hiccup
|
|
485
|
-
// admits the caller.
|
|
486
|
-
const admissionPolicy = await getChannelAdmissionPolicy("phone");
|
|
487
|
-
|
|
488
|
-
// Verdict-first caller trust so this preflight matches handleSetup's ACL.
|
|
489
|
-
// routeSetup uses it when present and not resolutionFailed, else falls back
|
|
490
|
-
// to local resolution. The reader returns null on failure, keeping the
|
|
491
|
-
// local path on a gateway blip.
|
|
492
|
-
const isInbound = sessionContext?.direction !== "outbound";
|
|
493
|
-
const otherPartyNumber = isInbound ? from : to;
|
|
494
|
-
const verdict = await getPhoneCallerVerdict(otherPartyNumber);
|
|
495
|
-
|
|
496
|
-
const { outcome } = routeSetup({
|
|
497
|
-
callSessionId,
|
|
498
|
-
session: session ?? null,
|
|
499
|
-
from,
|
|
500
|
-
to,
|
|
501
|
-
admissionPolicy,
|
|
502
|
-
verdict,
|
|
503
|
-
});
|
|
504
|
-
|
|
505
|
-
// The media-stream transport supports normal_call and deny (which speaks
|
|
506
|
-
// a message and tears down). All other outcomes require interactive
|
|
507
|
-
// sub-flows (DTMF entry, name capture, guardian wait) that media-stream
|
|
508
|
-
// cannot perform. Reject these deterministically before stream bootstrap.
|
|
509
|
-
if (outcome.action !== "normal_call" && outcome.action !== "deny") {
|
|
280
|
+
const readiness = await resolveTelephonyCredentialReadiness();
|
|
281
|
+
if (readiness.status === "not-ready") {
|
|
510
282
|
log.warn(
|
|
511
|
-
{
|
|
512
|
-
|
|
513
|
-
setupAction: outcome.action,
|
|
514
|
-
strategy: "media-stream-custom",
|
|
515
|
-
},
|
|
516
|
-
"Media-stream preflight rejected unsupported interactive setup flow — falling back to ConversationRelay with Deepgram",
|
|
517
|
-
);
|
|
518
|
-
// Fall back to ConversationRelay so the interactive flow can proceed
|
|
519
|
-
// through the relay server which supports it natively.
|
|
520
|
-
return buildConversationRelayTwiml(
|
|
521
|
-
callSessionId,
|
|
522
|
-
profile,
|
|
523
|
-
sessionContext,
|
|
524
|
-
verificationSessionId,
|
|
525
|
-
{ transcriptionProvider: fallbackProvider, speechModel: fallbackModel },
|
|
283
|
+
{ callSessionId, missing: readiness.missing },
|
|
284
|
+
"Telephony credential preflight failed — returning setup-required TwiML",
|
|
526
285
|
);
|
|
286
|
+
recordCallEvent(callSessionId, "telephony_credential_preflight_failed", {
|
|
287
|
+
missing: readiness.missing,
|
|
288
|
+
});
|
|
289
|
+
return buildSetupRequiredTwiml(readiness.userMessage);
|
|
527
290
|
}
|
|
528
291
|
|
|
529
292
|
return buildMediaStreamTwiml(callSessionId, verificationSessionId);
|
|
530
293
|
}
|
|
531
294
|
|
|
532
295
|
/**
|
|
533
|
-
* Build
|
|
296
|
+
* Build `<Say>` + `<Hangup/>` TwiML for calls blocked by the credential
|
|
297
|
+
* preflight, so the caller hears why the call cannot proceed.
|
|
534
298
|
*/
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
direction: "inbound" | "outbound";
|
|
543
|
-
inviteFriendName: string | null;
|
|
544
|
-
inviteGuardianName: string | null;
|
|
545
|
-
} | null,
|
|
546
|
-
verificationSessionId: string | null | undefined,
|
|
547
|
-
sttAttrs: { transcriptionProvider: string; speechModel: string | undefined },
|
|
548
|
-
): Promise<string> {
|
|
549
|
-
const rawHints = await resolveCallHints(sessionContext, profile.hints);
|
|
550
|
-
|
|
551
|
-
const speechConfig: TwilioRelaySpeechConfig = {
|
|
552
|
-
transcriptionProvider: sttAttrs.transcriptionProvider,
|
|
553
|
-
speechModel: sttAttrs.speechModel,
|
|
554
|
-
hints: rawHints && rawHints.length > 0 ? rawHints : undefined,
|
|
555
|
-
interruptSensitivity: profile.interruptSensitivity,
|
|
556
|
-
};
|
|
557
|
-
|
|
558
|
-
const relayUrl = buildTwilioRelayUrl(TWILIO_PUBLIC_BASE_URL_PLACEHOLDER);
|
|
559
|
-
const welcomeGreeting = buildWelcomeGreeting(sessionContext?.task ?? null);
|
|
560
|
-
const relayToken = TWILIO_RELAY_TOKEN_PLACEHOLDER;
|
|
561
|
-
|
|
562
|
-
const customParameters: Record<string, string> | undefined =
|
|
563
|
-
verificationSessionId ? { verificationSessionId } : undefined;
|
|
564
|
-
|
|
565
|
-
const twiml = generateTwiML(
|
|
566
|
-
callSessionId,
|
|
567
|
-
relayUrl,
|
|
568
|
-
welcomeGreeting,
|
|
569
|
-
profile,
|
|
570
|
-
speechConfig,
|
|
571
|
-
relayToken,
|
|
572
|
-
customParameters,
|
|
573
|
-
);
|
|
574
|
-
|
|
575
|
-
log.info(
|
|
576
|
-
{
|
|
577
|
-
callSessionId,
|
|
578
|
-
strategy: "conversation-relay-native",
|
|
579
|
-
transcriptionProvider: sttAttrs.transcriptionProvider,
|
|
580
|
-
},
|
|
581
|
-
"Returning ConversationRelay TwiML",
|
|
582
|
-
);
|
|
583
|
-
|
|
584
|
-
return twiml;
|
|
299
|
+
function buildSetupRequiredTwiml(userMessage: string): string {
|
|
300
|
+
const sayCopy = `${userMessage} Please finish voice setup and call again. Goodbye.`;
|
|
301
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
302
|
+
<Response>
|
|
303
|
+
<Say>${escapeXml(sayCopy)}</Say>
|
|
304
|
+
<Hangup/>
|
|
305
|
+
</Response>`;
|
|
585
306
|
}
|
|
586
307
|
|
|
587
308
|
/**
|
|
588
|
-
* Build Stream TwiML
|
|
309
|
+
* Build Stream TwiML connecting the call to the daemon's media-stream server.
|
|
589
310
|
*/
|
|
590
311
|
function buildMediaStreamTwiml(
|
|
591
312
|
callSessionId: string,
|
|
@@ -606,10 +327,7 @@ function buildMediaStreamTwiml(
|
|
|
606
327
|
customParameters,
|
|
607
328
|
);
|
|
608
329
|
|
|
609
|
-
log.info(
|
|
610
|
-
{ callSessionId, strategy: "media-stream-custom" },
|
|
611
|
-
"Returning Stream TwiML",
|
|
612
|
-
);
|
|
330
|
+
log.info({ callSessionId }, "Returning Stream TwiML");
|
|
613
331
|
|
|
614
332
|
return twiml;
|
|
615
333
|
}
|
|
@@ -779,22 +497,8 @@ export async function handleStatusCallback(req: Request): Promise<Response> {
|
|
|
779
497
|
return new Response(null, { status: 200 });
|
|
780
498
|
}
|
|
781
499
|
|
|
782
|
-
/**
|
|
783
|
-
* Called when the ConversationRelay connection ends.
|
|
784
|
-
* Returns empty TwiML to acknowledge.
|
|
785
|
-
*/
|
|
786
|
-
export async function handleConnectAction(_req: Request): Promise<Response> {
|
|
787
|
-
log.info("ConversationRelay connect-action callback received");
|
|
788
|
-
return new Response('<?xml version="1.0" encoding="UTF-8"?><Response/>', {
|
|
789
|
-
status: 200,
|
|
790
|
-
headers: { "Content-Type": "text/xml" },
|
|
791
|
-
});
|
|
792
|
-
}
|
|
793
|
-
|
|
794
500
|
// ── Transport-agnostic internal route handlers ───────────────────────
|
|
795
501
|
|
|
796
|
-
const EMPTY_TWIML = '<?xml version="1.0" encoding="UTF-8"?><Response/>';
|
|
797
|
-
|
|
798
502
|
/**
|
|
799
503
|
* Internal voice-webhook handler for gateway→runtime forwarding.
|
|
800
504
|
* Accepts JSON body `{ params, originalUrl? }` from the gateway.
|
|
@@ -832,11 +536,3 @@ export function handleInternalStatusCallback({
|
|
|
832
536
|
processStatusCallback(params);
|
|
833
537
|
return new RouteResponse(null, {});
|
|
834
538
|
}
|
|
835
|
-
|
|
836
|
-
/**
|
|
837
|
-
* Internal connect-action handler for gateway→runtime forwarding.
|
|
838
|
-
*/
|
|
839
|
-
export function handleInternalConnectAction(): RouteResponse {
|
|
840
|
-
log.info("ConversationRelay connect-action callback received");
|
|
841
|
-
return new RouteResponse(EMPTY_TWIML, TWIML_HEADERS);
|
|
842
|
-
}
|
package/src/calls/types.ts
CHANGED
|
@@ -16,6 +16,7 @@ export type CallEventType =
|
|
|
16
16
|
| "user_instruction_relayed"
|
|
17
17
|
| "call_ended"
|
|
18
18
|
| "call_failed"
|
|
19
|
+
| "telephony_credential_preflight_failed"
|
|
19
20
|
| "callee_verification_started"
|
|
20
21
|
| "callee_verification_succeeded"
|
|
21
22
|
| "callee_verification_failed"
|
|
@@ -55,9 +56,10 @@ export type PendingQuestionStatus =
|
|
|
55
56
|
| "cancelled";
|
|
56
57
|
|
|
57
58
|
/**
|
|
58
|
-
* Explicit call mode written at session creation time. The
|
|
59
|
-
* uses this as the primary signal for deterministic
|
|
60
|
-
* with Twilio
|
|
59
|
+
* Explicit call mode written at session creation time. The media-stream
|
|
60
|
+
* server's setup router uses this as the primary signal for deterministic
|
|
61
|
+
* flow selection, with Twilio custom parameters as a secondary/observability
|
|
62
|
+
* signal.
|
|
61
63
|
*/
|
|
62
64
|
export type CallMode = "normal" | "verification" | "invite";
|
|
63
65
|
|
|
@@ -2,6 +2,7 @@ import { getIsPlatform } from "../config/env-registry.js";
|
|
|
2
2
|
import { loadConfig } from "../config/loader.js";
|
|
3
3
|
import type { AssistantConfig } from "../config/types.js";
|
|
4
4
|
import { getPublicBaseUrl } from "../inbound/public-ingress-urls.js";
|
|
5
|
+
import { resolveTelephonyCredentialReadiness } from "./telephony-credential-preflight.js";
|
|
5
6
|
|
|
6
7
|
const SERVICE_UNAVAILABLE_STATUS = 503 as const;
|
|
7
8
|
|
|
@@ -32,6 +33,14 @@ function fail(error: string): VoiceIngressPreflightFailure {
|
|
|
32
33
|
export async function preflightVoiceIngress(): Promise<VoiceIngressPreflightResult> {
|
|
33
34
|
const ingressConfig = loadConfig();
|
|
34
35
|
|
|
36
|
+
// The daemon performs both STT and TTS on the media-stream transport —
|
|
37
|
+
// in every deployment mode, platform-hosted included — so credential
|
|
38
|
+
// readiness gates outbound placement before any Twilio call is made.
|
|
39
|
+
const readiness = await resolveTelephonyCredentialReadiness();
|
|
40
|
+
if (readiness.status === "not-ready") {
|
|
41
|
+
return fail(readiness.userMessage);
|
|
42
|
+
}
|
|
43
|
+
|
|
35
44
|
// Platform-callback deployments register routes with the platform and receive
|
|
36
45
|
// stable callback URLs. No public ingress URL or local gateway is involved.
|
|
37
46
|
if (getIsPlatform()) {
|
|
@@ -17,15 +17,13 @@ export interface VoiceQualityProfile {
|
|
|
17
17
|
/**
|
|
18
18
|
* Build a Twilio-compatible ElevenLabs voice string.
|
|
19
19
|
*
|
|
20
|
-
* Twilio
|
|
20
|
+
* Twilio's native TTS voice attribute accepts:
|
|
21
21
|
* - bare voiceId
|
|
22
22
|
* - voiceId-model-speed_stability_similarity
|
|
23
23
|
*
|
|
24
24
|
* We default to bare voiceId unless a model is explicitly configured.
|
|
25
25
|
* This avoids forcing model/tuning suffixes that may be rejected for some
|
|
26
26
|
* voice + model combinations.
|
|
27
|
-
*
|
|
28
|
-
* See: https://www.twilio.com/docs/voice/conversationrelay/voice-configuration
|
|
29
27
|
*/
|
|
30
28
|
export function buildElevenLabsVoiceSpec(config: {
|
|
31
29
|
voiceId: string;
|
|
@@ -47,7 +45,7 @@ export function buildElevenLabsVoiceSpec(config: {
|
|
|
47
45
|
}
|
|
48
46
|
|
|
49
47
|
/**
|
|
50
|
-
* Resolve a valid native Twilio voice for the
|
|
48
|
+
* Resolve a valid native Twilio voice for the configured TTS provider.
|
|
51
49
|
*
|
|
52
50
|
* Returns the registered {@link NativeTwilioVoiceSpec} for `providerId` when one
|
|
53
51
|
* exists; otherwise — no builder registered (e.g. a synthesized-play provider
|
|
@@ -81,23 +79,20 @@ function resolveNativeTwilioVoice(
|
|
|
81
79
|
/**
|
|
82
80
|
* Resolve the effective voice quality profile from config.
|
|
83
81
|
*
|
|
84
|
-
* The
|
|
82
|
+
* The profile always carries a valid, non-empty native Twilio voice:
|
|
85
83
|
*
|
|
86
|
-
* - **native-twilio** providers (e.g. ElevenLabs):
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
* invalid parameters") and drop the call. These providers have no registered
|
|
95
|
-
* native builder, so they resolve to the ElevenLabs fallback voice.
|
|
84
|
+
* - **native-twilio** providers (e.g. ElevenLabs): the voice is built from
|
|
85
|
+
* the provider's registered {@link NativeTwilioVoiceSpec} builder.
|
|
86
|
+
* - **synthesized-play** providers (e.g. Fish Audio): the daemon synthesizes
|
|
87
|
+
* audio itself, so the native voice is a fallback only — an empty voice
|
|
88
|
+
* makes Twilio reject a native-TTS turn with error 64106 ("TTS provider
|
|
89
|
+
* rejected the request due to invalid parameters") and drop the call.
|
|
90
|
+
* These providers have no registered native builder, so they resolve to
|
|
91
|
+
* the ElevenLabs fallback voice.
|
|
96
92
|
*
|
|
97
93
|
* NOTE: STT provider and speech model are intentionally NOT part of this
|
|
98
|
-
* profile
|
|
99
|
-
*
|
|
100
|
-
* single point of ownership.
|
|
94
|
+
* profile — the daemon owns STT on the media-stream transport (see
|
|
95
|
+
* `resolveTelephonySttCapability` in providers/speech-to-text/resolve.ts).
|
|
101
96
|
*/
|
|
102
97
|
export function resolveVoiceQualityProfile(
|
|
103
98
|
config?: ReturnType<typeof loadConfig>,
|