@vellumai/assistant 0.11.3 → 0.11.4-staging.1
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 +11 -6
- package/docs/architecture/memory.md +11 -0
- package/docs/architecture/turn-actor.md +70 -0
- package/docs/flux-turn-detection-spike.md +243 -0
- package/docs/stt-provider-onboarding.md +3 -1
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/channels.ts +11 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/channels.ts +11 -0
- package/node_modules/@vellumai/gateway-client/src/admission-policy-contract.ts +34 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +2 -0
- package/node_modules/@vellumai/service-contracts/src/channels.ts +11 -0
- package/openapi.yaml +140 -38
- package/package.json +1 -1
- package/scripts/voice-ttft-spike.ts +3 -3
- package/src/__tests__/app-compiler.test.ts +38 -3
- package/src/__tests__/attachments-store.test.ts +21 -12
- package/src/__tests__/byok-default-profile-ensure.test.ts +2 -0
- package/src/__tests__/call-setup-flow-name-capture.test.ts +0 -1
- package/src/__tests__/call-site-routing-provider.test.ts +1 -1
- package/src/__tests__/channel-availability-routes.test.ts +14 -1
- package/src/__tests__/channel-capabilities-dedupe.test.ts +214 -0
- package/src/__tests__/channel-delivery-store.test.ts +14 -14
- package/src/__tests__/config-loader-backfill.test.ts +3 -3
- package/src/__tests__/config-schema.test.ts +25 -10
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +8 -11
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +8 -11
- package/src/__tests__/conversation-agent-loop.test.ts +28 -20
- package/src/__tests__/conversation-attention-store.test.ts +63 -0
- package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +0 -4
- package/src/__tests__/conversation-fork-crud.test.ts +69 -0
- package/src/__tests__/conversation-fork-referential.test.ts +67 -0
- package/src/__tests__/conversation-fork-retrospective.test.ts +24 -0
- package/src/__tests__/conversation-notifiers-provenance.test.ts +59 -0
- package/src/__tests__/conversation-queue.test.ts +55 -4
- package/src/__tests__/conversation-runtime-assembly.test.ts +134 -102
- package/src/__tests__/conversation-runtime-workspace.test.ts +14 -10
- package/src/__tests__/credential-prompt-route.test.ts +7 -10
- package/src/__tests__/custom-profile-ensure.test.ts +5 -1
- package/src/__tests__/discord-access-request-privacy.test.ts +5 -1
- package/src/__tests__/discord-requester-notice-privacy.test.ts +3 -3
- package/src/__tests__/document-append-idempotency.test.ts +233 -0
- package/src/__tests__/edit-propagation.test.ts +0 -7
- package/src/__tests__/helpers/mock-actor-context.ts +49 -0
- package/src/__tests__/helpers/mock-conversation.ts +13 -1
- package/src/__tests__/injector-chain.test.ts +63 -41
- package/src/__tests__/injector-disk-pressure.test.ts +11 -23
- package/src/__tests__/llm-context-resolution.test.ts +73 -1
- package/src/__tests__/llm-schema.test.ts +5 -2
- package/src/__tests__/mcp-list-plugin-servers.test.ts +250 -0
- package/src/__tests__/memory-retrieval-hook.test.ts +6 -5
- package/src/__tests__/messages-read-boundary-guard.test.ts +134 -0
- package/src/__tests__/mtime-cache.test.ts +1 -1
- package/src/__tests__/non-member-access-request.test.ts +0 -20
- package/src/__tests__/outbound-slack-persistence.test.ts +40 -1
- package/src/__tests__/plugin-import-boundary-guard.test.ts +5 -0
- package/src/__tests__/plugin-secret-pattern-contribution.test.ts +1 -1
- package/src/__tests__/post-compaction-reinjection-idempotency.test.ts +14 -7
- package/src/__tests__/provider-commit-message-generator.test.ts +20 -0
- package/src/__tests__/run-conversation-turn-persistence.test.ts +434 -105
- package/src/__tests__/scoped-approval-grants.test.ts +11 -6
- package/src/__tests__/secret-ingress-channel.test.ts +0 -1
- package/src/__tests__/skills.test.ts +32 -0
- package/src/__tests__/slack-edit-ordering-characterization.test.ts +0 -1
- package/src/__tests__/subagent-call-site-routing.test.ts +31 -19
- package/src/__tests__/subagent-spawn-and-await.test.ts +14 -10
- package/src/__tests__/turn-events-store.test.ts +43 -0
- package/src/__tests__/user-plugin-loader.test.ts +1 -1
- package/src/__tests__/visible-app-context.test.ts +16 -9
- package/src/__tests__/worker-entrypoint-guards.test.ts +54 -0
- package/src/__tests__/worker-plugin-surface.test.ts +77 -0
- package/src/__tests__/workspace-migration-142-consolidate-voice-front-door.test.ts +158 -0
- package/src/__tests__/workspace-migration-143-repair-deprecated-codex-model-id.test.ts +133 -0
- package/src/__tests__/workspace-migration-144-convert-stranded-subscription-openai-profiles.test.ts +316 -0
- package/src/__tests__/workspace-migration-145-collapse-profile-bindings-to-entries.test.ts +325 -0
- package/src/acp/__tests__/acp-claude-oauth.test.ts +10 -2
- package/src/acp/__tests__/auth-required.test.ts +161 -0
- package/src/acp/acp-claude-oauth.ts +19 -2
- package/src/acp/agent-process.test.ts +100 -0
- package/src/acp/agent-process.ts +29 -26
- package/src/acp/auth-required.ts +102 -0
- package/src/acp/session-manager.test.ts +119 -0
- package/src/acp/session-manager.ts +68 -2
- package/src/api/events/acp-auth-required.ts +55 -0
- package/src/api/index.ts +7 -0
- package/src/apps/app-store.ts +3 -0
- package/src/bundler/package-resolver.ts +2 -30
- package/src/calls/__tests__/voice-session-bridge.test.ts +173 -1
- package/src/calls/__tests__/voice-triage-escalate.test.ts +94 -0
- package/src/calls/call-controller.ts +9 -2
- package/src/calls/call-setup-flow.ts +0 -1
- package/src/calls/media-stream-stt-session.ts +15 -0
- package/src/calls/voice-session-bridge.ts +71 -16
- package/src/calls/voice-triage-escalate.ts +104 -2
- package/src/channels/__tests__/plugin-channel-declarations.test.ts +161 -0
- package/src/channels/config.ts +13 -0
- package/src/channels/plugin-channel-declarations.ts +108 -0
- package/src/channels/types.ts +30 -0
- package/src/cli/AGENTS.md +5 -2
- package/src/cli/commands/credentials.help.ts +2 -2
- package/src/cli/commands/inference-providers.ts +1 -1
- package/src/cli/commands/mcp.help.ts +13 -4
- package/src/cli/commands/mcp.ts +9 -0
- package/src/cli/commands/memory/__tests__/memory-v3.test.ts +128 -5
- package/src/cli/commands/memory/index.help.ts +43 -1
- package/src/cli/commands/memory/memory-v3.ts +64 -0
- package/src/cli/commands/stt.help.ts +27 -2
- package/src/cli/lib/__tests__/upgrade-plugin.test.ts +39 -0
- package/src/cli/lib/bundled-marketplace.json +13 -0
- package/src/cli/lib/upgrade-plugin.ts +42 -0
- package/src/config/__tests__/default-profile-catalog.test.ts +34 -2
- package/src/config/__tests__/default-provider.test.ts +6 -1
- package/src/config/__tests__/profile-materialization.test.ts +75 -19
- package/src/config/bundled-skills/acp/SKILL.md +6 -7
- package/src/config/bundled-skills/document-editor/SKILL.md +2 -2
- package/src/config/bundled-skills/document-editor/TOOLS.json +2 -2
- package/src/config/bundled-skills/media-processing/services/preprocess.ts +14 -4
- package/src/config/bundled-skills/settings/TOOLS.json +3 -3
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.test.ts +22 -1
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +9 -2
- package/src/config/call-site-defaults.ts +4 -5
- package/src/config/default-profile-catalog.ts +82 -11
- package/src/config/default-profile-names.ts +4 -1
- package/src/config/default-provider-resolution.ts +4 -0
- package/src/config/llm-context-resolution.ts +11 -3
- package/src/config/llm-resolver.ts +28 -1
- package/src/config/profile-materialization.ts +70 -22
- package/src/config/schemas/__tests__/live-voice.test.ts +107 -4
- package/src/config/schemas/call-site-catalog.ts +4 -4
- package/src/config/schemas/live-voice.ts +57 -23
- package/src/config/schemas/llm.ts +59 -32
- package/src/config/schemas/mcp.ts +23 -0
- package/src/config/schemas/plugin-updates.ts +6 -2
- package/src/config/schemas/stt.ts +1 -0
- package/src/context/outbound-sanitize.ts +96 -1
- package/src/daemon/__tests__/plugin-mcp-reconcile.test.ts +82 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +15 -10
- package/src/daemon/conversation-agent-loop.ts +17 -6
- package/src/daemon/conversation-messaging.ts +5 -1
- package/src/daemon/conversation-notifiers.ts +9 -1
- package/src/daemon/conversation-process.ts +9 -6
- package/src/daemon/conversation-runtime-assembly.ts +3 -4
- package/src/daemon/conversation-tool-setup.ts +1 -2
- package/src/daemon/conversation.ts +48 -0
- package/src/daemon/mcp-reload-service.ts +36 -6
- package/src/daemon/process-message.ts +13 -3
- package/src/daemon/providers-setup.ts +6 -3
- package/src/daemon/trust-context-types.ts +29 -0
- package/src/daemon/wake-conversation-ops.ts +3 -2
- package/src/documents/document-store.ts +138 -5
- package/src/hooks/hook-loader.ts +3 -3
- package/src/hooks/registry.ts +50 -6
- package/src/inbound/__tests__/oauth-callback-url.test.ts +83 -0
- package/src/inbound/oauth-callback-url.ts +61 -0
- package/src/live-voice/__tests__/live-voice-agent-turn.test.ts +1 -104
- package/src/live-voice/__tests__/live-voice-events.test.ts +7 -8
- package/src/live-voice/__tests__/live-voice-flux-turn-end.test.ts +932 -0
- package/src/live-voice/__tests__/live-voice-metrics.test.ts +115 -8
- package/src/live-voice/__tests__/live-voice-photo.test.ts +100 -0
- package/src/live-voice/__tests__/live-voice-progress.test.ts +60 -194
- package/src/live-voice/__tests__/live-voice-stt.test.ts +14 -0
- package/src/live-voice/__tests__/live-voice-triage-escalate.test.ts +29 -0
- package/src/live-voice/__tests__/live-voice-tts-session.test.ts +0 -483
- package/src/live-voice/__tests__/live-voice-vad.test.ts +0 -16
- package/src/live-voice/__tests__/progress-narration.test.ts +214 -0
- package/src/live-voice/live-voice-archive.ts +2 -0
- package/src/live-voice/live-voice-metrics.ts +57 -32
- package/src/live-voice/live-voice-photo.ts +1 -2
- package/src/live-voice/live-voice-session.ts +535 -314
- package/src/live-voice/progress-narration.ts +277 -0
- package/src/live-voice/protocol.ts +21 -1
- package/src/mcp/__tests__/effective-config.test.ts +238 -0
- package/src/mcp/__tests__/mcp-auth-orchestrator.test.ts +0 -1
- package/src/mcp/__tests__/mcp-oauth-client-registration.test.ts +200 -0
- package/src/mcp/__tests__/mcp-oauth-provider.test.ts +9 -9
- package/src/mcp/__tests__/plugin-server-credential-isolation.test.ts +95 -0
- package/src/mcp/client.ts +16 -11
- package/src/mcp/effective-config.ts +113 -0
- package/src/mcp/manager.ts +11 -6
- package/src/mcp/mcp-auth-orchestrator.ts +13 -22
- package/src/mcp/mcp-oauth-provider.ts +205 -240
- package/src/monitoring/__tests__/plugin-auto-update.test.ts +166 -3
- package/src/monitoring/plugin-auto-update.ts +128 -24
- package/src/notifications/signal.ts +1 -0
- package/src/permissions/confirmation-guardian-request.test.ts +15 -11
- package/src/permissions/confirmation-guardian-request.ts +2 -2
- package/src/permissions/question-guardian-request.test.ts +14 -6
- package/src/permissions/question-guardian-request.ts +1 -2
- package/src/persistence/attachments-store.ts +8 -1
- package/src/persistence/bookmark-crud.ts +3 -7
- package/src/persistence/conversation-attention-store.ts +16 -45
- package/src/persistence/conversation-crud.ts +33 -4
- package/src/persistence/conversation-lineage.ts +9 -0
- package/src/persistence/conversation-queries.ts +108 -41
- package/src/persistence/delivery-crud.ts +38 -29
- package/src/persistence/external-conversation-store.ts +32 -4
- package/src/persistence/llm-request-log-store.ts +4 -10
- package/src/persistence/llm-usage-store.ts +8 -3
- package/src/persistence/message-reads.test.ts +197 -0
- package/src/persistence/message-reads.ts +211 -0
- package/src/persistence/migrations/366-chatgpt-subscription-row-identity.test.ts +120 -0
- package/src/persistence/migrations/366-chatgpt-subscription-row-identity.ts +62 -0
- package/src/persistence/real-user-turn-filter.ts +27 -3
- package/src/persistence/steps.ts +9 -0
- package/src/plugin-api/__tests__/oauth-callback-url-export.test.ts +29 -0
- package/src/plugin-api/conversation-turn.ts +168 -5
- package/src/plugin-api/index.ts +21 -5
- package/src/plugins/__tests__/mcp-servers.test.ts +371 -0
- package/src/plugins/defaults/memory/AGENTS.md +4 -0
- package/src/plugins/defaults/memory/__tests__/buffer-format.test.ts +204 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-accounting.test.ts +72 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +4 -1
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-provider-path.test.ts +4 -1
- package/src/plugins/defaults/memory/buffer-format.ts +165 -0
- package/src/plugins/defaults/memory/context-search/sources/conversations.ts +6 -0
- package/src/plugins/defaults/memory/graph/image-ref-utils.ts +3 -0
- package/src/plugins/defaults/memory/graph/tool-handlers.ts +1 -30
- package/src/plugins/defaults/memory/graph-topology/pending-buffer.test.ts +34 -0
- package/src/plugins/defaults/memory/graph-topology/pending-buffer.ts +8 -12
- package/src/plugins/defaults/memory/hooks/post-compact.ts +1 -4
- package/src/plugins/defaults/memory/indexer.ts +3 -1
- package/src/plugins/defaults/memory/memory-retrospective-accounting.ts +19 -7
- package/src/plugins/defaults/memory/src/__tests__/memory-v3-gate-stats.test.ts +281 -0
- package/src/plugins/defaults/memory/src/memory-v3-routes.ts +207 -0
- package/src/plugins/defaults/memory/substrate/__tests__/consolidation-job.test.ts +33 -0
- package/src/plugins/defaults/memory/substrate/__tests__/static-context.test.ts +199 -2
- package/src/plugins/defaults/memory/substrate/consolidation-job.ts +25 -18
- package/src/plugins/defaults/memory/substrate/skill-content.ts +8 -1
- package/src/plugins/defaults/memory/substrate/static-context.ts +160 -4
- package/src/plugins/defaults/memory/substrate/sweep-job.ts +2 -4
- package/src/plugins/defaults/memory/v1/graph/extraction.ts +3 -1
- package/src/plugins/defaults/memory/v3/prune.ts +2 -0
- package/src/plugins/defaults/memory/v3/selection-log-store.ts +2 -0
- package/src/plugins/defaults/memory/worker.ts +6 -3
- package/src/plugins/external-plugin-loader.ts +47 -0
- package/src/plugins/mcp-servers.ts +361 -0
- package/src/plugins/mtime-cache.ts +23 -49
- package/src/plugins/worker-plugin-surface.ts +33 -0
- package/src/providers/__tests__/connection-model-compat.test.ts +1 -1
- package/src/providers/__tests__/dispatch-connection-routing.test.ts +214 -2
- package/src/providers/__tests__/preflight-resolved-config.test.ts +57 -0
- package/src/providers/__tests__/retry-callsite.test.ts +5 -2
- package/src/providers/call-site-routing.ts +30 -3
- package/src/providers/connection-resolution.ts +194 -11
- package/src/providers/inference/auth.ts +6 -0
- package/src/providers/inference/connection-availability.ts +24 -2
- package/src/providers/inference/connections.ts +2 -0
- package/src/providers/model-intents.ts +26 -6
- package/src/providers/openai/codex-models.ts +2 -1
- package/src/providers/provider-send-message.ts +32 -3
- package/src/providers/speech-to-text/__tests__/deepgram-flux-frames.test.ts +433 -0
- package/src/providers/speech-to-text/__tests__/deepgram-flux-realtime.test.ts +620 -0
- package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +34 -0
- package/src/providers/speech-to-text/__tests__/resolve.test.ts +285 -6
- package/src/providers/speech-to-text/deepgram-flux-frames.ts +395 -0
- package/src/providers/speech-to-text/deepgram-flux-realtime.ts +719 -0
- package/src/providers/speech-to-text/provider-catalog.ts +99 -8
- package/src/providers/speech-to-text/resolve.ts +25 -2
- package/src/routes/worker.ts +17 -5
- package/src/runtime/access-request-helper.ts +9 -12
- package/src/runtime/agent-wake.ts +3 -3
- package/src/runtime/pre-first-message-gate.ts +4 -0
- package/src/runtime/routes/__tests__/acp-claude-auth-routes.test.ts +12 -4
- package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +219 -1
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +52 -0
- package/src/runtime/routes/__tests__/default-provider-routes.test.ts +61 -0
- package/src/runtime/routes/__tests__/inference-profiles-routes.test.ts +44 -0
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +102 -1
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +44 -0
- package/src/runtime/routes/__tests__/stt-routes.test.ts +25 -0
- package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +62 -1
- package/src/runtime/routes/channel-availability-routes.ts +32 -14
- package/src/runtime/routes/channel-route-shared.ts +0 -6
- package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +6 -6
- package/src/runtime/routes/conversation-list-routes.ts +112 -1
- package/src/runtime/routes/conversation-query-routes.ts +40 -27
- package/src/runtime/routes/credential-prompt-routes.ts +4 -7
- package/src/runtime/routes/default-provider-routes.ts +15 -0
- package/src/runtime/routes/inbound-message-handler.ts +17 -41
- package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +0 -1
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +0 -9
- package/src/runtime/routes/inbound-stages/admission-policy.ts +1 -17
- package/src/runtime/routes/inbound-stages/bootstrap-intercept.test.ts +0 -1
- package/src/runtime/routes/inbound-stages/bootstrap-intercept.ts +2 -3
- package/src/runtime/routes/inbound-stages/edit-intercept.ts +1 -3
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +0 -1
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +3 -4
- package/src/runtime/routes/inbound-stages/reaction-intercept.test.ts +0 -1
- package/src/runtime/routes/inbound-stages/reaction-intercept.ts +11 -20
- package/src/runtime/routes/inbound-stages/secret-ingress-check.ts +2 -3
- package/src/runtime/routes/inference-profiles-routes.ts +20 -11
- package/src/runtime/routes/inference-provider-connection-routes.ts +77 -15
- package/src/runtime/routes/log-export-routes.ts +3 -0
- package/src/runtime/routes/mcp-auth-routes.ts +148 -57
- package/src/runtime/routes/plugins-routes.ts +21 -3
- package/src/runtime/routes/stt-routes.ts +31 -25
- package/src/runtime/routes/surface-conversation-resolver.ts +3 -0
- package/src/runtime/routes/user-route-dispatcher.ts +39 -14
- package/src/runtime/routes/user-route-import.ts +108 -0
- package/src/schedule/worker.ts +6 -0
- package/src/security/oauth2.ts +6 -22
- package/src/stt/__tests__/daemon-batch-transcriber.test.ts +22 -0
- package/src/stt/__tests__/types.test.ts +94 -0
- package/src/stt/daemon-batch-transcriber.ts +10 -0
- package/src/stt/stt-stream-session.ts +8 -4
- package/src/stt/types.ts +103 -0
- package/src/subagent/manager.ts +1 -3
- package/src/subagent/types.ts +7 -6
- package/src/tools/acp/spawn.test.ts +97 -0
- package/src/tools/acp/spawn.ts +32 -0
- package/src/tools/document/document-tool.ts +12 -3
- package/src/tools/registry.ts +2 -1
- package/src/tools/workflows/run-workflow.ts +1 -2
- package/src/tts/__tests__/reasoning-tag-filter.test.ts +63 -0
- package/src/tts/reasoning-tag-filter.ts +110 -0
- package/src/workspace/byok-default-profile-ensure.ts +61 -18
- package/src/workspace/custom-profile-ensure.ts +4 -24
- package/src/workspace/migrations/142-consolidate-voice-front-door.ts +70 -0
- package/src/workspace/migrations/143-repair-deprecated-codex-model-id.ts +134 -0
- package/src/workspace/migrations/144-convert-stranded-subscription-openai-profiles.ts +265 -0
- package/src/workspace/migrations/145-collapse-profile-bindings-to-entries.ts +328 -0
- package/src/workspace/migrations/__tests__/141-stt-english-default-to-multilingual.test.ts +0 -10
- package/src/workspace/migrations/registry.ts +8 -0
- package/src/workspace/provider-commit-message-generator.ts +7 -5
- package/src/live-voice/__tests__/front-decision.test.ts +0 -645
- package/src/live-voice/front-decision.ts +0 -476
|
@@ -2,6 +2,7 @@ import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
|
2
2
|
|
|
3
3
|
import { setConfig } from "../../../__tests__/helpers/set-config.js";
|
|
4
4
|
import { getConfig } from "../../../config/loader.js";
|
|
5
|
+
import { SttError } from "../../../stt/types.js";
|
|
5
6
|
|
|
6
7
|
// ---------------------------------------------------------------------------
|
|
7
8
|
// Mocks — must be declared before any subject imports
|
|
@@ -491,7 +492,12 @@ describe("resolveTelephonySttCapability", () => {
|
|
|
491
492
|
// Tests — telephony capability alignment with provider catalog
|
|
492
493
|
// ---------------------------------------------------------------------------
|
|
493
494
|
|
|
494
|
-
import {
|
|
495
|
+
import type { SttProviderId } from "../../../stt/types.js";
|
|
496
|
+
import {
|
|
497
|
+
getProviderEntry,
|
|
498
|
+
listProviderIds,
|
|
499
|
+
supportsBoundary,
|
|
500
|
+
} from "../provider-catalog.js";
|
|
495
501
|
|
|
496
502
|
describe("telephony capability catalog alignment", () => {
|
|
497
503
|
/**
|
|
@@ -502,6 +508,16 @@ describe("telephony capability catalog alignment", () => {
|
|
|
502
508
|
* misalignment early.
|
|
503
509
|
*/
|
|
504
510
|
|
|
511
|
+
/**
|
|
512
|
+
* Providers that deliberately sit out telephony (`telephonyMode: "none"`).
|
|
513
|
+
* `deepgram-flux` is a streaming-only spike, and telephony is out of its
|
|
514
|
+
* scope. Nothing reroutes a call to another provider, so opting out here
|
|
515
|
+
* means a Flux-configured assistant does not transcribe calls.
|
|
516
|
+
*/
|
|
517
|
+
const TELEPHONY_OPT_OUT: ReadonlySet<SttProviderId> = new Set([
|
|
518
|
+
"deepgram-flux",
|
|
519
|
+
]);
|
|
520
|
+
|
|
505
521
|
test("deepgram catalog entry has realtime-ws telephonyMode", () => {
|
|
506
522
|
const entry = getProviderEntry("deepgram");
|
|
507
523
|
expect(entry).toBeDefined();
|
|
@@ -535,18 +551,34 @@ describe("telephony capability catalog alignment", () => {
|
|
|
535
551
|
expect(entry!.credentialProvider).toBe("openai");
|
|
536
552
|
});
|
|
537
553
|
|
|
538
|
-
test("every catalog provider has a non-none telephonyMode", () => {
|
|
539
|
-
// The telephony capability resolver assumes
|
|
540
|
-
//
|
|
541
|
-
//
|
|
542
|
-
//
|
|
554
|
+
test("every catalog provider has a non-none telephonyMode unless it opts out", () => {
|
|
555
|
+
// The telephony capability resolver assumes known providers participate
|
|
556
|
+
// in telephony over the media-stream transport. A provider with
|
|
557
|
+
// telephonyMode: "none" is reported as unsupported, so opting out has to
|
|
558
|
+
// be a deliberate, listed choice rather than an oversight.
|
|
543
559
|
for (const id of listProviderIds()) {
|
|
544
560
|
const entry = getProviderEntry(id);
|
|
545
561
|
expect(entry).toBeDefined();
|
|
562
|
+
if (TELEPHONY_OPT_OUT.has(id)) {
|
|
563
|
+
expect(entry!.telephonyMode).toBe("none");
|
|
564
|
+
continue;
|
|
565
|
+
}
|
|
546
566
|
expect(entry!.telephonyMode).not.toBe("none");
|
|
547
567
|
}
|
|
548
568
|
});
|
|
549
569
|
|
|
570
|
+
test("telephony opt-out providers resolve as unsupported", async () => {
|
|
571
|
+
for (const id of TELEPHONY_OPT_OUT) {
|
|
572
|
+
const entry = getProviderEntry(id);
|
|
573
|
+
mockVellumAvailable = false;
|
|
574
|
+
mockProviderKeys = { [entry!.credentialProvider]: `test-key-${id}` };
|
|
575
|
+
applyConfig({ provider: id });
|
|
576
|
+
|
|
577
|
+
const result = await resolveTelephonySttCapability();
|
|
578
|
+
expect(result.status).toBe("unsupported");
|
|
579
|
+
}
|
|
580
|
+
});
|
|
581
|
+
|
|
550
582
|
// -----------------------------------------------------------------------
|
|
551
583
|
// Stable provider identity
|
|
552
584
|
// -----------------------------------------------------------------------
|
|
@@ -574,6 +606,9 @@ describe("telephony capability catalog alignment", () => {
|
|
|
574
606
|
};
|
|
575
607
|
|
|
576
608
|
for (const id of listProviderIds()) {
|
|
609
|
+
if (TELEPHONY_OPT_OUT.has(id)) {
|
|
610
|
+
continue;
|
|
611
|
+
}
|
|
577
612
|
const credKey = credentialMap[id];
|
|
578
613
|
expect(credKey).toBeDefined();
|
|
579
614
|
|
|
@@ -1383,6 +1418,250 @@ describe("resolveStreamingTranscriber language plumbing", () => {
|
|
|
1383
1418
|
});
|
|
1384
1419
|
});
|
|
1385
1420
|
|
|
1421
|
+
// ---------------------------------------------------------------------------
|
|
1422
|
+
// Tests: advertised streaming capability vs. what the factory can build
|
|
1423
|
+
// ---------------------------------------------------------------------------
|
|
1424
|
+
|
|
1425
|
+
describe("streaming capability matches the streaming factory", () => {
|
|
1426
|
+
/**
|
|
1427
|
+
* The catalog's `daemon-streaming` boundary is load-bearing in three
|
|
1428
|
+
* places that must never disagree:
|
|
1429
|
+
*
|
|
1430
|
+
* 1. `resolveConversationStreamingSttCapability`, which preflight reports
|
|
1431
|
+
* as `supported`.
|
|
1432
|
+
* 2. `resolveStreamingTranscriber`, which has to actually build an adapter.
|
|
1433
|
+
* 3. The two user-facing "streaming-capable providers" strings, which list
|
|
1434
|
+
* exactly `listProviderIds().filter(id => supportsBoundary(id,
|
|
1435
|
+
* "daemon-streaming"))`: `stt/stt-stream-session.ts` and
|
|
1436
|
+
* `live-voice/live-voice-session.ts`.
|
|
1437
|
+
*
|
|
1438
|
+
* A provider that is advertised by (1) and (3) but resolves to `null` in
|
|
1439
|
+
* (2) makes preflight lie and sends the session down the provider-error
|
|
1440
|
+
* path, and the error message it lands on names the very provider that
|
|
1441
|
+
* just failed as a supported alternative. This suite is the guard: every
|
|
1442
|
+
* advertised provider must build.
|
|
1443
|
+
*
|
|
1444
|
+
* `deepgram-flux-realtime.js` is deliberately NOT mocked in this file, so
|
|
1445
|
+
* the Flux case constructs the real adapter.
|
|
1446
|
+
*/
|
|
1447
|
+
const STREAMING_CREDENTIAL: Record<string, string> = {
|
|
1448
|
+
deepgram: "deepgram",
|
|
1449
|
+
"deepgram-flux": "deepgram",
|
|
1450
|
+
"google-gemini": "gemini",
|
|
1451
|
+
"openai-whisper": "openai",
|
|
1452
|
+
xai: "xai",
|
|
1453
|
+
// vellum's credential is the platform connection, mocked below.
|
|
1454
|
+
vellum: "vellum",
|
|
1455
|
+
};
|
|
1456
|
+
|
|
1457
|
+
/** The exact list both user-facing error strings advertise. */
|
|
1458
|
+
function advertisedStreamingProviders(): readonly SttProviderId[] {
|
|
1459
|
+
return listProviderIds().filter((id) =>
|
|
1460
|
+
supportsBoundary(id, "daemon-streaming"),
|
|
1461
|
+
);
|
|
1462
|
+
}
|
|
1463
|
+
|
|
1464
|
+
function seedCredentialsFor(id: SttProviderId): void {
|
|
1465
|
+
const credential = STREAMING_CREDENTIAL[id];
|
|
1466
|
+
expect(credential).toBeDefined();
|
|
1467
|
+
mockVellumAvailable = id === "vellum";
|
|
1468
|
+
mockVelayConnection =
|
|
1469
|
+
id === "vellum"
|
|
1470
|
+
? {
|
|
1471
|
+
wsBaseUrl: "ws://gateway.test",
|
|
1472
|
+
httpBaseUrl: "http://gateway.test",
|
|
1473
|
+
mintServiceToken: () => "vk-test",
|
|
1474
|
+
}
|
|
1475
|
+
: null;
|
|
1476
|
+
mockProviderKeys = id === "vellum" ? {} : { [credential!]: `key-${id}` };
|
|
1477
|
+
applyConfig({ provider: id });
|
|
1478
|
+
}
|
|
1479
|
+
|
|
1480
|
+
beforeEach(() => {
|
|
1481
|
+
mockVellumAvailable = false;
|
|
1482
|
+
mockVelayConnection = null;
|
|
1483
|
+
mockProviderKeys = {};
|
|
1484
|
+
loggerWarnings.length = 0;
|
|
1485
|
+
});
|
|
1486
|
+
|
|
1487
|
+
test("the advertised list includes deepgram-flux", () => {
|
|
1488
|
+
// Guards the suite below against passing vacuously: if Flux dropped out of
|
|
1489
|
+
// the advertised list, those loops would assert nothing about it.
|
|
1490
|
+
expect(advertisedStreamingProviders()).toContain("deepgram-flux");
|
|
1491
|
+
});
|
|
1492
|
+
|
|
1493
|
+
test("every advertised provider reports supported AND builds a transcriber", async () => {
|
|
1494
|
+
for (const id of advertisedStreamingProviders()) {
|
|
1495
|
+
seedCredentialsFor(id);
|
|
1496
|
+
|
|
1497
|
+
const capability = await resolveConversationStreamingSttCapability();
|
|
1498
|
+
expect(capability.status).toBe("supported");
|
|
1499
|
+
|
|
1500
|
+
const transcriber = await resolveStreamingTranscriber();
|
|
1501
|
+
expect(transcriber).not.toBeNull();
|
|
1502
|
+
expect(transcriber!.boundaryId).toBe("daemon-streaming");
|
|
1503
|
+
}
|
|
1504
|
+
});
|
|
1505
|
+
|
|
1506
|
+
test("every advertised provider reports missing credentials AND builds nothing without them", async () => {
|
|
1507
|
+
for (const id of advertisedStreamingProviders()) {
|
|
1508
|
+
mockVellumAvailable = false;
|
|
1509
|
+
mockVelayConnection = null;
|
|
1510
|
+
mockProviderKeys = {};
|
|
1511
|
+
applyConfig({ provider: id });
|
|
1512
|
+
|
|
1513
|
+
const capability = await resolveConversationStreamingSttCapability();
|
|
1514
|
+
expect(capability.status).toBe("missing-credentials");
|
|
1515
|
+
expect(await resolveStreamingTranscriber()).toBeNull();
|
|
1516
|
+
}
|
|
1517
|
+
});
|
|
1518
|
+
});
|
|
1519
|
+
|
|
1520
|
+
// ---------------------------------------------------------------------------
|
|
1521
|
+
// Tests: deepgram-flux streaming resolution
|
|
1522
|
+
// ---------------------------------------------------------------------------
|
|
1523
|
+
|
|
1524
|
+
describe("deepgram-flux streaming resolution", () => {
|
|
1525
|
+
beforeEach(() => {
|
|
1526
|
+
mockVellumAvailable = false;
|
|
1527
|
+
mockVelayConnection = null;
|
|
1528
|
+
mockProviderKeys = {};
|
|
1529
|
+
loggerWarnings.length = 0;
|
|
1530
|
+
});
|
|
1531
|
+
|
|
1532
|
+
test("resolves a real Flux transcriber on the shared Deepgram key", async () => {
|
|
1533
|
+
mockProviderKeys = { deepgram: "dg-key" };
|
|
1534
|
+
applyConfig({ provider: "deepgram-flux" });
|
|
1535
|
+
|
|
1536
|
+
const transcriber = await resolveStreamingTranscriber({
|
|
1537
|
+
sampleRate: 16_000,
|
|
1538
|
+
});
|
|
1539
|
+
|
|
1540
|
+
expect(transcriber).not.toBeNull();
|
|
1541
|
+
expect(transcriber!.providerId).toBe("deepgram-flux");
|
|
1542
|
+
expect(transcriber!.boundaryId).toBe("daemon-streaming");
|
|
1543
|
+
// Flux owns turn boundaries, so callers feature-detecting this method
|
|
1544
|
+
// must fall back to stop().
|
|
1545
|
+
expect(transcriber!.finalizeUtterance).toBeUndefined();
|
|
1546
|
+
});
|
|
1547
|
+
|
|
1548
|
+
test("resolves from an explicit providerId, the way live voice asks", async () => {
|
|
1549
|
+
// Live voice derives its provider itself and passes it in rather than
|
|
1550
|
+
// letting the resolver re-read config.
|
|
1551
|
+
mockProviderKeys = { deepgram: "dg-key" };
|
|
1552
|
+
applyConfig({ provider: "openai-whisper" });
|
|
1553
|
+
|
|
1554
|
+
const transcriber = await resolveStreamingTranscriber({
|
|
1555
|
+
providerId: "deepgram-flux",
|
|
1556
|
+
});
|
|
1557
|
+
|
|
1558
|
+
expect(transcriber?.providerId).toBe("deepgram-flux");
|
|
1559
|
+
});
|
|
1560
|
+
|
|
1561
|
+
test("resolves null without a Deepgram key", async () => {
|
|
1562
|
+
mockProviderKeys = { openai: "sk-key" };
|
|
1563
|
+
applyConfig({ provider: "deepgram-flux" });
|
|
1564
|
+
|
|
1565
|
+
expect(await resolveStreamingTranscriber()).toBeNull();
|
|
1566
|
+
});
|
|
1567
|
+
|
|
1568
|
+
test("telephony callers resolve to null without a Flux-specific conditional", async () => {
|
|
1569
|
+
// The catalog's telephonyMode: "none" is the only gate. Boundary-
|
|
1570
|
+
// requiring callers fall back to per-turn batch transcription.
|
|
1571
|
+
mockProviderKeys = { deepgram: "dg-key" };
|
|
1572
|
+
applyConfig({ provider: "deepgram-flux" });
|
|
1573
|
+
|
|
1574
|
+
const transcriber = await resolveStreamingTranscriber({
|
|
1575
|
+
utteranceBoundaryFinals: true,
|
|
1576
|
+
});
|
|
1577
|
+
|
|
1578
|
+
expect(transcriber).toBeNull();
|
|
1579
|
+
expect(loggerWarnings).toHaveLength(1);
|
|
1580
|
+
expect(
|
|
1581
|
+
(loggerWarnings[0]!.data as { providerId?: unknown }).providerId,
|
|
1582
|
+
).toBe("deepgram-flux");
|
|
1583
|
+
});
|
|
1584
|
+
|
|
1585
|
+
test("telephony capability reports Flux as unsupported", async () => {
|
|
1586
|
+
mockProviderKeys = { deepgram: "dg-key" };
|
|
1587
|
+
applyConfig({ provider: "deepgram-flux" });
|
|
1588
|
+
|
|
1589
|
+
const result = await resolveTelephonySttCapability();
|
|
1590
|
+
|
|
1591
|
+
expect(result.status).toBe("unsupported");
|
|
1592
|
+
});
|
|
1593
|
+
|
|
1594
|
+
test("diarize: 'required' rejects Flux rather than silently dropping labels", async () => {
|
|
1595
|
+
mockProviderKeys = { deepgram: "dg-key" };
|
|
1596
|
+
applyConfig({ provider: "deepgram-flux" });
|
|
1597
|
+
|
|
1598
|
+
const transcriber = await resolveStreamingTranscriber({
|
|
1599
|
+
diarize: "required",
|
|
1600
|
+
});
|
|
1601
|
+
|
|
1602
|
+
expect(transcriber).toBeNull();
|
|
1603
|
+
});
|
|
1604
|
+
});
|
|
1605
|
+
|
|
1606
|
+
// ---------------------------------------------------------------------------
|
|
1607
|
+
// Tests: batch resolution against a streaming-only provider
|
|
1608
|
+
// ---------------------------------------------------------------------------
|
|
1609
|
+
|
|
1610
|
+
describe("deepgram-flux batch resolution", () => {
|
|
1611
|
+
beforeEach(() => {
|
|
1612
|
+
mockVellumAvailable = false;
|
|
1613
|
+
mockVelayConnection = null;
|
|
1614
|
+
mockProviderKeys = {};
|
|
1615
|
+
loggerWarnings.length = 0;
|
|
1616
|
+
});
|
|
1617
|
+
|
|
1618
|
+
/**
|
|
1619
|
+
* Every batch caller pairs a `null` resolve with "no speech-to-text
|
|
1620
|
+
* provider is configured". Flux is configured, and the operator who set it
|
|
1621
|
+
* needs to be told which of the two Deepgram entries batch runs on, so the
|
|
1622
|
+
* resolver raises a typed error instead of returning that `null`.
|
|
1623
|
+
*/
|
|
1624
|
+
test("throws a named error rather than resolving null", async () => {
|
|
1625
|
+
mockProviderKeys = { deepgram: "dg-key" };
|
|
1626
|
+
applyConfig({ provider: "deepgram-flux" });
|
|
1627
|
+
|
|
1628
|
+
await expect(resolveBatchTranscriber()).rejects.toThrow(
|
|
1629
|
+
'Deepgram Flux is streaming-only. Batch transcription requires the deepgram provider: set services.stt.provider to "deepgram".',
|
|
1630
|
+
);
|
|
1631
|
+
});
|
|
1632
|
+
|
|
1633
|
+
test("marks the error user-facing so friendly copy does not overwrite it", async () => {
|
|
1634
|
+
mockProviderKeys = { deepgram: "dg-key" };
|
|
1635
|
+
applyConfig({ provider: "deepgram-flux" });
|
|
1636
|
+
|
|
1637
|
+
const err = await resolveBatchTranscriber().catch((e: unknown) => e);
|
|
1638
|
+
|
|
1639
|
+
expect(err).toBeInstanceOf(SttError);
|
|
1640
|
+
expect((err as SttError).category).toBe("provider-error");
|
|
1641
|
+
expect((err as SttError).userFacing).toBe(true);
|
|
1642
|
+
});
|
|
1643
|
+
|
|
1644
|
+
test("logs the gap so a degrading caller still leaves a daemon-side trace", async () => {
|
|
1645
|
+
mockProviderKeys = { deepgram: "dg-key" };
|
|
1646
|
+
applyConfig({ provider: "deepgram-flux" });
|
|
1647
|
+
|
|
1648
|
+
await resolveBatchTranscriber().catch(() => undefined);
|
|
1649
|
+
|
|
1650
|
+
expect(loggerWarnings).toHaveLength(1);
|
|
1651
|
+
expect(
|
|
1652
|
+
(loggerWarnings[0]!.data as { providerId?: unknown }).providerId,
|
|
1653
|
+
).toBe("deepgram-flux");
|
|
1654
|
+
});
|
|
1655
|
+
|
|
1656
|
+
test("a provider that is absent from the catalog still resolves null", async () => {
|
|
1657
|
+
// "Unknown provider" is a different situation from "known provider,
|
|
1658
|
+
// wrong boundary", and only the latter has a fix worth naming.
|
|
1659
|
+
applyConfig({ provider: "not-a-provider" });
|
|
1660
|
+
|
|
1661
|
+
expect(await resolveBatchTranscriber()).toBeNull();
|
|
1662
|
+
});
|
|
1663
|
+
});
|
|
1664
|
+
|
|
1386
1665
|
describe("sttCredentialGapReason", () => {
|
|
1387
1666
|
test("vellum gets connection copy; API-key providers keep key copy", () => {
|
|
1388
1667
|
expect(sttCredentialGapReason("vellum")).toContain("platform connect");
|