


























@@ -2,9 +2,11 @@
22import { afterEach, beforeEach, describe, expect, it } from "vitest";
33import {
44VoiceCallConfigSchema,
5+resolveVoiceCallAgentSessionKey,
56resolveTwilioAuthToken,
67resolveVoiceCallEffectiveConfig,
78resolveVoiceCallNumberRouteKey,
9+resolveVoiceCallNumberRouteKeyForCall,
810resolveVoiceCallSessionKey,
911validateProviderConfig,
1012normalizeVoiceCallConfig,
@@ -296,7 +298,23 @@ describe("resolveVoiceCallConfig session routing", () => {
296298callId: "call-123",
297299phone: "+1 (555) 000-1111",
298300}),
299-).toBe("voice:15550001111");
301+).toBe("agent:main:voice:15550001111");
302+});
303+304+it("scopes generated voice session keys by configured agent", () => {
305+const config = resolveVoiceCallConfig({
306+enabled: true,
307+provider: "mock",
308+agentId: "Voice",
309+});
310+311+expect(
312+resolveVoiceCallSessionKey({
313+ config,
314+callId: "CALL-123",
315+phone: "+1 (555) 000-1111",
316+}),
317+).toBe("agent:voice:voice:15550001111");
300318});
301319302320it("can scope voice sessions to each call", () => {
@@ -313,10 +331,10 @@ describe("resolveVoiceCallConfig session routing", () => {
313331callId: "call-123",
314332phone: "+1 (555) 000-1111",
315333}),
316-).toBe("voice:call:call-123");
334+).toBe("agent:main:voice:call:call-123");
317335});
318336319-it("preserves explicit voice session keys", () => {
337+it("scopes explicit voice session keys by configured agent", () => {
320338const config = resolveVoiceCallConfig({
321339enabled: true,
322340provider: "mock",
@@ -328,9 +346,135 @@ describe("resolveVoiceCallConfig session routing", () => {
328346 config,
329347callId: "call-123",
330348phone: "+1 (555) 000-1111",
331-explicitSessionKey: "meet-room-1",
349+explicitSessionKey: "Meet-Room-1",
350+}),
351+).toBe("agent:main:meet-room-1");
352+});
353+354+it("scopes persisted and explicit keys at the agent session boundary", () => {
355+const config = resolveVoiceCallConfig({
356+enabled: true,
357+provider: "mock",
358+agentId: "Voice",
359+});
360+361+expect(
362+resolveVoiceCallAgentSessionKey({
363+ config,
364+sessionKey: "voice:call:legacy-call",
365+}),
366+).toBe("agent:voice:voice:call:legacy-call");
367+expect(
368+resolveVoiceCallAgentSessionKey({
369+ config,
370+sessionKey: "meet-room-1",
371+}),
372+).toBe("agent:voice:meet-room-1");
373+expect(
374+resolveVoiceCallAgentSessionKey({
375+ config,
376+sessionKey: "agent:main:shared-room",
377+}),
378+).toBe("agent:voice:agent:main:shared-room");
379+expect(
380+resolveVoiceCallAgentSessionKey({
381+ config,
382+sessionKey: "agent:other:Matrix:Channel:!RoomAbC:example.org",
383+}),
384+).toBe("agent:voice:agent:other:matrix:channel:!RoomAbC:example.org");
385+expect(
386+resolveVoiceCallAgentSessionKey({
387+ config,
388+sessionKey: "agent:voice:agent:other:matrix:channel:!RoomAbC:example.org",
389+}),
390+).toBe("agent:voice:agent:other:matrix:channel:!RoomAbC:example.org");
391+expect(
392+resolveVoiceCallAgentSessionKey({
393+ config,
394+sessionKey: "Signal:Group:AbC123=",
395+}),
396+).toBe("agent:voice:signal:group:AbC123=");
397+expect(
398+resolveVoiceCallAgentSessionKey({
399+ config,
400+sessionKey: "agent:broken",
401+}),
402+).toBe("agent:voice:agent:broken");
403+expect(
404+resolveVoiceCallAgentSessionKey({
405+ config,
406+sessionKey: "agent::broken",
407+}),
408+).toBe("agent:voice:agent::broken");
409+expect(
410+resolveVoiceCallAgentSessionKey({
411+ config,
412+sessionKey: "agent::Matrix:Channel:!RoomAbC:example.org",
413+}),
414+).toBe("agent:voice:agent::matrix:channel:!RoomAbC:example.org");
415+expect(
416+resolveVoiceCallAgentSessionKey({
417+ config,
418+sessionKey: "agent:other:room::part",
419+}),
420+).toBe("agent:voice:agent:other:room::part");
421+expect(
422+resolveVoiceCallAgentSessionKey({
423+ config,
424+sessionKey: "agent:voice:room::part",
425+}),
426+).toBe("agent:voice:room::part");
427+expect(
428+resolveVoiceCallAgentSessionKey({
429+ config,
430+sessionKey: "agent:voice::Matrix:Channel:!RoomAbC:example.org",
431+}),
432+).toBe("agent:voice:agent:voice::matrix:channel:!RoomAbC:example.org");
433+expect(
434+resolveVoiceCallAgentSessionKey({
435+ config,
436+sessionKey: "agent:bad/id:room",
437+}),
438+).toBe("agent:voice:agent:bad/id:room");
439+});
440+441+it("canonicalizes raw and scoped main aliases with the core session config", () => {
442+const config = resolveVoiceCallConfig({
443+enabled: true,
444+provider: "mock",
445+agentId: "Voice",
446+});
447+448+for (const sessionKey of ["main", "agent:voice:main"]) {
449+expect(
450+resolveVoiceCallAgentSessionKey({
451+ config,
452+ sessionKey,
453+coreSession: { mainKey: "work" },
454+}),
455+).toBe("agent:voice:work");
456+}
457+expect(
458+resolveVoiceCallAgentSessionKey({
459+ config,
460+sessionKey: "main",
461+coreSession: { scope: "global" },
462+}),
463+).toBe("global");
464+expect(
465+resolveVoiceCallAgentSessionKey({
466+ config,
467+sessionKey: "agent:main:main",
468+coreSession: { mainKey: "work" },
469+}),
470+).toBe("agent:voice:agent:main:main");
471+expect(
472+resolveVoiceCallAgentSessionKey({
473+ config,
474+sessionKey: "agent:main:main",
475+coreSession: { scope: "global" },
332476}),
333-).toBe("meet-room-1");
477+).toBe("agent:voice:agent:main:main");
334478});
335479336480it("resolves per-number inbound route overrides over global voice settings", () => {
@@ -395,6 +539,35 @@ describe("resolveVoiceCallConfig session routing", () => {
395539expect(effective.config).toBe(config);
396540expect(effective.config.inboundGreeting).toBe("Hello from global.");
397541});
542+543+it("uses dialed-number fallback only for inbound calls", () => {
544+expect(
545+resolveVoiceCallNumberRouteKeyForCall({
546+direction: "inbound",
547+to: "+15550001111",
548+}),
549+).toBe("+15550001111");
550+expect(
551+resolveVoiceCallNumberRouteKeyForCall({
552+direction: "outbound",
553+to: "+15550001111",
554+}),
555+).toBeUndefined();
556+expect(
557+resolveVoiceCallNumberRouteKeyForCall({
558+direction: "inbound",
559+to: "+15550001111",
560+metadata: { numberRouteKey: "+15550002222" },
561+}),
562+).toBe("+15550002222");
563+expect(
564+resolveVoiceCallNumberRouteKeyForCall({
565+direction: "outbound",
566+to: "+15550001111",
567+metadata: { numberRouteKey: "+15550002222" },
568+}),
569+).toBeUndefined();
570+});
398571});
399572400573describe("normalizeVoiceCallConfig", () => {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。