mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-27 21:07:01 -06:00
docs: document openai transport tests
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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}`)),
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user