Skip to content

Conversation

@davidzhao
Copy link
Member

No description provided.

Copy link

@thomasyuill-livekit thomasyuill-livekit left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM and tested it works locally

I don't have familiarity with this code base, so @lukasIO and @1egoman might have better insights, particularly around src/pages/api/token.ts

}, [containerRef, messages]);

// TODO(remove): debugging message rendering
console.log("messages", messages);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✂️

const newSettings = { ...config.settings };
newSettings.agent_name = value;
setUserSettings(newSettings);
console.log("agent name changed to", value);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✂️

source={Track.Source.Microphone}
>
<AudioInputTile trackRef={localMicTrack} />
{session.local.microphoneTrack ? (

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TIL - local tracks are available through the agent session object

? "hidden"
: "flex"
}`}
className={`flex gap-4 py-4 grow w-full selection:bg-${config.settings.theme_color}-900`}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worth noting: I saw a few other instances of this in the change, but also quite a few instances of this just generally in the project. It might be worth doing a separate pass to clean this up across the board.

Copy link

@1egoman 1egoman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the massive review, but I noticed a bunch of small things (and some broken behavior) you probably want to fix before merging.

>
<div className="flex flex-col min-h-full justify-end">
{messages.map((message, index, allMsg) => {
console.log("message", message);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(I think you probably want to get rid of this before merging)

Comment on lines +67 to +76
const [tokenFetchOptions, setTokenFetchOptions] =
useState<TokenSourceFetchOptions>({});

// initialize token fetch options from initial values, which can come from config
useEffect(() => {
if (roomState === ConnectionState.Connected) {
localParticipant.setCameraEnabled(config.settings.inputs.camera);
localParticipant.setMicrophoneEnabled(config.settings.inputs.mic);
}
}, [config, localParticipant, roomState]);
setTokenFetchOptions({
agentName: initialAgentOptions?.agentName,
agentMetadata: initialAgentOptions?.metadata,
});
}, []);
Copy link

@1egoman 1egoman Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thought: This technique you are using here of storing the agentName / agentMetadata in tokenFetchOptions like this could lead to some downstream problems, since tokenFetchOptions.agentName would start as undefined, but then if a user were to put something in the "agent name" textbox and get rid of it again, it would end up as an empty string.

Instead of doing it this way, it might be better to store the agent name / agent metadata separately and treat the the token fetch options as derived state built via a useMemo or similar.

Also I just want to call out since I think it's relevant: useSession doesn't need the tokenFetchOptions reference to be stable. It only keys on primative values within the object so if having it change every render simplifies things for some reason, that is perfectly fine to do.

Comment on lines +83 to +86
useEffect(() => {
// to debug room.incomingDataStreamManager
console.log("room handle", session.room);
}, [session.connectionState]);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(I think you probably want to get rid of this before merging)

Comment on lines +88 to +89
const localScreenTrack = session.room.localParticipant.getTrackPublication(
Track.Source.ScreenShare,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: Not related to this change directly, but seeing this makes me wonder if there's a good reason to better expose the local participant screenshare track directly from useSession. It maybe could be a way to make this a bit more elegant...


const chatTileContent = useMemo(() => {
if (voiceAssistant.agent) {
if (agent.internal.agentParticipant) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: This I think can be agent.isConnected?

Suggested change
if (agent.internal.agentParticipant) {
if (agent.isConnected) {

Comment on lines +53 to +58
const source = TokenSource.custom((options) => {
return {
serverUrl: url,
participantToken: token,
};
});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: IMO, this probably makes more sense semantically as a TokenSource.literal:

Suggested change
const source = TokenSource.custom((options) => {
return {
serverUrl: url,
participantToken: token,
};
});
const source = TokenSource.literal({
serverUrl: url,
participantToken: token,
});

Comment on lines +29 to +30
const [url, setUrl] = useState<string>("");
const [token, setToken] = useState<string>("");
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: I am not 100% sure here, but it looks like this is a behavior change? url / token will always be empty and not be defaulted to config.settings values now. Since I am not too familiar with this app, this might be intended, but it struck me as weird so I just wanted to call it out to make sure it was indeed intentional.

Comment on lines +12 to +18
type TokenRequest = {
room_name?: string;
participant_name?: string;
participant_identity?: string;
participant_metadata?: string;
participant_attributes?: Record<string, string>;
room_config?: ReturnType<RoomConfiguration["toJson"]>;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sugggestion: This could be TokenSourceRequestPayload instead.

Comment on lines +28 to +29
const roomName = request.room_name ?? request.roomName!;
const participantName = request.participant_name ?? request.participantName!;
Copy link

@1egoman 1egoman Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: It looks like you got rid of the fallback to an auto generated default room name / participant name if one wasn't specified in the body. Was there a good reason for this? If not, it might be worth adding this back in since right now I think with an empty body (which per the token endpoint specification is allowed), this would result in unset jwt payload metadata.

Comment on lines +37 to +38
// const { shouldConnect, wsUrl, token, mode, connect, disconnect } =
// useConnection();
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: There's some dead code here you might want to get rid of.

@bcherry bcherry self-requested a review December 9, 2025 18:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants