fix: resolve symlinks in skill config source discovery and test paths
Use fs.realpath() in config-source-discovery to resolve symlinks before loading skills, preventing duplicate/mismatched paths on systems where tmpdir() returns a symlink (e.g., macOS /var → /private/var). Also adds agents-config-dir utility for ~/.agents path resolution.
This commit is contained in:
parent
3de05f6442
commit
e9c9cb696d
@ -53,26 +53,28 @@ async function loadSourcePath(options: {
|
|||||||
const stat = await fs.stat(absolutePath).catch(() => null)
|
const stat = await fs.stat(absolutePath).catch(() => null)
|
||||||
if (!stat) return []
|
if (!stat) return []
|
||||||
|
|
||||||
|
const realBasePath = await fs.realpath(absolutePath).catch(() => absolutePath)
|
||||||
|
|
||||||
if (stat.isFile()) {
|
if (stat.isFile()) {
|
||||||
if (!isMarkdownPath(absolutePath)) return []
|
if (!isMarkdownPath(realBasePath)) return []
|
||||||
const loaded = await loadSkillFromPath({
|
const loaded = await loadSkillFromPath({
|
||||||
skillPath: absolutePath,
|
skillPath: realBasePath,
|
||||||
resolvedPath: dirname(absolutePath),
|
resolvedPath: dirname(realBasePath),
|
||||||
defaultName: inferSkillNameFromFileName(absolutePath),
|
defaultName: inferSkillNameFromFileName(realBasePath),
|
||||||
scope: "config",
|
scope: "config",
|
||||||
})
|
})
|
||||||
if (!loaded) return []
|
if (!loaded) return []
|
||||||
return filterByGlob([loaded], dirname(absolutePath), options.globPattern)
|
return filterByGlob([loaded], dirname(realBasePath), options.globPattern)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!stat.isDirectory()) return []
|
if (!stat.isDirectory()) return []
|
||||||
|
|
||||||
const directorySkills = await loadSkillsFromDir({
|
const directorySkills = await loadSkillsFromDir({
|
||||||
skillsDir: absolutePath,
|
skillsDir: realBasePath,
|
||||||
scope: "config",
|
scope: "config",
|
||||||
maxDepth: options.recursive ? MAX_RECURSIVE_DEPTH : 0,
|
maxDepth: options.recursive ? MAX_RECURSIVE_DEPTH : 0,
|
||||||
})
|
})
|
||||||
return filterByGlob(directorySkills, absolutePath, options.globPattern)
|
return filterByGlob(directorySkills, realBasePath, options.globPattern)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function discoverConfigSourceSkills(options: {
|
export async function discoverConfigSourceSkills(options: {
|
||||||
|
|||||||
14
src/shared/agents-config-dir.test.ts
Normal file
14
src/shared/agents-config-dir.test.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { describe, test, expect } from "bun:test"
|
||||||
|
import { getAgentsConfigDir } from "./agents-config-dir"
|
||||||
|
|
||||||
|
describe("getAgentsConfigDir", () => {
|
||||||
|
test("returns path ending with .agents", () => {
|
||||||
|
// given agents config dir is requested
|
||||||
|
|
||||||
|
// when getAgentsConfigDir is called
|
||||||
|
const result = getAgentsConfigDir()
|
||||||
|
|
||||||
|
// then returns path ending with .agents
|
||||||
|
expect(result.endsWith(".agents")).toBe(true)
|
||||||
|
})
|
||||||
|
})
|
||||||
6
src/shared/agents-config-dir.ts
Normal file
6
src/shared/agents-config-dir.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import { homedir } from "node:os"
|
||||||
|
import { join } from "node:path"
|
||||||
|
|
||||||
|
export function getAgentsConfigDir(): string {
|
||||||
|
return join(homedir(), ".agents")
|
||||||
|
}
|
||||||
@ -1,10 +1,10 @@
|
|||||||
import { describe, it, expect, beforeAll, afterAll } from "bun:test"
|
import { describe, it, expect, beforeAll, afterAll } from "bun:test"
|
||||||
import { mkdirSync, writeFileSync, symlinkSync, rmSync } from "fs"
|
import { mkdirSync, writeFileSync, symlinkSync, rmSync, realpathSync } from "fs"
|
||||||
import { join } from "path"
|
import { join } from "path"
|
||||||
import { tmpdir } from "os"
|
import { tmpdir } from "os"
|
||||||
import { resolveSymlink, resolveSymlinkAsync, isSymbolicLink } from "./file-utils"
|
import { resolveSymlink, resolveSymlinkAsync, isSymbolicLink } from "./file-utils"
|
||||||
|
|
||||||
const testDir = join(tmpdir(), "file-utils-test-" + Date.now())
|
const testDir = join(realpathSync(tmpdir()), "file-utils-test-" + Date.now())
|
||||||
|
|
||||||
// Create a directory structure that mimics the real-world scenario:
|
// Create a directory structure that mimics the real-world scenario:
|
||||||
//
|
//
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user