docs: document openai transport tests

This commit is contained in:
Peter Steinberger
2026-06-04 15:32:37 -04:00
parent 48d67e88d0
commit 1df9bca8e2
6 changed files with 20 additions and 0 deletions
@@ -1,3 +1,4 @@
// Verifies OpenAI Responses replay preserves reasoning and response item ids.
import type { AssistantMessage, Model, ToolResultMessage } from "openclaw/plugin-sdk/llm";
import { stream } from "openclaw/plugin-sdk/llm";
import { Type } from "typebox";
@@ -88,6 +89,7 @@ async function runAbortedOpenAIResponsesStream(params: {
}>;
replayResponsesItemIds?: boolean;
}) {
// Abort after payload capture so tests inspect serialization without network I/O.
const controller = new AbortController();
controller.abort();
let payload: Record<string, unknown> | undefined;
@@ -224,6 +226,7 @@ describe("openai-responses reasoning replay", () => {
});
it("does not replay a signed assistant message id after its reasoning item was pruned", async () => {
// Signed message ids are only safe to replay when their preceding reasoning item survived.
expect(
resolveReplayableResponsesMessageId({
replayResponsesItemIds: true,
+3
View File
@@ -1,3 +1,4 @@
// Verifies OpenAI model selections route between OpenClaw and Codex runtimes.
import { describe, expect, it } from "vitest";
import type { OpenClawConfig } from "../config/types.openclaw.js";
import {
@@ -21,6 +22,7 @@ describe("OpenAI runtime routing policy", () => {
});
it("does not force Codex for custom OpenAI-compatible base URLs", () => {
// A custom baseUrl means the provider key is only OpenAI-compatible, not official OpenAI.
const config = {
models: {
providers: {
@@ -90,6 +92,7 @@ describe("OpenAI runtime routing policy", () => {
});
it("keeps explicit OpenClaw plus Codex auth profile under the unified OpenAI provider", () => {
// OpenAI auth now stays canonical even when the runtime is not Codex.
expect(
listOpenAIAuthProfileProvidersForAgentRuntime({
provider: "openai",
@@ -1,3 +1,4 @@
// Verifies session thinking levels reach OpenAI and Codex Responses transports.
import { Agent, type StreamFn } from "openclaw/plugin-sdk/agent-core";
import {
createAssistantMessageEventStream,
@@ -119,6 +120,7 @@ function createCapturingStreamFn(
model: ResponsesModel,
capturedOptions: SimpleStreamOptions[],
): StreamFn {
// Captures Agent -> stream options while returning a complete assistant event.
return (_model, _context, options) => {
capturedOptions.push({ ...options });
const stream = createAssistantMessageEventStream();
@@ -164,6 +166,7 @@ async function captureProviderPayload<
) => ReturnType<StreamFn>;
options: SimpleStreamOptions;
}): Promise<Record<string, unknown>> {
// Stop at onPayload so transport serialization can be asserted without HTTP.
const payloadPromise = new Promise<Record<string, unknown>>((resolve, reject) => {
const timeout = setTimeout(
() => reject(new Error(`provider payload callback was not invoked for ${params.model.api}`)),
+3
View File
@@ -1,3 +1,4 @@
// Verifies OpenAI strict tool schema normalization and cache behavior.
import { beforeEach, describe, expect, it } from "vitest";
import {
clearOpenAIToolSchemaCacheForTest,
@@ -35,6 +36,7 @@ describe("OpenAI strict tool schema normalization", () => {
});
it("does not close permissive nested object schemas implicitly", () => {
// Nested permissive objects stay incompatible unless callers make them strict.
const schema = {
type: "object",
properties: {
@@ -69,6 +71,7 @@ describe("OpenAI strict tool schema normalization", () => {
});
it("reuses normalized strict schemas for stable tool schema objects", () => {
// Cache keys include unsupported-keyword policy, not just object identity.
const schema = {
type: "object",
properties: {
@@ -1,3 +1,4 @@
// Verifies OpenAI-compatible streaming payloads, failures, and transport wrapping.
import { createServer } from "node:http";
import type { Api, Model } from "openclaw/plugin-sdk/llm";
import { describe, expect, it, vi } from "vitest";
@@ -99,6 +100,7 @@ function createAzureResponsesModel(): Model<"azure-openai-responses"> {
}
function neverYieldsStream(): AsyncIterable<unknown> {
// Simulates an HTTP stream that opened but never delivered the first SSE event.
return {
[Symbol.asyncIterator]() {
return {
@@ -116,6 +118,7 @@ async function* streamChunks(chunks: readonly unknown[]): AsyncGenerator<never>
}
function expectRecordFields(record: unknown, expected: Record<string, unknown>) {
// Shared assertion helper for parsed transport payload/event records.
if (!record || typeof record !== "object") {
throw new Error("Expected record");
}
@@ -141,6 +144,7 @@ describe("openai transport stream", () => {
});
it("observes detail-less Responses failures without leaking request ids", async () => {
// Observation should preserve hashes/metadata shape while dropping raw request ids.
const model = createAzureResponsesModel();
const event = {
type: "response.failed",
+4
View File
@@ -1,3 +1,4 @@
// Verifies OpenClaw gateway tool schema, restart signaling, and config mutations.
import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
@@ -19,6 +20,7 @@ vi.mock("./tools/gateway.js", () => ({
}));
function requireGatewayTool(agentSessionKey?: string) {
// Tests run with restart enabled so schema and execution paths are visible.
return createGatewayTool({
...(agentSessionKey ? { agentSessionKey } : {}),
config: { commands: { restart: true } },
@@ -26,6 +28,7 @@ function requireGatewayTool(agentSessionKey?: string) {
}
function collectActionValues(schema: unknown, values: Set<string>): void {
// Tool schemas can expose actions through const, enum, or anyOf variants.
if (!schema || typeof schema !== "object") {
return;
}
@@ -109,6 +112,7 @@ function expectConfigMutationCall(params: {
raw: string;
sessionKey: string;
}) {
// Config writes must include the base hash from a preceding config.get read.
expect(params.callGatewayTool.mock.calls.some(([method]) => method === "config.get")).toBe(true);
const call = params.callGatewayTool.mock.calls.find(([method]) => method === params.action);
if (!call) {