Skip to content

Commit 4bb3f48

Browse files
committed
feat: rename agent.lifecycleState -> agent.state
This typing wise is very gross right now, since the name `AgentState` has already been claimed. So right now I'm calling my new agent state value "new state"... Not good.
1 parent 3a396bc commit 4bb3f48

File tree

1 file changed

+50
-51
lines changed

1 file changed

+50
-51
lines changed

packages/react/src/hooks/useAgent.ts

Lines changed: 50 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,20 @@ import { ConversationInstance } from './useConversationWith';
1414
const DEFAULT_AGENT_CONNECT_TIMEOUT_MILLISECONDS = 20_000;
1515

1616
/** State representing the current status of the agent, whether it is ready for speach, etc */
17-
export type AgentLifecycleState = 'unset' | 'initializing' | 'failed' | 'idle' | 'listening' | 'thinking' | 'speaking';
17+
export type AgentStateNew = 'unset' | 'initializing' | 'failed' | 'idle' | 'listening' | 'thinking' | 'speaking';
1818

1919
export enum AgentEvent {
2020
CameraChanged = 'cameraChanged',
2121
MicrophoneChanged = 'microphoneChanged',
2222
AttributesChanged = 'attributesChanged',
23-
ConversationalStateChanged = 'lifecycleStateChanged',
23+
StateChanged = 'lifecycleStateChanged',
2424
}
2525

2626
export type AgentCallbacks = {
2727
[AgentEvent.CameraChanged]: (newTrack: TrackReference<Track.Source.Camera, RemoteParticipant> | null) => void;
2828
[AgentEvent.MicrophoneChanged]: (newTrack: TrackReference<Track.Source.Microphone, RemoteParticipant> | null) => void;
2929
[AgentEvent.AttributesChanged]: (newAttributes: Record<string, string>) => void;
30-
[AgentEvent.ConversationalStateChanged]: (newAgentConversationalState: AgentLifecycleState) => void;
30+
[AgentEvent.StateChanged]: (newAgentState: AgentStateNew) => void;
3131
};
3232

