Skip to content

Commit f118da6

Browse files
authored
Agent SDK - ported on top of components-js primitives (#1207)
1 parent 2c299fb commit f118da6

34 files changed

+4900
-763
lines changed

.changeset/spotty-squids-search.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@livekit/components-react': patch
3+
'@livekit/components-core': patch
4+
---
5+
6+
Add initial version of agents sdk (useSession, etc)

packages/core/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
},
4646
"devDependencies": {
4747
"@livekit/components-styles": "workspace:*",
48-
"@livekit/protocol": "^1.38.0",
48+
"@livekit/protocol": "catalog:",
4949
"@microsoft/api-extractor": "^7.36.0",
5050
"@size-limit/file": "^11.0.2",
5151
"@size-limit/webpack": "^11.0.2",

packages/core/src/components/chat.ts

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* eslint-disable camelcase */
2-
import type { Participant, Room, ChatMessage, SendTextOptions } from 'livekit-client';
2+
import type { Room, SendTextOptions } from 'livekit-client';
33
import { compareVersions, RoomEvent } from 'livekit-client';
44
import { BehaviorSubject, Subject, scan, map, takeUntil, from, filter } from 'rxjs';
55
import {
@@ -9,15 +9,10 @@ import {
99
setupDataMessageHandler,
1010
} from '../observables/dataChannel';
1111
import { log } from '../logger';
12+
import { ChatMessage, ReceivedChatMessage } from '../messages/types';
1213

1314
/** @public */
14-
export type { ChatMessage };
15-
16-
/** @public */
17-
export interface ReceivedChatMessage extends ChatMessage {
18-
from?: Participant;
19-
attributes?: Record<string, string>;
20-
}
15+
export type { ChatMessage, ReceivedChatMessage };
2116

2217
export interface LegacyChatMessage extends ChatMessage {
2318
ignoreLegacy?: boolean;
@@ -55,7 +50,9 @@ function isIgnorableChatMessage(msg: ReceivedChatMessage | LegacyReceivedChatMes
5550
}
5651

5752
const decodeLegacyMsg = (message: Uint8Array) =>
58-
JSON.parse(new TextDecoder().decode(message)) as LegacyReceivedChatMessage | ReceivedChatMessage;
53+
JSON.parse(new TextDecoder().decode(message)) as
54+
| LegacyReceivedChatMessage
55+
| Exclude<ReceivedChatMessage, 'type'>;
5956

6057
const encodeLegacyMsg = (message: LegacyChatMessage) =>
6158
new TextEncoder().encode(JSON.stringify(message));
@@ -93,8 +90,9 @@ export function setupChat(room: Room, options?: ChatOptions) {
9390
timestamp,
9491
message: chunk,
9592
from: room.getParticipantByIdentity(participantInfo.identity),
93+
type: 'chatMessage',
9694
// editTimestamp: type === 'update' ? timestamp : undefined,
97-
} as ReceivedChatMessage;
95+
} satisfies ReceivedChatMessage;
9896
}),
9997
);
10098
streamObservable.subscribe({
@@ -111,7 +109,11 @@ export function setupChat(room: Room, options?: ChatOptions) {
111109
if (isIgnorableChatMessage(parsedMessage)) {
112110
return undefined;
113111
}
114-
const newMessage: ReceivedChatMessage = { ...parsedMessage, from: msg.from };
112+
const newMessage: ReceivedChatMessage = {
113+
...parsedMessage,
114+
type: 'chatMessage',
115+
from: msg.from,
116+
};
115117
return newMessage;
116118
}),
117119
filter((msg) => !!msg),
@@ -169,6 +171,7 @@ export function setupChat(room: Room, options?: ChatOptions) {
169171

170172
const receivedChatMsg: ReceivedChatMessage = {
171173
...chatMsg,
174+
type: 'chatMessage',
172175
from: room.localParticipant,
173176
attributes: options.attributes,
174177
};

packages/core/src/components/textStream.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { RoomEvent, type Room } from 'livekit-client';
22
import type { TextStreamInfo } from 'livekit-client/dist/src/room/types';
33
import { from, scan, Subject, type Observable } from 'rxjs';
44
import { share, tap } from 'rxjs/operators';
5+
import { ParticipantAgentAttributes } from '../helper';
56

67
export interface TextStreamData {
78
text: string;
@@ -57,7 +58,7 @@ export function setupTextStream(room: Room, topic: string): Observable<TextStrea
5758
const textStreamsSubject = new Subject<TextStreamData[]>();
5859
let textStreams: TextStreamData[] = [];
5960

60-
const segmentAttribute = 'lk.segment_id';
61+
const segmentAttribute = ParticipantAgentAttributes.TranscriptionSegmentId;
6162

6263
// Create shared observable and store in cache
6364
const sharedObservable = textStreamsSubject.pipe(

packages/core/src/helper/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ export {
1313
export { setDifference } from './set-helper';
1414
export { supportsScreenSharing } from './featureDetection';
1515
export * from './transcriptions';
16+
export * from './participant-attributes';
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/** An enum of first party livekit attributes generated by the serverside agents sdk */
2+
export enum ParticipantAgentAttributes {
3+
AgentState = 'lk.agent.state',
4+
PublishOnBehalf = 'lk.publish_on_behalf',
5+
6+
TranscriptionFinal = 'lk.transcription_final',
7+
TranscriptionSegmentId = 'lk.segment_id',
8+
TranscribedTrackId = 'lk.transcribed_track_id',
9+
}

packages/core/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ export * from './helper';
44
export * from './types';
55
export * from './sorting';
66
export * from './track-reference';
7+
export * from './messages';
78

89
export * from './components/mediaToggle';
910
export * from './components/mediaDeviceSelect';
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './types';
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import type { Participant, ChatMessage } from 'livekit-client';
2+
3+
/** @public */
4+
export type { ChatMessage };
5+
6+
export type SentMessage = ChatMessage;
7+
8+
type ReceivedMessageWithType<Type extends string, Metadata extends object = object> = {
9+
id: string;
10+
timestamp: number;
11+
12+
type: Type;
13+
14+
from?: Participant;
15+
attributes?: Record<string, string>;
16+
} & Metadata;
17+
18+
/** @public */
19+
export type ReceivedChatMessage = ReceivedMessageWithType<
20+
'chatMessage',
21+
ChatMessage & {
22+
from?: Participant;
23+
attributes?: Record<string, string>;
24+
}
25+
>;
26+
27+
export type ReceivedUserTranscriptionMessage = ReceivedMessageWithType<
28+
'userTranscript',
29+
{
30+
message: string;
31+
}
32+
>;
33+
34+
export type ReceivedAgentTranscriptionMessage = ReceivedMessageWithType<
35+
'agentTranscript',
36+
{
37+
message: string;
38+
}
39+
>;
40+
41+
/** @public */
42+
export type ReceivedMessage =
43+
| ReceivedUserTranscriptionMessage
44+
| ReceivedAgentTranscriptionMessage
45+
| ReceivedChatMessage;
46+
// TODO: images? attachments? rpc?

packages/core/src/observables/dataChannel.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,12 @@ export function setupChatMessageHandler(room: Room) {
9292
const send = async (text: string, options: SendTextOptions): Promise<ReceivedChatMessage> => {
9393
const msg = await room.localParticipant.sendChatMessage(text, options);
9494
await room.localParticipant.sendText(text, options);
95-
return { ...msg, from: room.localParticipant, attachedFiles: options.attachments };
95+
return {
96+
...msg,
97+
type: 'chatMessage',
98+
from: room.localParticipant,
99+
attachedFiles: options.attachments,
100+
};
96101
};
97102

98103
const edit = async (text: string, originalMsg: ChatMessage) => {

0 commit comments

Comments
 (0)