import { describe, expect } from "bun:test" import { Effect } from "effect" import { LLM, LLMEvent, Message } from "../../src" import { configure } from "../../src/providers/openai-compatible-responses" import { OpenAI } from "../../src/providers" import { OpenResponses } from "../../src/protocols/open-responses" import { OpenAICompatibleResponses } from "../../src/protocols/openai-compatible-responses" import { OpenAIResponses } from "../../src/protocols/openai-responses" import { LLMClient } from "../../src/route" import { it } from "../lib/effect" import { fixedResponse } from "../lib/http" import { sseEvents } from "../lib/sse" describe("Open Responses-compatible route", () => { it.effect("uses the Open Responses baseline for a configured deployment", () => Effect.gen(function* () { expect(OpenAICompatibleResponses.route.body).toBe(OpenResponses.protocol.body) expect(OpenAICompatibleResponses.route.transport).toBe(OpenResponses.httpTransport) expect(OpenAICompatibleResponses.route.body).not.toBe(OpenAIResponses.protocol.body) const model = configure({ apiKey: "test-key", baseURL: "https://responses.example.test/v1", provider: "example", }).model("example-model") const prepared = yield* LLMClient.prepare( LLM.request({ model, system: "You are concise.", prompt: "Say hello.", }), ) expect(prepared.route).toBe("openai-compatible-responses") expect(prepared.protocol).toBe("open-responses") expect(prepared.model).toMatchObject({ id: "example-model", provider: "example", route: { id: "openai-compatible-responses", endpoint: { baseURL: "https://responses.example.test/v1", path: "/responses", }, }, }) expect(prepared.body).toEqual({ model: "example-model", input: [ { role: "system", content: "You are concise." }, { role: "user", content: [{ type: "input_text", text: "Say hello." }] }, ], stream: true, }) }), ) it.effect("rejects OpenAI-native tools", () => Effect.gen(function* () { const model = configure({ apiKey: "test-key", baseURL: "https://responses.example.test/v1", }).model("example-model") const error = yield* LLMClient.prepare( LLM.request({ model, prompt: "Draw.", tools: [OpenAI.imageGeneration()] }), ).pipe(Effect.flip) expect(error.reason._tag).toBe("InvalidRequest") expect(error.message).toContain("Open Responses does not support provider-native tool image_generation") }), ) it.effect("omits OpenAI-only nullable phases from the Open Responses baseline", () => Effect.gen(function* () { const model = configure({ apiKey: "test-key", baseURL: "https://responses.example.test/v1", }).model("example-model") const prepared = yield* LLMClient.prepare( LLM.request({ model, messages: [ Message.assistant({ type: "text", text: "Unclassified.", providerMetadata: { openresponses: { phase: null } }, }), ], }), ) expect(prepared.body).toMatchObject({ input: [{ role: "assistant", content: [{ type: "output_text", text: "Unclassified." }] }], }) }), ) it.effect("reads standard options from the Open Responses namespace", () => Effect.gen(function* () { const model = configure({ apiKey: "test-key", baseURL: "https://responses.example.test/v1", providerOptions: { openresponses: { reasoningEffort: "low", store: true } }, }).model("example-model") const prepared = yield* LLMClient.prepare(LLM.request({ model, prompt: "Think." })) expect(prepared.body).toMatchObject({ reasoning: { effort: "low" }, store: true, }) }), ) it.effect("does not interpret OpenAI hosted-tool items", () => Effect.gen(function* () { const model = configure({ apiKey: "test-key", baseURL: "https://responses.example.test/v1", provider: "example", }).model("example-model") const response = yield* LLMClient.generate(LLM.request({ model, prompt: "Search." })).pipe( Effect.provide( fixedResponse( sseEvents( { type: "response.output_item.done", item: { type: "web_search_call", id: "ws_1", status: "completed", action: { query: "news" } }, }, { type: "response.completed", response: { id: "resp_1" } }, ), ), ), ) expect(response.toolCalls).toEqual([]) expect(response.events.find(LLMEvent.is.finish)).toMatchObject({ providerMetadata: { openresponses: { responseId: "resp_1" } }, }) }), ) })