Download src/agents/sessions/tools/path-utils.test.ts from SaylorTwift/openclaw: direct link, hf CLI and curl.
- Browser
- Download file 4 kB
-
https://huggingface.co/SaylorTwift/openclaw/resolve/main/src/agents/sessions/tools/path-utils.test.ts
- Command line
-
hf download hf://SaylorTwift/openclaw/src/agents/sessions/tools/path-utils.test.ts
-
curl -L -o path-utils.test.ts https://huggingface.co/SaylorTwift/openclaw/resolve/main/src/agents/sessions/tools/path-utils.test.ts
4 kB
| import fs from "node:fs/promises"; | |
| import os from "node:os"; | |
| import path from "node:path"; | |
| import { pathToFileURL } from "node:url"; | |
| import { afterEach, describe, expect, it } from "vitest"; | |
| import { useAutoCleanupTempDirTracker } from "../../../../test/helpers/temp-dir.js"; | |
| import { normalizeFileReferencePrefix } from "../../sandbox-paths.js"; | |
| import { getReadPathVariants, resolveLocalPathToCwd, resolveToCwd } from "./path-utils.js"; | |
| const tempDirs = useAutoCleanupTempDirTracker(afterEach); | |
| describe("resolveToCwd", () => { | |
| const cwd = path.resolve("workspace"); | |
| it("resolves ordinary relative paths against cwd", () => { | |
| expect(resolveToCwd("notes/today.md", cwd)).toBe(path.resolve(cwd, "notes/today.md")); | |
| }); | |
| it.each([ | |
| ["@notes.md", "notes.md"], | |
| ["@@notes.md", "@notes.md"], | |
| ["@@@notes.md", "@@notes.md"], | |
| ["./@notes.md", "@notes.md"], | |
| ])("consumes one reference prefix across resolver handoffs: %s", (input, filename) => { | |
| const normalized = normalizeFileReferencePrefix(input); | |
| expect(resolveToCwd(normalized, cwd)).toBe(path.resolve(cwd, filename)); | |
| expect(resolveToCwd(normalizeFileReferencePrefix(normalized), cwd)).toBe( | |
| path.resolve(cwd, filename), | |
| ); | |
| }); | |
| it("preserves home and file URL references without decoding escaped mentions", () => { | |
| const target = path.resolve(cwd, "notes.txt"); | |
| const url = pathToFileURL(target).href; | |
| expect(resolveToCwd(normalizeFileReferencePrefix(`@${url}`), cwd)).toBe(target); | |
| expect(resolveToCwd(normalizeFileReferencePrefix(`@@${url}`), cwd)).toBe( | |
| path.resolve(cwd, `@${url}`), | |
| ); | |
| expect(resolveToCwd(normalizeFileReferencePrefix("@~/notes.txt"), cwd)).toBe( | |
| resolveToCwd("~/notes.txt", cwd), | |
| ); | |
| }); | |
| it("keeps Unicode spaces in the destination path", () => { | |
| const nnbsp = "Screenshot 9.30\u202FAM.png"; | |
| const ascii = "Screenshot 9.30 AM.png"; | |
| expect(resolveToCwd(nnbsp, cwd)).toBe(path.resolve(cwd, nnbsp)); | |
| expect(resolveToCwd(nnbsp, cwd)).not.toBe(path.resolve(cwd, ascii)); | |
| }); | |
| it("resolves valid file URLs to their filesystem path", () => { | |
| const target = path.resolve(cwd, "notes.txt"); | |
| expect(resolveToCwd(pathToFileURL(target).href, cwd)).toBe(target); | |
| }); | |
| it("keeps lexical backend paths independent of local literal @ names", async () => { | |
| const tempCwd = tempDirs.make("openclaw-at-path-"); | |
| await fs.writeFile(path.join(tempCwd, "@literal.txt"), "literal", "utf8"); | |
| expect(resolveLocalPathToCwd("@literal.txt", tempCwd)).toBe(path.join(tempCwd, "@literal.txt")); | |
| expect(resolveLocalPathToCwd("@missing.txt", tempCwd)).toBe(path.join(tempCwd, "missing.txt")); | |
| expect(resolveToCwd("@literal.txt", tempCwd)).toBe(path.join(tempCwd, "literal.txt")); | |
| }); | |
| it("keeps malformed file URLs on the ordinary relative-path path", () => { | |
| const malformed = "file://%"; | |
| expect(resolveToCwd(malformed, cwd)).toBe(path.resolve(cwd, malformed)); | |
| }); | |
| it.runIf(process.platform === "win32")( | |
| "expands a Windows-style home prefix against the OS home", | |
| () => { | |
| const homeDir = process.env.HOME ?? os.homedir(); | |
| expect(resolveToCwd("~\\notes.txt", cwd)).toBe(path.resolve(homeDir, "notes.txt")); | |
| }, | |
| ); | |
| it.runIf(process.platform !== "win32")( | |
| "keeps a backslash-prefixed tilde literal on POSIX", | |
| () => { | |
| expect(resolveToCwd("~\\notes.txt", cwd)).toBe(path.resolve(cwd, "~\\notes.txt")); | |
| }, | |
| ); | |
| }); | |
| describe("getReadPathVariants", () => { | |
| it("keeps the parent path unchanged for every filename fallback", () => { | |
| const cwd = path.resolve("workspace"); | |
| const parent = path.join(cwd, "cafe\u0301 d'accord 9.30 PM\u202Farchive"); | |
| const filePath = path.join(parent, "re\u0301sume\u0301 9.30 PM d'accord.txt"); | |
| const variants = getReadPathVariants(filePath); | |
| expect(variants.length).toBeGreaterThan(0); | |
| expect(new Set(variants.map((variant) => path.dirname(variant)))).toEqual(new Set([parent])); | |
| }); | |
| }); | |