import type { StreamFn } from "@earendil-works/pi-agent-core"; import { createNativeOpenAIResponsesModel, createParameterFreeTool, createPermissiveTool, createStrictCompatibleTool, normalizedParameterFreeSchema, } from "openclaw/plugin-sdk/agent-runtime-test-contracts"; import { describe, expect, it } from "vitest"; import { buildProviderToolCompatFamilyHooks } from "../plugin-sdk/provider-tools.js"; import { buildOpenAIResponsesParams } from "./openai-transport-stream.js"; import { createOpenAIResponsesContextManagementWrapper } from "./pi-embedded-runner/openai-stream-wrappers.js"; describe("OpenAI transport schema normalization runtime contract", () => { it("keeps HTTP Responses strict decisions stable for the same tool set", () => { const tools = [createStrictCompatibleTool(), createPermissiveTool()] as never; const httpParams = buildOpenAIResponsesParams( createNativeOpenAIResponsesModel() as never, { systemPrompt: "system", messages: [], tools } as never, undefined, ) as { tools?: Array<{ strict?: boolean; parameters?: unknown }> }; expect(httpParams.tools?.map((tool) => tool.strict)).toEqual([false, false]); }); it("normalizes parameter-free tool schemas to the strict-compatible HTTP Responses shape", () => { const tools = [createParameterFreeTool()] as never; const httpParams = buildOpenAIResponsesParams( createNativeOpenAIResponsesModel() as never, { systemPrompt: "system", messages: [], tools } as never, undefined, ) as { tools?: Array<{ strict?: boolean; parameters?: unknown }> }; const normalizedSchema = normalizedParameterFreeSchema(); expect(httpParams.tools?.[0]?.strict).toBe(true); expect(httpParams.tools?.[0]?.parameters).toEqual(normalizedSchema); }); it("keeps provider-prepared parameter-free schemas strict-compatible for HTTP Responses", () => { const hooks = buildProviderToolCompatFamilyHooks("openai"); const tools = hooks.normalizeToolSchemas({ provider: "openai", modelId: "gpt-5.4", modelApi: "openai-responses", tools: [createParameterFreeTool()] as never, }) as never; const httpParams = buildOpenAIResponsesParams( createNativeOpenAIResponsesModel() as never, { systemPrompt: "system", messages: [], tools } as never, undefined, ) as { tools?: Array<{ strict?: boolean; parameters?: unknown }> }; const normalizedSchema = normalizedParameterFreeSchema(); expect(httpParams.tools?.[0]?.strict).toBe(true); expect(httpParams.tools?.[0]?.parameters).toEqual(normalizedSchema); }); it("passes prepared executable schemas through compaction-triggered Responses requests", () => { const hooks = buildProviderToolCompatFamilyHooks("openai"); const tools = hooks.normalizeToolSchemas({ provider: "openai", modelId: "gpt-5.4", modelApi: "openai-responses", tools: [createParameterFreeTool()] as never, }) as never; const model = createNativeOpenAIResponsesModel() as never; let payload: | { context_management?: unknown; tools?: Array<{ parameters?: unknown }> } | undefined; const baseStreamFn: StreamFn = (modelArg, contextArg, optionsArg) => { payload = buildOpenAIResponsesParams( modelArg, { ...(contextArg as unknown as Record), systemPrompt: "system", messages: [], tools, } as never, optionsArg as never, ) as typeof payload; optionsArg?.onPayload?.(payload, modelArg); return {} as ReturnType; }; const streamFn = createOpenAIResponsesContextManagementWrapper(baseStreamFn, { responsesServerCompaction: true, }); void streamFn(model, { systemPrompt: "system", messages: [], tools } as never, {}); expect(payload?.context_management).toEqual([ { type: "compaction", compact_threshold: 140_000, }, ]); expect(payload?.tools?.[0]?.parameters).toEqual(normalizedParameterFreeSchema()); }); });