From 0e34358e74b1c1666a8ff17f895198e87d7dbae8 Mon Sep 17 00:00:00 2001 From: decolua Date: Sat, 13 Jun 2026 16:47:25 +0700 Subject: [PATCH] test(open-sse): extend golden response stream to kiro/ollama (T0.5) Lock chunk/usage/tool/thinking/finish behavior for kiro + ollama before chunkBuilder refactor. Sanitize volatile stream/tool ids. Co-authored-by: Cursor --- .../golden-response-stream.test.js.snap | 143 ++++++++++++++++++ .../translator/golden-response-stream.test.js | 34 ++++- 2 files changed, 174 insertions(+), 3 deletions(-) diff --git a/tests/translator/__snapshots__/golden-response-stream.test.js.snap b/tests/translator/__snapshots__/golden-response-stream.test.js.snap index a8d8bf51..0baa653e 100644 --- a/tests/translator/__snapshots__/golden-response-stream.test.js.snap +++ b/tests/translator/__snapshots__/golden-response-stream.test.js.snap @@ -302,3 +302,146 @@ exports[`GOLDEN response stream: Gemini → OpenAI > text + thought(no-sig) + fu }, ] `; + +exports[`GOLDEN response stream: Kiro → OpenAI > text + reasoning + toolUse + usage + stop 1`] = ` +[ + { + "choices": [ + { + "delta": { + "content": "Hello", + "role": "assistant", + }, + "finish_reason": null, + "index": 0, + }, + ], + "created": 0, + "id": "chatcmpl-", + "model": "kiro", + "object": "chat.completion.chunk", + }, + { + "choices": [ + { + "delta": { + "reasoning_content": "thinking", + }, + "finish_reason": null, + "index": 0, + }, + ], + "created": 0, + "id": "chatcmpl-", + "model": "kiro", + "object": "chat.completion.chunk", + }, + { + "choices": [ + { + "delta": { + "tool_calls": [ + { + "function": { + "arguments": "{"city":"NYC"}", + "name": "get_weather", + }, + "id": "tu_1", + "index": 0, + "type": "function", + }, + ], + }, + "finish_reason": null, + "index": 0, + }, + ], + "created": 0, + "id": "chatcmpl-", + "model": "kiro", + "object": "chat.completion.chunk", + }, + { + "choices": [ + { + "delta": {}, + "finish_reason": "stop", + "index": 0, + }, + ], + "created": 0, + "id": "chatcmpl-", + "model": "kiro", + "object": "chat.completion.chunk", + "usage": { + "completion_tokens": 5, + "prompt_tokens": 10, + "total_tokens": 15, + }, + }, +] +`; + +exports[`GOLDEN response stream: Ollama → OpenAI > content + thinking + tool_calls + done usage 1`] = ` +[ + { + "choices": [ + { + "delta": { + "content": "Hi", + "reasoning_content": "reason", + }, + "finish_reason": null, + "index": 0, + }, + ], + "created": 0, + "id": "chatcmpl-", + "model": "qwen3", + "object": "chat.completion.chunk", + }, + { + "choices": [ + { + "delta": { + "tool_calls": [ + { + "function": { + "arguments": "{"q":"x"}", + "name": "search", + }, + "id": "call_0_", + "index": 0, + "type": "function", + }, + ], + }, + "finish_reason": null, + "index": 0, + }, + ], + "created": 0, + "id": "chatcmpl-", + "model": "qwen3", + "object": "chat.completion.chunk", + }, + { + "choices": [ + { + "delta": {}, + "finish_reason": "tool_calls", + "index": 0, + }, + ], + "created": 0, + "id": "chatcmpl-", + "model": "qwen3", + "object": "chat.completion.chunk", + "usage": { + "completion_tokens": 4, + "prompt_tokens": 8, + "total_tokens": 12, + }, + }, +] +`; diff --git a/tests/translator/golden-response-stream.test.js b/tests/translator/golden-response-stream.test.js index 6d47ac7f..011464a3 100644 --- a/tests/translator/golden-response-stream.test.js +++ b/tests/translator/golden-response-stream.test.js @@ -6,12 +6,16 @@ import "./registerAll.js"; import { translateResponse, initState } from "../../open-sse/translator/index.js"; import { FORMATS } from "../../open-sse/translator/formats.js"; -// Chuẩn hoá field động (Date.now trong created + gemini tool id) để snapshot ổn định. +// Chuẩn hoá field động (Date.now trong created + id) để snapshot ổn định. function stripVolatile(chunks) { return JSON.parse(JSON.stringify(chunks), (key, val) => { if (key === "created") return 0; - // gemini sinh id = `${name}-${Date.now()}-${idx}` → chuẩn hoá phần timestamp - if (key === "id" && typeof val === "string") return val.replace(/-\d{10,}-(\d+)$/, "--$1"); + if (key === "id" && typeof val === "string") { + return val + .replace(/-\d{10,}-(\d+)$/, "--$1") // gemini: name--idx + .replace(/^chatcmpl-\d{10,}$/, "chatcmpl-") // kiro/ollama stream id + .replace(/^call_(\d+)_\d{10,}$/, "call_$1_"); // ollama tool id + } return val; }); } @@ -67,3 +71,27 @@ describe("GOLDEN response stream: Gemini → OpenAI", () => { expect(runStream(FORMATS.GEMINI, FORMATS.OPENAI, events)).toMatchSnapshot(); }); }); + +describe("GOLDEN response stream: Kiro → OpenAI", () => { + it("text + reasoning + toolUse + usage + stop", () => { + const events = [ + { assistantResponseEvent: { content: "Hello" }, _eventType: "assistantResponseEvent" }, + { reasoningContentEvent: { text: "thinking" }, _eventType: "reasoningContentEvent" }, + { toolUseEvent: { toolUseId: "tu_1", name: "get_weather", input: { city: "NYC" } }, _eventType: "toolUseEvent" }, + { usageEvent: { inputTokens: 10, outputTokens: 5 }, _eventType: "usageEvent" }, + { _eventType: "messageStopEvent" }, + ]; + expect(runStream(FORMATS.KIRO, FORMATS.OPENAI, events)).toMatchSnapshot(); + }); +}); + +describe("GOLDEN response stream: Ollama → OpenAI", () => { + it("content + thinking + tool_calls + done usage", () => { + const events = [ + { model: "qwen3", message: { role: "assistant", content: "Hi", thinking: "reason" } }, + { model: "qwen3", message: { role: "assistant", tool_calls: [{ function: { name: "search", arguments: { q: "x" } } }] } }, + { model: "qwen3", done: true, done_reason: "stop", prompt_eval_count: 8, eval_count: 4 }, + ]; + expect(runStream(FORMATS.OLLAMA, FORMATS.OPENAI, events)).toMatchSnapshot(); + }); +});