3333
type AgentInstanceCommon = {
@@ -50,7 +50,7 @@ type AgentInstanceCommon = {
5050
};
5151

5252
type AgentStateAvailable = AgentInstanceCommon & {
53-
lifecycleState: "listening" | "thinking" | "speaking";
53+
state: "listening" | "thinking" | "speaking";
5454
failureReasons: null;
5555

5656
/** Is the agent ready for user interaction? */
@@ -61,7 +61,7 @@ type AgentStateAvailable = AgentInstanceCommon & {
6161
};
6262

6363
type AgentStateUnAvailable = AgentInstanceCommon & {
64-
lifecycleState: "unset" | "initializing" | "idle";
64+
state: "unset" | "initializing" | "idle";
6565
failureReasons: null;
6666

6767
/** Is the agent ready for user interaction? */
@@ -72,7 +72,7 @@ type AgentStateUnAvailable = AgentInstanceCommon & {
7272
};
7373

7474
type AgentStateFailed = AgentInstanceCommon & {
75-
lifecycleState: "failed";
75+
state: "failed";
7676
failureReasons: Array<string>;
7777

7878
/** Is the agent ready for user interaction? */
@@ -93,40 +93,40 @@ type AgentActions = {
9393
waitUntilMicrophone: (signal?: AbortSignal) => Promise<TrackReference<Track.Source.Microphone, RemoteParticipant>>;
9494
};
9595

96-
type AgentState = AgentStateAvailable | AgentStateUnAvailable | AgentStateFailed;
97-
export type AgentInstance = AgentState & AgentActions;
96+
type AgentStateCases = AgentStateAvailable | AgentStateUnAvailable | AgentStateFailed;
97+
export type AgentInstance = AgentStateCases & AgentActions;
9898

99-
const generateDerivedLifecycleStateValues = <LifecycleState extends AgentLifecycleState>(lifecycleState: LifecycleState) => ({
99+
const generateDerivedStateValues = <State extends AgentStateNew>(state: State) => ({
100100
isAvailable: (
101-
lifecycleState === 'listening' ||
102-
lifecycleState === 'thinking' ||
103-
lifecycleState === 'speaking'
101+
state === 'listening' ||
102+
state === 'thinking' ||
103+
state === 'speaking'
104104
),
105105
} as {
106-
isAvailable: LifecycleState extends 'listening' | 'thinking' | 'speaking' ? true : false,
106+
isAvailable: State extends 'listening' | 'thinking' | 'speaking' ? true : false,
107107
});
108108

109109
const useAgentTimeoutIdStore = create<{
110110
agentTimeoutFailureReason: string | null,
111111
startAgentTimeout: (agentConnectTimeoutMilliseconds?: number) => void;
112112
clearAgentTimeout: () => void;
113-
updateAgentTimeoutConversationalState: (agentConversationalState: AgentLifecycleState) => void;
113+
updateAgentTimeoutState: (agentState: AgentStateNew) => void;
114114
updateAgentTimeoutParticipantExists: (agentParticipantExists: boolean) => void;
115115
subtle: {
116116
agentTimeoutId: ReturnType<typeof setTimeout> | null;
117-
agentConversationalState: AgentLifecycleState;
117+
agentState: AgentStateNew;
118118
agentParticipantExists: boolean;
119119
};
120120
}>((set, get) => {
121121
const startAgentConnectedTimeout = (agentConnectTimeoutMilliseconds?: number) => {
122122
return setTimeout(() => {
123-
const { subtle: { agentConversationalState, agentParticipantExists } } = get();
123+
const { subtle: { agentState: agentConversationalState, agentParticipantExists } } = get();
124124
if (!agentParticipantExists) {
125125
set((old) => ({ ...old, agentTimeoutFailureReason: 'Agent did not join the room.' }));
126126
return;
127127
}
128128

129-
const { isAvailable } = generateDerivedLifecycleStateValues(agentConversationalState);
129+
const { isAvailable } = generateDerivedStateValues(agentConversationalState);
130130
if (!isAvailable) {
131131
set((old) => ({ ...old, agentTimeoutFailureReason: 'Agent connected but did not complete initializing.' }));
132132
return;
@@ -148,7 +148,7 @@ const useAgentTimeoutIdStore = create<{
148148
subtle: {
149149
...old.subtle,
150150
agentTimeoutId: startAgentConnectedTimeout(agentConnectTimeoutMilliseconds),
151-
agentConversationalState: 'unset',
151+
agentState: 'unset',
152152
agentParticipantExists: false,
153153
},
154154
};
@@ -165,23 +165,23 @@ const useAgentTimeoutIdStore = create<{
165165
subtle: {
166166
...old.subtle,
167167
agentTimeoutId: null,
168-
agentConversationalState: 'unset',
168+
agentState: 'unset',
169169
agentParticipantExists: false,
170170
},
171171
};
172172
});
173173
},
174174

175-
updateAgentTimeoutConversationalState: (agentConversationalState: AgentLifecycleState) => {
176-
set((old) => ({ ...old, subtle: { ...old.subtle, agentConversationalState } }));
175+
updateAgentTimeoutState: (agentState: AgentStateNew) => {
176+
set((old) => ({ ...old, subtle: { ...old.subtle, agentState: agentState } }));
177177
},
178178
updateAgentTimeoutParticipantExists: (agentParticipantExists: boolean) => {
179179
set((old) => ({ ...old, subtle: { ...old.subtle, agentParticipantExists } }));
180180
},
181181

182182
subtle: {
183183
agentTimeoutId: null,
184-
agentConversationalState: 'unset',
184+
agentState: 'unset',
185185
agentParticipantExists: false,
186186
},
187187
};
@@ -292,45 +292,44 @@ export function useAgent(conversation: ConversationStub, _name?: string): AgentI
292292
agentTimeoutFailureReason,
293293
startAgentTimeout,
294294
clearAgentTimeout,
295-
updateAgentTimeoutConversationalState,
295+
updateAgentTimeoutState: updateAgentTimeoutConversationalState,
296296
updateAgentTimeoutParticipantExists,
297297
} = useAgentTimeoutIdStore();
298298

299299
const failureReasons = useMemo(() => {
300300
return agentTimeoutFailureReason ? [ agentTimeoutFailureReason ] : [];
301301
}, [agentTimeoutFailureReason]);
302302

303-
const lifecycleState = useMemo(() => {
303+
const state = useMemo(() => {
304304
if (failureReasons.length > 0) {
305305
return 'failed';
306306
}
307307

308-
let newConversationalState: AgentLifecycleState = 'unset';
308+
let newState: AgentStateNew = 'unset';
309309

310310
if (roomConnectionState !== ConnectionState.Disconnected) {
311-
newConversationalState = 'initializing';
311+
newState = 'initializing';
312312
}
313313

314314
// If the microphone preconnect buffer is active, then the state should be "listening" rather
315315
// than "initializing"
316316
if (localMicTrack) {
317-
newConversationalState = 'listening';
317+
newState = 'listening';
318318
}
319319

320320
if (agentParticipant && agentParticipantAttributes[ParticipantAgentAttributes.AgentState]) {
321321
// ref: https://github.com/livekit/agents/blob/65170238db197f62f479eb7aaef1c0e18bfad6e7/livekit-agents/livekit/agents/voice/events.py#L97
322322
const agentState = agentParticipantAttributes[ParticipantAgentAttributes.AgentState] as 'initializing' | 'idle' | 'listening' | 'thinking' | 'speaking';
323-
newConversationalState = agentState;
323+
newState = agentState;
324324
}
325325

326-
return newConversationalState;
326+
return newState;
327327
}, [failureReasons, roomConnectionState, localMicTrack, agentParticipant, agentParticipantAttributes]);
328328

329329
useEffect(() => {
330-
console.log('AGENT TIMEOUT FAILURE REASON:', lifecycleState);
331-
emitter.emit(AgentEvent.ConversationalStateChanged, lifecycleState);
332-
updateAgentTimeoutConversationalState(lifecycleState);
333-
}, [emitter, lifecycleState]);
330+
emitter.emit(AgentEvent.StateChanged, state);
331+
updateAgentTimeoutConversationalState(state);
332+
}, [emitter, state]);
334333
useEffect(() => {
335334
updateAgentTimeoutParticipantExists(agentParticipant !== null);
336335
}, [agentParticipant]);
@@ -357,12 +356,12 @@ export function useAgent(conversation: ConversationStub, _name?: string): AgentI
357356
case 'connected':
358357
case 'reconnecting':
359358
case 'signalReconnecting':
360-
switch (lifecycleState) {
359+
switch (state) {
361360
case 'speaking':
362361
case 'listening':
363362
case 'initializing':
364363
case 'thinking':
365-
return lifecycleState;
364+
return state;
366365

367366
case 'idle':
368367
case 'unset':
@@ -371,9 +370,9 @@ export function useAgent(conversation: ConversationStub, _name?: string): AgentI
371370
return 'disconnected';
372371
}
373372
}
374-
}, [conversation.connectionState, lifecycleState]);
373+
}, [conversation.connectionState, state]);
375374

376-
const agentState: AgentState = useMemo(() => {
375+
const agentState: AgentStateCases = useMemo(() => {
377376
const common: AgentInstanceCommon = {
378377
[Symbol.toStringTag]: "AgentInstance",
379378

@@ -387,15 +386,15 @@ export function useAgent(conversation: ConversationStub, _name?: string): AgentI
387386
},
388387
};
389388

390-
switch (lifecycleState) {
389+
switch (state) {
391390
case 'listening':
392391
case 'thinking':
393392
case 'speaking':
394393
return {
395394
...common,
396395

397-
lifecycleState,
398-
...generateDerivedLifecycleStateValues(lifecycleState),
396+
state,
397+
...generateDerivedStateValues(state),
399398
failureReasons: null,
400399

401400
camera: videoTrack,
@@ -408,8 +407,8 @@ export function useAgent(conversation: ConversationStub, _name?: string): AgentI
408407
return {
409408
...common,
410409

411-
lifecycleState,
412-
...generateDerivedLifecycleStateValues(lifecycleState),
410+
state,
411+
...generateDerivedStateValues(state),
413412
failureReasons: null,
414413

415414
// Clear inner values if no longer connected
@@ -421,8 +420,8 @@ export function useAgent(conversation: ConversationStub, _name?: string): AgentI
421420
return {
422421
...common,
423422

424-
lifecycleState: 'failed',
425-
...generateDerivedLifecycleStateValues('failed'),
423+
state: 'failed',
424+
...generateDerivedStateValues('failed'),
426425
failureReasons,
427426

428427
// Clear inner values if no longer connected
@@ -435,20 +434,20 @@ export function useAgent(conversation: ConversationStub, _name?: string): AgentI
435434
emitter,
436435
agentParticipant,
437436

438-
lifecycleState,
437+
state,
439438
videoTrack,
440439
audioTrack,
441440
]);
442441

443442
const waitUntilAvailable = useCallback(async (signal?: AbortSignal) => {
444-
const { isAvailable } = generateDerivedLifecycleStateValues(lifecycleState);
443+
const { isAvailable } = generateDerivedStateValues(state);
445444
if (isAvailable) {
446445
return;
447446
}
448447

449448
return new Promise<void>((resolve, reject) => {
450-
const stateChangedHandler = (state: AgentLifecycleState) => {
451-
const { isAvailable } = generateDerivedLifecycleStateValues(state);
449+
const stateChangedHandler = (state: AgentStateNew) => {
450+
const { isAvailable } = generateDerivedStateValues(state);
452451
if (!isAvailable) {
453452
return;
454453
}
@@ -461,14 +460,14 @@ export function useAgent(conversation: ConversationStub, _name?: string): AgentI
461460
};
462461

463462
const cleanup = () => {
464-
emitter.off(AgentEvent.ConversationalStateChanged, stateChangedHandler);
463+
emitter.off(AgentEvent.StateChanged, stateChangedHandler);
465464
signal?.removeEventListener('abort', abortHandler);
466465
};
467466

468-
emitter.on(AgentEvent.ConversationalStateChanged, stateChangedHandler);
467+
emitter.on(AgentEvent.StateChanged, stateChangedHandler);
469468
signal?.addEventListener('abort', abortHandler);
470469
});
471-
}, [lifecycleState, emitter]);
470+
}, [state, emitter]);
472471

473472
const waitUntilCamera = useCallback((signal?: AbortSignal) => {
474473
return new Promise<TrackReference<Track.Source.Camera, RemoteParticipant>>((resolve, reject) => {

0 commit comments

Comments
 (0)