in src/formatters.ts [23:84]
export function formatResponseBody({
res,
allResponseChunks,
cliOptions,
}: {
res: express.Response;
allResponseChunks: string;
cliOptions: CliOptions;
}) {
if (cliOptions.raw) {
return allResponseChunks;
}
const isStreamedResponse =
res.getHeader('content-type') === 'text/event-stream' ||
res.getHeader('transfer-encoding') === 'chunked';
if (!isStreamedResponse) {
try {
return JSON.stringify(JSON.parse(allResponseChunks), null, 2);
} catch (e) {
return allResponseChunks;
}
}
const lines = allResponseChunks
.split(/\r?\n/) // Handle both \n and \r\n
.map((line) => line.trim());
const hasSSEChunks = lines.some((line) => line.startsWith('data:'));
console.log(`Chunks: ${allResponseChunks.length}`);
console.log(`Lines: ${lines.length}`);
console.log(`Server-sent events (SSE): ${hasSSEChunks.valueOf()}`);
console.log(`-----\n`);
if (!hasSSEChunks) {
return lines
.map((line) => {
try {
const parsedLine = JSON.parse(line);
return parsedLine.message.content;
} catch (e) {
return line;
}
})
.join('');
}
const parsedSSEChunks = lines
.filter((line) => line.startsWith('data:') && line !== 'data: [DONE]') // Filter out non-data and [DONE]
.map((line) => JSON.parse(line.slice(5).trim()));
const isOpenAIChunk = parsedSSEChunks.some(
(chunk) => chunk.object === 'chat.completion.chunk' && chunk.choices,
);
if (!isOpenAIChunk) {
return JSON.stringify(parsedSSEChunks, null, 2);
}
const mergedMessage = mergeOpenAIChunks(parsedSSEChunks);
return JSON.stringify(mergedMessage, null, 2);
}