mirror of
https://github.com/moltbot/moltbot.git
synced 2026-03-07 22:44:16 +00:00
test(gateway): reuse shared openai timeout e2e helpers
This commit is contained in:
@@ -149,12 +149,7 @@ function decodeBodyText(body: unknown): string {
|
||||
return "";
|
||||
}
|
||||
|
||||
async function buildOpenAIResponsesSse(params: OpenAIResponsesParams): Promise<Response> {
|
||||
const events: OpenAIResponseStreamEvent[] = [];
|
||||
for await (const event of fakeOpenAIResponsesStream(params)) {
|
||||
events.push(event);
|
||||
}
|
||||
|
||||
function buildSseResponse(events: unknown[]): Response {
|
||||
const sse = `${events.map((e) => `data: ${JSON.stringify(e)}\n\n`).join("")}data: [DONE]\n\n`;
|
||||
const encoder = new TextEncoder();
|
||||
const body = new ReadableStream<Uint8Array>({
|
||||
@@ -169,6 +164,46 @@ async function buildOpenAIResponsesSse(params: OpenAIResponsesParams): Promise<R
|
||||
});
|
||||
}
|
||||
|
||||
export function buildOpenAIResponsesTextSse(text: string): Response {
|
||||
return buildSseResponse([
|
||||
{
|
||||
type: "response.output_item.added",
|
||||
item: {
|
||||
type: "message",
|
||||
id: "msg_test_1",
|
||||
role: "assistant",
|
||||
content: [],
|
||||
status: "in_progress",
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "response.output_item.done",
|
||||
item: {
|
||||
type: "message",
|
||||
id: "msg_test_1",
|
||||
role: "assistant",
|
||||
status: "completed",
|
||||
content: [{ type: "output_text", text, annotations: [] }],
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "response.completed",
|
||||
response: {
|
||||
status: "completed",
|
||||
usage: { input_tokens: 10, output_tokens: 10, total_tokens: 20 },
|
||||
},
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
async function buildOpenAIResponsesSse(params: OpenAIResponsesParams): Promise<Response> {
|
||||
const events: OpenAIResponseStreamEvent[] = [];
|
||||
for await (const event of fakeOpenAIResponsesStream(params)) {
|
||||
events.push(event);
|
||||
}
|
||||
return buildSseResponse(events);
|
||||
}
|
||||
|
||||
export function installOpenAiResponsesMock(params?: { baseUrl?: string }) {
|
||||
const originalFetch = globalThis.fetch;
|
||||
const baseUrl = params?.baseUrl ?? "https://api.openai.com/v1";
|
||||
|
||||
@@ -3,78 +3,11 @@ import fs from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { extractPayloadText } from "../src/gateway/test-helpers.agent-results.js";
|
||||
import { startGatewayWithClient } from "../src/gateway/test-helpers.e2e.js";
|
||||
import { buildOpenAIResponsesTextSse } from "../src/gateway/test-helpers.openai-mock.js";
|
||||
import { buildOpenAiResponsesProviderConfig } from "../src/gateway/test-openai-responses-model.js";
|
||||
|
||||
type OpenAIResponseStreamEvent =
|
||||
| { type: "response.output_item.added"; item: Record<string, unknown> }
|
||||
| { type: "response.output_item.done"; item: Record<string, unknown> }
|
||||
| {
|
||||
type: "response.completed";
|
||||
response: {
|
||||
status: "completed";
|
||||
usage: {
|
||||
input_tokens: number;
|
||||
output_tokens: number;
|
||||
total_tokens: number;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
function buildOpenAIResponsesSse(text: string): Response {
|
||||
const events: OpenAIResponseStreamEvent[] = [
|
||||
{
|
||||
type: "response.output_item.added",
|
||||
item: {
|
||||
type: "message",
|
||||
id: "msg_test_1",
|
||||
role: "assistant",
|
||||
content: [],
|
||||
status: "in_progress",
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "response.output_item.done",
|
||||
item: {
|
||||
type: "message",
|
||||
id: "msg_test_1",
|
||||
role: "assistant",
|
||||
status: "completed",
|
||||
content: [{ type: "output_text", text, annotations: [] }],
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "response.completed",
|
||||
response: {
|
||||
status: "completed",
|
||||
usage: { input_tokens: 10, output_tokens: 10, total_tokens: 20 },
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const sse = `${events.map((e) => `data: ${JSON.stringify(e)}\n\n`).join("")}data: [DONE]\n\n`;
|
||||
const encoder = new TextEncoder();
|
||||
const body = new ReadableStream<Uint8Array>({
|
||||
start(controller) {
|
||||
controller.enqueue(encoder.encode(sse));
|
||||
controller.close();
|
||||
},
|
||||
});
|
||||
return new Response(body, {
|
||||
status: 200,
|
||||
headers: { "content-type": "text/event-stream" },
|
||||
});
|
||||
}
|
||||
|
||||
function extractPayloadText(result: unknown): string {
|
||||
const record = result as Record<string, unknown>;
|
||||
const payloads = Array.isArray(record.payloads) ? record.payloads : [];
|
||||
const texts = payloads
|
||||
.map((p) => (p && typeof p === "object" ? (p as Record<string, unknown>).text : undefined))
|
||||
.filter((t): t is string => typeof t === "string" && t.trim().length > 0);
|
||||
return texts.join("\n").trim();
|
||||
}
|
||||
|
||||
describe("provider timeouts (e2e)", () => {
|
||||
it(
|
||||
"falls back when the primary provider aborts with a timeout-like AbortError",
|
||||
@@ -107,7 +40,7 @@ describe("provider timeouts (e2e)", () => {
|
||||
|
||||
if (url.startsWith(`${fallbackBaseUrl}/responses`)) {
|
||||
counts.fallback += 1;
|
||||
return buildOpenAIResponsesSse("fallback-ok");
|
||||
return buildOpenAIResponsesTextSse("fallback-ok");
|
||||
}
|
||||
|
||||
if (!originalFetch) {
|
||||
|
||||
Reference in New Issue
Block a user