import { describe, expect, it } from "vitest"; import { buildCodexNativeWebSearchTool, describeCodexNativeWebSearch, patchCodexNativeWebSearchPayload, resolveCodexNativeSearchActivation, resolveCodexNativeWebSearchConfig, shouldSuppressManagedWebSearchTool, } from "./codex-native-web-search.js"; const baseConfig = { tools: { web: { search: { enabled: true, openaiCodex: { enabled: true, mode: "cached", }, }, }, }, } as const; describe("resolveCodexNativeSearchActivation", () => { it("returns managed_only when native Codex search is disabled", () => { const result = resolveCodexNativeSearchActivation({ config: { tools: { web: { search: { enabled: true } } } }, modelProvider: "openai-codex", modelApi: "openai-codex-responses", }); expect(result.state).toBe("managed_only"); expect(result.inactiveReason).toBe("codex_not_enabled"); }); it("returns managed_only for non-eligible models", () => { const result = resolveCodexNativeSearchActivation({ config: baseConfig, modelProvider: "openai", modelApi: "openai-responses", }); expect(result.state).toBe("managed_only"); expect(result.inactiveReason).toBe("model_not_eligible"); }); it("activates for direct openai-codex when auth exists", () => { const result = resolveCodexNativeSearchActivation({ config: { ...baseConfig, auth: { profiles: { "openai-codex:default": { provider: "openai-codex", mode: "oauth", }, }, }, }, modelProvider: "openai-codex", modelApi: "openai-codex-responses", }); expect(result.state).toBe("native_active"); expect(result.codexMode).toBe("cached"); }); it("falls back to managed_only when direct openai-codex auth is missing", () => { const result = resolveCodexNativeSearchActivation({ config: baseConfig, modelProvider: "openai-codex", modelApi: "openai-codex-responses", }); expect(result.state).toBe("managed_only"); expect(result.inactiveReason).toBe("codex_auth_missing"); }); it("activates for api-compatible openai-codex-responses providers without separate Codex auth", () => { const result = resolveCodexNativeSearchActivation({ config: baseConfig, modelProvider: "gateway", modelApi: "openai-codex-responses", }); expect(result.state).toBe("native_active"); }); it("keeps all search disabled when global web search is disabled", () => { const result = resolveCodexNativeSearchActivation({ config: { tools: { web: { search: { enabled: false, openaiCodex: { enabled: true, mode: "live" }, }, }, }, }, modelProvider: "openai-codex", modelApi: "openai-codex-responses", }); expect(result.state).toBe("managed_only"); expect(result.inactiveReason).toBe("globally_disabled"); }); }); describe("Codex native web-search payload helpers", () => { it("omits the summary when global web search is disabled", () => { expect( describeCodexNativeWebSearch({ tools: { web: { search: { enabled: false, openaiCodex: { enabled: true, mode: "live", }, }, }, }, }), ).toBeUndefined(); }); it("normalizes optional config values", () => { const result = resolveCodexNativeWebSearchConfig({ tools: { web: { search: { openaiCodex: { enabled: true, allowedDomains: [" example.com ", "example.com", ""], contextSize: "high", userLocation: { country: " US ", city: " New York ", timezone: "America/New_York", }, }, }, }, }, }); expect(result).toMatchObject({ enabled: true, mode: "cached", allowedDomains: ["example.com"], contextSize: "high", userLocation: { country: "US", city: "New York", timezone: "America/New_York", }, }); }); it("builds the native Responses web_search tool", () => { expect( buildCodexNativeWebSearchTool({ tools: { web: { search: { openaiCodex: { enabled: true, mode: "live", allowedDomains: ["example.com"], contextSize: "medium", userLocation: { country: "US" }, }, }, }, }, }), ).toEqual({ type: "web_search", external_web_access: true, filters: { allowed_domains: ["example.com"] }, search_context_size: "medium", user_location: { type: "approximate", country: "US", }, }); }); it("injects native web_search into provider payloads", () => { const payload: Record = { tools: [{ type: "function", name: "read" }] }; const result = patchCodexNativeWebSearchPayload({ payload, config: baseConfig }); expect(result.status).toBe("injected"); expect(payload.tools).toEqual([ { type: "function", name: "read" }, { type: "web_search", external_web_access: false }, ]); }); it("does not inject a duplicate native web_search tool", () => { const payload: Record = { tools: [{ type: "web_search" }] }; const result = patchCodexNativeWebSearchPayload({ payload, config: baseConfig }); expect(result.status).toBe("native_tool_already_present"); expect(payload.tools).toEqual([{ type: "web_search" }]); }); }); describe("shouldSuppressManagedWebSearchTool", () => { it("suppresses managed web_search only when native Codex search is active", () => { expect( shouldSuppressManagedWebSearchTool({ config: baseConfig, modelProvider: "gateway", modelApi: "openai-codex-responses", }), ).toBe(true); expect( shouldSuppressManagedWebSearchTool({ config: baseConfig, modelProvider: "openai", modelApi: "openai-responses", }), ).toBe(false); }); }); describe("isCodexNativeWebSearchRelevant", () => { it("treats a default model with model-level openai-codex-responses api as relevant", async () => { const { isCodexNativeWebSearchRelevant } = await import("./codex-native-web-search.js"); expect( isCodexNativeWebSearchRelevant({ config: { agents: { defaults: { model: { primary: "gateway/gpt-5.4", }, }, }, models: { providers: { gateway: { api: "openai-responses", baseUrl: "https://gateway.example/v1", models: [ { id: "gpt-5.4", name: "gpt-5.4", api: "openai-codex-responses", reasoning: false, input: ["text"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 128_000, maxTokens: 16_384, }, ], }, }, }, }, }), ).toBe(true); }); });