Files
openclaw/src/agents/codex-native-web-search.test.ts
EVA 860dad268d [codex] Add contract-first Pi/Codex runtime plan suite (#71096)
* test: add pi codex runtime contract coverage

* test: expand pi codex tool runtime contracts

* test: tighten tool runtime contracts

* test: reset tool contract param cache

* test: document codex tool middleware fixture

* test: type pi tool contract events

* test: satisfy pi tool contract test types

* test: cover tool media telemetry contracts

* test: reset plugin runtime after tool contracts

* test: add auth profile runtime contracts

* test: strengthen auth profile runtime contracts

* test: clarify auth profile contract fixtures

* test: expand auth profile contract matrix

* test: assert unrelated cli auth isolation

* test: expand auth profile contract matrix

* test: tighten auth profile contract expectations

* test: add outcome fallback runtime contracts

* test: strengthen outcome fallback contracts

* test: isolate outcome fallback contracts

* test: cover codex terminal outcome signals

* test: expand terminal fallback contracts

* test: add delivery no reply runtime contracts

* test: document json no-reply delivery gap

* test: align delivery contract fixtures

* test: add transcript repair runtime contracts

* test: tighten transcript repair contracts

* test: add prompt overlay runtime contracts

* test: tighten prompt overlay contract scope

* test: type prompt overlay contracts

* test: add schema normalization runtime contracts

* test: clarify schema normalization contract gaps

* test: simplify schema normalization contracts

* test: tighten schema normalization contract gaps

* test: cover compaction schema contract

* test: satisfy schema contract lint

* test: add transport params runtime contracts

* test: tighten transport params contract scope

* test: isolate transport params contracts

* test: lock exact transport defaults

* feat: add agent runtime plan foundation

* fix: preserve codex harness auth profiles

* fix: route followup delivery through runtime plan

* fix: normalize parameter-free openai tool schemas

* fix: satisfy runtime plan type checks

* fix: narrow followup delivery runtime planning

* fix: apply codex app-server auth profiles

* fix: classify codex terminal outcomes

* fix: prevent harness auth leakage into unrelated cli providers

* feat: expand agent runtime plan policy contract

* fix: route pi runtime policy through runtime plan

* fix: route codex runtime policy through runtime plan

* fix: route fallback outcome classification through runtime plan

* refactor: make runtime plan contracts topology-safe

* fix: restore runtime plan test type coverage

* fix: align runtime plan schema contract assertions

* fix: stabilize incomplete turn runtime tests

* fix: stabilize codex native web search test

* fix: preserve codex auth profile secret refs

* fix: keep runtime resolved refs canonical

* fix: preserve permissive nested openai schemas

* fix: accept Codex auth provider aliases

* test: update media-only groups mock

* fix: resolve runtime plan rebase checks

* fix: resolve runtime plan rebase checks

---------

Co-authored-by: Eva <eva@100yen.org>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-04-24 18:34:01 +01:00

270 lines
7.3 KiB
TypeScript

import { describe, expect, it } from "vitest";
import {
buildCodexNativeWebSearchTool,
describeCodexNativeWebSearch,
patchCodexNativeWebSearchPayload,
resolveCodexNativeSearchActivation,
resolveCodexNativeWebSearchConfig,
isCodexNativeWebSearchRelevant,
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<string, unknown> = { 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<string, unknown> = { 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", () => {
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);
});
});