in src/requests/stream-reader.ts [153:225]
export function aggregateResponses(
responses: GenerateContentResponse[],
): GenerateContentResponse {
const lastResponse = responses[responses.length - 1];
const aggregatedResponse: GenerateContentResponse = {
promptFeedback: lastResponse?.promptFeedback,
};
for (const response of responses) {
if (response.candidates) {
let candidateIndex = 0;
for (const candidate of response.candidates) {
if (!aggregatedResponse.candidates) {
aggregatedResponse.candidates = [];
}
if (!aggregatedResponse.candidates[candidateIndex]) {
aggregatedResponse.candidates[candidateIndex] = {
index: candidateIndex,
} as GenerateContentCandidate;
}
// Keep overwriting, the last one will be final
aggregatedResponse.candidates[candidateIndex].citationMetadata =
candidate.citationMetadata;
aggregatedResponse.candidates[candidateIndex].groundingMetadata =
candidate.groundingMetadata;
aggregatedResponse.candidates[candidateIndex].finishReason =
candidate.finishReason;
aggregatedResponse.candidates[candidateIndex].finishMessage =
candidate.finishMessage;
aggregatedResponse.candidates[candidateIndex].safetyRatings =
candidate.safetyRatings;
/**
* Candidates should always have content and parts, but this handles
* possible malformed responses.
*/
if (candidate.content && candidate.content.parts) {
if (!aggregatedResponse.candidates[candidateIndex].content) {
aggregatedResponse.candidates[candidateIndex].content = {
role: candidate.content.role || "user",
parts: [],
};
}
const newPart: Partial<Part> = {};
for (const part of candidate.content.parts) {
if (part.text) {
newPart.text = part.text;
}
if (part.functionCall) {
newPart.functionCall = part.functionCall;
}
if (part.executableCode) {
newPart.executableCode = part.executableCode;
}
if (part.codeExecutionResult) {
newPart.codeExecutionResult = part.codeExecutionResult;
}
if (Object.keys(newPart).length === 0) {
newPart.text = "";
}
aggregatedResponse.candidates[candidateIndex].content.parts.push(
newPart as Part,
);
}
}
}
candidateIndex++;
}
if (response.usageMetadata) {
aggregatedResponse.usageMetadata = response.usageMetadata;
}
}
return aggregatedResponse;
}