refactor(open-sse): extract chunkBuilder, dedup chat.completion.chunk (B1)

Add helpers/chunkBuilder.js; apply to claude/gemini/kiro/ollama/commandcode/
openai-responses response translators. Caller supplies id/created/model so each
keeps exact id-generation + usage semantics. Extend golden response stream to
openai-responses (codex). No behavior change; gate: no regression.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
decolua
2026-06-13 17:05:42 +07:00
parent 0e34358e74
commit 17202f7111
10 changed files with 270 additions and 295 deletions

View File

@@ -1,19 +1,14 @@
import { register } from "../index.js";
import { FORMATS } from "../formats.js";
import { buildChunk } from "../helpers/chunkBuilder.js";
// Create OpenAI chunk helper
function createChunk(state, delta, finishReason = null) {
return {
id: `chatcmpl-${state.messageId}`,
object: "chat.completion.chunk",
created: Math.floor(Date.now() / 1000),
model: state.model,
choices: [{
index: 0,
delta,
finish_reason: finishReason
}]
};
return buildChunk(
{ id: `chatcmpl-${state.messageId}`, created: Math.floor(Date.now() / 1000), model: state.model },
delta,
finishReason
);
}
// Convert Claude stream chunk to OpenAI format
@@ -129,13 +124,7 @@ export function claudeToOpenAIResponse(chunk, state) {
if (chunk.delta?.stop_reason) {
state.finishReason = convertStopReason(chunk.delta.stop_reason);
const finalChunk = {
id: `chatcmpl-${state.messageId}`,
object: "chat.completion.chunk",
created: Math.floor(Date.now() / 1000),
model: state.model,
choices: [{ index: 0, delta: {}, finish_reason: state.finishReason }]
};
const finalChunk = createChunk(state, {}, state.finishReason);
if (state.usage) {
finalChunk.usage = {
@@ -169,18 +158,7 @@ export function claudeToOpenAIResponse(chunk, state) {
total_tokens: (state.usage.input_tokens || 0) + (state.usage.output_tokens || 0)
}
} : {};
results.push({
id: `chatcmpl-${state.messageId}`,
object: "chat.completion.chunk",
created: Math.floor(Date.now() / 1000),
model: state.model,
choices: [{
index: 0,
delta: {},
finish_reason: finishReason
}],
...usageObj
});
results.push({ ...createChunk(state, {}, finishReason), ...usageObj });
state.finishReasonSent = true;
}
break;