
















@@ -5,8 +5,10 @@ import path from "node:path";
55import { describe, expect, it } from "vitest";
66import {
77appendBoundedReproOutput,
8+outputContainsStandaloneToolOk,
89runZaiFallbackRepro,
910resolveZaiFallbackPnpmCommand,
11+sessionTranscriptHasToolResult,
1012} from "../../scripts/zai-fallback-repro.ts";
11131214describe("zai fallback repro command resolution", () => {
@@ -38,6 +40,32 @@ describe("zai fallback repro command resolution", () => {
3840expect(second).toEqual({ text: "fghij", truncatedChars: 5 });
3941});
404243+it("scans session transcripts with a byte cap", async () => {
44+const root = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-zai-session-test-"));
45+try {
46+const sessionFile = path.join(root, "session.jsonl");
47+await fs.writeFile(
48+sessionFile,
49+`${"x".repeat(70_000)}\n{"event":"message","toolResult":true}\n`,
50+"utf8",
51+);
52+53+await expect(sessionTranscriptHasToolResult(sessionFile)).resolves.toBe(true);
54+await expect(sessionTranscriptHasToolResult(sessionFile, 1024)).resolves.toBe(false);
55+await expect(sessionTranscriptHasToolResult(path.join(root, "missing.jsonl"))).resolves.toBe(
56+false,
57+);
58+} finally {
59+await fs.rm(root, { force: true, recursive: true });
60+}
61+});
62+63+it("requires tool-ok as a standalone output line", () => {
64+expect(outputContainsStandaloneToolOk("before\ntool-ok\nafter\n")).toBe(true);
65+expect(outputContainsStandaloneToolOk("before tool-ok after\n")).toBe(false);
66+expect(outputContainsStandaloneToolOk("tool-okay\n")).toBe(false);
67+});
68+4169it("cleans temporary repro state after fallback proof", async () => {
4270const tempRoots: string[] = [];
4371const calls: string[] = [];
@@ -70,14 +98,74 @@ describe("zai fallback repro command resolution", () => {
7098await fs.mkdir(path.dirname(sessionFile), { recursive: true });
7199await fs.writeFile(sessionFile, '{"toolResult":true}\n', "utf8");
72100}
73-return { code: 0, signal: null, stderr: "", stdout: "" };
101+return {
102+code: 0,
103+signal: null,
104+stderr: "",
105+stdout: label === "run2" ? "tool-ok\n" : "",
106+};
74107},
75-warn: () => {},
76108});
7710978110expect(exitCode).toBe(0);
79111expect(calls).toEqual(["run1", "run2"]);
80112expect(tempRoots).toHaveLength(1);
81113await expect(fs.stat(tempRoots[0])).rejects.toMatchObject({ code: "ENOENT" });
82114});
115+116+it("fails when run 1 does not leave tool result evidence", async () => {
117+const calls: string[] = [];
118+const errors: string[] = [];
119+120+const exitCode = await runZaiFallbackRepro({
121+env: {
122+ANTHROPIC_API_KEY: "anthropic-test-key",
123+OPENCLAW_ZAI_FALLBACK_SESSION_ID: "session-test",
124+PATH: process.env.PATH,
125+ZAI_API_KEY: "zai-test-key",
126+},
127+error: (message) => errors.push(message),
128+log: () => {},
129+runCommand: async (label) => {
130+calls.push(label);
131+return { code: 0, signal: null, stderr: "", stdout: "" };
132+},
133+});
134+135+expect(exitCode).toBe(1);
136+expect(calls).toEqual(["run1"]);
137+expect(errors).toContain("FAIL: no toolResult entries detected in session history.");
138+});
139+140+it("fails when fallback exits zero without returning tool-ok", async () => {
141+const errors: string[] = [];
142+143+const exitCode = await runZaiFallbackRepro({
144+env: {
145+ANTHROPIC_API_KEY: "anthropic-test-key",
146+OPENCLAW_ZAI_FALLBACK_SESSION_ID: "session-test",
147+PATH: process.env.PATH,
148+ZAI_API_KEY: "zai-test-key",
149+},
150+error: (message) => errors.push(message),
151+log: () => {},
152+runCommand: async (label, _args, env) => {
153+if (label === "run1") {
154+const sessionFile = path.join(
155+String(env.OPENCLAW_STATE_DIR),
156+"agents",
157+"main",
158+"sessions",
159+"session-test.jsonl",
160+);
161+await fs.mkdir(path.dirname(sessionFile), { recursive: true });
162+await fs.writeFile(sessionFile, '{"toolResult":true}\n', "utf8");
163+}
164+return { code: 0, signal: null, stderr: "", stdout: "not-it\n" };
165+},
166+});
167+168+expect(exitCode).toBe(1);
169+expect(errors).toContain("FAIL: fallback run did not return standalone tool-ok.");
170+});
83171});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。