


























@@ -86,6 +86,23 @@ describe("edit tool recovery hardening", () => {
8686});
8787}
888889+function expectRecoveredText(result: Awaited<ReturnType<AnyAgentTool["execute"]>>, text: string) {
90+expect((result as { isError?: unknown }).isError).toBe(false);
91+const first = result.content[0];
92+expect(first?.type).toBe("text");
93+expect(first?.type === "text" ? first.text : undefined).toBe(text);
94+}
95+96+async function expectPathMissing(targetPath: string) {
97+try {
98+await fs.access(targetPath);
99+throw new Error(`expected ${targetPath} to be missing`);
100+} catch (error) {
101+const code = error && typeof error === "object" && "code" in error ? error.code : undefined;
102+expect(code).toBe("ENOENT");
103+}
104+}
105+89106it("adds current file contents to exact-match mismatch errors", async () => {
90107tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-edit-recovery-"));
91108const filePath = path.join(tmpDir, "demo.txt");
@@ -136,11 +153,7 @@ describe("edit tool recovery hardening", () => {
136153undefined,
137154);
138155139-expect(result).toMatchObject({ isError: false });
140-expect(result.content[0]).toMatchObject({
141-type: "text",
142-text: `Successfully replaced text in ${filePath}.`,
143-});
156+expectRecoveredText(result, `Successfully replaced text in ${filePath}.`);
144157});
145158146159it("does not recover false success when the file never changed", async () => {
@@ -186,11 +199,7 @@ describe("edit tool recovery hardening", () => {
186199undefined,
187200);
188201189-expect(result).toMatchObject({ isError: false });
190-expect(result.content[0]).toMatchObject({
191-type: "text",
192-text: `Successfully replaced text in ${filePath}.`,
193-});
202+expectRecoveredText(result, `Successfully replaced text in ${filePath}.`);
194203});
195204196205it("recovers multi-edit payloads after a post-write throw", async () => {
@@ -218,11 +227,7 @@ describe("edit tool recovery hardening", () => {
218227undefined,
219228);
220229221-expect(result).toMatchObject({ isError: false });
222-expect(result.content[0]).toMatchObject({
223-type: "text",
224-text: `Successfully replaced 2 block(s) in ${filePath}.`,
225-});
230+expectRecoveredText(result, `Successfully replaced 2 block(s) in ${filePath}.`);
226231});
227232228233it("recovers tilde paths against the OS home even when OPENCLAW_HOME differs", async () => {
@@ -257,14 +262,8 @@ describe("edit tool recovery hardening", () => {
257262undefined,
258263);
259264260-expect(result).toMatchObject({ isError: false });
261-expect(result.content[0]).toMatchObject({
262-type: "text",
263-text: "Successfully replaced text in ~/demo.txt.",
264-});
265-await expect(fs.access(path.join(openclawHome, "demo.txt"))).rejects.toMatchObject({
266-code: "ENOENT",
267-});
265+expectRecoveredText(result, "Successfully replaced text in ~/demo.txt.");
266+await expectPathMissing(path.join(openclawHome, "demo.txt"));
268267} finally {
269268if (previousHome === undefined) {
270269delete process.env.HOME;
@@ -305,10 +304,6 @@ describe("edit tool recovery hardening", () => {
305304undefined,
306305);
307306308-expect(result).toMatchObject({ isError: false });
309-expect(result.content[0]).toMatchObject({
310-type: "text",
311-text: `Successfully replaced text in ${filePath}.`,
312-});
307+expectRecoveredText(result, `Successfully replaced text in ${filePath}.`);
313308});
314309});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。