|
| 1 | +import { describe, expect, test } from "bun:test"; |
| 2 | +import { BEARER_CREDENTIAL_SENTINEL } from "@intx/inference"; |
| 3 | +import type { ConversationTurn, LastCycleSource } from "@intx/types/runtime"; |
| 4 | +import { ENVIRONMENT_TAG_NAME, PRODUCT_NAME } from "../branding.js"; |
| 5 | +import { |
| 6 | + CODEX_ACCOUNT_ID_OPTION, |
| 7 | + CODEX_RESPONSES_PROVIDER, |
| 8 | + CODEX_SESSION_ID_OPTION, |
| 9 | + createCodexResponsesAdapter, |
| 10 | +} from "./codex-responses.js"; |
| 11 | + |
| 12 | +const source: LastCycleSource = { |
| 13 | + sourceId: "codex/test", |
| 14 | + provider: CODEX_RESPONSES_PROVIDER, |
| 15 | + model: "gpt-5.1-codex", |
| 16 | +}; |
| 17 | + |
| 18 | +function userTurn(text: string): ConversationTurn { |
| 19 | + return { role: "user", timestamp: 0, content: [{ type: "text", text }] }; |
| 20 | +} |
| 21 | + |
| 22 | +describe("createCodexResponsesAdapter", () => { |
| 23 | + test("forwards providerOptions.reasoning_effort onto reasoning.effort", () => { |
| 24 | + const adapter = createCodexResponsesAdapter(source); |
| 25 | + const request = adapter.buildRequest([userTurn("hello")], "gpt-5.1-codex", { |
| 26 | + providerOptions: { reasoning_effort: "high" }, |
| 27 | + }); |
| 28 | + const body = JSON.parse(request.body) as { |
| 29 | + reasoning?: { effort?: string }; |
| 30 | + }; |
| 31 | + expect(body.reasoning).toEqual({ effort: "high" }); |
| 32 | + }); |
| 33 | + |
| 34 | + test("omits reasoning when effort is none or unset", () => { |
| 35 | + const adapter = createCodexResponsesAdapter(source); |
| 36 | + const unset = JSON.parse( |
| 37 | + adapter.buildRequest([userTurn("hello")], "gpt-5.1-codex", {}).body, |
| 38 | + ) as { reasoning?: unknown }; |
| 39 | + const none = JSON.parse( |
| 40 | + adapter.buildRequest([userTurn("hello")], "gpt-5.1-codex", { |
| 41 | + providerOptions: { reasoning_effort: "none" }, |
| 42 | + }).body, |
| 43 | + ) as { reasoning?: unknown }; |
| 44 | + expect(unset.reasoning).toBeUndefined(); |
| 45 | + expect(none.reasoning).toBeUndefined(); |
| 46 | + }); |
| 47 | + |
| 48 | + test("lifts host account and session option keys into Codex headers", () => { |
| 49 | + const adapter = createCodexResponsesAdapter(source); |
| 50 | + const request = adapter.buildRequest([userTurn("hi")], "gpt-5.1-codex", { |
| 51 | + providerOptions: { |
| 52 | + [CODEX_ACCOUNT_ID_OPTION]: "acct-1", |
| 53 | + [CODEX_SESSION_ID_OPTION]: "sess-1", |
| 54 | + }, |
| 55 | + }); |
| 56 | + expect(request.url).toBe("/codex/responses"); |
| 57 | + expect(request.headers["authorization"]).toBe(BEARER_CREDENTIAL_SENTINEL); |
| 58 | + expect(request.headers["chatgpt-account-id"]).toBe("acct-1"); |
| 59 | + expect(request.headers["session_id"]).toBe("sess-1"); |
| 60 | + const body = JSON.parse(request.body) as { prompt_cache_key?: string }; |
| 61 | + expect(body.prompt_cache_key).toBe("sess-1"); |
| 62 | + }); |
| 63 | + |
| 64 | + test("wraps the system prompt with host product identity as a developer item", () => { |
| 65 | + const adapter = createCodexResponsesAdapter(source); |
| 66 | + const request = adapter.buildRequest([userTurn("x")], "gpt-5.1-codex", { |
| 67 | + systemPrompt: "be terse", |
| 68 | + }); |
| 69 | + const body = JSON.parse(request.body) as { |
| 70 | + instructions?: unknown; |
| 71 | + input: { role?: string; content?: { text?: string }[] }[]; |
| 72 | + }; |
| 73 | + expect(body.instructions).toBeUndefined(); |
| 74 | + expect(body.input[0]?.role).toBe("developer"); |
| 75 | + const wrapped = body.input[0]?.content?.[0]?.text ?? ""; |
| 76 | + expect(wrapped).toContain(`<${ENVIRONMENT_TAG_NAME} priority="0">`); |
| 77 | + expect(wrapped).toContain(`${PRODUCT_NAME} is the harness`); |
| 78 | + expect(wrapped).toContain("be terse"); |
| 79 | + expect(body.input[1]?.role).toBe("user"); |
| 80 | + }); |
| 81 | +}); |
0 commit comments