



















@@ -1236,23 +1236,32 @@ describe("runCodexAppServerAttempt", () => {
12361236});
1237123712381238it("routes native Codex execution through an OpenClaw sandbox exec-server when opted in", async () => {
1239-const runtimeId = `codex-test-runtime-${path.basename(tempDir)}`;
1240-const restoreSandboxBackend = registerSandboxBackend("codex-test-sandbox", async () => ({
1241-id: "codex-test-sandbox",
1242- runtimeId,
1243-runtimeLabel: "Codex Test Sandbox",
1244-workdir: "/workspace",
1245-buildExecSpec: async () => ({
1246-argv: ["true"],
1247-env: {},
1248-stdinMode: "pipe-closed" as const,
1249-}),
1250-runShellCommand: async () => ({
1251-stdout: Buffer.alloc(0),
1252-stderr: Buffer.alloc(0),
1253-code: 0,
1239+const appServer = createThreadLifecycleAppServerOptions();
1240+const sandbox = {
1241+ ...createSandboxContext({
1242+runShellCommand: async () => ({
1243+stdout: Buffer.alloc(0),
1244+stderr: Buffer.alloc(0),
1245+code: 0,
1246+}),
12541247}),
1255-}));
1248+backendId: "codex-test-sandbox",
1249+runtimeId: `codex-test-runtime-${path.basename(tempDir)}`,
1250+runtimeLabel: "Codex Test Sandbox",
1251+};
1252+const request = vi.fn(async (method: string, _requestParams?: unknown) => {
1253+if (method === "environment/add") {
1254+return {};
1255+}
1256+if (method === "thread/start") {
1257+return threadStartResult();
1258+}
1259+throw new Error(`unexpected method: ${method}`);
1260+});
1261+const client = {
1262+getServerVersion: () => "0.132.0",
1263+ request,
1264+};
12561265try {
12571266testing.setOpenClawCodingToolsFactoryForTests(() => [
12581267createRuntimeDynamicTool("exec"),
@@ -1277,26 +1286,64 @@ describe("runCodexAppServerAttempt", () => {
12771286},
12781287},
12791288} as never;
1280-const { requests, waitForMethod, completeTurn } = createStartedThreadHarness();
1281-1282-const run = runCodexAppServerAttempt(params, {
1289+const nativeToolSurfaceEnabled = testing.shouldEnableCodexAppServerNativeToolSurface(
1290+params,
1291+sandbox as never,
1292+{ sandboxExecServerEnabled: true },
1293+);
1294+const dynamicTools = await testing.buildDynamicTools({
1295+ params,
1296+resolvedWorkspace: workspaceDir,
1297+effectiveWorkspace: "/workspace",
1298+sandboxSessionKey: params.sessionKey!,
1299+sandbox: sandbox as never,
1300+ nativeToolSurfaceEnabled,
1301+runAbortController: new AbortController(),
1302+sessionAgentId: "main",
12831303pluginConfig: {
12841304appServer: {
12851305mode: "yolo",
12861306experimental: { sandboxExecServer: true },
12871307},
12881308},
1309+onYieldDetected: () => undefined,
12891310});
1290-await waitForMethod("turn/start");
1291-await completeTurn({ threadId: "thread-1", turnId: "turn-1" });
1292-await run;
1311+const environment = await ensureCodexSandboxExecServerEnvironment({
1312+client: client as never,
1313+sandbox: sandbox as never,
1314+appServerStartOptions: appServer.start,
1315+});
1316+if (!environment) {
1317+throw new Error("expected sandbox exec-server environment");
1318+}
1319+const environmentSelection = [environment];
129313201294-const environmentAdd = requests.find((request) => request.method === "environment/add");
1295-const environmentAddParams = environmentAdd?.params as
1321+await startOrResumeThread({
1322+client: client as never,
1323+ params,
1324+cwd: environment.cwd,
1325+dynamicTools: dynamicTools as never,
1326+ appServer,
1327+nativeCodeModeEnabled: nativeToolSurfaceEnabled,
1328+nativeCodeModeOnlyEnabled: false,
1329+userMcpServersEnabled: nativeToolSurfaceEnabled,
1330+ environmentSelection,
1331+});
1332+1333+const turnParams = buildTurnStartParams(params, {
1334+threadId: "thread-1",
1335+cwd: environment.cwd,
1336+ appServer,
1337+sandboxPolicy: { type: "externalSandbox", networkAccess: "enabled" },
1338+ environmentSelection,
1339+});
1340+1341+const environmentAdd = request.mock.calls.find(([method]) => method === "environment/add");
1342+const environmentAddParams = environmentAdd?.[1] as
12961343| { environmentId?: string; execServerUrl?: string }
12971344| undefined;
1298-const startRequest = requests.find((request) => request.method === "thread/start");
1299-const startParams = startRequest?.params as
1345+const startRequest = request.mock.calls.find(([method]) => method === "thread/start");
1346+const startParams = startRequest?.[1] as
13001347| {
13011348cwd?: string;
13021349dynamicTools?: Array<{ name: string }>;
@@ -1308,15 +1355,8 @@ describe("runCodexAppServerAttempt", () => {
13081355};
13091356}
13101357| undefined;
1311-const turnRequest = requests.find((request) => request.method === "turn/start");
1312-const turnParams = turnRequest?.params as
1313-| {
1314-cwd?: string;
1315-environments?: Array<{ environmentId?: string; cwd?: string }>;
1316-sandboxPolicy?: { type?: string; networkAccess?: string };
1317-}
1318-| undefined;
131913581359+expect(nativeToolSurfaceEnabled).toBe(true);
13201360expect(environmentAddParams?.environmentId).toMatch(/^openclaw-sandbox-/);
13211361expect(environmentAddParams?.execServerUrl).toMatch(/^ws:\/\/127\.0\.0\.1:/);
13221362expect(startParams?.cwd).toBe("/workspace");
@@ -1327,14 +1367,14 @@ describe("runCodexAppServerAttempt", () => {
13271367{ environmentId: environmentAddParams?.environmentId, cwd: "/workspace" },
13281368]);
13291369expect(startParams?.sandbox).toBe("danger-full-access");
1330-expect(turnParams?.sandboxPolicy).toEqual({
1370+expect(turnParams.sandboxPolicy).toEqual({
13311371type: "externalSandbox",
13321372networkAccess: "enabled",
13331373});
1334-expect(turnParams?.cwd).toBe("/workspace");
1335-expect(turnParams?.environments).toEqual(startParams?.environments);
1374+expect(turnParams.cwd).toBe("/workspace");
1375+expect(turnParams.environments).toEqual(startParams?.environments);
13361376} finally {
1337-restoreSandboxBackend();
1377+await releaseCodexSandboxExecServerEnvironment(sandbox as never);
13381378}
13391379});
13401380此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。