@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
|
@@ -21,11 +21,18 @@
|
|
|
21
21
|
* - WebSocket `open` -> extract callSessionId from upgrade params,
|
|
22
22
|
* create `MediaStreamCallSession`.
|
|
23
23
|
* - Media stream `start` event -> capture streamSid/callSid, wire
|
|
24
|
-
* output adapter,
|
|
24
|
+
* output adapter, run setup routing and hand the outcome to a
|
|
25
|
+
* `CallSetupFlow` (deny, verification, invite redemption, name
|
|
26
|
+
* capture / guardian wait, unverified caller, normal call). The
|
|
27
|
+
* controller is created only once the flow completes with a
|
|
28
|
+
* `proceed-*` result.
|
|
25
29
|
* - Media stream `media` events -> forwarded to STT session for
|
|
26
30
|
* turn detection and transcription.
|
|
27
|
-
* - STT `onTranscriptFinal` -> routed to
|
|
31
|
+
* - STT `onTranscriptFinal` -> routed to the active setup flow's
|
|
32
|
+
* `pushTranscriptFinal()`, else the controller's
|
|
28
33
|
* `handleCallerUtterance()`.
|
|
34
|
+
* - STT `onDtmf` -> routed to the active setup flow's
|
|
35
|
+
* `pushDtmfDigit()` for code-collection sub-flows.
|
|
29
36
|
* - STT `onSpeechStart` -> barge-in: clears outbound audio queue
|
|
30
37
|
* and interrupts the in-flight LLM turn via the controller.
|
|
31
38
|
* - Media stream `stop` event / WebSocket close -> finalize call.
|
|
@@ -34,10 +41,22 @@
|
|
|
34
41
|
import type { ServerWebSocket } from "bun";
|
|
35
42
|
|
|
36
43
|
import { revokeScopedApprovalGrantsForContext } from "../approvals/scoped-approval-grants.js";
|
|
37
|
-
import {
|
|
44
|
+
import {
|
|
45
|
+
getGuardianDelivery,
|
|
46
|
+
getGuardianDeliveryFresh,
|
|
47
|
+
voiceGuardianDisplayName,
|
|
48
|
+
} from "../contacts/guardian-delivery-reader.js";
|
|
49
|
+
import { getAssistantName } from "../daemon/identity-helpers.js";
|
|
50
|
+
import { addMessage } from "../persistence/conversation-crud.js";
|
|
51
|
+
import { resolveGuardianName } from "../prompts/user-reference.js";
|
|
38
52
|
import { getLogger } from "../util/logger.js";
|
|
39
53
|
import { CallController } from "./call-controller.js";
|
|
40
|
-
import {
|
|
54
|
+
import {
|
|
55
|
+
formatDuration,
|
|
56
|
+
postPointerMessageSafe,
|
|
57
|
+
} from "./call-pointer-messages.js";
|
|
58
|
+
import { CallSetupFlow, type CallSetupFlowDeps } from "./call-setup-flow.js";
|
|
59
|
+
import type { SetupFlowResult } from "./call-setup-flow-types.js";
|
|
41
60
|
import { speakSystemPrompt } from "./call-speech-output.js";
|
|
42
61
|
import {
|
|
43
62
|
fireCallTranscriptNotifier,
|
|
@@ -64,6 +83,24 @@ import {
|
|
|
64
83
|
import { routeSetup } from "./relay-setup-router.js";
|
|
65
84
|
|
|
66
85
|
const log = getLogger("media-stream-server");
|
|
86
|
+
const UUID_SHAPED_NAME =
|
|
87
|
+
/^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Resolve the assistant's display name from identity configuration.
|
|
91
|
+
* Returns the trimmed name, or null when unavailable or UUID-shaped.
|
|
92
|
+
*/
|
|
93
|
+
function resolveAssistantLabel(): string | null {
|
|
94
|
+
try {
|
|
95
|
+
const trimmed = getAssistantName()?.trim();
|
|
96
|
+
if (!trimmed || UUID_SHAPED_NAME.test(trimmed)) {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
return trimmed;
|
|
100
|
+
} catch {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
67
104
|
|
|
68
105
|
// ---------------------------------------------------------------------------
|
|
69
106
|
// Active sessions registry (keyed by callSessionId)
|
|
@@ -89,6 +126,15 @@ export class MediaStreamCallSession {
|
|
|
89
126
|
private output: MediaStreamOutput;
|
|
90
127
|
private sttSession: MediaStreamSttSession;
|
|
91
128
|
private controller: CallController | null = null;
|
|
129
|
+
/**
|
|
130
|
+
* Active setup flow driving the pre-conversation phase (verification,
|
|
131
|
+
* invite redemption, name capture, guardian wait, deny). Non-null from
|
|
132
|
+
* setup routing until the flow completes; caller input routes into it
|
|
133
|
+
* instead of the controller while set.
|
|
134
|
+
*/
|
|
135
|
+
private setupFlow: CallSetupFlow | null = null;
|
|
136
|
+
/** Guardian displayName primed from the gateway binding during setup. */
|
|
137
|
+
private primedGuardianDisplayName: string | undefined;
|
|
92
138
|
private streamSid: string | null = null;
|
|
93
139
|
private callSid: string | null = null;
|
|
94
140
|
private disposed = false;
|
|
@@ -155,6 +201,13 @@ export class MediaStreamCallSession {
|
|
|
155
201
|
return this.controller;
|
|
156
202
|
}
|
|
157
203
|
|
|
204
|
+
/**
|
|
205
|
+
* Get the active setup flow (for test assertions).
|
|
206
|
+
*/
|
|
207
|
+
getSetupFlow(): CallSetupFlow | null {
|
|
208
|
+
return this.setupFlow;
|
|
209
|
+
}
|
|
210
|
+
|
|
158
211
|
/**
|
|
159
212
|
* Resolves once the async setup routing started by the `start` frame has
|
|
160
213
|
* settled. Test-only convenience — production code does not await this.
|
|
@@ -199,9 +252,24 @@ export class MediaStreamCallSession {
|
|
|
199
252
|
handleTransportClosed(code?: number, reason?: string): void {
|
|
200
253
|
if (this.disposed) return;
|
|
201
254
|
|
|
255
|
+
// Tear down an in-flight setup flow first: clears its timers and emits
|
|
256
|
+
// the guardian-wait callback handoff when the caller opted in.
|
|
257
|
+
const setupFlow = this.setupFlow;
|
|
258
|
+
this.setupFlow = null;
|
|
259
|
+
setupFlow?.dispose("transport_closed");
|
|
260
|
+
|
|
202
261
|
const session = getCallSession(this.callSessionId);
|
|
203
262
|
if (!session) return;
|
|
204
|
-
if (isTerminalState(session.status))
|
|
263
|
+
if (isTerminalState(session.status)) {
|
|
264
|
+
// A hangup during a flow-terminal goodbye: dispose above swallowed the
|
|
265
|
+
// flow's pending complete(), so finalize + revoke grants here. Normal
|
|
266
|
+
// completion nulls setupFlow and hasFinalized() covers flow-side
|
|
267
|
+
// finalization, keeping this exactly-once.
|
|
268
|
+
if (setupFlow && !setupFlow.hasFinalized()) {
|
|
269
|
+
this.runFinalizationAndGrantCleanup(session);
|
|
270
|
+
}
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
205
273
|
|
|
206
274
|
const isNormalClose = code === 1000;
|
|
207
275
|
const terminationReason = isNormalClose ? "normal_stop" : "premature_abort";
|
|
@@ -232,19 +300,14 @@ export class MediaStreamCallSession {
|
|
|
232
300
|
const durationMs = session.startedAt
|
|
233
301
|
? Date.now() - session.startedAt
|
|
234
302
|
: 0;
|
|
235
|
-
|
|
303
|
+
postPointerMessageSafe(
|
|
236
304
|
session.initiatedFromConversationId,
|
|
237
305
|
"completed",
|
|
238
306
|
session.toNumber,
|
|
239
307
|
{
|
|
240
308
|
duration: durationMs > 0 ? formatDuration(durationMs) : undefined,
|
|
241
309
|
},
|
|
242
|
-
)
|
|
243
|
-
log.warn(
|
|
244
|
-
{ conversationId: session.initiatedFromConversationId, err },
|
|
245
|
-
"Skipping pointer write — origin conversation may no longer exist",
|
|
246
|
-
);
|
|
247
|
-
});
|
|
310
|
+
);
|
|
248
311
|
}
|
|
249
312
|
} else {
|
|
250
313
|
const detail =
|
|
@@ -261,39 +324,22 @@ export class MediaStreamCallSession {
|
|
|
261
324
|
});
|
|
262
325
|
|
|
263
326
|
if (session.initiatedFromConversationId) {
|
|
264
|
-
|
|
327
|
+
postPointerMessageSafe(
|
|
265
328
|
session.initiatedFromConversationId,
|
|
266
329
|
"failed",
|
|
267
330
|
session.toNumber,
|
|
268
331
|
{ reason: detail },
|
|
269
|
-
)
|
|
270
|
-
log.warn(
|
|
271
|
-
{ conversationId: session.initiatedFromConversationId, err },
|
|
272
|
-
"Skipping pointer write — origin conversation may no longer exist",
|
|
273
|
-
);
|
|
274
|
-
});
|
|
332
|
+
);
|
|
275
333
|
}
|
|
276
334
|
}
|
|
277
335
|
|
|
278
|
-
|
|
279
|
-
// Revoke by both callSessionId and conversationId because the
|
|
280
|
-
// guardian-approval-interception minting path sets callSessionId: null
|
|
281
|
-
// but always sets conversationId.
|
|
282
|
-
try {
|
|
283
|
-
revokeScopedApprovalGrantsForContext({
|
|
284
|
-
callSessionId: this.callSessionId,
|
|
285
|
-
});
|
|
286
|
-
revokeScopedApprovalGrantsForContext({
|
|
287
|
-
conversationId: session.conversationId,
|
|
288
|
-
});
|
|
289
|
-
} catch (err) {
|
|
290
|
-
log.warn(
|
|
291
|
-
{ err, callSessionId: this.callSessionId },
|
|
292
|
-
"Failed to revoke scoped grants on media-stream transport close",
|
|
293
|
-
);
|
|
294
|
-
}
|
|
336
|
+
this.revokeScopedGrants(session.conversationId);
|
|
295
337
|
|
|
296
|
-
|
|
338
|
+
// A setup flow that reached a flow-terminal path already ran
|
|
339
|
+
// finalizeCall — keep finalization exactly-once.
|
|
340
|
+
if (!setupFlow?.hasFinalized()) {
|
|
341
|
+
finalizeCall(this.callSessionId, session.conversationId);
|
|
342
|
+
}
|
|
297
343
|
}
|
|
298
344
|
|
|
299
345
|
/**
|
|
@@ -305,6 +351,9 @@ export class MediaStreamCallSession {
|
|
|
305
351
|
|
|
306
352
|
this.sttSession.dispose();
|
|
307
353
|
|
|
354
|
+
this.setupFlow?.dispose("teardown");
|
|
355
|
+
this.setupFlow = null;
|
|
356
|
+
|
|
308
357
|
if (this.controller) {
|
|
309
358
|
this.controller.destroy();
|
|
310
359
|
unregisterCallController(this.callSessionId);
|
|
@@ -365,11 +414,11 @@ export class MediaStreamCallSession {
|
|
|
365
414
|
});
|
|
366
415
|
|
|
367
416
|
// ── Setup-policy routing ────────────────────────────────────────
|
|
368
|
-
// Run
|
|
369
|
-
//
|
|
370
|
-
//
|
|
371
|
-
//
|
|
372
|
-
//
|
|
417
|
+
// Run routeSetup() to enforce ACL/deny/escalate, verification, and
|
|
418
|
+
// invite flows. The resulting outcome is handed to a CallSetupFlow,
|
|
419
|
+
// which drives every interactive sub-flow (DTMF/spoken code entry,
|
|
420
|
+
// invite redemption, name capture, guardian wait) over this
|
|
421
|
+
// transport.
|
|
373
422
|
const from = session?.fromNumber ?? "";
|
|
374
423
|
const to = session?.toNumber ?? "";
|
|
375
424
|
|
|
@@ -377,41 +426,41 @@ export class MediaStreamCallSession {
|
|
|
377
426
|
// (e.g. guardian_only) is enforced on this transport too — not just the
|
|
378
427
|
// gateway webhook's no_one kill switch. The reader fails open to `null`
|
|
379
428
|
// by contract, so a transport hiccup admits the caller.
|
|
380
|
-
|
|
429
|
+
//
|
|
430
|
+
// Concurrently, prime the guardian displayName used by setup-flow copy
|
|
431
|
+
// and warm the phone-channel guardian-delivery cache for routeSetup's
|
|
432
|
+
// SYNC resolveActorTrust fallback (gateway-side binding writes don't
|
|
433
|
+
// invalidate the daemon cache, so read fresh). All three are independent
|
|
434
|
+
// IPC reads on different cache keys.
|
|
435
|
+
const [admissionPolicy] = await Promise.all([
|
|
436
|
+
getChannelAdmissionPolicy("phone"),
|
|
437
|
+
this.primeGuardianDisplayName(),
|
|
438
|
+
getGuardianDeliveryFresh({ channelTypes: ["phone"] }),
|
|
439
|
+
]);
|
|
381
440
|
|
|
382
441
|
// The admission-policy read above yields the event loop; if Twilio closed
|
|
383
442
|
// the WebSocket meanwhile, the close handler will have called destroy().
|
|
384
443
|
// Abort setup so we don't create a controller or speak on a disposed
|
|
385
444
|
// session.
|
|
386
|
-
if (this.
|
|
387
|
-
log.info(
|
|
388
|
-
{ callSessionId: this.callSessionId },
|
|
389
|
-
"Media-stream session disposed during admission read — aborting setup",
|
|
390
|
-
);
|
|
391
|
-
this.setupRouting = false;
|
|
445
|
+
if (this.abortIfDisposed("admission read")) {
|
|
392
446
|
return;
|
|
393
447
|
}
|
|
394
448
|
|
|
395
|
-
// Verdict-first caller trust so this transport enforces the
|
|
396
|
-
// ACL
|
|
397
|
-
//
|
|
398
|
-
//
|
|
449
|
+
// Verdict-first caller trust so this transport enforces the gateway
|
|
450
|
+
// ACL. routeSetup uses it when present and not resolutionFailed, else
|
|
451
|
+
// falls back to local resolution. The reader returns null on failure,
|
|
452
|
+
// keeping the local path on a gateway blip.
|
|
399
453
|
const isInbound = session?.initiatedFromConversationId == null;
|
|
400
454
|
const otherPartyNumber = isInbound ? from : to;
|
|
401
455
|
const verdict = await getPhoneCallerVerdict(otherPartyNumber);
|
|
402
456
|
|
|
403
457
|
// The verdict read above yields the event loop; abort if the session was
|
|
404
458
|
// disposed meanwhile, matching the admission-read guard above.
|
|
405
|
-
if (this.
|
|
406
|
-
log.info(
|
|
407
|
-
{ callSessionId: this.callSessionId },
|
|
408
|
-
"Media-stream session disposed during verdict read — aborting setup",
|
|
409
|
-
);
|
|
410
|
-
this.setupRouting = false;
|
|
459
|
+
if (this.abortIfDisposed("verdict read")) {
|
|
411
460
|
return;
|
|
412
461
|
}
|
|
413
462
|
|
|
414
|
-
const { outcome, resolved } = routeSetup({
|
|
463
|
+
const { outcome, resolved } = await routeSetup({
|
|
415
464
|
callSessionId: this.callSessionId,
|
|
416
465
|
session: session ?? null,
|
|
417
466
|
from,
|
|
@@ -421,6 +470,12 @@ export class MediaStreamCallSession {
|
|
|
421
470
|
verdict,
|
|
422
471
|
});
|
|
423
472
|
|
|
473
|
+
// routeSetup can yield the event loop (gateway voice-invite read); abort
|
|
474
|
+
// if the session was disposed meanwhile, matching the guards above.
|
|
475
|
+
if (this.abortIfDisposed("setup routing")) {
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
478
|
+
|
|
424
479
|
log.info(
|
|
425
480
|
{
|
|
426
481
|
callSessionId: this.callSessionId,
|
|
@@ -431,141 +486,175 @@ export class MediaStreamCallSession {
|
|
|
431
486
|
"Media stream session started",
|
|
432
487
|
);
|
|
433
488
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
this.controller = new CallController(
|
|
446
|
-
this.callSessionId,
|
|
447
|
-
this.output,
|
|
448
|
-
session?.task ?? null,
|
|
449
|
-
{
|
|
450
|
-
assistantId: resolved.assistantId,
|
|
451
|
-
trustContext: initialTrustContext,
|
|
452
|
-
},
|
|
453
|
-
);
|
|
454
|
-
registerCallController(this.callSessionId, this.controller);
|
|
489
|
+
const flow = new CallSetupFlow(
|
|
490
|
+
this.callSessionId,
|
|
491
|
+
this.output,
|
|
492
|
+
this.buildSetupFlowDeps(session),
|
|
493
|
+
);
|
|
494
|
+
this.setupFlow = flow;
|
|
495
|
+
// Routing/ACL cleared — the flow owns the setup phase from here, so
|
|
496
|
+
// transcripts and DTMF route into it until it completes.
|
|
497
|
+
this.setupRouting = false;
|
|
498
|
+
await flow.start(outcome, resolved);
|
|
499
|
+
}
|
|
455
500
|
|
|
456
|
-
|
|
457
|
-
// transcripts and barge-in are handled normally.
|
|
458
|
-
this.setupRouting = false;
|
|
501
|
+
// ── Setup flow wiring ─────────────────────────────────────────────
|
|
459
502
|
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
503
|
+
/**
|
|
504
|
+
* Abort a pending setup when the session was disposed across an await
|
|
505
|
+
* in {@link handleStart}: logs the stage and clears the setup-routing
|
|
506
|
+
* input gate. Returns true when setup must abort.
|
|
507
|
+
*/
|
|
508
|
+
private abortIfDisposed(stage: string): boolean {
|
|
509
|
+
if (!this.disposed) {
|
|
510
|
+
return false;
|
|
511
|
+
}
|
|
512
|
+
log.info(
|
|
513
|
+
{ callSessionId: this.callSessionId, stage },
|
|
514
|
+
"Media-stream session disposed during setup — aborting",
|
|
515
|
+
);
|
|
516
|
+
this.setupRouting = false;
|
|
517
|
+
return true;
|
|
518
|
+
}
|
|
469
519
|
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
520
|
+
/**
|
|
521
|
+
* Real side-effect surface for the {@link CallSetupFlow}. Pure-logic
|
|
522
|
+
* deps (code validation, invite redemption, guardian notification,
|
|
523
|
+
* trust re-resolution, guardian wait construction) use the flow's
|
|
524
|
+
* real-implementation defaults.
|
|
525
|
+
*/
|
|
526
|
+
private buildSetupFlowDeps(
|
|
527
|
+
session: ReturnType<typeof getCallSession>,
|
|
528
|
+
): CallSetupFlowDeps {
|
|
529
|
+
return {
|
|
530
|
+
speakSystemPrompt: (text) => speakSystemPrompt(this.output, text),
|
|
531
|
+
updateCallSession,
|
|
532
|
+
recordCallEvent,
|
|
533
|
+
onComplete: (result) => this.handleSetupFlowResult(result, session),
|
|
534
|
+
getCallSession,
|
|
535
|
+
// Flow-terminal paths set a terminal session status, so the
|
|
536
|
+
// transport-close handler skips its cleanup — revoke scoped grants
|
|
537
|
+
// here alongside finalization.
|
|
538
|
+
finalizeCall: (callSessionId, conversationId) => {
|
|
539
|
+
this.revokeScopedGrants(conversationId);
|
|
540
|
+
finalizeCall(callSessionId, conversationId);
|
|
541
|
+
},
|
|
542
|
+
addMessage,
|
|
543
|
+
postPointerMessage: postPointerMessageSafe,
|
|
544
|
+
fireCallTranscriptNotifier,
|
|
545
|
+
resolveGuardianLabel: () =>
|
|
546
|
+
resolveGuardianName(this.primedGuardianDisplayName),
|
|
547
|
+
resolveAssistantLabel,
|
|
548
|
+
};
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
/**
|
|
552
|
+
* Continue the call once the setup flow reaches a terminal result:
|
|
553
|
+
* create + register the call controller and fire the matching opener
|
|
554
|
+
* for `proceed-*` variants, or complete finalization for `ended`
|
|
555
|
+
* (the flow already spoke its terminal copy, set terminal status,
|
|
556
|
+
* and scheduled its own delayed `endSession`).
|
|
557
|
+
*/
|
|
558
|
+
private handleSetupFlowResult(
|
|
559
|
+
result: SetupFlowResult,
|
|
560
|
+
session: ReturnType<typeof getCallSession>,
|
|
561
|
+
): void {
|
|
562
|
+
const flow = this.setupFlow;
|
|
563
|
+
this.setupFlow = null;
|
|
564
|
+
|
|
565
|
+
if (result.kind === "ended") {
|
|
566
|
+
// handleTransportClosed will see the terminal status and exit early
|
|
567
|
+
// when the WebSocket closes, so run cleanup inline — unless a
|
|
568
|
+
// flow-terminal path already finalized (grants revoked there too).
|
|
569
|
+
if (!flow?.hasFinalized()) {
|
|
490
570
|
this.runFinalizationAndGrantCleanup(session);
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
571
|
+
}
|
|
572
|
+
return;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
const controller = new CallController(
|
|
576
|
+
this.callSessionId,
|
|
577
|
+
this.output,
|
|
578
|
+
session?.task ?? null,
|
|
579
|
+
{
|
|
580
|
+
assistantId: result.assistantId,
|
|
581
|
+
trustContext: result.trustContext,
|
|
582
|
+
},
|
|
583
|
+
);
|
|
584
|
+
this.controller = controller;
|
|
585
|
+
registerCallController(this.callSessionId, controller);
|
|
586
|
+
|
|
587
|
+
const opener =
|
|
588
|
+
result.kind === "proceed-post-verification-greeting"
|
|
589
|
+
? controller.startPostVerificationGreeting()
|
|
590
|
+
: result.kind === "proceed-handoff-spoken"
|
|
591
|
+
? Promise.resolve(controller.markNextCallerTurnAsOpeningAck())
|
|
592
|
+
: controller.startInitialGreeting();
|
|
593
|
+
|
|
594
|
+
const deferredTranscripts = result.deferredTranscripts ?? [];
|
|
595
|
+
void opener
|
|
596
|
+
.then(async () => {
|
|
597
|
+
// Replay transcripts buffered during mid-setup trust re-resolution,
|
|
598
|
+
// in order, so the caller's first utterance runs under the upgraded
|
|
599
|
+
// trust context.
|
|
600
|
+
for (const text of deferredTranscripts) {
|
|
601
|
+
await controller.handleCallerUtterance(text);
|
|
602
|
+
}
|
|
603
|
+
})
|
|
604
|
+
.catch((err) => {
|
|
505
605
|
log.error(
|
|
506
|
-
{
|
|
507
|
-
|
|
508
|
-
action: outcome.action,
|
|
509
|
-
},
|
|
510
|
-
"Media-stream transport received unsupported setup flow — preflight guard should have prevented this",
|
|
606
|
+
{ err, callSessionId: this.callSessionId },
|
|
607
|
+
"Failed to start call flow after setup completion",
|
|
511
608
|
);
|
|
512
|
-
|
|
513
|
-
reason: `Setup flow '${outcome.action}' not supported on media-stream transport (preflight guard bypass)`,
|
|
514
|
-
transport: "media-stream",
|
|
515
|
-
});
|
|
516
|
-
updateCallSession(this.callSessionId, {
|
|
517
|
-
status: "failed",
|
|
518
|
-
endedAt: Date.now(),
|
|
519
|
-
lastError: `Setup flow '${outcome.action}' not supported on media-stream transport — preflight guard should have prevented this`,
|
|
520
|
-
});
|
|
521
|
-
// Run finalization now because handleTransportClosed will see
|
|
522
|
-
// terminal status and exit early when the WebSocket closes.
|
|
523
|
-
this.runFinalizationAndGrantCleanup(session);
|
|
524
|
-
void speakSystemPrompt(
|
|
525
|
-
this.output,
|
|
526
|
-
"Sorry, this call requires additional verification that isn't available right now. Please try calling back. Goodbye.",
|
|
527
|
-
).finally(() => {
|
|
528
|
-
setTimeout(
|
|
529
|
-
() =>
|
|
530
|
-
this.output.endSession(
|
|
531
|
-
`Unsupported setup flow: ${outcome.action} (preflight guard bypass)`,
|
|
532
|
-
),
|
|
533
|
-
3000,
|
|
534
|
-
);
|
|
535
|
-
});
|
|
536
|
-
return;
|
|
537
|
-
}
|
|
609
|
+
});
|
|
538
610
|
}
|
|
539
611
|
|
|
540
|
-
|
|
612
|
+
/**
|
|
613
|
+
* Prime the guardian displayName from the gateway binding so the
|
|
614
|
+
* synchronous setup-flow label path can read it without an IPC
|
|
615
|
+
* round-trip.
|
|
616
|
+
*/
|
|
617
|
+
private async primeGuardianDisplayName(): Promise<void> {
|
|
618
|
+
const list = await getGuardianDelivery();
|
|
619
|
+
this.primedGuardianDisplayName = voiceGuardianDisplayName(list);
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
// ── Finalization helpers for early-teardown paths ─────────────────
|
|
541
623
|
|
|
542
624
|
/**
|
|
543
|
-
*
|
|
544
|
-
*
|
|
545
|
-
*
|
|
546
|
-
*
|
|
547
|
-
* early — so we must perform cleanup here to avoid leaking grants
|
|
548
|
-
* and skipping `finalizeCall()` side-effects.
|
|
625
|
+
* Revoke any scoped approval grants bound to this call session.
|
|
626
|
+
* Revoke by both callSessionId and conversationId because the
|
|
627
|
+
* guardian-approval-interception minting path sets callSessionId: null
|
|
628
|
+
* but always sets conversationId.
|
|
549
629
|
*/
|
|
550
|
-
private
|
|
551
|
-
session: ReturnType<typeof getCallSession>,
|
|
552
|
-
): void {
|
|
630
|
+
private revokeScopedGrants(conversationId: string | undefined): void {
|
|
553
631
|
try {
|
|
554
632
|
revokeScopedApprovalGrantsForContext({
|
|
555
633
|
callSessionId: this.callSessionId,
|
|
556
634
|
});
|
|
557
|
-
if (
|
|
558
|
-
revokeScopedApprovalGrantsForContext({
|
|
559
|
-
conversationId: session.conversationId,
|
|
560
|
-
});
|
|
635
|
+
if (conversationId) {
|
|
636
|
+
revokeScopedApprovalGrantsForContext({ conversationId });
|
|
561
637
|
}
|
|
562
638
|
} catch (err) {
|
|
563
639
|
log.warn(
|
|
564
640
|
{ err, callSessionId: this.callSessionId },
|
|
565
|
-
"Failed to revoke scoped grants
|
|
641
|
+
"Failed to revoke scoped grants for media-stream session",
|
|
566
642
|
);
|
|
567
643
|
}
|
|
644
|
+
}
|
|
568
645
|
|
|
646
|
+
/**
|
|
647
|
+
* Run scoped-grant revocation and call finalization inline. Used for
|
|
648
|
+
* setup-terminal paths which set terminal status before `endSession()`.
|
|
649
|
+
* When the WebSocket subsequently closes, {@link handleTransportClosed}
|
|
650
|
+
* sees the terminal status and exits early — so cleanup must happen
|
|
651
|
+
* here to avoid leaking grants and skipping `finalizeCall()`
|
|
652
|
+
* side-effects.
|
|
653
|
+
*/
|
|
654
|
+
private runFinalizationAndGrantCleanup(
|
|
655
|
+
session: ReturnType<typeof getCallSession>,
|
|
656
|
+
): void {
|
|
657
|
+
this.revokeScopedGrants(session?.conversationId);
|
|
569
658
|
if (session?.conversationId) {
|
|
570
659
|
finalizeCall(this.callSessionId, session.conversationId);
|
|
571
660
|
}
|
|
@@ -581,12 +670,16 @@ export class MediaStreamCallSession {
|
|
|
581
670
|
// handleBargeIn path so initial inbound audio frames do not cancel a
|
|
582
671
|
// still-starting initial turn.
|
|
583
672
|
//
|
|
584
|
-
// clearAudio runs
|
|
585
|
-
//
|
|
586
|
-
//
|
|
673
|
+
// clearAudio runs via the onAccepted hook so it only fires when the
|
|
674
|
+
// barge-in passes the speaking gate — an ignored barge-in (controller
|
|
675
|
+
// idle/processing) must not flush queued/in-flight TTS such as a
|
|
676
|
+
// buffered greeting. The hook runs before handleInterrupt so the
|
|
677
|
+
// end-of-turn mark it enqueues survives the queue flush.
|
|
587
678
|
if (this.output && this.controller) {
|
|
588
|
-
this.output
|
|
589
|
-
const accepted = this.controller.handleBargeIn()
|
|
679
|
+
const output = this.output;
|
|
680
|
+
const accepted = this.controller.handleBargeIn(() =>
|
|
681
|
+
output.clearAudio(),
|
|
682
|
+
);
|
|
590
683
|
if (accepted) {
|
|
591
684
|
this.bargeInAccepted++;
|
|
592
685
|
log.info(
|
|
@@ -594,6 +687,11 @@ export class MediaStreamCallSession {
|
|
|
594
687
|
"Media-stream barge-in accepted — cleared outbound audio",
|
|
595
688
|
);
|
|
596
689
|
} else {
|
|
690
|
+
// No turn to abort, but a completed turn's tail can still be
|
|
691
|
+
// playing from Twilio's buffer — flush only that buffer so the
|
|
692
|
+
// caller isn't talked over. Queued speech that hasn't reached
|
|
693
|
+
// Twilio yet (greeting, handoff prompt) is preserved.
|
|
694
|
+
output.clearBufferedAudio();
|
|
597
695
|
this.bargeInIgnored++;
|
|
598
696
|
log.debug(
|
|
599
697
|
{ callSessionId: this.callSessionId },
|
|
@@ -619,6 +717,23 @@ export class MediaStreamCallSession {
|
|
|
619
717
|
|
|
620
718
|
this.transcriptFinalsProduced++;
|
|
621
719
|
|
|
720
|
+
// While a setup flow is active it owns caller speech (name capture,
|
|
721
|
+
// spoken code entry, guardian-wait utterances). Fire the transcript
|
|
722
|
+
// notifier for UI subscribers, then route into the flow.
|
|
723
|
+
if (this.setupFlow) {
|
|
724
|
+
const setupSession = getCallSession(this.callSessionId);
|
|
725
|
+
if (setupSession) {
|
|
726
|
+
fireCallTranscriptNotifier(
|
|
727
|
+
setupSession.conversationId,
|
|
728
|
+
this.callSessionId,
|
|
729
|
+
"caller",
|
|
730
|
+
text,
|
|
731
|
+
);
|
|
732
|
+
}
|
|
733
|
+
this.setupFlow.pushTranscriptFinal(text);
|
|
734
|
+
return;
|
|
735
|
+
}
|
|
736
|
+
|
|
622
737
|
if (!this.controller) {
|
|
623
738
|
log.warn(
|
|
624
739
|
{ callSessionId: this.callSessionId },
|
|
@@ -671,6 +786,10 @@ export class MediaStreamCallSession {
|
|
|
671
786
|
dtmfDigit: digit,
|
|
672
787
|
transport: "media-stream",
|
|
673
788
|
});
|
|
789
|
+
|
|
790
|
+
// While a setup flow is active, digits feed its code-collection
|
|
791
|
+
// sub-flows (the flow itself records no per-digit events).
|
|
792
|
+
this.setupFlow?.pushDtmfDigit(digit);
|
|
674
793
|
}
|
|
675
794
|
|
|
676
795
|
private handleStreamStop(): void {
|