ismeth 45a850afc0 fix: enforce directory param in skill resolution, replace legacy k2p5 model ID
- Make directory required in SkillLoadOptions, getAllSkills, and async
  skill template resolvers to prevent unsafe process.cwd() fallback
- Remove dead skill export and process.cwd() fallback in skill tool
- Replace kimi-for-coding/k2p5 with kimi-for-coding/kimi-k2.5 in
  council-members-generator
2026-02-24 22:26:47 +09:00

78 lines
2.7 KiB
TypeScript

import { createBuiltinSkills } from "../builtin-skills/skills"
import { discoverSkills } from "./loader"
import type { LoadedSkill } from "./types"
import type { SkillResolutionOptions } from "./skill-resolution-options"
const skillCache = new Map<string, LoadedSkill[]>()
export function clearSkillCache(): void {
skillCache.clear()
}
export async function getAllSkills(options: SkillResolutionOptions & { directory: string }): Promise<LoadedSkill[]> {
const directory = options.directory
const cacheKey = `${options?.browserProvider ?? "playwright"}:${directory}`
const hasDisabledSkills = options?.disabledSkills && options.disabledSkills.size > 0
// Skip cache if disabledSkills is provided (varies between calls)
if (!hasDisabledSkills) {
const cached = skillCache.get(cacheKey)
if (cached) return cached
}
const [discoveredSkills, builtinSkillDefinitions] = await Promise.all([
discoverSkills({ includeClaudeCodePaths: true, directory: options?.directory }),
Promise.resolve(
createBuiltinSkills({
browserProvider: options?.browserProvider,
disabledSkills: options?.disabledSkills,
})
),
])
const builtinSkillsAsLoaded: LoadedSkill[] = builtinSkillDefinitions.map((skill) => ({
name: skill.name,
definition: {
name: skill.name,
description: skill.description,
template: skill.template,
model: skill.model,
agent: skill.agent,
subtask: skill.subtask,
},
scope: "builtin" as const,
license: skill.license,
compatibility: skill.compatibility,
metadata: skill.metadata as Record<string, string> | undefined,
allowedTools: skill.allowedTools,
mcpConfig: skill.mcpConfig,
}))
// Provider-gated skill names that should be filtered based on browserProvider
const providerGatedSkillNames = new Set(["agent-browser", "playwright"])
const browserProvider = options?.browserProvider ?? "playwright"
// Filter discovered skills to exclude provider-gated names that don't match the selected provider
const filteredDiscoveredSkills = discoveredSkills.filter((skill) => {
if (!providerGatedSkillNames.has(skill.name)) {
return true
}
// For provider-gated skills, only include if it matches the selected provider
return skill.name === browserProvider
})
const discoveredNames = new Set(filteredDiscoveredSkills.map((skill) => skill.name))
const uniqueBuiltins = builtinSkillsAsLoaded.filter((skill) => !discoveredNames.has(skill.name))
let allSkills = [...filteredDiscoveredSkills, ...uniqueBuiltins]
// Filter discovered skills by disabledSkills (builtin skills are already filtered by createBuiltinSkills)
if (hasDisabledSkills) {
allSkills = allSkills.filter((skill) => !options!.disabledSkills!.has(skill.name))
} else {
skillCache.set(cacheKey, allSkills)
}
return allSkills
}