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
This commit is contained in:
ismeth
2026-02-20 21:53:05 +01:00
committed by YeonGyu-Kim
parent 9330ec806b
commit d0639baeca
9 changed files with 17 additions and 18 deletions
+1 -1
View File
@@ -27,7 +27,7 @@ const COUNCIL_CANDIDATES: Array<{
}, },
{ {
provider: (a) => a.kimiForCoding, provider: (a) => a.kimiForCoding,
model: "kimi-for-coding/k2p5", model: "kimi-for-coding/kimi-k2.5",
name: "Kimi 2.5", name: "Kimi 2.5",
} }
] ]
@@ -185,7 +185,7 @@ describe("resolveMultipleSkillsAsync", () => {
const skillNames = ["playwright", "git-master"] const skillNames = ["playwright", "git-master"]
// when: resolving multiple skills async // when: resolving multiple skills async
const result = await resolveMultipleSkillsAsync(skillNames) const result = await resolveMultipleSkillsAsync(skillNames, { directory: process.cwd() })
// then: all builtin skills resolved // then: all builtin skills resolved
expect(result.resolved.size).toBe(2) expect(result.resolved.size).toBe(2)
@@ -199,7 +199,7 @@ describe("resolveMultipleSkillsAsync", () => {
const skillNames = ["playwright", "nonexistent-skill-12345"] const skillNames = ["playwright", "nonexistent-skill-12345"]
// when: resolving multiple skills async // when: resolving multiple skills async
const result = await resolveMultipleSkillsAsync(skillNames) const result = await resolveMultipleSkillsAsync(skillNames, { directory: process.cwd() })
// then: existing skills resolved, non-existing in notFound // then: existing skills resolved, non-existing in notFound
expect(result.resolved.size).toBe(1) expect(result.resolved.size).toBe(1)
@@ -289,7 +289,7 @@ describe("resolveMultipleSkillsAsync", () => {
const skillNames = ["git-master"] const skillNames = ["git-master"]
// when: resolving without any gitMasterConfig // when: resolving without any gitMasterConfig
const result = await resolveMultipleSkillsAsync(skillNames) const result = await resolveMultipleSkillsAsync(skillNames, { directory: process.cwd() })
// then: watermark is injected (default is ON) // then: watermark is injected (default is ON)
expect(result.resolved.size).toBe(1) expect(result.resolved.size).toBe(1)
@@ -363,7 +363,7 @@ describe("resolveMultipleSkillsAsync", () => {
const skillNames: string[] = [] const skillNames: string[] = []
// when: resolving multiple skills async // when: resolving multiple skills async
const result = await resolveMultipleSkillsAsync(skillNames) const result = await resolveMultipleSkillsAsync(skillNames, { directory: process.cwd() })
// then: empty results // then: empty results
expect(result.resolved.size).toBe(0) expect(result.resolved.size).toBe(0)
@@ -9,8 +9,8 @@ export function clearSkillCache(): void {
skillCache.clear() skillCache.clear()
} }
export async function getAllSkills(options?: SkillResolutionOptions): Promise<LoadedSkill[]> { export async function getAllSkills(options: SkillResolutionOptions & { directory: string }): Promise<LoadedSkill[]> {
const directory = options?.directory ?? process.cwd() const directory = options.directory
const cacheKey = `${options?.browserProvider ?? "playwright"}:${directory}` const cacheKey = `${options?.browserProvider ?? "playwright"}:${directory}`
const hasDisabledSkills = options?.disabledSkills && options.disabledSkills.size > 0 const hasDisabledSkills = options?.disabledSkills && options.disabledSkills.size > 0
@@ -4,6 +4,6 @@ export interface SkillResolutionOptions {
gitMasterConfig?: GitMasterConfig gitMasterConfig?: GitMasterConfig
browserProvider?: BrowserAutomationProvider browserProvider?: BrowserAutomationProvider
disabledSkills?: Set<string> disabledSkills?: Set<string>
/** Project directory to discover project-level skills from. Falls back to process.cwd() if not provided. */ /** Project directory to discover project-level skills from. Required for async resolution — process.cwd() is unsafe in OpenCode. */
directory?: string directory?: string
} }
@@ -51,7 +51,7 @@ export function resolveMultipleSkills(
export async function resolveSkillContentAsync( export async function resolveSkillContentAsync(
skillName: string, skillName: string,
options?: SkillResolutionOptions options: SkillResolutionOptions & { directory: string }
): Promise<string | null> { ): Promise<string | null> {
const allSkills = await getAllSkills(options) const allSkills = await getAllSkills(options)
const skill = allSkills.find((loadedSkill) => loadedSkill.name === skillName) const skill = allSkills.find((loadedSkill) => loadedSkill.name === skillName)
@@ -68,7 +68,7 @@ export async function resolveSkillContentAsync(
export async function resolveMultipleSkillsAsync( export async function resolveMultipleSkillsAsync(
skillNames: string[], skillNames: string[],
options?: SkillResolutionOptions options: SkillResolutionOptions & { directory: string }
): Promise<{ resolved: Map<string, string>; notFound: string[] }> { ): Promise<{ resolved: Map<string, string>; notFound: string[] }> {
const allSkills = await getAllSkills(options) const allSkills = await getAllSkills(options)
const skillMap = new Map<string, LoadedSkill>() const skillMap = new Map<string, LoadedSkill>()
+1 -1
View File
@@ -4,7 +4,7 @@ import { discoverSkills } from "../../features/opencode-skill-loader"
export async function resolveSkillContent( export async function resolveSkillContent(
skills: string[], skills: string[],
options: { gitMasterConfig?: GitMasterConfig; browserProvider?: BrowserAutomationProvider, disabledSkills?: Set<string>, directory?: string } options: { gitMasterConfig?: GitMasterConfig; browserProvider?: BrowserAutomationProvider; disabledSkills?: Set<string>; directory: string }
): Promise<{ content: string | undefined; contents: string[]; error: string | null }> { ): Promise<{ content: string | undefined; contents: string[]; error: string | null }> {
if (skills.length === 0) { if (skills.length === 0) {
return { content: undefined, contents: [], error: null } return { content: undefined, contents: [], error: null }
+1 -1
View File
@@ -1,3 +1,3 @@
export * from "./constants" export * from "./constants"
export * from "./types" export * from "./types"
export { skill, createSkillTool } from "./tools" export { createSkillTool } from "./tools"
+3 -4
View File
@@ -24,7 +24,7 @@ import {
mergeNativeSkills, mergeNativeSkills,
} from "./native-skills" } from "./native-skills"
export function createSkillTool(options: SkillLoadOptions = {}): ToolDefinition { export function createSkillTool(options: SkillLoadOptions): ToolDefinition {
let cachedDescription: string | null = null let cachedDescription: string | null = null
const getSkills = async (): Promise<LoadedSkill[]> => { const getSkills = async (): Promise<LoadedSkill[]> => {
@@ -32,6 +32,7 @@ export function createSkillTool(options: SkillLoadOptions = {}): ToolDefinition
const discovered = await getAllSkills({ const discovered = await getAllSkills({
disabledSkills: options?.disabledSkills, disabledSkills: options?.disabledSkills,
browserProvider: options?.browserProvider, browserProvider: options?.browserProvider,
directory: options.directory,
}) })
const allSkills = !options.skills const allSkills = !options.skills
? discovered ? discovered
@@ -138,7 +139,7 @@ export function createSkillTool(options: SkillLoadOptions = {}): ToolDefinition
body = injectGitMasterConfig(body, options.gitMasterConfig) body = injectGitMasterConfig(body, options.gitMasterConfig)
} }
const dir = matchedSkill.path ? dirname(matchedSkill.path) : matchedSkill.resolvedPath || options.directory || process.cwd() const dir = matchedSkill.path ? dirname(matchedSkill.path) : matchedSkill.resolvedPath || options.directory
const output = [ const output = [
`## Skill: ${matchedSkill.name}`, `## Skill: ${matchedSkill.name}`,
@@ -192,5 +193,3 @@ export function createSkillTool(options: SkillLoadOptions = {}): ToolDefinition
}, },
}) })
} }
export const skill: ToolDefinition = createSkillTool()
+2 -2
View File
@@ -45,6 +45,6 @@ export interface SkillLoadOptions {
get(name: string): { name: string; description: string; location: string; content: string } | undefined | Promise<{ name: string; description: string; location: string; content: string } | undefined> get(name: string): { name: string; description: string; location: string; content: string } | undefined | Promise<{ name: string; description: string; location: string; content: string } | undefined>
dirs(): string[] | Promise<string[]> dirs(): string[] | Promise<string[]>
} }
/** Project directory for skill discovery and base directory resolution. Should be ctx.directory from PluginContext. */ /** Project directory for skill discovery and base directory resolution. Must be ctx.directory from PluginContext -- process.cwd() is unsafe in OpenCode. */
directory?: string directory: string
} }