feat: add skill metadata and discovery functions to opencode-skill-loader
- Add license, compatibility, metadata, and allowed-tools fields to SkillMetadata interface - Add corresponding fields to LoadedSkill interface with proper type transformations - Implement parseAllowedTools() helper for parsing comma/space-separated allowed tools - Add discoverSkills() function with includeClaudeCodePaths option for flexible skill discovery - Add getSkillByName() function for efficient skill lookup by name - Support both OpenCode and Claude Code skill paths based on configuration 🤖 GENERATED WITH ASSISTANCE OF [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode)
This commit is contained in:
@@ -16,6 +16,11 @@ import type { SkillScope, SkillMetadata, LoadedSkill } from "./types"
|
|||||||
* @param defaultName - Fallback name if not specified in frontmatter
|
* @param defaultName - Fallback name if not specified in frontmatter
|
||||||
* @param scope - Source scope for priority ordering
|
* @param scope - Source scope for priority ordering
|
||||||
*/
|
*/
|
||||||
|
function parseAllowedTools(allowedTools: string | undefined): string[] | undefined {
|
||||||
|
if (!allowedTools) return undefined
|
||||||
|
return allowedTools.split(/\s+/).filter(Boolean)
|
||||||
|
}
|
||||||
|
|
||||||
function loadSkillFromPath(
|
function loadSkillFromPath(
|
||||||
skillPath: string,
|
skillPath: string,
|
||||||
resolvedPath: string,
|
resolvedPath: string,
|
||||||
@@ -58,6 +63,10 @@ $ARGUMENTS
|
|||||||
resolvedPath,
|
resolvedPath,
|
||||||
definition,
|
definition,
|
||||||
scope,
|
scope,
|
||||||
|
license: data.license,
|
||||||
|
compatibility: data.compatibility,
|
||||||
|
metadata: data.metadata,
|
||||||
|
allowedTools: parseAllowedTools(data["allowed-tools"]),
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
return null
|
return null
|
||||||
@@ -177,3 +186,41 @@ export function discoverAllSkills(): LoadedSkill[] {
|
|||||||
|
|
||||||
return [...opencodeProjectSkills, ...projectSkills, ...opencodeGlobalSkills, ...userSkills]
|
return [...opencodeProjectSkills, ...projectSkills, ...opencodeGlobalSkills, ...userSkills]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface DiscoverSkillsOptions {
|
||||||
|
includeClaudeCodePaths?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Discover skills with optional filtering.
|
||||||
|
* When includeClaudeCodePaths is false, only loads from OpenCode paths.
|
||||||
|
*/
|
||||||
|
export function discoverSkills(options: DiscoverSkillsOptions = {}): LoadedSkill[] {
|
||||||
|
const { includeClaudeCodePaths = true } = options
|
||||||
|
|
||||||
|
const opencodeProjectDir = join(process.cwd(), ".opencode", "skill")
|
||||||
|
const opencodeGlobalDir = join(homedir(), ".config", "opencode", "skill")
|
||||||
|
|
||||||
|
const opencodeProjectSkills = loadSkillsFromDir(opencodeProjectDir, "opencode-project")
|
||||||
|
const opencodeGlobalSkills = loadSkillsFromDir(opencodeGlobalDir, "opencode")
|
||||||
|
|
||||||
|
if (!includeClaudeCodePaths) {
|
||||||
|
return [...opencodeProjectSkills, ...opencodeGlobalSkills]
|
||||||
|
}
|
||||||
|
|
||||||
|
const projectDir = join(process.cwd(), ".claude", "skills")
|
||||||
|
const userDir = join(getClaudeConfigDir(), "skills")
|
||||||
|
|
||||||
|
const projectSkills = loadSkillsFromDir(projectDir, "project")
|
||||||
|
const userSkills = loadSkillsFromDir(userDir, "user")
|
||||||
|
|
||||||
|
return [...opencodeProjectSkills, ...projectSkills, ...opencodeGlobalSkills, ...userSkills]
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a skill by name from all available sources.
|
||||||
|
*/
|
||||||
|
export function getSkillByName(name: string, options: DiscoverSkillsOptions = {}): LoadedSkill | undefined {
|
||||||
|
const skills = discoverSkills(options)
|
||||||
|
return skills.find(s => s.name === name)
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,6 +9,10 @@ export interface SkillMetadata {
|
|||||||
"argument-hint"?: string
|
"argument-hint"?: string
|
||||||
agent?: string
|
agent?: string
|
||||||
subtask?: boolean
|
subtask?: boolean
|
||||||
|
license?: string
|
||||||
|
compatibility?: string
|
||||||
|
metadata?: Record<string, string>
|
||||||
|
"allowed-tools"?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LoadedSkill {
|
export interface LoadedSkill {
|
||||||
@@ -17,4 +21,8 @@ export interface LoadedSkill {
|
|||||||
resolvedPath: string
|
resolvedPath: string
|
||||||
definition: CommandDefinition
|
definition: CommandDefinition
|
||||||
scope: SkillScope
|
scope: SkillScope
|
||||||
|
license?: string
|
||||||
|
compatibility?: string
|
||||||
|
metadata?: Record<string, string>
|
||||||
|
allowedTools?: string[]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user