





















@@ -1233,76 +1233,101 @@ describe("runCliAgent spawn path", () => {
12331233});
1234123412351235it("keeps captured live prepared backend cleanup with the whole-run owner", async () => {
1236-let stdoutListener: ((chunk: string) => void) | undefined;
1237-let resolveExit: ((exit: RunExit) => void) | undefined;
1238-const exited = new Promise<RunExit>((resolve) => {
1239-resolveExit = resolve;
1240-});
1241-supervisorSpawnMock.mockImplementation(async (...args: unknown[]) => {
1242-const input = (args[0] ?? {}) as { onStdout?: (chunk: string) => void };
1243-stdoutListener = input.onStdout;
1244-return {
1245-runId: "captured-live-cleanup-run",
1246-pid: 2347,
1247-startedAtMs: Date.now(),
1248-stdin: {
1249-write: vi.fn((dataValue: string, cb?: (err?: Error | null) => void) => {
1250-stdoutListener?.(
1251-[
1252-JSON.stringify({
1253-type: "system",
1254-subtype: "init",
1255-session_id: "captured-live-cleanup",
1256-}),
1257-JSON.stringify({
1258-type: "result",
1259-session_id: "captured-live-cleanup",
1260-result: "ok",
1261-}),
1262-].join("\n") + "\n",
1263-);
1264-cb?.();
1265-}),
1266-end: vi.fn(),
1236+const mcpConfigDir = await fs.mkdtemp(
1237+path.join(os.tmpdir(), "openclaw-cli-captured-mcp-config-"),
1238+);
1239+const mcpConfigPath = path.join(mcpConfigDir, "mcp.json");
1240+await fs.writeFile(
1241+mcpConfigPath,
1242+`${JSON.stringify(
1243+ {
1244+ mcpServers: {
1245+ openclaw: {
1246+ type: "http",
1247+ url: "http://127.0.0.1:23119/mcp",
1248+ headers: {},
1249+ },
1250+ },
12671251 },
1268-wait: vi.fn(() => exited),
1269-cancel: vi.fn(() =>
1270-resolveExit?.({
1271-reason: "manual-cancel",
1272-exitCode: null,
1273-exitSignal: null,
1274-durationMs: 1,
1275-stdout: "",
1276-stderr: "",
1277-timedOut: false,
1278-noOutputTimedOut: false,
1279-}),
1280-),
1281-};
1282-});
1283-const preparedBackendCleanup = vi.fn(async () => {});
1284-const context = buildPreparedCliRunContext({
1285-provider: "claude-cli",
1286-model: "sonnet",
1287-runId: "run-captured-live-cleanup",
1288-prompt: "first",
1289-backend: {
1290-args: ["-p", "--strict-mcp-config", "--mcp-config", "/tmp/mcp-captured.json"],
1291-liveSession: "claude-stdio",
1292-},
1293-mcpConfigHash: "captured-cleanup-mcp-config",
1294-mcpDeliveryCapture: true,
1295-});
1296-context.preparedBackend.cleanup = preparedBackendCleanup;
1252+ null,
1253+ 2,
1254+ )}\n`,
1255+"utf-8",
1256+);
1257+try {
1258+let stdoutListener: ((chunk: string) => void) | undefined;
1259+let resolveExit: ((exit: RunExit) => void) | undefined;
1260+const exited = new Promise<RunExit>((resolve) => {
1261+resolveExit = resolve;
1262+});
1263+supervisorSpawnMock.mockImplementation(async (...args: unknown[]) => {
1264+const input = (args[0] ?? {}) as { onStdout?: (chunk: string) => void };
1265+stdoutListener = input.onStdout;
1266+return {
1267+runId: "captured-live-cleanup-run",
1268+pid: 2347,
1269+startedAtMs: Date.now(),
1270+stdin: {
1271+write: vi.fn((dataValue: string, cb?: (err?: Error | null) => void) => {
1272+stdoutListener?.(
1273+[
1274+JSON.stringify({
1275+type: "system",
1276+subtype: "init",
1277+session_id: "captured-live-cleanup",
1278+}),
1279+JSON.stringify({
1280+type: "result",
1281+session_id: "captured-live-cleanup",
1282+result: "ok",
1283+}),
1284+].join("\n") + "\n",
1285+);
1286+cb?.();
1287+}),
1288+end: vi.fn(),
1289+},
1290+wait: vi.fn(() => exited),
1291+cancel: vi.fn(() =>
1292+resolveExit?.({
1293+reason: "manual-cancel",
1294+exitCode: null,
1295+exitSignal: null,
1296+durationMs: 1,
1297+stdout: "",
1298+stderr: "",
1299+timedOut: false,
1300+noOutputTimedOut: false,
1301+}),
1302+),
1303+};
1304+});
1305+const preparedBackendCleanup = vi.fn(async () => {});
1306+const context = buildPreparedCliRunContext({
1307+provider: "claude-cli",
1308+model: "sonnet",
1309+runId: "run-captured-live-cleanup",
1310+prompt: "first",
1311+backend: {
1312+args: ["-p", "--strict-mcp-config", "--mcp-config", mcpConfigPath],
1313+liveSession: "claude-stdio",
1314+},
1315+mcpConfigHash: "captured-cleanup-mcp-config",
1316+mcpDeliveryCapture: true,
1317+});
1318+context.preparedBackend.cleanup = preparedBackendCleanup;
129713191298-const result = await executePreparedCliRun(context);
1320+ const result = await executePreparedCliRun(context);
129913211300-expect(result.text).toBe("ok");
1301-expect(context.preparedBackend.cleanup).toBe(preparedBackendCleanup);
1302-expect(preparedBackendCleanup).not.toHaveBeenCalled();
1322+ expect(result.text).toBe("ok");
1323+ expect(context.preparedBackend.cleanup).toBe(preparedBackendCleanup);
1324+ expect(preparedBackendCleanup).not.toHaveBeenCalled();
130313251304-await context.preparedBackend.cleanup?.();
1305-expect(preparedBackendCleanup).toHaveBeenCalledOnce();
1326+await context.preparedBackend.cleanup?.();
1327+expect(preparedBackendCleanup).toHaveBeenCalledOnce();
1328+} finally {
1329+await fs.rm(mcpConfigDir, { recursive: true, force: true });
1330+}
13061331});
1307133213081333it("preserves completed output when system prompt cleanup fails after delivery", async () => {
@@ -1792,10 +1817,13 @@ describe("runCliAgent spawn path", () => {
17921817});
17931818})(),
17941819);
1820+const rejectedRun = runs[16];
1821+const rejectedRunExpectation = expect(rejectedRun).rejects.toThrow(
1822+"Too many Claude CLI live sessions are active.",
1823+);
1795182417961825await vi.waitFor(() => expect(supervisorSpawnMock).toHaveBeenCalledTimes(16));
1797-const rejectedRun = runs[16];
1798-await expect(rejectedRun).rejects.toThrow("Too many Claude CLI live sessions are active.");
1826+await rejectedRunExpectation;
17991827releaseSpawn?.();
18001828await expect(Promise.all(runs.slice(0, 16))).resolves.toHaveLength(16);
18011829expect(supervisorSpawnMock).toHaveBeenCalledTimes(16);
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。