import assert from "node:assert/strict"; import test from "node:test"; import { runPlainChatCompletionsStream, runToolAwareChatCompletionsStream, runToolAwareOpenAIChatStream, type ToolAwareStreamingEvent, } from "../src/llm/chat-tools.js"; async function* streamFrom(events: any[]) { for (const event of events) { await Promise.resolve(); yield event; } } async function collectEvents(iterable: AsyncIterable) { const events: ToolAwareStreamingEvent[] = []; for await (const event of iterable) { events.push(event); } return events; } test("OpenAI Responses stream emits text deltas as they arrive", async () => { const outputMessage = { id: "msg_1", type: "message", role: "assistant", status: "completed", content: [{ type: "output_text", text: "Hello" }], }; const client = { responses: { create: async () => streamFrom([ { type: "response.output_item.added", item: { ...outputMessage, content: [] }, output_index: 0 }, { type: "response.output_text.delta", delta: "Hel", output_index: 0, content_index: 0 }, { type: "response.output_text.delta", delta: "lo", output_index: 0, content_index: 0 }, { type: "response.output_item.done", item: outputMessage, output_index: 0 }, { type: "response.completed", response: { status: "completed", output_text: "Hello", output: [outputMessage], usage: { input_tokens: 2, output_tokens: 1, total_tokens: 3 }, }, }, ]), }, }; const events = await collectEvents( runToolAwareOpenAIChatStream({ client: client as any, model: "gpt-test", messages: [{ role: "user", content: "Say hello" }], }) ); assert.deepEqual( events.map((event) => event.type), ["delta", "delta", "done"] ); assert.deepEqual( events.filter((event) => event.type === "delta").map((event) => event.text), ["Hel", "lo"] ); assert.equal(events.at(-1)?.type === "done" ? events.at(-1)?.result.text : null, "Hello"); }); test("OpenAI-compatible Chat Completions stream emits text deltas as they arrive", async () => { const client = { chat: { completions: { create: async () => streamFrom([ { choices: [{ delta: { role: "assistant" } }] }, { choices: [{ delta: { content: "Hel" } }] }, { choices: [{ delta: { content: "lo" } }] }, { choices: [{ delta: {}, finish_reason: "stop" }], usage: { prompt_tokens: 2, completion_tokens: 1, total_tokens: 3 }, }, ]), }, }, }; const events = await collectEvents( runToolAwareChatCompletionsStream({ client: client as any, model: "grok-test", messages: [{ role: "user", content: "Say hello" }], }) ); assert.deepEqual( events.map((event) => event.type), ["delta", "delta", "done"] ); assert.deepEqual( events.filter((event) => event.type === "delta").map((event) => event.text), ["Hel", "lo"] ); assert.equal(events.at(-1)?.type === "done" ? events.at(-1)?.result.text : null, "Hello"); }); test("plain Chat Completions stream does not send Sybil-managed tools", async () => { let requestBody: any = null; const client = { chat: { completions: { create: async (body: any) => { requestBody = body; return streamFrom([ { choices: [{ delta: { content: "Hi" } }] }, { choices: [{ delta: {}, finish_reason: "stop" }] }, ]); }, }, }, }; const events = await collectEvents( runPlainChatCompletionsStream({ client: client as any, model: "hermes-agent", messages: [{ role: "user", content: "Say hi" }], }) ); assert.equal(requestBody.model, "hermes-agent"); assert.equal(requestBody.stream, true); assert.equal("tools" in requestBody, false); assert.deepEqual( events.map((event) => event.type), ["delta", "done"] ); assert.equal(events.at(-1)?.type === "done" ? events.at(-1)?.result.text : null, "Hi"); });