in src/lib/genai-live-client.ts [177:241]
protected async onmessage(message: LiveServerMessage) {
if (message.setupComplete) {
this.log("server.send", "setupComplete");
this.emit("setupcomplete");
return;
}
if (message.toolCall) {
this.log("server.toolCall", message);
this.emit("toolcall", message.toolCall);
return;
}
if (message.toolCallCancellation) {
this.log("server.toolCallCancellation", message);
this.emit("toolcallcancellation", message.toolCallCancellation);
return;
}
// this json also might be `contentUpdate { interrupted: true }`
// or contentUpdate { end_of_turn: true }
if (message.serverContent) {
const { serverContent } = message;
if ("interrupted" in serverContent) {
this.log("server.content", "interrupted");
this.emit("interrupted");
return;
}
if ("turnComplete" in serverContent) {
this.log("server.content", "turnComplete");
this.emit("turncomplete");
}
if ("modelTurn" in serverContent) {
let parts: Part[] = serverContent.modelTurn?.parts || [];
// when its audio that is returned for modelTurn
const audioParts = parts.filter(
(p) => p.inlineData && p.inlineData.mimeType?.startsWith("audio/pcm")
);
const base64s = audioParts.map((p) => p.inlineData?.data);
// strip the audio parts out of the modelTurn
const otherParts = difference(parts, audioParts);
// console.log("otherParts", otherParts);
base64s.forEach((b64) => {
if (b64) {
const data = base64ToArrayBuffer(b64);
this.emit("audio", data);
this.log(`server.audio`, `buffer (${data.byteLength})`);
}
});
if (!otherParts.length) {
return;
}
parts = otherParts;
const content: { modelTurn: Content } = { modelTurn: { parts } };
this.emit("content", content);
this.log(`server.content`, message);
}
} else {
console.log("received unmatched message", message);
}
}