Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 61 additions & 41 deletions ARCHITECTURE.md

Large diffs are not rendered by default.

835 changes: 835 additions & 0 deletions assistant/src/__tests__/call-controller.test.ts

Large diffs are not rendered by default.

1,496 changes: 0 additions & 1,496 deletions assistant/src/__tests__/call-orchestrator.test.ts

This file was deleted.

48 changes: 24 additions & 24 deletions assistant/src/__tests__/call-state.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,19 @@ import {
registerCallCompletionNotifier,
unregisterCallCompletionNotifier,
fireCallCompletionNotifier,
registerCallOrchestrator,
unregisterCallOrchestrator,
getCallOrchestrator,
registerCallController,
unregisterCallController,
getCallController,
} from '../calls/call-state.js';
import type { CallOrchestrator } from '../calls/call-orchestrator.js';
import type { CallController } from '../calls/call-controller.js';

describe('call-state', () => {
// Clean up notifiers between tests
beforeEach(() => {
unregisterCallQuestionNotifier('test-conv');
unregisterCallTranscriptNotifier('test-conv');
unregisterCallCompletionNotifier('test-conv');
unregisterCallOrchestrator('test-session');
unregisterCallController('test-session');
});

// ── Question notifiers ────────────────────────────────────────────
Expand Down Expand Up @@ -135,40 +135,40 @@ describe('call-state', () => {
fireCallCompletionNotifier('unregistered-conv', 'session-1');
});

// ── Orchestrator registry ─────────────────────────────────────────
// ── Controller registry ─────────────────────────────────────────

test('registerCallOrchestrator + getCallOrchestrator: retrieves orchestrator', () => {
const fakeOrchestrator = { id: 'fake-orch' } as unknown as CallOrchestrator;
test('registerCallController + getCallController: retrieves controller', () => {
const fakeController = { id: 'fake-ctrl' } as unknown as CallController;

registerCallOrchestrator('test-session', fakeOrchestrator);
registerCallController('test-session', fakeController);

const retrieved = getCallOrchestrator('test-session');
expect(retrieved).toBe(fakeOrchestrator);
const retrieved = getCallController('test-session');
expect(retrieved).toBe(fakeController);
});

test('unregisterCallOrchestrator: getCallOrchestrator returns undefined after unregister', () => {
const fakeOrchestrator = { id: 'fake-orch-2' } as unknown as CallOrchestrator;
test('unregisterCallController: getCallController returns undefined after unregister', () => {
const fakeController = { id: 'fake-ctrl-2' } as unknown as CallController;

registerCallOrchestrator('test-session', fakeOrchestrator);
unregisterCallOrchestrator('test-session');
registerCallController('test-session', fakeController);
unregisterCallController('test-session');

const retrieved = getCallOrchestrator('test-session');
const retrieved = getCallController('test-session');
expect(retrieved).toBeUndefined();
});

test('getCallOrchestrator returns undefined for unregistered session', () => {
const retrieved = getCallOrchestrator('nonexistent-session');
test('getCallController returns undefined for unregistered session', () => {
const retrieved = getCallController('nonexistent-session');
expect(retrieved).toBeUndefined();
});

test('registering a new orchestrator for same session overwrites the previous one', () => {
const first = { id: 'first' } as unknown as CallOrchestrator;
const second = { id: 'second' } as unknown as CallOrchestrator;
test('registering a new controller for same session overwrites the previous one', () => {
const first = { id: 'first' } as unknown as CallController;
const second = { id: 'second' } as unknown as CallController;

registerCallOrchestrator('test-session', first);
registerCallOrchestrator('test-session', second);
registerCallController('test-session', first);
registerCallController('test-session', second);

const retrieved = getCallOrchestrator('test-session');
const retrieved = getCallController('test-session');
expect(retrieved).toBe(second);
});
});
18 changes: 9 additions & 9 deletions assistant/src/__tests__/relay-server.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -263,8 +263,8 @@ describe('relay-server', () => {
const connectedEvents = events.filter(e => e.eventType === 'call_connected');
expect(connectedEvents.length).toBe(1);

// Verify orchestrator was created
expect(relay.getOrchestrator()).not.toBeNull();
// Verify controller was created
expect(relay.getController()).not.toBeNull();

relay.destroy();
});
Expand Down Expand Up @@ -815,11 +815,11 @@ describe('relay-server', () => {
to: '+15552222222',
}));

expect(relay.getOrchestrator()).not.toBeNull();
expect(relay.getController()).not.toBeNull();

relay.destroy();

expect(relay.getOrchestrator()).toBeNull();
expect(relay.getController()).toBeNull();
});

test('destroy: can be called multiple times without error', () => {
Expand Down Expand Up @@ -1145,7 +1145,7 @@ describe('relay-server', () => {
to: '+15551111111',
}));

const runtimeContext = (relay.getOrchestrator() as unknown as { guardianContext?: { sourceChannel?: string; actorRole?: string; guardianExternalUserId?: string } })?.guardianContext;
const runtimeContext = (relay.getController() as unknown as { guardianContext?: { sourceChannel?: string; actorRole?: string; guardianExternalUserId?: string } })?.guardianContext;
expect(runtimeContext?.sourceChannel).toBe('voice');
expect(runtimeContext?.actorRole).toBe('guardian');
expect(runtimeContext?.guardianExternalUserId).toBe('+15550001111');
Expand Down Expand Up @@ -1181,7 +1181,7 @@ describe('relay-server', () => {
to: '+15551111111',
}));

const runtimeContext = (relay.getOrchestrator() as unknown as {
const runtimeContext = (relay.getController() as unknown as {
guardianContext?: {
sourceChannel?: string;
actorRole?: string;
Expand All @@ -1197,7 +1197,7 @@ describe('relay-server', () => {
relay.destroy();
});

test('inbound guardian verification updates orchestrator context to guardian', async () => {
test('inbound guardian verification updates controller context to guardian', async () => {
ensureConversation('conv-guardian-context-upgrade');
const session = createCallSession({
conversationId: 'conv-guardian-context-upgrade',
Expand All @@ -1219,7 +1219,7 @@ describe('relay-server', () => {
to: session.toNumber,
}));

const preVerify = (relay.getOrchestrator() as unknown as {
const preVerify = (relay.getController() as unknown as {
guardianContext?: { actorRole?: string };
})?.guardianContext;
expect(preVerify?.actorRole).toBe('unverified_channel');
Expand All @@ -1233,7 +1233,7 @@ describe('relay-server', () => {

await new Promise((resolve) => setTimeout(resolve, 10));

const postVerify = (relay.getOrchestrator() as unknown as {
const postVerify = (relay.getController() as unknown as {
guardianContext?: { sourceChannel?: string; actorRole?: string; guardianExternalUserId?: string };
})?.guardianContext;
expect(postVerify?.sourceChannel).toBe('voice');
Expand Down
Loading