Skip to content

Commit e7c6c82

Browse files
Smidgeao-anam
andauthored
feat: add support for CLIENT_TOOL_EVENT data channel messages (#164)
Co-authored-by: Alex Osland <[email protected]>
1 parent 14c8b26 commit e7c6c82

File tree

11 files changed

+94
-10
lines changed

11 files changed

+94
-10
lines changed

src/modules/StreamingClient.ts

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,32 @@
1+
import {
2+
ClientMetricMeasurement,
3+
createRTCStatsReport,
4+
sendClientMetric,
5+
} from '../lib/ClientMetrics';
16
import {
27
EngineApiRestClient,
38
InternalEventEmitter,
49
PublicEventEmitter,
510
SignallingClient,
11+
ToolCallManager,
612
} from '../modules';
713
import {
814
AnamEvent,
9-
InputAudioState,
15+
ApiGatewayConfig,
1016
AudioPermissionState,
17+
ClientToolEvent,
18+
ConnectionClosedCode,
19+
DataChannelMessage,
20+
InputAudioState,
1121
InternalEvent,
1222
SignalMessage,
1323
SignalMessageAction,
1424
StreamingClientOptions,
25+
WebRtcClientToolEvent,
1526
WebRtcTextMessageEvent,
16-
ConnectionClosedCode,
17-
ApiGatewayConfig,
18-
DataChannelMessage,
1927
} from '../types';
2028
import { TalkMessageStream } from '../types/TalkMessageStream';
2129
import { TalkStreamInterruptedSignalMessage } from '../types/signalling/TalkStreamInterruptedSignalMessage';
22-
import {
23-
ClientMetricMeasurement,
24-
createRTCStatsReport,
25-
sendClientMetric,
26-
} from '../lib/ClientMetrics';
2730

2831
const SUCCESS_METRIC_POLLING_TIMEOUT_MS = 15000; // After this time we will stop polling for the first frame and consider the session a failure.
2932
const STATS_COLLECTION_INTERVAL_MS = 5000;
@@ -671,6 +674,22 @@ export class StreamingClient {
671674
message.data as WebRtcTextMessageEvent,
672675
);
673676
break;
677+
case DataChannelMessage.CLIENT_TOOL_EVENT:
678+
const webRtcToolEvent = message.data as WebRtcClientToolEvent;
679+
680+
this.internalEventEmitter.emit(
681+
InternalEvent.WEBRTC_CLIENT_TOOL_EVENT_RECEIVED,
682+
webRtcToolEvent,
683+
);
684+
const clientToolEvent =
685+
ToolCallManager.WebRTCClientToolEventToClientToolEvent(
686+
webRtcToolEvent,
687+
);
688+
this.publicEventEmitter.emit(
689+
AnamEvent.CLIENT_TOOL_EVENT_RECEIVED,
690+
clientToolEvent,
691+
);
692+
break;
674693
// Unknown message types are silently ignored to maintain forward compatibility
675694
default:
676695
break;

src/modules/ToolCallManager.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { ClientToolEvent, WebRtcClientToolEvent } from '../types/streaming';
2+
3+
export class ToolCallManager {
4+
/**
5+
* Converts a WebRtcClientToolEvent to a ClientToolEvent
6+
*/
7+
static WebRTCClientToolEventToClientToolEvent(
8+
webRtcEvent: WebRtcClientToolEvent,
9+
): ClientToolEvent {
10+
return {
11+
eventUid: webRtcEvent.event_uid,
12+
sessionId: webRtcEvent.session_id,
13+
eventName: webRtcEvent.event_name,
14+
eventData: webRtcEvent.event_data,
15+
timestamp: webRtcEvent.timestamp,
16+
timestampUserAction: webRtcEvent.timestamp_user_action,
17+
userActionCorrelationId: webRtcEvent.user_action_correlation_id,
18+
};
19+
}
20+
}

src/modules/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ export { InternalEventEmitter } from './InternalEventEmitter';
55
export { MessageHistoryClient } from './MessageHistoryClient';
66
export { PublicEventEmitter } from './PublicEventEmitter';
77
export { StreamingClient } from './StreamingClient';
8+
export { ToolCallManager } from './ToolCallManager';

src/types/events/internal/InternalEvent.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ export enum InternalEvent {
22
WEB_SOCKET_OPEN = 'WEB_SOCKET_OPEN',
33
SIGNAL_MESSAGE_RECEIVED = 'SIGNAL_MESSAGE_RECEIVED',
44
WEBRTC_CHAT_MESSAGE_RECEIVED = 'WEBRTC_CHAT_MESSAGE_RECEIVED',
5+
WEBRTC_CLIENT_TOOL_EVENT_RECEIVED = 'WEBRTC_CLIENT_TOOL_EVENT_RECEIVED',
56
}

src/types/events/internal/InternalEventCallbacks.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {
22
InternalEvent,
33
SignalMessage,
44
WebRtcTextMessageEvent,
5+
WebRtcClientToolEvent,
56
} from '../../index';
67

78
export type InternalEventCallbacks = {
@@ -12,4 +13,7 @@ export type InternalEventCallbacks = {
1213
[InternalEvent.WEBRTC_CHAT_MESSAGE_RECEIVED]: (
1314
message: WebRtcTextMessageEvent,
1415
) => void;
16+
[InternalEvent.WEBRTC_CLIENT_TOOL_EVENT_RECEIVED]: (
17+
webRtcToolEvent: WebRtcClientToolEvent,
18+
) => void;
1519
};

src/types/events/public/AnamEvent.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,5 @@ export enum AnamEvent {
1414
MIC_PERMISSION_GRANTED = 'MIC_PERMISSION_GRANTED',
1515
MIC_PERMISSION_DENIED = 'MIC_PERMISSION_DENIED',
1616
INPUT_AUDIO_DEVICE_CHANGED = 'INPUT_AUDIO_DEVICE_CHANGED',
17+
CLIENT_TOOL_EVENT_RECEIVED = 'CLIENT_TOOL_EVENT_RECEIVED',
1718
}

src/types/events/public/EventCallbacks.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
import { ConnectionClosedCode } from './ConnectionClosedCodes';
2-
import { Message, MessageStreamEvent, AnamEvent } from '../../index';
2+
import {
3+
Message,
4+
MessageStreamEvent,
5+
AnamEvent,
6+
ClientToolEvent,
7+
} from '../../index';
38

49
export type EventCallbacks = {
510
[AnamEvent.MESSAGE_HISTORY_UPDATED]: (messages: Message[]) => void;
@@ -22,4 +27,7 @@ export type EventCallbacks = {
2227
[AnamEvent.MIC_PERMISSION_GRANTED]: () => void;
2328
[AnamEvent.MIC_PERMISSION_DENIED]: (error: string) => void;
2429
[AnamEvent.INPUT_AUDIO_DEVICE_CHANGED]: (deviceId: string) => void;
30+
[AnamEvent.CLIENT_TOOL_EVENT_RECEIVED]: (
31+
clientToolEvent: ClientToolEvent,
32+
) => void;
2533
};
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
export interface ClientToolEvent {
2+
// Core event fields
3+
eventUid: string; // Unique ID for this event
4+
sessionId: string; // Session ID
5+
eventName: string; // The tool name (e.g., "redirect")
6+
eventData: Record<string, any>; // LLM-generated parameters
7+
8+
// Timing & correlation
9+
timestamp: string; // ISO timestamp when event was created
10+
timestampUserAction: string; // ISO timestamp of user action that triggered this
11+
userActionCorrelationId: string; // Correlation ID for tracking
12+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
export enum DataChannelMessage {
22
SPEECH_TEXT = 'speechText',
3+
CLIENT_TOOL_EVENT = 'clientToolEvent',
34
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
export interface WebRtcClientToolEvent {
2+
// Core event fields
3+
event_uid: string; // Unique ID for this event
4+
session_id: string; // Session ID
5+
event_name: string; // The tool name (e.g., "redirect")
6+
event_data: Record<string, any>; // LLM-generated parameters
7+
8+
// Timing & correlation
9+
timestamp: string; // ISO timestamp when event was created
10+
timestamp_user_action: string; // ISO timestamp of user action that triggered this
11+
user_action_correlation_id: string; // Correlation ID for tracking
12+
13+
// Metadata
14+
used_outside_engine: boolean; // Always true for client events
15+
}

0 commit comments

Comments
 (0)