import { buildCopilotDynamicHeaders } from "openclaw/plugin-sdk/provider-stream-shared"; import { describe, expect, it, vi } from "vitest"; import { wrapCopilotAnthropicStream, wrapCopilotOpenAIResponsesStream, wrapCopilotProviderStream, } from "./stream.js"; describe("wrapCopilotAnthropicStream", () => { it("adds Copilot headers and Anthropic cache markers for Claude payloads", async () => { const payloads: Array<{ messages: Array>; }> = []; const baseStreamFn = vi.fn((model, _context, options) => { const payload = { messages: [ { role: "system", content: "system prompt" }, { role: "assistant", content: [{ type: "thinking", text: "draft", cache_control: { type: "ephemeral" } }], }, ], }; options?.onPayload?.(payload, model); payloads.push(payload); return { async *[Symbol.asyncIterator]() {}, } as never; }); const wrapped = wrapCopilotAnthropicStream(baseStreamFn); const messages = [ { role: "user", content: [ { type: "text", text: "look" }, { type: "image", image: "data:image/png;base64,abc" }, ], }, ] as Parameters[0]["messages"]; const context = { messages }; const expectedCopilotHeaders = buildCopilotDynamicHeaders({ messages, hasImages: true, }); void wrapped( { provider: "github-copilot", api: "anthropic-messages", id: "claude-sonnet-4.6", } as never, context as never, { headers: { "X-Test": "1" }, }, ); expect(baseStreamFn).toHaveBeenCalledOnce(); expect(baseStreamFn.mock.calls[0]?.[2]).toMatchObject({ headers: { ...expectedCopilotHeaders, "X-Test": "1", }, }); expect(payloads[0]?.messages).toEqual([ { role: "system", content: [{ type: "text", text: "system prompt", cache_control: { type: "ephemeral" } }], }, { role: "assistant", content: [{ type: "thinking", text: "draft" }], }, ]); }); it("leaves non-Anthropic Copilot models untouched", () => { const baseStreamFn = vi.fn(() => ({ async *[Symbol.asyncIterator]() {} }) as never); const wrapped = wrapCopilotAnthropicStream(baseStreamFn); const options = { headers: { Existing: "1" } }; void wrapped( { provider: "github-copilot", api: "openai-responses", id: "gpt-4.1", } as never, { messages: [{ role: "user", content: "hi" }] } as never, options as never, ); expect(baseStreamFn).toHaveBeenCalledWith(expect.anything(), expect.anything(), options); }); it("rewrites Copilot Responses connection-bound IDs before payload send", () => { const connectionBoundId = Buffer.from(`reasoning-${"x".repeat(24)}`).toString("base64"); const payloads: Array<{ input: Array> }> = []; const baseStreamFn = vi.fn((_model, _context, options) => { const payload = { input: [{ id: connectionBoundId, type: "reasoning" }] }; options?.onPayload?.(payload, _model); payloads.push(payload); return { async *[Symbol.asyncIterator]() {}, } as never; }); const wrapped = wrapCopilotOpenAIResponsesStream(baseStreamFn); void wrapped( { provider: "github-copilot", api: "openai-responses", id: "gpt-5.4", } as never, { messages: [{ role: "user", content: "hi" }] } as never, {}, ); expect(payloads[0]?.input[0]?.id).toMatch(/^rs_[a-f0-9]{16}$/); }); it("rewrites Copilot Responses IDs returned by an existing payload hook", async () => { const connectionBoundId = Buffer.from(`message-${"y".repeat(24)}`).toString("base64"); let returnedPayload: unknown; const baseStreamFn = vi.fn(async (_model, _context, options) => { returnedPayload = await options?.onPayload?.({ input: [] }, _model); return { async *[Symbol.asyncIterator]() {}, } as never; }); const wrapped = wrapCopilotOpenAIResponsesStream(baseStreamFn); await wrapped( { provider: "github-copilot", api: "openai-responses", id: "gpt-5.4", } as never, { messages: [{ role: "user", content: "hi" }] } as never, { onPayload: () => ({ input: [{ id: connectionBoundId, type: "message" }] }), } as never, ); expect((returnedPayload as { input: Array> }).input[0]?.id).toMatch( /^msg_[a-f0-9]{16}$/, ); }); it("adapts provider stream context without changing wrapper behavior", () => { const baseStreamFn = vi.fn(() => ({ async *[Symbol.asyncIterator]() {} }) as never); const wrapped = wrapCopilotProviderStream({ streamFn: baseStreamFn, } as never); void wrapped( { provider: "github-copilot", api: "openai-responses", id: "gpt-4.1", } as never, { messages: [{ role: "user", content: "hi" }] } as never, {}, ); expect(baseStreamFn).toHaveBeenCalledOnce(); }); });