From e8cece82ef316f7a3e96080f35e4d0314d711a63 Mon Sep 17 00:00:00 2001 From: Shakker Date: Fri, 29 May 2026 18:20:04 +0100 Subject: [PATCH] perf: speed up skills filtering --- src/skills/discovery/status.ts | 32 ++++++++++++++++++-------------- src/skills/loading/workspace.ts | 10 ++++++---- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/src/skills/discovery/status.ts b/src/skills/discovery/status.ts index 702352b45a3c..5950f23a924f 100644 --- a/src/skills/discovery/status.ts +++ b/src/skills/discovery/status.ts @@ -237,18 +237,23 @@ function normalizeInstallOptions( return [toOption(preferred.spec, preferred.index)]; } +type BuildSkillStatusContext = { + config?: OpenClawConfig; + prefs: SkillsInstallPreferences; + eligibility?: SkillEligibilityContext; + allowBundled: string[] | undefined; + agentSkillFilter?: string[]; + workspaceDir: string; + clawhubLockRead: ClawHubSkillsLockfileStatusRead; +}; + function buildSkillStatus( indexed: SkillIndexEntry, - config?: OpenClawConfig, - prefs?: SkillsInstallPreferences, - eligibility?: SkillEligibilityContext, - allowBundled?: string[], - agentSkillFilter?: string[], - workspaceDir?: string, - clawhubLockRead?: ClawHubSkillsLockfileStatusRead, + context: BuildSkillStatusContext, ): SkillStatusEntry { const entry = indexed.entry; const skillKey = indexed.skillKey; + const { config, prefs, eligibility, allowBundled, agentSkillFilter, workspaceDir } = context; const skillConfig = resolveSkillConfig(config, skillKey); const disabled = skillConfig?.enabled === false; const blockedByAllowlist = !isBundledSkillAllowed(entry, allowBundled); @@ -283,7 +288,7 @@ function buildSkillStatus( workspaceDir, skillDir: entry.skill.baseDir, skillKey, - lockRead: clawhubLockRead, + lockRead: context.clawhubLockRead, }) : undefined; const skillCard = resolveLocalSkillCardStatusSync(entry.skill.baseDir); @@ -310,7 +315,7 @@ function buildSkillStatus( requirements: required, missing, configChecks, - install: normalizeInstallOptions(entry, prefs ?? resolveSkillsInstallPreferences(config)), + install: normalizeInstallOptions(entry, prefs), ...(clawhub ? { clawhub } : {}), ...(skillCard ? { skillCard } : {}), }; @@ -351,16 +356,15 @@ export function buildWorkspaceSkillStatus( agentId: opts?.agentId, agentSkillFilter, skills: skillIndexEntries.map((entry) => - buildSkillStatus( - entry, - opts?.config, + buildSkillStatus(entry, { + config: opts?.config, prefs, - opts?.eligibility, + eligibility: opts?.eligibility, allowBundled, agentSkillFilter, workspaceDir, clawhubLockRead, - ), + }), ), }; } diff --git a/src/skills/loading/workspace.ts b/src/skills/loading/workspace.ts index 4fc8f072269b..0723d34d8ce1 100644 --- a/src/skills/loading/workspace.ts +++ b/src/skills/loading/workspace.ts @@ -119,10 +119,12 @@ function filterSkillEntries( const normalized = normalizeSkillFilter(skillFilter) ?? []; const label = normalized.length > 0 ? normalized.join(", ") : "(none)"; skillsLogger.debug(`Applying skill filter: ${label}`); - filtered = - normalized.length > 0 - ? filtered.filter((entry) => normalized.includes(entry.skill.name)) - : []; + if (normalized.length > 0) { + const allowed = new Set(normalized); + filtered = filtered.filter((entry) => allowed.has(entry.skill.name)); + } else { + filtered = []; + } skillsLogger.debug( `After skill filter: ${filtered.map((entry) => entry.skill.name).join(", ") || "(none)"}`, );