Merge pull request #1370 from misyuari/fix/refactor-skills

fix: update skill resolution to support disabled skills functionality
This commit is contained in:
YeonGyu-Kim 2026-02-04 13:47:26 +09:00 committed by GitHub
commit dee8cf1720
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 171 additions and 44 deletions

View File

@ -41,7 +41,7 @@ describe("createBuiltinAgents with model overrides", () => {
} }
// #when // #when
const agents = await createBuiltinAgents([], overrides, undefined, TEST_DEFAULT_MODEL) const agents = await createBuiltinAgents([], overrides, undefined, TEST_DEFAULT_MODEL, undefined, undefined, [], undefined, undefined)
// #then // #then
expect(agents.sisyphus.model).toBe("github-copilot/gpt-5.2") expect(agents.sisyphus.model).toBe("github-copilot/gpt-5.2")
@ -103,7 +103,7 @@ describe("createBuiltinAgents with model overrides", () => {
const cacheSpy = spyOn(connectedProvidersCache, "readConnectedProvidersCache").mockReturnValue(["openai"]) const cacheSpy = spyOn(connectedProvidersCache, "readConnectedProvidersCache").mockReturnValue(["openai"])
// #when // #when
const agents = await createBuiltinAgents([], {}, undefined, TEST_DEFAULT_MODEL) const agents = await createBuiltinAgents([], {}, undefined, TEST_DEFAULT_MODEL, undefined, undefined, [], undefined, undefined)
// #then - oracle resolves via connected cache fallback to openai/gpt-5.2 (not system default) // #then - oracle resolves via connected cache fallback to openai/gpt-5.2 (not system default)
expect(agents.oracle.model).toBe("openai/gpt-5.2") expect(agents.oracle.model).toBe("openai/gpt-5.2")
@ -132,7 +132,7 @@ describe("createBuiltinAgents with model overrides", () => {
} }
// #when // #when
const agents = await createBuiltinAgents([], overrides, undefined, TEST_DEFAULT_MODEL) const agents = await createBuiltinAgents([], overrides, undefined, TEST_DEFAULT_MODEL, undefined, undefined, [], undefined, undefined)
// #then // #then
expect(agents.oracle.model).toBe("openai/gpt-5.2") expect(agents.oracle.model).toBe("openai/gpt-5.2")
@ -148,7 +148,7 @@ describe("createBuiltinAgents with model overrides", () => {
} }
// #when // #when
const agents = await createBuiltinAgents([], overrides, undefined, TEST_DEFAULT_MODEL) const agents = await createBuiltinAgents([], overrides, undefined, TEST_DEFAULT_MODEL, undefined, undefined, [], undefined, undefined)
// #then // #then
expect(agents.oracle.model).toBe("anthropic/claude-sonnet-4") expect(agents.oracle.model).toBe("anthropic/claude-sonnet-4")
@ -164,12 +164,25 @@ describe("createBuiltinAgents with model overrides", () => {
} }
// #when // #when
const agents = await createBuiltinAgents([], overrides, undefined, TEST_DEFAULT_MODEL) const agents = await createBuiltinAgents([], overrides, undefined, TEST_DEFAULT_MODEL, undefined, undefined, [], undefined, undefined)
// #then // #then
expect(agents.sisyphus.model).toBe("github-copilot/gpt-5.2") expect(agents.sisyphus.model).toBe("github-copilot/gpt-5.2")
expect(agents.sisyphus.temperature).toBe(0.5) expect(agents.sisyphus.temperature).toBe(0.5)
}) })
test("createBuiltinAgents excludes disabled skills from availableSkills", async () => {
// #given
const disabledSkills = new Set(["playwright"])
// #when
const agents = await createBuiltinAgents([], {}, undefined, TEST_DEFAULT_MODEL, undefined, undefined, [], undefined, undefined, undefined, disabledSkills)
// #then
expect(agents.sisyphus.prompt).not.toContain("playwright")
expect(agents.sisyphus.prompt).toContain("frontend-ui-ux")
expect(agents.sisyphus.prompt).toContain("git-master")
})
}) })
describe("createBuiltinAgents without systemDefaultModel", () => { describe("createBuiltinAgents without systemDefaultModel", () => {

View File

@ -57,7 +57,8 @@ export function buildAgent(
model: string, model: string,
categories?: CategoriesConfig, categories?: CategoriesConfig,
gitMasterConfig?: GitMasterConfig, gitMasterConfig?: GitMasterConfig,
browserProvider?: BrowserAutomationProvider browserProvider?: BrowserAutomationProvider,
disabledSkills?: Set<string>
): AgentConfig { ): AgentConfig {
const base = isFactory(source) ? source(model) : source const base = isFactory(source) ? source(model) : source
const categoryConfigs: Record<string, CategoryConfig> = categories const categoryConfigs: Record<string, CategoryConfig> = categories
@ -81,7 +82,7 @@ export function buildAgent(
} }
if (agentWithCategory.skills?.length) { if (agentWithCategory.skills?.length) {
const { resolved } = resolveMultipleSkills(agentWithCategory.skills, { gitMasterConfig, browserProvider }) const { resolved } = resolveMultipleSkills(agentWithCategory.skills, { gitMasterConfig, browserProvider, disabledSkills })
if (resolved.size > 0) { if (resolved.size > 0) {
const skillContent = Array.from(resolved.values()).join("\n\n") const skillContent = Array.from(resolved.values()).join("\n\n")
base.prompt = skillContent + (base.prompt ? "\n\n" + base.prompt : "") base.prompt = skillContent + (base.prompt ? "\n\n" + base.prompt : "")
@ -234,7 +235,8 @@ export async function createBuiltinAgents(
discoveredSkills: LoadedSkill[] = [], discoveredSkills: LoadedSkill[] = [],
client?: any, client?: any,
browserProvider?: BrowserAutomationProvider, browserProvider?: BrowserAutomationProvider,
uiSelectedModel?: string uiSelectedModel?: string,
disabledSkills?: Set<string>
): Promise<Record<string, AgentConfig>> { ): Promise<Record<string, AgentConfig>> {
const connectedProviders = readConnectedProvidersCache() const connectedProviders = readConnectedProvidersCache()
// IMPORTANT: Do NOT pass client to fetchAvailableModels during plugin initialization. // IMPORTANT: Do NOT pass client to fetchAvailableModels during plugin initialization.
@ -258,7 +260,7 @@ export async function createBuiltinAgents(
description: categories?.[name]?.description ?? CATEGORY_DESCRIPTIONS[name] ?? "General tasks", description: categories?.[name]?.description ?? CATEGORY_DESCRIPTIONS[name] ?? "General tasks",
})) }))
const builtinSkills = createBuiltinSkills({ browserProvider }) const builtinSkills = createBuiltinSkills({ browserProvider, disabledSkills })
const builtinSkillNames = new Set(builtinSkills.map(s => s.name)) const builtinSkillNames = new Set(builtinSkills.map(s => s.name))
const builtinAvailable: AvailableSkill[] = builtinSkills.map((skill) => ({ const builtinAvailable: AvailableSkill[] = builtinSkills.map((skill) => ({
@ -311,7 +313,7 @@ export async function createBuiltinAgents(
if (!resolution) continue if (!resolution) continue
const { model, variant: resolvedVariant } = resolution const { model, variant: resolvedVariant } = resolution
let config = buildAgent(source, model, mergedCategories, gitMasterConfig, browserProvider) let config = buildAgent(source, model, mergedCategories, gitMasterConfig, browserProvider, disabledSkills)
// Apply resolved variant from model fallback chain // Apply resolved variant from model fallback chain
if (resolvedVariant) { if (resolvedVariant) {

View File

@ -86,4 +86,58 @@ describe("createBuiltinSkills", () => {
expect(defaultSkills).toHaveLength(4) expect(defaultSkills).toHaveLength(4)
expect(agentBrowserSkills).toHaveLength(4) expect(agentBrowserSkills).toHaveLength(4)
}) })
test("should exclude playwright when it is in disabledSkills", () => {
// #given
const options = { disabledSkills: new Set(["playwright"]) }
// #when
const skills = createBuiltinSkills(options)
// #then
expect(skills.map((s) => s.name)).not.toContain("playwright")
expect(skills.map((s) => s.name)).toContain("frontend-ui-ux")
expect(skills.map((s) => s.name)).toContain("git-master")
expect(skills.map((s) => s.name)).toContain("dev-browser")
expect(skills.length).toBe(3)
})
test("should exclude multiple skills when they are in disabledSkills", () => {
// #given
const options = { disabledSkills: new Set(["playwright", "git-master"]) }
// #when
const skills = createBuiltinSkills(options)
// #then
expect(skills.map((s) => s.name)).not.toContain("playwright")
expect(skills.map((s) => s.name)).not.toContain("git-master")
expect(skills.map((s) => s.name)).toContain("frontend-ui-ux")
expect(skills.map((s) => s.name)).toContain("dev-browser")
expect(skills.length).toBe(2)
})
test("should return an empty array when all skills are disabled", () => {
// #given
const options = {
disabledSkills: new Set(["playwright", "frontend-ui-ux", "git-master", "dev-browser"]),
}
// #when
const skills = createBuiltinSkills(options)
// #then
expect(skills.length).toBe(0)
})
test("should return all skills when disabledSkills set is empty", () => {
// #given
const options = { disabledSkills: new Set<string>() }
// #when
const skills = createBuiltinSkills(options)
// #then
expect(skills.length).toBe(4)
})
}) })

View File

@ -11,12 +11,19 @@ import {
export interface CreateBuiltinSkillsOptions { export interface CreateBuiltinSkillsOptions {
browserProvider?: BrowserAutomationProvider browserProvider?: BrowserAutomationProvider
disabledSkills?: Set<string>
} }
export function createBuiltinSkills(options: CreateBuiltinSkillsOptions = {}): BuiltinSkill[] { export function createBuiltinSkills(options: CreateBuiltinSkillsOptions = {}): BuiltinSkill[] {
const { browserProvider = "playwright" } = options const { browserProvider = "playwright", disabledSkills } = options
const browserSkill = browserProvider === "agent-browser" ? agentBrowserSkill : playwrightSkill const browserSkill = browserProvider === "agent-browser" ? agentBrowserSkill : playwrightSkill
return [browserSkill, frontendUiUxSkill, gitMasterSkill, devBrowserSkill] const skills = [browserSkill, frontendUiUxSkill, gitMasterSkill, devBrowserSkill]
if (!disabledSkills) {
return skills
}
return skills.filter((skill) => !disabledSkills.has(skill.name))
} }

View File

@ -33,10 +33,12 @@ describe("resolveSkillContent", () => {
expect(result).toBeNull() expect(result).toBeNull()
}) })
it("should return null for empty string", () => { it("should return null for disabled skill", () => {
// given: builtin skills // given: frontend-ui-ux skill disabled
// when: resolving content for empty string const options = { disabledSkills: new Set(["frontend-ui-ux"]) }
const result = resolveSkillContent("")
// when: resolving content for disabled skill
const result = resolveSkillContent("frontend-ui-ux", options)
// then: returns null // then: returns null
expect(result).toBeNull() expect(result).toBeNull()
@ -96,6 +98,20 @@ describe("resolveMultipleSkills", () => {
expect(result.notFound).toEqual(["skill-one", "skill-two", "skill-three"]) expect(result.notFound).toEqual(["skill-one", "skill-two", "skill-three"])
}) })
it("should treat disabled skills as not found", () => {
// #given: frontend-ui-ux disabled, playwright not disabled
const skillNames = ["frontend-ui-ux", "playwright"]
const options = { disabledSkills: new Set(["frontend-ui-ux"]) }
// #when: resolving multiple skills with disabled one
const result = resolveMultipleSkills(skillNames, options)
// #then: frontend-ui-ux in notFound, playwright resolved
expect(result.resolved.size).toBe(1)
expect(result.resolved.has("playwright")).toBe(true)
expect(result.notFound).toEqual(["frontend-ui-ux"])
})
it("should preserve skill order in resolved map", () => { it("should preserve skill order in resolved map", () => {
// given: list of skill names in specific order // given: list of skill names in specific order
const skillNames = ["playwright", "frontend-ui-ux"] const skillNames = ["playwright", "frontend-ui-ux"]
@ -111,21 +127,24 @@ describe("resolveMultipleSkills", () => {
}) })
describe("resolveSkillContentAsync", () => { describe("resolveSkillContentAsync", () => {
it("should return template for builtin skill", async () => { it("should return template for builtin skill async", async () => {
// given: builtin skill 'frontend-ui-ux' // given: builtin skill 'frontend-ui-ux'
// when: resolving content async // when: resolving content async
const result = await resolveSkillContentAsync("frontend-ui-ux") const options = { disabledSkills: new Set(["frontend-ui-ux"]) }
const result = await resolveSkillContentAsync("git-master", options)
// then: returns template string // then: returns template string
expect(result).not.toBeNull() expect(result).not.toBeNull()
expect(typeof result).toBe("string") expect(typeof result).toBe("string")
expect(result).toContain("Role: Designer-Turned-Developer") expect(result).toContain("Git Master Agent")
}) })
it("should return null for non-existent skill", async () => { it("should return null for disabled skill async", async () => {
// given: non-existent skill name // given: frontend-ui-ux disabled
// when: resolving content async const options = { disabledSkills: new Set(["frontend-ui-ux"]) }
const result = await resolveSkillContentAsync("definitely-not-a-skill-12345")
// when: resolving content async for disabled skill
const result = await resolveSkillContentAsync("frontend-ui-ux", options)
// then: returns null // then: returns null
expect(result).toBeNull() expect(result).toBeNull()
@ -133,9 +152,9 @@ describe("resolveSkillContentAsync", () => {
}) })
describe("resolveMultipleSkillsAsync", () => { describe("resolveMultipleSkillsAsync", () => {
it("should resolve builtin skills", async () => { it("should resolve builtin skills async", async () => {
// given: builtin skill names // given: builtin skill names
const skillNames = ["playwright", "frontend-ui-ux"] 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)
@ -144,10 +163,10 @@ describe("resolveMultipleSkillsAsync", () => {
expect(result.resolved.size).toBe(2) expect(result.resolved.size).toBe(2)
expect(result.notFound).toEqual([]) expect(result.notFound).toEqual([])
expect(result.resolved.get("playwright")).toContain("Playwright Browser Automation") expect(result.resolved.get("playwright")).toContain("Playwright Browser Automation")
expect(result.resolved.get("frontend-ui-ux")).toContain("Designer-Turned-Developer") expect(result.resolved.get("git-master")).toContain("Git Master Agent")
}) })
it("should handle partial success with non-existent skills", async () => { it("should handle partial success with non-existent skills async", async () => {
// given: mix of existing and non-existing skills // given: mix of existing and non-existing skills
const skillNames = ["playwright", "nonexistent-skill-12345"] const skillNames = ["playwright", "nonexistent-skill-12345"]
@ -160,6 +179,20 @@ describe("resolveMultipleSkillsAsync", () => {
expect(result.resolved.get("playwright")).toContain("Playwright Browser Automation") expect(result.resolved.get("playwright")).toContain("Playwright Browser Automation")
}) })
it("should treat disabled skills as not found async", async () => {
// #given: frontend-ui-ux disabled
const skillNames = ["frontend-ui-ux", "playwright"]
const options = { disabledSkills: new Set(["frontend-ui-ux"]) }
// #when: resolving multiple skills async with disabled one
const result = await resolveMultipleSkillsAsync(skillNames, options)
// #then: frontend-ui-ux in notFound, playwright resolved
expect(result.resolved.size).toBe(1)
expect(result.resolved.has("playwright")).toBe(true)
expect(result.notFound).toEqual(["frontend-ui-ux"])
})
it("should NOT inject watermark when both options are disabled", async () => { it("should NOT inject watermark when both options are disabled", async () => {
// given: git-master skill with watermark disabled // given: git-master skill with watermark disabled
const skillNames = ["git-master"] const skillNames = ["git-master"]

View File

@ -8,6 +8,7 @@ import type { GitMasterConfig, BrowserAutomationProvider } from "../../config/sc
export interface SkillResolutionOptions { export interface SkillResolutionOptions {
gitMasterConfig?: GitMasterConfig gitMasterConfig?: GitMasterConfig
browserProvider?: BrowserAutomationProvider browserProvider?: BrowserAutomationProvider
disabledSkills?: Set<string>
} }
const cachedSkillsByProvider = new Map<string, LoadedSkill[]>() const cachedSkillsByProvider = new Map<string, LoadedSkill[]>()
@ -23,7 +24,12 @@ async function getAllSkills(options?: SkillResolutionOptions): Promise<LoadedSki
const [discoveredSkills, builtinSkillDefs] = await Promise.all([ const [discoveredSkills, builtinSkillDefs] = await Promise.all([
discoverSkills({ includeClaudeCodePaths: true }), discoverSkills({ includeClaudeCodePaths: true }),
Promise.resolve(createBuiltinSkills({ browserProvider: options?.browserProvider })), Promise.resolve(
createBuiltinSkills({
browserProvider: options?.browserProvider,
disabledSkills: options?.disabledSkills,
})
),
]) ])
const builtinSkillsAsLoaded: LoadedSkill[] = builtinSkillDefs.map((skill) => ({ const builtinSkillsAsLoaded: LoadedSkill[] = builtinSkillDefs.map((skill) => ({
@ -122,7 +128,10 @@ export function injectGitMasterConfig(template: string, config?: GitMasterConfig
} }
export function resolveSkillContent(skillName: string, options?: SkillResolutionOptions): string | null { export function resolveSkillContent(skillName: string, options?: SkillResolutionOptions): string | null {
const skills = createBuiltinSkills({ browserProvider: options?.browserProvider }) const skills = createBuiltinSkills({
browserProvider: options?.browserProvider,
disabledSkills: options?.disabledSkills,
})
const skill = skills.find((s) => s.name === skillName) const skill = skills.find((s) => s.name === skillName)
if (!skill) return null if (!skill) return null
@ -137,7 +146,10 @@ export function resolveMultipleSkills(skillNames: string[], options?: SkillResol
resolved: Map<string, string> resolved: Map<string, string>
notFound: string[] notFound: string[]
} { } {
const skills = createBuiltinSkills({ browserProvider: options?.browserProvider }) const skills = createBuiltinSkills({
browserProvider: options?.browserProvider,
disabledSkills: options?.disabledSkills,
})
const skillMap = new Map(skills.map((s) => [s.name, s.template])) const skillMap = new Map(skills.map((s) => [s.name, s.template]))
const resolved = new Map<string, string>() const resolved = new Map<string, string>()

View File

@ -388,6 +388,7 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
const lookAt = isMultimodalLookerEnabled ? createLookAt(ctx) : null; const lookAt = isMultimodalLookerEnabled ? createLookAt(ctx) : null;
const browserProvider = const browserProvider =
pluginConfig.browser_automation_engine?.provider ?? "playwright"; pluginConfig.browser_automation_engine?.provider ?? "playwright";
const disabledSkills = new Set<string>(pluginConfig.disabled_skills ?? []);
const delegateTask = createDelegateTask({ const delegateTask = createDelegateTask({
manager: backgroundManager, manager: backgroundManager,
client: ctx.client, client: ctx.client,
@ -396,6 +397,7 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
gitMasterConfig: pluginConfig.git_master, gitMasterConfig: pluginConfig.git_master,
sisyphusJuniorModel: pluginConfig.agents?.["sisyphus-junior"]?.model, sisyphusJuniorModel: pluginConfig.agents?.["sisyphus-junior"]?.model,
browserProvider, browserProvider,
disabledSkills,
onSyncSessionCreated: async (event) => { onSyncSessionCreated: async (event) => {
log("[index] onSyncSessionCreated callback", { log("[index] onSyncSessionCreated callback", {
sessionID: event.sessionID, sessionID: event.sessionID,
@ -414,11 +416,8 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
}); });
}, },
}); });
const disabledSkills = new Set(pluginConfig.disabled_skills ?? []);
const systemMcpNames = getSystemMcpServerNames(); const systemMcpNames = getSystemMcpServerNames();
const builtinSkills = createBuiltinSkills({ browserProvider }).filter( const builtinSkills = createBuiltinSkills({ browserProvider, disabledSkills }).filter((skill) => {
(skill) => {
if (disabledSkills.has(skill.name as never)) return false;
if (skill.mcpConfig) { if (skill.mcpConfig) {
for (const mcpName of Object.keys(skill.mcpConfig)) { for (const mcpName of Object.keys(skill.mcpConfig)) {
if (systemMcpNames.has(mcpName)) return false; if (systemMcpNames.has(mcpName)) return false;
@ -450,6 +449,7 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
mcpManager: skillMcpManager, mcpManager: skillMcpManager,
getSessionID: getSessionIDForMcp, getSessionID: getSessionIDForMcp,
gitMasterConfig: pluginConfig.git_master, gitMasterConfig: pluginConfig.git_master,
disabledSkills
}); });
const skillMcpTool = createSkillMcpTool({ const skillMcpTool = createSkillMcpTool({
manager: skillMcpManager, manager: skillMcpManager,

View File

@ -157,6 +157,7 @@ export function createConfigHandler(deps: ConfigHandlerDeps) {
// config.model represents the currently active model in OpenCode (including UI selection) // config.model represents the currently active model in OpenCode (including UI selection)
// Pass it as uiSelectedModel so it takes highest priority in model resolution // Pass it as uiSelectedModel so it takes highest priority in model resolution
const currentModel = config.model as string | undefined; const currentModel = config.model as string | undefined;
const disabledSkills = new Set<string>(pluginConfig.disabled_skills ?? []);
const builtinAgents = await createBuiltinAgents( const builtinAgents = await createBuiltinAgents(
migratedDisabledAgents, migratedDisabledAgents,
pluginConfig.agents, pluginConfig.agents,
@ -167,7 +168,8 @@ export function createConfigHandler(deps: ConfigHandlerDeps) {
allDiscoveredSkills, allDiscoveredSkills,
ctx.client, ctx.client,
browserProvider, browserProvider,
currentModel // uiSelectedModel - takes highest priority currentModel, // uiSelectedModel - takes highest priority
disabledSkills
); );
// Claude Code agents: Do NOT apply permission migration // Claude Code agents: Do NOT apply permission migration
@ -358,7 +360,8 @@ export function createConfigHandler(deps: ConfigHandlerDeps) {
: {}; : {};
const planDemoteConfig = shouldDemotePlan const planDemoteConfig = shouldDemotePlan
? { mode: "subagent" as const } ? { mode: "subagent" as const
}
: undefined; : undefined;
config.agent = { config.agent = {

View File

@ -44,7 +44,7 @@ interface SessionMessage {
export async function resolveSkillContent( export async function resolveSkillContent(
skills: string[], skills: string[],
options: { gitMasterConfig?: GitMasterConfig; browserProvider?: BrowserAutomationProvider } options: { gitMasterConfig?: GitMasterConfig; browserProvider?: BrowserAutomationProvider, disabledSkills?: Set<string> }
): Promise<{ content: string | undefined; error: string | null }> { ): Promise<{ content: string | undefined; error: string | null }> {
if (skills.length === 0) { if (skills.length === 0) {
return { content: undefined, error: null } return { content: undefined, error: null }

View File

@ -83,6 +83,7 @@ Prompts MUST be in English.`
const { content: skillContent, error: skillError } = await resolveSkillContent(args.load_skills, { const { content: skillContent, error: skillError } = await resolveSkillContent(args.load_skills, {
gitMasterConfig: options.gitMasterConfig, gitMasterConfig: options.gitMasterConfig,
browserProvider: options.browserProvider, browserProvider: options.browserProvider,
disabledSkills: options.disabledSkills,
}) })
if (skillError) { if (skillError) {
return skillError return skillError

View File

@ -41,6 +41,7 @@ export interface DelegateTaskToolOptions {
gitMasterConfig?: GitMasterConfig gitMasterConfig?: GitMasterConfig
sisyphusJuniorModel?: string sisyphusJuniorModel?: string
browserProvider?: BrowserAutomationProvider browserProvider?: BrowserAutomationProvider
disabledSkills?: Set<string>
onSyncSessionCreated?: (event: SyncSessionCreatedEvent) => Promise<void> onSyncSessionCreated?: (event: SyncSessionCreatedEvent) => Promise<void>
} }

View File

@ -133,7 +133,7 @@ export function createSkillTool(options: SkillLoadOptions = {}): ToolDefinition
const getSkills = async (): Promise<LoadedSkill[]> => { const getSkills = async (): Promise<LoadedSkill[]> => {
if (options.skills) return options.skills if (options.skills) return options.skills
if (cachedSkills) return cachedSkills if (cachedSkills) return cachedSkills
cachedSkills = await getAllSkills() cachedSkills = await getAllSkills({disabledSkills: options?.disabledSkills})
return cachedSkills return cachedSkills
} }

View File

@ -28,4 +28,5 @@ export interface SkillLoadOptions {
getSessionID?: () => string getSessionID?: () => string
/** Git master configuration for watermark/co-author settings */ /** Git master configuration for watermark/co-author settings */
gitMasterConfig?: GitMasterConfig gitMasterConfig?: GitMasterConfig
disabledSkills?: Set<string>
} }