@vellumai/assistant 0.10.2-dev.202606250318.5e7cfb0 → 0.10.2
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/bun.lock +0 -20
- package/docs/workspace-tools.md +33 -42
- package/eslint-rules/cli-no-daemon-internals.js +0 -6
- package/node_modules/@vellumai/gateway-client/src/__tests__/trust-verdict-contract.test.ts +0 -31
- package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +0 -44
- package/node_modules/@vellumai/gateway-client/src/index.ts +0 -14
- package/node_modules/@vellumai/gateway-client/src/trust-verdict-contract.ts +0 -17
- package/node_modules/@vellumai/service-contracts/package.json +0 -1
- package/node_modules/@vellumai/service-contracts/src/index.ts +0 -1
- package/openapi.yaml +0 -155
- package/package.json +1 -4
- package/scripts/test.sh +15 -36
- package/src/__tests__/actor-token-service.test.ts +14 -36
- package/src/__tests__/agent-loop-override-profile.test.ts +0 -1
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +0 -2
- package/src/__tests__/agent-wake-override-profile.test.ts +0 -2
- package/src/__tests__/annotate-activity-metadata.test.ts +0 -2
- package/src/__tests__/annotate-risk-options.test.ts +0 -2
- package/src/__tests__/approval-cascade.test.ts +0 -2
- package/src/__tests__/assistant-attachments.test.ts +0 -42
- package/src/__tests__/background-workers-disk-pressure.test.ts +0 -2
- package/src/__tests__/btw-routes.test.ts +0 -2
- package/src/__tests__/build-persisted-content.test.ts +0 -2
- package/src/__tests__/call-controller.test.ts +0 -19
- package/src/__tests__/channel-guardian.test.ts +58 -94
- package/src/__tests__/channel-reply-delivery.test.ts +0 -2
- package/src/__tests__/compaction-events.test.ts +0 -2
- package/src/__tests__/compaction.benchmark.test.ts +0 -2
- package/src/__tests__/compactor-call-site-logging.test.ts +0 -2
- package/src/__tests__/compactor-low-watermark-cut.test.ts +0 -2
- package/src/__tests__/compactor-preserved-tail-count.test.ts +0 -2
- package/src/__tests__/compactor-summary-call-truncation.test.ts +0 -2
- package/src/__tests__/compactor-web-search-strip.test.ts +0 -2
- package/src/__tests__/config-loader-backfill.test.ts +10 -123
- package/src/__tests__/config-schema.test.ts +0 -1
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +29 -31
- package/src/__tests__/contacts-relay-reads.test.ts +15 -13
- package/src/__tests__/conversation-abort-tool-results.test.ts +0 -2
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +0 -2
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +0 -2
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +0 -2
- package/src/__tests__/conversation-agent-loop.test.ts +0 -134
- package/src/__tests__/conversation-analysis-routes.test.ts +0 -2
- package/src/__tests__/conversation-app-control-lifecycle.test.ts +0 -2
- package/src/__tests__/conversation-confirmation-signals.test.ts +0 -2
- package/src/__tests__/conversation-history-web-search.test.ts +0 -2
- package/src/__tests__/conversation-load-history-repair.test.ts +0 -2
- package/src/__tests__/conversation-load-history-stripped.test.ts +0 -2
- package/src/__tests__/conversation-pairing.test.ts +0 -2
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +0 -2
- package/src/__tests__/conversation-process-callsite.test.ts +0 -2
- package/src/__tests__/conversation-provider-retry-repair.test.ts +0 -2
- package/src/__tests__/conversation-queue.test.ts +0 -91
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +0 -14
- package/src/__tests__/conversation-routes-slash-commands.test.ts +0 -14
- package/src/__tests__/conversation-slash-queue.test.ts +0 -2
- package/src/__tests__/conversation-slash-unknown.test.ts +0 -2
- package/src/__tests__/conversation-speed-override.test.ts +0 -2
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +0 -29
- package/src/__tests__/conversation-title-service.test.ts +0 -2
- package/src/__tests__/conversation-tool-setup-attribution.test.ts +0 -47
- package/src/__tests__/conversation-usage.test.ts +0 -2
- package/src/__tests__/conversation-workspace-cache-state.test.ts +0 -2
- package/src/__tests__/conversation-workspace-injection.test.ts +0 -2
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -2
- package/src/__tests__/credential-security-invariants.test.ts +1 -1
- package/src/__tests__/db-migration-rollback.test.ts +171 -205
- package/src/__tests__/db-test-helpers.ts +4 -5
- package/src/__tests__/deterministic-verification-control-plane.test.ts +2 -4
- package/src/__tests__/disk-pressure-guard.test.ts +0 -41
- package/src/__tests__/dm-persistence.test.ts +0 -2
- package/src/__tests__/emit-signal-routing-intent.test.ts +5 -10
- package/src/__tests__/events-dev-bypass-actor.test.ts +1 -7
- package/src/__tests__/exploration-drift-hook.test.ts +2 -3
- package/src/__tests__/filing-service.test.ts +0 -2
- package/src/__tests__/guardian-binding-drift-heal.test.ts +10 -75
- package/src/__tests__/guardian-dispatch.test.ts +1 -95
- package/src/__tests__/guardian-outbound-http.test.ts +0 -13
- package/src/__tests__/heartbeat-disk-pressure.test.ts +0 -2
- package/src/__tests__/heartbeat-service.test.ts +0 -2
- package/src/__tests__/helpers/channel-test-adapter.ts +7 -1
- package/src/__tests__/host-app-control-routes.test.ts +30 -24
- package/src/__tests__/host-bash-routes.test.ts +41 -31
- package/src/__tests__/host-browser-routes.test.ts +32 -26
- package/src/__tests__/host-cu-routes-targeted.test.ts +33 -25
- package/src/__tests__/host-file-routes-targeted.test.ts +52 -40
- package/src/__tests__/host-transfer-routes-targeted.test.ts +43 -31
- package/src/__tests__/http-user-message-parity.test.ts +8 -290
- package/src/__tests__/inbound-invite-redemption.test.ts +0 -28
- package/src/__tests__/inbound-slack-persistence.test.ts +0 -2
- package/src/__tests__/invite-redemption-service.test.ts +0 -198
- package/src/__tests__/llm-context-normalization.test.ts +0 -105
- package/src/__tests__/llm-request-log-error-payload.test.ts +9 -71
- package/src/__tests__/llm-usage-store.test.ts +0 -25
- package/src/__tests__/mcp-health-check.test.ts +1 -2
- package/src/__tests__/media-stream-server-integration.test.ts +0 -127
- package/src/__tests__/memory-retrieval-hook.test.ts +0 -2
- package/src/__tests__/messaging-send-tool.test.ts +0 -2
- package/src/__tests__/migration-import-from-url.test.ts +2 -2
- package/src/__tests__/mtime-cache.test.ts +5 -146
- package/src/__tests__/native-web-search.test.ts +0 -2
- package/src/__tests__/non-member-access-request.test.ts +17 -189
- package/src/__tests__/notification-broadcaster.test.ts +0 -4
- package/src/__tests__/notification-decision-recipient-context.test.ts +32 -33
- package/src/__tests__/notification-deep-link.test.ts +0 -6
- package/src/__tests__/notification-guardian-path.test.ts +0 -19
- package/src/__tests__/openai-provider.test.ts +12 -22
- package/src/__tests__/openai-responses-provider.test.ts +2 -12
- package/src/__tests__/outbound-slack-persistence.test.ts +0 -2
- package/src/__tests__/pending-interactions-resolved-event.test.ts +4 -7
- package/src/__tests__/persistence-secret-redaction.test.ts +0 -2
- package/src/__tests__/plugin-bootstrap.test.ts +73 -3
- package/src/__tests__/plugin-route-contribution.test.ts +17 -4
- package/src/__tests__/plugin-tool-contribution.test.ts +18 -3
- package/src/__tests__/plugin-types.test.ts +2 -0
- package/src/__tests__/process-message-background-slack.test.ts +0 -2
- package/src/__tests__/process-message-display-content.test.ts +0 -2
- package/src/__tests__/provider-error-scenarios.test.ts +4 -5
- package/src/__tests__/provider-usage-tracking.test.ts +0 -39
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +0 -2
- package/src/__tests__/registry.test.ts +1 -4
- package/src/__tests__/relay-server.test.ts +25 -694
- package/src/__tests__/runtime-attachment-metadata.test.ts +1 -0
- package/src/__tests__/secret-ingress-http.test.ts +0 -14
- package/src/__tests__/send-endpoint-busy.test.ts +8 -30
- package/src/__tests__/skills.test.ts +0 -44
- package/src/__tests__/slack-inbound-verification.test.ts +2 -47
- package/src/__tests__/stt-hints.test.ts +13 -44
- package/src/__tests__/subagent-detail.test.ts +0 -27
- package/src/__tests__/subagent-disposal.test.ts +0 -65
- package/src/__tests__/subagent-notify-parent.test.ts +0 -2
- package/src/__tests__/subagent-role-registry.test.ts +2 -7
- package/src/__tests__/subagent-spawn-tool-fork.test.ts +0 -2
- package/src/__tests__/subagent-tools.test.ts +0 -2
- package/src/__tests__/suggestion-routes.test.ts +0 -2
- package/src/__tests__/title-generate-hook.test.ts +0 -2
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +0 -2
- package/src/__tests__/tool-executor.test.ts +11 -16
- package/src/__tests__/tool-preview-lifecycle.test.ts +0 -2
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +0 -2
- package/src/__tests__/tool-start-timestamp.test.ts +0 -2
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +10 -10
- package/src/__tests__/twilio-routes.test.ts +0 -96
- package/src/__tests__/ui-file-upload-surface.test.ts +0 -86
- package/src/__tests__/verification-control-plane-policy.test.ts +0 -2
- package/src/__tests__/voice-invite-redemption.test.ts +0 -33
- package/src/__tests__/web-search-backend-failure.test.ts +0 -2
- package/src/__tests__/workspace-migration-remove-hooks.test.ts +35 -14
- package/src/__tests__/workspace-tool-loader.test.ts +2 -195
- package/src/__tests__/workspace-tools-watcher-flag.test.ts +70 -0
- package/src/agent/loop.ts +0 -56
- package/src/api/index.ts +1 -19
- package/src/api/responses/llm-request-log-entry.ts +0 -29
- package/src/api/responses/subagent-detail.ts +0 -17
- package/src/api/surfaces.ts +3 -39
- package/src/approvals/guardian-request-resolvers.ts +11 -1
- package/src/calls/__tests__/relay-setup-router.test.ts +4 -262
- package/src/calls/call-domain.ts +3 -3
- package/src/calls/guardian-dispatch.ts +8 -10
- package/src/calls/inbound-trust-reader.ts +1 -17
- package/src/calls/media-stream-server.ts +0 -21
- package/src/calls/relay-server.ts +50 -167
- package/src/calls/relay-setup-router.ts +7 -37
- package/src/calls/relay-verification.ts +4 -4
- package/src/calls/stt-hints.ts +12 -9
- package/src/calls/twilio-routes.ts +4 -14
- package/src/channels/types.ts +20 -10
- package/src/cli/commands/__tests__/cache.test.ts +1 -8
- package/src/cli/commands/cache.ts +181 -194
- package/src/cli/commands/db/__tests__/repair.test.ts +5 -6
- package/src/cli/commands/db/status.ts +1 -37
- package/src/cli/commands/mcp.ts +218 -252
- package/src/cli/commands/memory/index.ts +0 -2
- package/src/cli/commands/plugins.ts +3 -75
- package/src/cli/lib/__tests__/install-from-github.test.ts +0 -102
- package/src/cli/lib/__tests__/list-installed-plugins.test.ts +1 -160
- package/src/cli/lib/list-installed-plugins.ts +1 -179
- package/src/config/__tests__/sync-gated-profiles.test.ts +3 -11
- package/src/config/bundled-skills/contacts/tools/contact-merge.ts +17 -27
- package/src/config/bundled-skills/contacts/tools/contact-search.ts +3 -13
- package/src/config/bundled-skills/subagent/SKILL.md +1 -1
- package/src/config/bundled-skills/subagent/TOOLS.json +1 -1
- package/src/config/feature-flag-registry.json +13 -5
- package/src/config/loader.ts +5 -38
- package/src/config/schemas/__tests__/memory-v3.test.ts +0 -1
- package/src/config/schemas/memory-lifecycle.ts +0 -12
- package/src/config/schemas/memory-v3.ts +0 -7
- package/src/config/schemas/memory.ts +0 -4
- package/src/config/schemas/timeouts.ts +0 -8
- package/src/config/seed-inference-profiles.ts +11 -21
- package/src/config/skills.ts +5 -27
- package/src/config/sync-gated-profiles.ts +13 -12
- package/src/contacts/contacts-write.ts +0 -3
- package/src/daemon/assistant-attachments.ts +4 -27
- package/src/daemon/conversation-agent-loop.ts +0 -28
- package/src/daemon/conversation-process.ts +16 -35
- package/src/daemon/conversation-surfaces.ts +38 -111
- package/src/daemon/conversation-tool-setup.ts +16 -50
- package/src/daemon/conversation.ts +1 -13
- package/src/daemon/disk-pressure-guard.ts +2 -12
- package/src/daemon/event-loop-watchdog.ts +1 -28
- package/src/daemon/external-plugins-bootstrap.ts +34 -4
- package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +0 -25
- package/src/daemon/handlers/config-a2a.ts +14 -6
- package/src/daemon/handlers/config-channels.ts +22 -78
- package/src/daemon/handlers/conversations.ts +0 -77
- package/src/daemon/lifecycle.ts +0 -4
- package/src/daemon/mcp-reload-service.ts +0 -10
- package/src/daemon/memory-v2-startup.test.ts +0 -72
- package/src/daemon/memory-v2-startup.ts +19 -87
- package/src/daemon/message-types/conversations.ts +0 -2
- package/src/daemon/message-types/surfaces.ts +12 -12
- package/src/daemon/server.ts +4 -0
- package/src/daemon/shutdown-handlers.ts +0 -20
- package/src/daemon/tool-setup-types.ts +0 -9
- package/src/daemon/workspace-tools-watcher.ts +328 -0
- package/src/ipc/__tests__/clients-list-ipc.test.ts +1 -1
- package/src/ipc/assistant-server.ts +2 -2
- package/src/mcp/__tests__/mcp-auth-orchestrator.test.ts +0 -1
- package/src/mcp/client.ts +1 -15
- package/src/mcp/mcp-auth-orchestrator.ts +1 -6
- package/src/mcp/mcp-oauth-provider.ts +8 -19
- package/src/memory/__tests__/memory-retrospective-job.test.ts +0 -8
- package/src/memory/conversation-crud.ts +0 -38
- package/src/memory/db-connection.ts +3 -22
- package/src/memory/db-init.ts +502 -36
- package/src/memory/db-singleton.ts +4 -6
- package/src/memory/jobs-worker.ts +0 -58
- package/src/memory/llm-request-log-store.ts +1 -26
- package/src/memory/llm-usage-store.ts +20 -48
- package/src/memory/memory-retrospective-job.ts +8 -9
- package/src/memory/migrations/209-strip-thinking-from-consolidated.ts +56 -130
- package/src/memory/migrations/__tests__/run-migrations.test.ts +2 -2
- package/src/memory/migrations/registry.ts +573 -0
- package/src/memory/migrations/run-migrations.ts +6 -90
- package/src/memory/migrations/validate-migration-state.ts +66 -101
- package/src/memory/schema/conversations.ts +0 -9
- package/src/memory/schema/infrastructure.ts +0 -20
- package/src/memory/v2/__tests__/cli-command-store.test.ts +0 -25
- package/src/memory/v2/__tests__/skill-store.test.ts +0 -80
- package/src/memory/v2/cli-command-store.ts +38 -75
- package/src/memory/v2/prompts/consolidation.ts +82 -13
- package/src/memory/v2/prompts/router.ts +93 -21
- package/src/memory/v2/skill-store.ts +31 -68
- package/src/notifications/__tests__/broadcaster.test.ts +8 -16
- package/src/notifications/__tests__/decision-engine.test.ts +9 -78
- package/src/notifications/broadcaster.ts +1 -8
- package/src/notifications/decision-engine.ts +7 -15
- package/src/notifications/destination-resolver.ts +24 -68
- package/src/notifications/emit-signal.ts +14 -39
- package/src/permissions/question-prompter.test.ts +1 -1
- package/src/permissions/question-prompter.ts +4 -7
- package/src/plugin-api/index.ts +6 -6
- package/src/plugin-api/types.ts +5 -3
- package/src/plugin-api/vision-support.test.ts +4 -28
- package/src/plugin-api/vision-support.ts +31 -66
- package/src/plugins/defaults/advisor/__tests__/consult.test.ts +0 -161
- package/src/plugins/defaults/advisor/consult.ts +6 -110
- package/src/plugins/defaults/advisor/steering.ts +2 -14
- package/src/plugins/defaults/advisor/tools/advisor.ts +5 -32
- package/src/plugins/defaults/exploration-drift/hooks/post-tool-use.ts +1 -2
- package/src/plugins/defaults/image-fallback/__tests__/image-fallback.test.ts +7 -47
- package/src/plugins/defaults/image-fallback/hooks/post-tool-use.ts +11 -10
- package/src/plugins/defaults/image-fallback/hooks/user-prompt-submit.ts +20 -12
- package/src/plugins/defaults/image-fallback/src/caption-blocks.ts +11 -42
- package/src/plugins/defaults/memory-v3-shadow/__tests__/injection.test.ts +3 -33
- package/src/plugins/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +4 -48
- package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +8 -4
- package/src/plugins/defaults/memory-v3-shadow/injector.ts +15 -43
- package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +2 -11
- package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +13 -77
- package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +11 -12
- package/src/plugins/mtime-cache.ts +291 -76
- package/src/plugins/pipeline.ts +13 -111
- package/src/plugins/types.ts +2 -0
- package/src/providers/anthropic/client.ts +0 -5
- package/src/providers/call-site-routing.ts +0 -4
- package/src/providers/model-catalog.ts +0 -16
- package/src/providers/openai/__tests__/api-error-detail.test.ts +120 -0
- package/src/providers/openai/chat-completions-provider.ts +83 -37
- package/src/providers/openai/responses-provider.ts +46 -50
- package/src/providers/openrouter/client.ts +0 -5
- package/src/providers/provider-send-message.ts +0 -4
- package/src/providers/ratelimit.ts +0 -4
- package/src/providers/retry.ts +0 -4
- package/src/providers/types.ts +0 -9
- package/src/providers/usage-tracking.ts +0 -4
- package/src/runtime/__tests__/trust-verdict-consumer.test.ts +3 -335
- package/src/runtime/access-request-helper.ts +39 -19
- package/src/runtime/actor-trust-resolver.ts +2 -2
- package/src/runtime/assistant-event-hub.ts +1 -1
- package/src/runtime/assistant-stream-state.ts +2 -9
- package/src/runtime/auth/require-bound-guardian.ts +11 -21
- package/src/runtime/channel-verification-service.ts +31 -56
- package/src/runtime/confirmation-request-guardian-bridge.ts +3 -3
- package/src/runtime/guardian-vellum-migration.ts +7 -66
- package/src/runtime/invite-redemption-service.ts +187 -198
- package/src/runtime/local-actor-identity.ts +11 -76
- package/src/runtime/pending-interactions.ts +1 -11
- package/src/runtime/routes/__tests__/channel-verification-revoke.test.ts +5 -56
- package/src/runtime/routes/__tests__/channel-verification-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/surface-action-routes.test.ts +0 -187
- package/src/runtime/routes/browser-routes.ts +1 -1
- package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +5 -13
- package/src/runtime/routes/channel-verification-routes.ts +3 -3
- package/src/runtime/routes/contact-routes.ts +32 -8
- package/src/runtime/routes/conversation-cli-routes.ts +5 -4
- package/src/runtime/routes/conversation-list-routes.ts +7 -4
- package/src/runtime/routes/conversation-query-routes.ts +0 -72
- package/src/runtime/routes/conversation-routes.ts +85 -84
- package/src/runtime/routes/events-routes.ts +2 -2
- package/src/runtime/routes/global-search-routes.ts +1 -3
- package/src/runtime/routes/guardian-action-routes.ts +5 -4
- package/src/runtime/routes/host-app-control-routes.ts +4 -5
- package/src/runtime/routes/host-bash-routes.ts +4 -5
- package/src/runtime/routes/host-browser-routes.ts +11 -9
- package/src/runtime/routes/host-cu-routes.ts +4 -5
- package/src/runtime/routes/host-file-routes.ts +4 -5
- package/src/runtime/routes/host-transfer-routes.ts +6 -6
- package/src/runtime/routes/http-adapter.ts +1 -1
- package/src/runtime/routes/identity-routes.ts +2 -3
- package/src/runtime/routes/inbound-message-handler.ts +5 -5
- package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +5 -97
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +49 -61
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +4 -16
- package/src/runtime/routes/inbound-stages/escalation-intercept.ts +7 -7
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +8 -21
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +3 -14
- package/src/runtime/routes/index.ts +0 -2
- package/src/runtime/routes/llm-context-normalization.ts +0 -83
- package/src/runtime/routes/mcp-auth-routes.ts +19 -171
- package/src/runtime/routes/migration-rollback-routes.ts +3 -4
- package/src/runtime/routes/migration-routes.ts +1 -4
- package/src/runtime/routes/subagents-routes.ts +0 -5
- package/src/runtime/routes/surface-action-routes.ts +56 -42
- package/src/runtime/services/__tests__/conversation-serializer.test.ts +0 -1
- package/src/runtime/services/conversation-serializer.ts +9 -7
- package/src/runtime/tool-grant-request-helper.ts +3 -3
- package/src/runtime/trust-verdict-consumer.ts +9 -85
- package/src/runtime/verification-outbound-actions.ts +18 -18
- package/src/signals/user-message.ts +0 -16
- package/src/subagent/manager.ts +0 -9
- package/src/subagent/types.ts +3 -3
- package/src/telemetry/types.ts +1 -34
- package/src/telemetry/usage-telemetry-reporter.test.ts +2 -3
- package/src/telemetry/usage-telemetry-reporter.ts +3 -87
- package/src/tools/ask-question/ask-question-tool.test.ts +0 -29
- package/src/tools/ask-question/ask-question-tool.ts +0 -13
- package/src/tools/executor.ts +4 -4
- package/src/tools/registry.ts +0 -18
- package/src/tools/shared/filesystem/path-policy.ts +5 -12
- package/src/tools/tool-approval-handler.ts +1 -1
- package/src/tools/tool-defaults.ts +2 -9
- package/src/tools/tool-manifest.ts +0 -3
- package/src/tools/types.ts +2 -17
- package/src/tools/workspace-tools/loader.ts +244 -348
- package/src/util/errors.ts +1 -26
- package/src/util/platform.ts +0 -5
- package/src/workflows/library.test.ts +0 -140
- package/src/workflows/library.ts +28 -82
- package/src/workspace/migrations/017-seed-persona-dirs.ts +34 -3
- package/src/workspace/migrations/019-scope-journal-to-guardian.ts +24 -3
- package/src/workspace/migrations/048-remove-workspace-hooks.ts +66 -14
- package/src/workspace/migrations/registry.ts +0 -2
- package/node_modules/@vellumai/gateway-client/src/__tests__/guardian-delivery-contract.test.ts +0 -91
- package/node_modules/@vellumai/gateway-client/src/guardian-delivery-contract.ts +0 -48
- package/node_modules/@vellumai/service-contracts/src/__tests__/channels.test.ts +0 -28
- package/node_modules/@vellumai/service-contracts/src/channels.ts +0 -41
- package/src/__tests__/code-search-tool.test.ts +0 -585
- package/src/__tests__/guardian-expiry-notifier.test.ts +0 -282
- package/src/__tests__/mcp-config-secret-boundary.test.ts +0 -390
- package/src/__tests__/plugin-pipeline.test.ts +0 -96
- package/src/__tests__/sse-actor-principal-guardian-source.test.ts +0 -102
- package/src/__tests__/steer-on-enqueue-question.test.ts +0 -181
- package/src/__tests__/workspace-migration-111-prune-seeded-callsite-defaults.test.ts +0 -208
- package/src/agent/loop-exclusive-tool.test.ts +0 -150
- package/src/api/constants/sse-replay.ts +0 -41
- package/src/api/events/conversation-notice.ts +0 -26
- package/src/approvals/guardian-channel-delivery.ts +0 -30
- package/src/approvals/guardian-expiry-notifier.ts +0 -148
- package/src/cli/commands/memory/__tests__/worker.test.ts +0 -302
- package/src/cli/commands/memory/worker.ts +0 -175
- package/src/config/__tests__/loader-callsite-strip-fallback.test.ts +0 -143
- package/src/config/prune-seeded-callsite-defaults.ts +0 -110
- package/src/contacts/__tests__/contacts-write-revoke-relay.test.ts +0 -129
- package/src/contacts/__tests__/guardian-delivery-reader.test.ts +0 -312
- package/src/contacts/__tests__/member-write-relay.test.ts +0 -202
- package/src/contacts/guardian-delivery-reader.ts +0 -223
- package/src/contacts/member-write-relay.ts +0 -189
- package/src/daemon/conversation-notices.ts +0 -60
- package/src/daemon/handlers/__tests__/config-channels.test.ts +0 -225
- package/src/hooks/hook-loader.ts +0 -341
- package/src/mcp/mcp-header-store.ts +0 -134
- package/src/memory/__tests__/301-create-watchdog-events.test.ts +0 -110
- package/src/memory/__tests__/prompt-override.test.ts +0 -192
- package/src/memory/__tests__/watchdog-events-store.test.ts +0 -161
- package/src/memory/migrations/300-add-processing-started-at.ts +0 -30
- package/src/memory/migrations/301-create-watchdog-events.ts +0 -45
- package/src/memory/migrations/__tests__/209-strip-thinking-from-consolidated.test.ts +0 -224
- package/src/memory/prompt-override.ts +0 -129
- package/src/memory/steps.ts +0 -573
- package/src/memory/watchdog-events-store.ts +0 -87
- package/src/memory/worker-control.ts +0 -118
- package/src/memory/worker-process.ts +0 -72
- package/src/notifications/__tests__/connected-channels.test.ts +0 -114
- package/src/notifications/__tests__/destination-resolver.test.ts +0 -256
- package/src/onboarding/checkin-event.test.ts +0 -222
- package/src/onboarding/checkin-event.ts +0 -321
- package/src/onboarding/schedule-checkin.ts +0 -190
- package/src/plugins/defaults/advisor/__tests__/context-pack-gating.test.ts +0 -106
- package/src/plugins/defaults/advisor/__tests__/context-pack.test.ts +0 -60
- package/src/plugins/defaults/advisor/context-pack.ts +0 -288
- package/src/plugins/defaults/memory-v3-shadow/pool-select.test.ts +0 -146
- package/src/plugins/surface-import.ts +0 -121
- package/src/providers/openai/__tests__/api-error-normalization.test.ts +0 -321
- package/src/providers/openai/api-error-normalization.ts +0 -270
- package/src/runtime/__tests__/channel-verification-service.test.ts +0 -133
- package/src/runtime/__tests__/guardian-vellum-migration.test.ts +0 -181
- package/src/runtime/__tests__/is-guardian-bound-for-channel.test.ts +0 -66
- package/src/runtime/__tests__/local-principal-trust.test.ts +0 -164
- package/src/runtime/anchored-guardian.test.ts +0 -156
- package/src/runtime/anchored-guardian.ts +0 -135
- package/src/runtime/auth/__tests__/require-bound-guardian.test.ts +0 -99
- package/src/runtime/local-principal-trust.ts +0 -52
- package/src/runtime/routes/__tests__/contact-routes.test.ts +0 -212
- package/src/runtime/routes/__tests__/global-search-routes.test.ts +0 -93
- package/src/runtime/routes/onboarding-checkin-routes.ts +0 -86
- package/src/tools/filesystem/search.ts +0 -543
- package/src/util/telemetry-db-path.ts +0 -24
- package/src/workspace/migrations/111-prune-seeded-callsite-defaults.ts +0 -134
|
@@ -8,16 +8,15 @@
|
|
|
8
8
|
|
|
9
9
|
import { randomInt } from "node:crypto";
|
|
10
10
|
|
|
11
|
-
import type { AdmissionPolicy
|
|
11
|
+
import type { AdmissionPolicy } from "@vellumai/gateway-client";
|
|
12
12
|
import type { ServerWebSocket } from "bun";
|
|
13
13
|
|
|
14
14
|
import {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
} from "../contacts/
|
|
15
|
+
findGuardianForChannel,
|
|
16
|
+
listGuardianChannels,
|
|
17
|
+
} from "../contacts/contact-store.js";
|
|
18
18
|
import { getAssistantName } from "../daemon/identity-helpers.js";
|
|
19
19
|
import type { ServerMessage } from "../daemon/message-protocol.js";
|
|
20
|
-
import type { TrustContext } from "../daemon/trust-context.js";
|
|
21
20
|
import { getCanonicalGuardianRequest } from "../memory/canonical-guardian-store.js";
|
|
22
21
|
import { addMessage } from "../memory/conversation-crud.js";
|
|
23
22
|
import { revokeScopedApprovalGrantsForContext } from "../memory/scoped-approval-grants.js";
|
|
@@ -27,11 +26,6 @@ import {
|
|
|
27
26
|
resolveActorTrust,
|
|
28
27
|
toTrustContext,
|
|
29
28
|
} from "../runtime/actor-trust-resolver.js";
|
|
30
|
-
import {
|
|
31
|
-
trustContextFromVerdict,
|
|
32
|
-
verdictHasMemberIdentity,
|
|
33
|
-
verdictMemberUnresolvable,
|
|
34
|
-
} from "../runtime/trust-verdict-consumer.js";
|
|
35
29
|
import {
|
|
36
30
|
composeVerificationVoice,
|
|
37
31
|
GUARDIAN_VERIFY_TEMPLATE_KEYS,
|
|
@@ -56,10 +50,6 @@ import {
|
|
|
56
50
|
import { ConversationRelayTransport } from "./call-transport.js";
|
|
57
51
|
import { getChannelAdmissionPolicy } from "./channel-admission-reader.js";
|
|
58
52
|
import { finalizeCall } from "./finalize-call.js";
|
|
59
|
-
import {
|
|
60
|
-
getInboundTrustVerdict,
|
|
61
|
-
getPhoneCallerVerdict,
|
|
62
|
-
} from "./inbound-trust-reader.js";
|
|
63
53
|
import {
|
|
64
54
|
classifyWaitUtterance,
|
|
65
55
|
emitAccessRequestCallbackHandoff,
|
|
@@ -262,10 +252,6 @@ export class RelayConnection {
|
|
|
262
252
|
private accessRequestWaitStartedAt: number = 0;
|
|
263
253
|
private heartbeatSequence = 0;
|
|
264
254
|
|
|
265
|
-
// Guardian displayName primed from the gateway binding at setup, read
|
|
266
|
-
// synchronously by the heartbeat-driven wait-label path.
|
|
267
|
-
private primedGuardianDisplayName: string | undefined;
|
|
268
|
-
|
|
269
255
|
// In-wait prompt handling state
|
|
270
256
|
private lastInWaitReplyAt = 0;
|
|
271
257
|
private static readonly IN_WAIT_REPLY_COOLDOWN_MS = 3000;
|
|
@@ -275,12 +261,6 @@ export class RelayConnection {
|
|
|
275
261
|
private callbackOptIn = false;
|
|
276
262
|
private callbackHandoffNotified = false;
|
|
277
263
|
|
|
278
|
-
// True while mid-call trust is being re-resolved (async). handlePrompt defers
|
|
279
|
-
// prompts to trustReResolvePending so a verified caller can't start a turn
|
|
280
|
-
// under the stale pre-verification trust context during the await window.
|
|
281
|
-
private trustReResolving = false;
|
|
282
|
-
private trustReResolvePending: RelayPromptMessage[] = [];
|
|
283
|
-
|
|
284
264
|
constructor(ws: ServerWebSocket<RelayWebSocketData>, callSessionId: string) {
|
|
285
265
|
this.ws = ws;
|
|
286
266
|
this.callSessionId = callSessionId;
|
|
@@ -601,21 +581,12 @@ export class RelayConnection {
|
|
|
601
581
|
const session = getCallSession(this.callSessionId);
|
|
602
582
|
this.recordSetupBookkeeping(session, msg);
|
|
603
583
|
|
|
604
|
-
await this.primeGuardianDisplayName();
|
|
605
|
-
|
|
606
584
|
// Resolve the phone channel's inbound admission floor. The reader fails
|
|
607
585
|
// open to `null` by contract, so a transport hiccup admits the caller.
|
|
608
586
|
const admissionPolicy = await getChannelAdmissionPolicy("phone");
|
|
609
587
|
|
|
610
|
-
// Verdict-first caller trust. routeSetup uses it when present and not
|
|
611
|
-
// resolutionFailed, else falls back to local resolution. The reader
|
|
612
|
-
// returns null on failure, so a gateway blip keeps the local path.
|
|
613
|
-
const isInbound = session?.initiatedFromConversationId == null;
|
|
614
|
-
const otherPartyNumber = isInbound ? msg.from : msg.to;
|
|
615
|
-
const verdict = await getPhoneCallerVerdict(otherPartyNumber);
|
|
616
|
-
|
|
617
588
|
try {
|
|
618
|
-
await this.routeSetupOutcome(msg, session, admissionPolicy
|
|
589
|
+
await this.routeSetupOutcome(msg, session, admissionPolicy);
|
|
619
590
|
} catch (err) {
|
|
620
591
|
// Never leave the connection stranded in "setting_up": a setup that
|
|
621
592
|
// throws before reaching a terminal outcome would otherwise drop every
|
|
@@ -644,7 +615,6 @@ export class RelayConnection {
|
|
|
644
615
|
msg: RelaySetupMessage,
|
|
645
616
|
session: ReturnType<typeof getCallSession>,
|
|
646
617
|
admissionPolicy: AdmissionPolicy | null,
|
|
647
|
-
verdict: TrustVerdict | null,
|
|
648
618
|
): Promise<void> {
|
|
649
619
|
const { outcome, resolved } = routeSetup({
|
|
650
620
|
callSessionId: this.callSessionId,
|
|
@@ -653,7 +623,6 @@ export class RelayConnection {
|
|
|
653
623
|
to: msg.to,
|
|
654
624
|
customParameters: msg.customParameters,
|
|
655
625
|
admissionPolicy,
|
|
656
|
-
verdict,
|
|
657
626
|
});
|
|
658
627
|
|
|
659
628
|
const initialTrustContext = toTrustContext(
|
|
@@ -902,95 +871,6 @@ export class RelayConnection {
|
|
|
902
871
|
);
|
|
903
872
|
}
|
|
904
873
|
|
|
905
|
-
/**
|
|
906
|
-
* Re-resolve caller trust after a mid-call verification/activation. Prefers
|
|
907
|
-
* the gateway verdict (authoritative right after the gateway updated the
|
|
908
|
-
* binding); falls back to local resolution on a missing/failed/unusable
|
|
909
|
-
* verdict so a blip never drops the call. Mirrors the setup path's
|
|
910
|
-
* verdict-first-with-fallback condition.
|
|
911
|
-
*/
|
|
912
|
-
private async resolveMidCallTrustContext(
|
|
913
|
-
assistantId: string,
|
|
914
|
-
fromNumber: string,
|
|
915
|
-
): Promise<TrustContext> {
|
|
916
|
-
const verdict = await getInboundTrustVerdict({
|
|
917
|
-
channelType: "phone",
|
|
918
|
-
actorExternalId: fromNumber,
|
|
919
|
-
});
|
|
920
|
-
|
|
921
|
-
// Only a MEMBERLESS unknown verdict is treated as a stale gateway view and
|
|
922
|
-
// falls back to local: the caller was just activated, and invite redemption
|
|
923
|
-
// writes the channel assistant-side, so the gateway may not see the member
|
|
924
|
-
// yet — local resolution has it. A MEMBERFUL unknown verdict (blocked/revoked
|
|
925
|
-
// member, carrying contactId/channelId) is honored so its deny ACL is
|
|
926
|
-
// enforced; falling back could lose the gateway's member status if local
|
|
927
|
-
// state is stale.
|
|
928
|
-
const memberlessUnknown =
|
|
929
|
-
verdict?.trustClass === "unknown" && !verdictHasMemberIdentity(verdict);
|
|
930
|
-
const usable =
|
|
931
|
-
verdict &&
|
|
932
|
-
!verdict.resolutionFailed &&
|
|
933
|
-
!verdictMemberUnresolvable(verdict) &&
|
|
934
|
-
!memberlessUnknown;
|
|
935
|
-
|
|
936
|
-
if (usable) {
|
|
937
|
-
return trustContextFromVerdict(verdict, {
|
|
938
|
-
sourceChannel: "phone",
|
|
939
|
-
conversationExternalId: fromNumber,
|
|
940
|
-
});
|
|
941
|
-
}
|
|
942
|
-
|
|
943
|
-
return toTrustContext(
|
|
944
|
-
resolveActorTrust({
|
|
945
|
-
assistantId,
|
|
946
|
-
sourceChannel: "phone",
|
|
947
|
-
conversationExternalId: fromNumber,
|
|
948
|
-
actorExternalId: fromNumber,
|
|
949
|
-
}),
|
|
950
|
-
fromNumber,
|
|
951
|
-
);
|
|
952
|
-
}
|
|
953
|
-
|
|
954
|
-
/**
|
|
955
|
-
* Re-resolve mid-call trust and install it on the controller, deferring any
|
|
956
|
-
* prompt that arrives during the async window. Guards the gap between
|
|
957
|
-
* connectionState flipping to "connected" and the upgraded context landing so
|
|
958
|
-
* a verified caller never starts a turn under the stale pre-verification
|
|
959
|
-
* trust. Clears the guard in a finally and flushes buffered prompts under the
|
|
960
|
-
* new context, so an IPC error can't wedge the call.
|
|
961
|
-
*/
|
|
962
|
-
private async reResolveAndApplyTrustContext(
|
|
963
|
-
assistantId: string,
|
|
964
|
-
fromNumber: string,
|
|
965
|
-
): Promise<void> {
|
|
966
|
-
if (!this.controller) return;
|
|
967
|
-
this.trustReResolving = true;
|
|
968
|
-
try {
|
|
969
|
-
const context = await this.resolveMidCallTrustContext(
|
|
970
|
-
assistantId,
|
|
971
|
-
fromNumber,
|
|
972
|
-
);
|
|
973
|
-
this.controller.setTrustContext(context);
|
|
974
|
-
} finally {
|
|
975
|
-
this.trustReResolving = false;
|
|
976
|
-
this.flushDeferredPrompts();
|
|
977
|
-
}
|
|
978
|
-
}
|
|
979
|
-
|
|
980
|
-
/**
|
|
981
|
-
* Replay prompts buffered while trust was re-resolving. Runs after the
|
|
982
|
-
* upgraded context is installed so deferred utterances are answered under the
|
|
983
|
-
* correct trust.
|
|
984
|
-
*/
|
|
985
|
-
private flushDeferredPrompts(): void {
|
|
986
|
-
if (this.trustReResolvePending.length === 0) return;
|
|
987
|
-
const pending = this.trustReResolvePending;
|
|
988
|
-
this.trustReResolvePending = [];
|
|
989
|
-
for (const msg of pending) {
|
|
990
|
-
void this.handlePrompt(msg);
|
|
991
|
-
}
|
|
992
|
-
}
|
|
993
|
-
|
|
994
874
|
/**
|
|
995
875
|
* Shared post-activation handoff for all trusted-contact success paths
|
|
996
876
|
* (access-request approval, invite redemption, verification code).
|
|
@@ -998,7 +878,7 @@ export class RelayConnection {
|
|
|
998
878
|
* transition copy, and marks the next utterance as opening-ack so the
|
|
999
879
|
* LLM continues naturally.
|
|
1000
880
|
*/
|
|
1001
|
-
private
|
|
881
|
+
private continueCallAfterTrustedContactActivation(params: {
|
|
1002
882
|
assistantId: string;
|
|
1003
883
|
fromNumber: string;
|
|
1004
884
|
activationReason?:
|
|
@@ -1013,25 +893,26 @@ export class RelayConnection {
|
|
|
1013
893
|
* address.
|
|
1014
894
|
*/
|
|
1015
895
|
inviteeName?: string | null;
|
|
1016
|
-
}):
|
|
896
|
+
}): void {
|
|
1017
897
|
const { assistantId, fromNumber } = params;
|
|
1018
898
|
|
|
1019
899
|
// Contact activation is handled by the gateway — the assistant no
|
|
1020
900
|
// longer writes contact/channel records on inbound voice calls.
|
|
1021
901
|
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
this.accessRequestWaitActive = false;
|
|
1029
|
-
updateCallSession(this.callSessionId, { status: "in_progress" });
|
|
902
|
+
const updatedTrust = resolveActorTrust({
|
|
903
|
+
assistantId,
|
|
904
|
+
sourceChannel: "phone",
|
|
905
|
+
conversationExternalId: fromNumber,
|
|
906
|
+
actorExternalId: fromNumber,
|
|
907
|
+
});
|
|
1030
908
|
|
|
1031
909
|
if (this.controller) {
|
|
1032
|
-
|
|
910
|
+
this.controller.setTrustContext(toTrustContext(updatedTrust, fromNumber));
|
|
1033
911
|
}
|
|
1034
912
|
|
|
913
|
+
this.connectionState = "connected";
|
|
914
|
+
updateCallSession(this.callSessionId, { status: "in_progress" });
|
|
915
|
+
|
|
1035
916
|
const guardianLabel = this.resolveGuardianLabel();
|
|
1036
917
|
let handoffText: string;
|
|
1037
918
|
|
|
@@ -1164,7 +1045,7 @@ export class RelayConnection {
|
|
|
1164
1045
|
const assistantId = this.verificationAssistantId;
|
|
1165
1046
|
const fromNumber = this.verificationFromNumber;
|
|
1166
1047
|
|
|
1167
|
-
const result =
|
|
1048
|
+
const result = attemptVerificationCode({
|
|
1168
1049
|
verificationAssistantId: assistantId,
|
|
1169
1050
|
verificationFromNumber: fromNumber,
|
|
1170
1051
|
enteredCode,
|
|
@@ -1210,7 +1091,15 @@ export class RelayConnection {
|
|
|
1210
1091
|
|
|
1211
1092
|
// Update trust context on the controller so the LLM knows this is the guardian
|
|
1212
1093
|
if (this.controller) {
|
|
1213
|
-
|
|
1094
|
+
const verifiedActorTrust = resolveActorTrust({
|
|
1095
|
+
assistantId,
|
|
1096
|
+
sourceChannel: "phone",
|
|
1097
|
+
conversationExternalId: fromNumber,
|
|
1098
|
+
actorExternalId: fromNumber,
|
|
1099
|
+
});
|
|
1100
|
+
this.controller.setTrustContext(
|
|
1101
|
+
toTrustContext(verifiedActorTrust, fromNumber),
|
|
1102
|
+
);
|
|
1214
1103
|
}
|
|
1215
1104
|
|
|
1216
1105
|
// Mark session as in-progress and transition to guardian conversation
|
|
@@ -1227,7 +1116,7 @@ export class RelayConnection {
|
|
|
1227
1116
|
);
|
|
1228
1117
|
}
|
|
1229
1118
|
} else if (result.verificationType === "trusted_contact") {
|
|
1230
|
-
|
|
1119
|
+
this.continueCallAfterTrustedContactActivation({
|
|
1231
1120
|
assistantId,
|
|
1232
1121
|
fromNumber,
|
|
1233
1122
|
activationReason: "trusted_contact_verified",
|
|
@@ -1236,7 +1125,15 @@ export class RelayConnection {
|
|
|
1236
1125
|
// Inbound guardian verification: binding already handled above,
|
|
1237
1126
|
// proceed to normal call flow.
|
|
1238
1127
|
if (this.controller) {
|
|
1239
|
-
|
|
1128
|
+
const verifiedActorTrust = resolveActorTrust({
|
|
1129
|
+
assistantId,
|
|
1130
|
+
sourceChannel: "phone",
|
|
1131
|
+
conversationExternalId: fromNumber,
|
|
1132
|
+
actorExternalId: fromNumber,
|
|
1133
|
+
});
|
|
1134
|
+
this.controller.setTrustContext(
|
|
1135
|
+
toTrustContext(verifiedActorTrust, fromNumber),
|
|
1136
|
+
);
|
|
1240
1137
|
this.startNormalCallFlow(this.controller, true);
|
|
1241
1138
|
}
|
|
1242
1139
|
}
|
|
@@ -1399,7 +1296,7 @@ export class RelayConnection {
|
|
|
1399
1296
|
* Creates a canonical access request, notifies the guardian, and
|
|
1400
1297
|
* enters the bounded wait loop for the guardian decision.
|
|
1401
1298
|
*/
|
|
1402
|
-
private
|
|
1299
|
+
private handleNameCaptureResponse(callerName: string): void {
|
|
1403
1300
|
if (!this.accessRequestAssistantId || !this.accessRequestFromNumber) {
|
|
1404
1301
|
return;
|
|
1405
1302
|
}
|
|
@@ -1420,7 +1317,7 @@ export class RelayConnection {
|
|
|
1420
1317
|
// Create canonical access request and notify the guardian, including
|
|
1421
1318
|
// the caller's spoken name and voice channel metadata.
|
|
1422
1319
|
try {
|
|
1423
|
-
const accessResult =
|
|
1320
|
+
const accessResult = notifyGuardianOfAccessRequest({
|
|
1424
1321
|
canonicalAssistantId: this.accessRequestAssistantId,
|
|
1425
1322
|
sourceChannel: "phone",
|
|
1426
1323
|
conversationExternalId: this.accessRequestFromNumber,
|
|
@@ -1513,7 +1410,7 @@ export class RelayConnection {
|
|
|
1513
1410
|
}
|
|
1514
1411
|
|
|
1515
1412
|
if (request.status === "approved") {
|
|
1516
|
-
|
|
1413
|
+
this.handleAccessRequestApproved();
|
|
1517
1414
|
} else if (request.status === "denied") {
|
|
1518
1415
|
void this.handleAccessRequestDenied();
|
|
1519
1416
|
}
|
|
@@ -1565,7 +1462,7 @@ export class RelayConnection {
|
|
|
1565
1462
|
* Handle an approved access request: activate the caller as a trusted
|
|
1566
1463
|
* contact, update runtime context, and continue with normal call flow.
|
|
1567
1464
|
*/
|
|
1568
|
-
private
|
|
1465
|
+
private handleAccessRequestApproved(): void {
|
|
1569
1466
|
this.clearAccessRequestWait();
|
|
1570
1467
|
|
|
1571
1468
|
const assistantId = this.accessRequestAssistantId!;
|
|
@@ -1583,7 +1480,7 @@ export class RelayConnection {
|
|
|
1583
1480
|
"Access request approved — caller activated and continuing call",
|
|
1584
1481
|
);
|
|
1585
1482
|
|
|
1586
|
-
|
|
1483
|
+
this.continueCallAfterTrustedContactActivation({
|
|
1587
1484
|
assistantId,
|
|
1588
1485
|
fromNumber,
|
|
1589
1486
|
activationReason: "access_approved",
|
|
@@ -1791,7 +1688,7 @@ export class RelayConnection {
|
|
|
1791
1688
|
"Voice invite redemption succeeded",
|
|
1792
1689
|
);
|
|
1793
1690
|
|
|
1794
|
-
|
|
1691
|
+
this.continueCallAfterTrustedContactActivation({
|
|
1795
1692
|
assistantId: this.inviteRedemptionAssistantId,
|
|
1796
1693
|
fromNumber: this.inviteRedemptionFromNumber,
|
|
1797
1694
|
activationReason: "invite_redeemed",
|
|
@@ -1834,20 +1731,15 @@ export class RelayConnection {
|
|
|
1834
1731
|
* Resolve a human-readable guardian label for voice wait copy.
|
|
1835
1732
|
* Delegates to the shared resolveGuardianName() which checks the
|
|
1836
1733
|
* guardian's per-user persona file (users/<slug>.md) first, then falls
|
|
1837
|
-
* back to
|
|
1838
|
-
* DEFAULT_USER_REFERENCE.
|
|
1734
|
+
* back to Contact.displayName, then DEFAULT_USER_REFERENCE.
|
|
1839
1735
|
*/
|
|
1840
1736
|
private resolveGuardianLabel(): string {
|
|
1841
|
-
|
|
1842
|
-
|
|
1737
|
+
// Look up the guardian contact for a displayName fallback
|
|
1738
|
+
const voiceGuardian = findGuardianForChannel("phone");
|
|
1739
|
+
const guardianChannels = voiceGuardian ? null : listGuardianChannels();
|
|
1740
|
+
const guardianContact = voiceGuardian?.contact ?? guardianChannels?.contact;
|
|
1843
1741
|
|
|
1844
|
-
|
|
1845
|
-
* Prime the guardian displayName from the gateway binding so the
|
|
1846
|
-
* synchronous wait-label path can read it without an IPC round-trip.
|
|
1847
|
-
*/
|
|
1848
|
-
private async primeGuardianDisplayName(): Promise<void> {
|
|
1849
|
-
const list = await getGuardianDelivery();
|
|
1850
|
-
this.primedGuardianDisplayName = voiceGuardianDisplayName(list);
|
|
1742
|
+
return resolveGuardianName(guardianContact?.displayName);
|
|
1851
1743
|
}
|
|
1852
1744
|
|
|
1853
1745
|
/**
|
|
@@ -2025,15 +1917,6 @@ export class RelayConnection {
|
|
|
2025
1917
|
return;
|
|
2026
1918
|
}
|
|
2027
1919
|
|
|
2028
|
-
// Defer (don't drop) prompts while trust is being re-resolved mid-call so a
|
|
2029
|
-
// verified caller's first utterance runs under the upgraded context, not the
|
|
2030
|
-
// stale pre-verification one. flushDeferredPrompts replays them in order
|
|
2031
|
-
// once the new context lands.
|
|
2032
|
-
if (this.trustReResolving) {
|
|
2033
|
-
this.trustReResolvePending.push(msg);
|
|
2034
|
-
return;
|
|
2035
|
-
}
|
|
2036
|
-
|
|
2037
1920
|
// Prompts arriving before setup routing/ACL completes are dropped — never
|
|
2038
1921
|
// persisted or emitted — so a not-yet-authorized caller's speech can't be
|
|
2039
1922
|
// stored ahead of the admission floor / trust ACL decision.
|
|
@@ -2059,7 +1942,7 @@ export class RelayConnection {
|
|
|
2059
1942
|
{ callSessionId: this.callSessionId, callerName },
|
|
2060
1943
|
"Name captured from unknown inbound caller",
|
|
2061
1944
|
);
|
|
2062
|
-
|
|
1945
|
+
this.handleNameCaptureResponse(callerName);
|
|
2063
1946
|
return;
|
|
2064
1947
|
}
|
|
2065
1948
|
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* next — without performing any side effects itself.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import type { AdmissionPolicy
|
|
9
|
+
import type { AdmissionPolicy } from "@vellumai/gateway-client";
|
|
10
10
|
|
|
11
11
|
import { getConfig } from "../config/loader.js";
|
|
12
12
|
import { getContact } from "../contacts/contact-store.js";
|
|
@@ -21,10 +21,6 @@ import {
|
|
|
21
21
|
type AdmissionPolicyResult,
|
|
22
22
|
enforceAdmissionPolicy,
|
|
23
23
|
} from "../runtime/routes/inbound-stages/admission-policy.js";
|
|
24
|
-
import {
|
|
25
|
-
actorTrustContextFromVerdict,
|
|
26
|
-
verdictMemberUnresolvable,
|
|
27
|
-
} from "../runtime/trust-verdict-consumer.js";
|
|
28
24
|
import { getLogger } from "../util/logger.js";
|
|
29
25
|
import type { CallSession } from "./types.js";
|
|
30
26
|
|
|
@@ -44,12 +40,6 @@ interface SetupContext {
|
|
|
44
40
|
* preserving all pre-admission behavior.
|
|
45
41
|
*/
|
|
46
42
|
admissionPolicy?: AdmissionPolicy | null;
|
|
47
|
-
/**
|
|
48
|
-
* Gateway-stamped caller trust verdict. When present and not
|
|
49
|
-
* `resolutionFailed`, the caller's trust is built from it; otherwise the
|
|
50
|
-
* router falls back to local resolution.
|
|
51
|
-
*/
|
|
52
|
-
verdict?: TrustVerdict | null;
|
|
53
43
|
}
|
|
54
44
|
|
|
55
45
|
// ── Setup outcomes ───────────────────────────────────────────────────
|
|
@@ -122,32 +112,12 @@ export function routeSetup(ctx: SetupContext): {
|
|
|
122
112
|
const isInbound = ctx.session?.initiatedFromConversationId == null;
|
|
123
113
|
const otherPartyNumber = isInbound ? ctx.from : ctx.to;
|
|
124
114
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
// reassembled (malformed/mixed-version status·policy) also falls back to local
|
|
132
|
-
// resolution, so voice never trusts a member it cannot ACL-check. A real
|
|
133
|
-
// stranger verdict (no member identity) still takes the verdict path —
|
|
134
|
-
// memberRecord null is correct there.
|
|
135
|
-
const usable =
|
|
136
|
-
ctx.verdict &&
|
|
137
|
-
!ctx.verdict.resolutionFailed &&
|
|
138
|
-
!verdictMemberUnresolvable(ctx.verdict);
|
|
139
|
-
const actorTrust = usable
|
|
140
|
-
? actorTrustContextFromVerdict(ctx.verdict!, {
|
|
141
|
-
sourceChannel: "phone",
|
|
142
|
-
conversationExternalId: otherPartyNumber,
|
|
143
|
-
actorDisplayName: undefined,
|
|
144
|
-
})
|
|
145
|
-
: resolveActorTrust({
|
|
146
|
-
assistantId,
|
|
147
|
-
sourceChannel: "phone",
|
|
148
|
-
conversationExternalId: otherPartyNumber,
|
|
149
|
-
actorExternalId: otherPartyNumber || undefined,
|
|
150
|
-
});
|
|
115
|
+
const actorTrust = resolveActorTrust({
|
|
116
|
+
assistantId,
|
|
117
|
+
sourceChannel: "phone",
|
|
118
|
+
conversationExternalId: otherPartyNumber,
|
|
119
|
+
actorExternalId: otherPartyNumber || undefined,
|
|
120
|
+
});
|
|
151
121
|
|
|
152
122
|
const resolved: SetupResolved = {
|
|
153
123
|
assistantId,
|
|
@@ -112,9 +112,9 @@ type VerificationCallResult =
|
|
|
112
112
|
* so the caller can apply side-effects (state mutations, TTS, session
|
|
113
113
|
* updates) without this function needing access to the relay connection.
|
|
114
114
|
*/
|
|
115
|
-
export
|
|
115
|
+
export function attemptVerificationCode(
|
|
116
116
|
params: VerificationCallParams,
|
|
117
|
-
):
|
|
117
|
+
): VerificationCallResult {
|
|
118
118
|
const {
|
|
119
119
|
verificationAssistantId,
|
|
120
120
|
verificationFromNumber,
|
|
@@ -142,7 +142,7 @@ export async function attemptVerificationCode(
|
|
|
142
142
|
let canonicalPrincipal: string | undefined;
|
|
143
143
|
|
|
144
144
|
if (result.verificationType === "guardian") {
|
|
145
|
-
const existingBinding =
|
|
145
|
+
const existingBinding = getGuardianBinding(
|
|
146
146
|
verificationAssistantId,
|
|
147
147
|
"phone",
|
|
148
148
|
);
|
|
@@ -155,7 +155,7 @@ export async function attemptVerificationCode(
|
|
|
155
155
|
};
|
|
156
156
|
} else {
|
|
157
157
|
// Resolve canonical principal from the vellum channel binding
|
|
158
|
-
const vellumBinding =
|
|
158
|
+
const vellumBinding = getGuardianBinding(
|
|
159
159
|
verificationAssistantId,
|
|
160
160
|
"vellum",
|
|
161
161
|
);
|
package/src/calls/stt-hints.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { findContactByAddress, listContacts } from "../contacts/contact-store.js";
|
|
2
1
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
findContactByAddress,
|
|
3
|
+
findGuardianForChannel,
|
|
4
|
+
listContacts,
|
|
5
|
+
listGuardianChannels,
|
|
6
|
+
} from "../contacts/contact-store.js";
|
|
6
7
|
import { getAssistantName } from "../daemon/identity-helpers.js";
|
|
7
8
|
import { DEFAULT_USER_REFERENCE, resolveGuardianName } from "../prompts/user-reference.js";
|
|
8
9
|
import { getLogger } from "../util/logger.js";
|
|
@@ -118,7 +119,7 @@ export function buildSttHints(input: SttHintsInput): string {
|
|
|
118
119
|
* {@link buildSttHints}. All DB lookups are best-effort — errors are
|
|
119
120
|
* logged but never propagate so hints can never fail a call.
|
|
120
121
|
*/
|
|
121
|
-
export
|
|
122
|
+
export function resolveCallHints(
|
|
122
123
|
session: {
|
|
123
124
|
task: string | null;
|
|
124
125
|
toNumber: string;
|
|
@@ -128,14 +129,16 @@ export async function resolveCallHints(
|
|
|
128
129
|
inviteGuardianName: string | null;
|
|
129
130
|
} | null,
|
|
130
131
|
staticHints: string[],
|
|
131
|
-
):
|
|
132
|
+
): string {
|
|
132
133
|
const assistantName = getAssistantName();
|
|
133
134
|
|
|
134
|
-
//
|
|
135
|
+
// Look up the guardian contact for a displayName fallback (mirrors relay-server pattern)
|
|
135
136
|
let guardianDisplayName: string | undefined;
|
|
136
137
|
try {
|
|
137
|
-
const
|
|
138
|
-
|
|
138
|
+
const voiceGuardian = findGuardianForChannel("phone");
|
|
139
|
+
const guardianChannels = voiceGuardian ? null : listGuardianChannels();
|
|
140
|
+
const guardianContact = voiceGuardian?.contact ?? guardianChannels?.contact;
|
|
141
|
+
guardianDisplayName = guardianContact?.displayName;
|
|
139
142
|
} catch (err) {
|
|
140
143
|
logger.warn({ err }, "Failed to look up guardian contact for STT hints");
|
|
141
144
|
}
|
|
@@ -55,7 +55,6 @@ import {
|
|
|
55
55
|
updateCallSession,
|
|
56
56
|
} from "./call-store.js";
|
|
57
57
|
import { getChannelAdmissionPolicy } from "./channel-admission-reader.js";
|
|
58
|
-
import { getPhoneCallerVerdict } from "./inbound-trust-reader.js";
|
|
59
58
|
import { routeSetup } from "./relay-setup-router.js";
|
|
60
59
|
import { resolveCallHints } from "./stt-hints.js";
|
|
61
60
|
import { resolveTelephonySttRouting } from "./telephony-stt-routing.js";
|
|
@@ -299,7 +298,7 @@ async function processVoiceWebhook(
|
|
|
299
298
|
"Inbound voice webhook — creating/reusing session",
|
|
300
299
|
);
|
|
301
300
|
|
|
302
|
-
const { session } =
|
|
301
|
+
const { session } = createInboundVoiceSession({
|
|
303
302
|
callSid,
|
|
304
303
|
fromNumber: callerFrom,
|
|
305
304
|
toNumber: callerTo,
|
|
@@ -485,21 +484,12 @@ async function buildVoiceWebhookTwiml(
|
|
|
485
484
|
// admits the caller.
|
|
486
485
|
const admissionPolicy = await getChannelAdmissionPolicy("phone");
|
|
487
486
|
|
|
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
487
|
const { outcome } = routeSetup({
|
|
497
488
|
callSessionId,
|
|
498
489
|
session: session ?? null,
|
|
499
490
|
from,
|
|
500
491
|
to,
|
|
501
492
|
admissionPolicy,
|
|
502
|
-
verdict,
|
|
503
493
|
});
|
|
504
494
|
|
|
505
495
|
// The media-stream transport supports normal_call and deny (which speaks
|
|
@@ -532,7 +522,7 @@ async function buildVoiceWebhookTwiml(
|
|
|
532
522
|
/**
|
|
533
523
|
* Build ConversationRelay TwiML for Twilio-native STT providers.
|
|
534
524
|
*/
|
|
535
|
-
|
|
525
|
+
function buildConversationRelayTwiml(
|
|
536
526
|
callSessionId: string,
|
|
537
527
|
profile: ReturnType<typeof resolveVoiceQualityProfile>,
|
|
538
528
|
sessionContext: {
|
|
@@ -545,8 +535,8 @@ async function buildConversationRelayTwiml(
|
|
|
545
535
|
} | null,
|
|
546
536
|
verificationSessionId: string | null | undefined,
|
|
547
537
|
sttAttrs: { transcriptionProvider: string; speechModel: string | undefined },
|
|
548
|
-
):
|
|
549
|
-
const rawHints =
|
|
538
|
+
): string {
|
|
539
|
+
const rawHints = resolveCallHints(sessionContext, profile.hints);
|
|
550
540
|
|
|
551
541
|
const speechConfig: TwilioRelaySpeechConfig = {
|
|
552
542
|
transcriptionProvider: sttAttrs.transcriptionProvider,
|
package/src/channels/types.ts
CHANGED
|
@@ -1,16 +1,26 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
export const CHANNEL_IDS = [
|
|
2
|
+
"telegram",
|
|
3
|
+
"phone",
|
|
4
|
+
"vellum",
|
|
5
|
+
"whatsapp",
|
|
6
|
+
"slack",
|
|
7
|
+
"email",
|
|
8
|
+
"platform",
|
|
9
|
+
"a2a",
|
|
10
|
+
] as const;
|
|
6
11
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
12
|
+
export type ChannelId = (typeof CHANNEL_IDS)[number];
|
|
13
|
+
|
|
14
|
+
export function isChannelId(value: unknown): value is ChannelId {
|
|
15
|
+
return (
|
|
16
|
+
typeof value === "string" &&
|
|
17
|
+
(CHANNEL_IDS as readonly string[]).includes(value)
|
|
18
|
+
);
|
|
19
|
+
}
|
|
11
20
|
|
|
12
21
|
export function parseChannelId(value: unknown): ChannelId | null {
|
|
13
|
-
|
|
22
|
+
if (isChannelId(value)) return value;
|
|
23
|
+
return null;
|
|
14
24
|
}
|
|
15
25
|
|
|
16
26
|
export interface TurnChannelContext {
|
|
@@ -88,15 +88,8 @@ mock.module("../../../util/logger.js", () => ({
|
|
|
88
88
|
}));
|
|
89
89
|
|
|
90
90
|
mock.module("../../lib/cache-fs.js", () => ({
|
|
91
|
-
readFileSync: (path: string
|
|
92
|
-
// Stdin must be read via fd 0, not by reopening "/dev/stdin": a spawned
|
|
93
|
-
// subprocess whose stdin is a pipe (Bun.spawn stdin:"pipe") cannot reopen
|
|
94
|
-
// its read-end by path — open("/dev/stdin") fails ENXIO. Throwing here on
|
|
95
|
-
// the path makes any regression to path-based reading fail loudly.
|
|
91
|
+
readFileSync: (path: string, encoding?: BufferEncoding) => {
|
|
96
92
|
if (path === "/dev/stdin") {
|
|
97
|
-
throw new Error("ENXIO: no such device or address, open '/dev/stdin'");
|
|
98
|
-
}
|
|
99
|
-
if (path === 0) {
|
|
100
93
|
if (mockStdinContent === null) {
|
|
101
94
|
throw new Error("EAGAIN: resource temporarily unavailable");
|
|
102
95
|
}
|