feat: auto-resolve @path references in skill templates to absolute paths
Skill loaders previously only told agents that @path references are relative to the skill directory, but agents often failed to resolve them. Now @path/with/slash patterns are automatically expanded to absolute paths during template construction.
This commit is contained in:
@@ -5,6 +5,7 @@ import yaml from "js-yaml"
|
||||
import { parseFrontmatter } from "../../shared/frontmatter"
|
||||
import { sanitizeModelField } from "../../shared/model-sanitizer"
|
||||
import { resolveSymlink, isMarkdownFile } from "../../shared/file-utils"
|
||||
import { resolveSkillPathReferences } from "../../shared/skill-path-resolver"
|
||||
import type { CommandDefinition } from "../claude-code-command-loader/types"
|
||||
import type { SkillScope, SkillMetadata, LoadedSkill } from "./types"
|
||||
import type { SkillMcpConfig } from "../skill-mcp-manager/types"
|
||||
@@ -90,11 +91,12 @@ export async function loadSkillFromPathAsync(
|
||||
const isOpencodeSource = scope === "opencode" || scope === "opencode-project"
|
||||
const formattedDescription = `(${scope} - Skill) ${originalDescription}`
|
||||
|
||||
const resolvedBody = resolveSkillPathReferences(body.trim(), resolvedPath)
|
||||
const wrappedTemplate = `<skill-instruction>
|
||||
Base directory for this skill: ${resolvedPath}/
|
||||
File references (@path) in this skill are relative to this directory.
|
||||
|
||||
${body.trim()}
|
||||
${resolvedBody}
|
||||
</skill-instruction>
|
||||
|
||||
<user-request>
|
||||
|
||||
@@ -4,6 +4,7 @@ import yaml from "js-yaml"
|
||||
import { parseFrontmatter } from "../../shared/frontmatter"
|
||||
import { sanitizeModelField } from "../../shared/model-sanitizer"
|
||||
import { resolveSymlinkAsync, isMarkdownFile } from "../../shared/file-utils"
|
||||
import { resolveSkillPathReferences } from "../../shared/skill-path-resolver"
|
||||
import { getClaudeConfigDir } from "../../shared"
|
||||
import { getOpenCodeConfigDir } from "../../shared/opencode-config-dir"
|
||||
import type { CommandDefinition } from "../claude-code-command-loader/types"
|
||||
@@ -84,11 +85,12 @@ async function loadSkillFromPath(
|
||||
const isOpencodeSource = scope === "opencode" || scope === "opencode-project"
|
||||
const formattedDescription = `(${scope} - Skill) ${originalDescription}`
|
||||
|
||||
const resolvedBody = resolveSkillPathReferences(body.trim(), resolvedPath)
|
||||
const templateContent = `<skill-instruction>
|
||||
Base directory for this skill: ${resolvedPath}/
|
||||
File references (@path) in this skill are relative to this directory.
|
||||
|
||||
${body.trim()}
|
||||
${resolvedBody}
|
||||
</skill-instruction>
|
||||
|
||||
<user-request>
|
||||
|
||||
@@ -8,6 +8,7 @@ import { homedir } from "os"
|
||||
import { parseFrontmatter } from "../../shared/frontmatter"
|
||||
import { sanitizeModelField } from "../../shared/model-sanitizer"
|
||||
import { deepMerge } from "../../shared/deep-merge"
|
||||
import { resolveSkillPathReferences } from "../../shared/skill-path-resolver"
|
||||
|
||||
function parseAllowedToolsFromMetadata(allowedTools: string | string[] | undefined): string[] | undefined {
|
||||
if (!allowedTools) return undefined
|
||||
@@ -105,11 +106,12 @@ function configEntryToLoaded(
|
||||
const description = entry.description || fileMetadata.description || ""
|
||||
const resolvedPath = entry.from ? dirname(resolveFilePath(entry.from, configDir)) : configDir || process.cwd()
|
||||
|
||||
const resolvedTemplate = resolveSkillPathReferences(template.trim(), resolvedPath)
|
||||
const wrappedTemplate = `<skill-instruction>
|
||||
Base directory for this skill: ${resolvedPath}/
|
||||
File references (@path) in this skill are relative to this directory.
|
||||
|
||||
${template.trim()}
|
||||
${resolvedTemplate}
|
||||
</skill-instruction>
|
||||
|
||||
<user-request>
|
||||
|
||||
Reference in New Issue
Block a user