mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 10:40:43 +00:00
perf: lazy codex app server test imports
This commit is contained in:
@@ -8,6 +8,12 @@ import { type CodexAppServerClientFactory } from "./src/app-server/client-factor
|
||||
import type { CodexAppServerClient } from "./src/app-server/client.js";
|
||||
import { resolveCodexAppServerRuntimeOptions } from "./src/app-server/config.js";
|
||||
import { readModelListResult } from "./src/app-server/models.js";
|
||||
import {
|
||||
assertCodexThreadStartResponse,
|
||||
assertCodexTurnStartResponse,
|
||||
readCodexErrorNotification,
|
||||
readCodexTurnCompletedNotification,
|
||||
} from "./src/app-server/protocol-validators.js";
|
||||
import {
|
||||
isJsonObject,
|
||||
type CodexServerNotification,
|
||||
@@ -17,13 +23,6 @@ import {
|
||||
type CodexTurnStartParams,
|
||||
type JsonObject,
|
||||
} from "./src/app-server/protocol.js";
|
||||
import {
|
||||
assertCodexThreadStartResponse,
|
||||
assertCodexTurnStartResponse,
|
||||
readCodexErrorNotification,
|
||||
readCodexTurnCompletedNotification,
|
||||
} from "./src/app-server/protocol-validators.js";
|
||||
import { createIsolatedCodexAppServerClient } from "./src/app-server/shared-client.js";
|
||||
|
||||
const DEFAULT_CODEX_IMAGE_MODEL =
|
||||
FALLBACK_CODEX_MODELS.find((model) => model.inputModalities.includes("image"))?.id ??
|
||||
@@ -83,11 +82,14 @@ async function describeCodexImages(
|
||||
const ownsClient = !options.clientFactory;
|
||||
const client = options.clientFactory
|
||||
? await options.clientFactory(appServer.start, req.profile)
|
||||
: await createIsolatedCodexAppServerClient({
|
||||
startOptions: appServer.start,
|
||||
timeoutMs,
|
||||
authProfileId: req.profile,
|
||||
});
|
||||
: await import("./src/app-server/shared-client.js").then(
|
||||
({ createIsolatedCodexAppServerClient }) =>
|
||||
createIsolatedCodexAppServerClient({
|
||||
startOptions: appServer.start,
|
||||
timeoutMs,
|
||||
authProfileId: req.profile,
|
||||
}),
|
||||
);
|
||||
const abortController = new AbortController();
|
||||
const timeout = setTimeout(() => abortController.abort("timeout"), timeoutMs);
|
||||
timeout.unref?.();
|
||||
@@ -229,7 +231,8 @@ function createCodexImageTurnCollector(threadId: string) {
|
||||
return;
|
||||
}
|
||||
if (notification.method === "turn/completed") {
|
||||
completedTurn = readCodexTurnCompletedNotification(notification.params)?.turn ?? completedTurn;
|
||||
completedTurn =
|
||||
readCodexTurnCompletedNotification(notification.params)?.turn ?? completedTurn;
|
||||
resolveCompletion?.();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import type { CodexAppServerClient } from "./client.js";
|
||||
import type { CodexAppServerStartOptions } from "./config.js";
|
||||
import { getSharedCodexAppServerClient } from "./shared-client.js";
|
||||
|
||||
export type CodexAppServerClientFactory = (
|
||||
startOptions?: CodexAppServerStartOptions,
|
||||
@@ -10,7 +9,10 @@ export type CodexAppServerClientFactory = (
|
||||
export const defaultCodexAppServerClientFactory: CodexAppServerClientFactory = (
|
||||
startOptions,
|
||||
authProfileId,
|
||||
) => getSharedCodexAppServerClient({ startOptions, authProfileId });
|
||||
) =>
|
||||
import("./shared-client.js").then(({ getSharedCodexAppServerClient }) =>
|
||||
getSharedCodexAppServerClient({ startOptions, authProfileId }),
|
||||
);
|
||||
|
||||
export function createCodexAppServerClientFactoryTestHooks(
|
||||
setFactory: (factory: CodexAppServerClientFactory) => void,
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
import type { CodexAppServerStartOptions } from "./config.js";
|
||||
import type { v2 } from "./protocol-generated/typescript/index.js";
|
||||
import { readCodexModelListResponse } from "./protocol-validators.js";
|
||||
import {
|
||||
createIsolatedCodexAppServerClient,
|
||||
getSharedCodexAppServerClient,
|
||||
} from "./shared-client.js";
|
||||
|
||||
export type CodexAppServerModel = {
|
||||
id: string;
|
||||
@@ -38,6 +34,8 @@ export async function listCodexAppServerModels(
|
||||
): Promise<CodexAppServerModelListResult> {
|
||||
const timeoutMs = options.timeoutMs ?? 2500;
|
||||
const useSharedClient = options.sharedClient !== false;
|
||||
const { createIsolatedCodexAppServerClient, getSharedCodexAppServerClient } =
|
||||
await import("./shared-client.js");
|
||||
const client = useSharedClient
|
||||
? await getSharedCodexAppServerClient({
|
||||
startOptions: options.startOptions,
|
||||
|
||||
@@ -32,6 +32,10 @@ import { resolveCodexAppServerRuntimeOptions } from "./config.js";
|
||||
import { createCodexDynamicToolBridge } from "./dynamic-tools.js";
|
||||
import { handleCodexAppServerElicitationRequest } from "./elicitation-bridge.js";
|
||||
import { CodexAppServerEventProjector } from "./event-projector.js";
|
||||
import {
|
||||
assertCodexTurnStartResponse,
|
||||
readCodexDynamicToolCallParams,
|
||||
} from "./protocol-validators.js";
|
||||
import {
|
||||
isJsonObject,
|
||||
type CodexServerNotification,
|
||||
@@ -40,10 +44,6 @@ import {
|
||||
type JsonObject,
|
||||
type JsonValue,
|
||||
} from "./protocol.js";
|
||||
import {
|
||||
assertCodexTurnStartResponse,
|
||||
readCodexDynamicToolCallParams,
|
||||
} from "./protocol-validators.js";
|
||||
import { readCodexAppServerBinding, type CodexAppServerThreadBinding } from "./session-binding.js";
|
||||
import { clearSharedCodexAppServerClient } from "./shared-client.js";
|
||||
import {
|
||||
@@ -58,6 +58,7 @@ import {
|
||||
recordCodexTrajectoryContext,
|
||||
} from "./trajectory.js";
|
||||
import { mirrorCodexAppServerTranscript } from "./transcript-mirror.js";
|
||||
import { filterToolsForVisionInputs } from "./vision-tools.js";
|
||||
|
||||
let clientFactory = defaultCodexAppServerClientFactory;
|
||||
|
||||
@@ -601,19 +602,6 @@ async function buildDynamicTools(input: DynamicToolBuildParams) {
|
||||
});
|
||||
}
|
||||
|
||||
function filterToolsForVisionInputs<T extends { name?: string }>(
|
||||
tools: T[],
|
||||
params: {
|
||||
modelHasVision: boolean;
|
||||
hasInboundImages: boolean;
|
||||
},
|
||||
): T[] {
|
||||
if (!params.modelHasVision || !params.hasInboundImages) {
|
||||
return tools;
|
||||
}
|
||||
return tools.filter((tool) => tool.name !== "image");
|
||||
}
|
||||
|
||||
async function withCodexStartupTimeout<T>(params: {
|
||||
timeoutMs: number;
|
||||
timeoutFloorMs?: number;
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { __testing } from "./run-attempt.js";
|
||||
import { filterToolsForVisionInputs } from "./vision-tools.js";
|
||||
|
||||
describe("Codex dynamic tool filtering", () => {
|
||||
it("drops the image tool when the model already has inbound vision input", () => {
|
||||
const toolNames = __testing
|
||||
.filterToolsForVisionInputs([{ name: "image" }, { name: "read" }, { name: "write" }], {
|
||||
const toolNames = filterToolsForVisionInputs(
|
||||
[{ name: "image" }, { name: "read" }, { name: "write" }],
|
||||
{
|
||||
modelHasVision: true,
|
||||
hasInboundImages: true,
|
||||
})
|
||||
.map((tool) => tool.name);
|
||||
},
|
||||
).map((tool) => tool.name);
|
||||
|
||||
expect(toolNames).toContain("read");
|
||||
expect(toolNames).toContain("write");
|
||||
@@ -19,13 +20,13 @@ describe("Codex dynamic tool filtering", () => {
|
||||
const tools = [{ name: "image" }, { name: "read" }];
|
||||
|
||||
expect(
|
||||
__testing.filterToolsForVisionInputs(tools, {
|
||||
filterToolsForVisionInputs(tools, {
|
||||
modelHasVision: false,
|
||||
hasInboundImages: true,
|
||||
}),
|
||||
).toBe(tools);
|
||||
expect(
|
||||
__testing.filterToolsForVisionInputs(tools, {
|
||||
filterToolsForVisionInputs(tools, {
|
||||
modelHasVision: true,
|
||||
hasInboundImages: false,
|
||||
}),
|
||||
|
||||
12
extensions/codex/src/app-server/vision-tools.ts
Normal file
12
extensions/codex/src/app-server/vision-tools.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
export function filterToolsForVisionInputs<T extends { name?: string }>(
|
||||
tools: T[],
|
||||
params: {
|
||||
modelHasVision: boolean;
|
||||
hasInboundImages: boolean;
|
||||
},
|
||||
): T[] {
|
||||
if (!params.modelHasVision || !params.hasInboundImages) {
|
||||
return tools;
|
||||
}
|
||||
return tools.filter((tool) => tool.name !== "image");
|
||||
}
|
||||
Reference in New Issue
Block a user