feat: scan workspace .agents/skills/ directories for skill imports

Add scanWorkspaceSkills method to skill service that iterates all
workspace local paths for a company and imports SKILL.md files from
.agents/skills/ subdirectories. Uses path.join for cross-platform
compatibility (Windows/macOS/Linux). The scan runs automatically
when skills are listed via IPC, with graceful error handling per
workspace so one bad path does not block the entire listing.

Also adds listWorkspaceLocalPaths to database for retrieving workspace
paths by company.
This commit is contained in:
ZacharyZhang-NY committed 2026-03-27 22:38:02 -04:00
1 parent 831acc3b06
commit 3b756fd30d
3 files changed
+52 -1

No files matched your search

+38
View File
@@ -701,6 +701,43 @@ export function createSkillService({ db, profileDir, logger }: SkillServiceDepen
return inventory;
}
// ---- Workspace .agents/skills/ scanning (Bug 6) ----
/**
* Scan all workspace local paths for a company, looking for
* `.agents/skills/` directories containing SKILL.md files.
* Auto-imports any found skills that are not already in the database.
* Cross-platform: uses path.join for correct separators.
*/
async function scanWorkspaceSkills(
companyId: string,
): Promise<SkillImportResult[]> {
const workspacePaths = db.listWorkspaceLocalPaths(companyId);
const allResults: SkillImportResult[] = [];
for (const wsPath of workspacePaths) {
const agentsSkillsDir = join(wsPath, ".agents", "skills");
if (!existsSync(agentsSkillsDir)) continue;
try {
const stat = statSync(agentsSkillsDir);
if (!stat.isDirectory()) continue;
const results = await importFromLocal(companyId, agentsSkillsDir);
allResults.push(...results);
logger.info(
`Scanned workspace skills: ${agentsSkillsDir} — imported ${results.length} skill(s)`,
);
} catch (err) {
// Log but don't fail the entire scan if one workspace has issues
const message = err instanceof Error ? err.message : String(err);
logger.warn(`Failed to scan workspace skills at ${agentsSkillsDir}: ${message}`);
}
}
return allResults;
}
// ---- Public API ----
return {
@@ -715,5 +752,6 @@ export function createSkillService({ db, profileDir, logger }: SkillServiceDepen
removeFromAgent,
checkUpdateStatus,
listRuntimeSkillEntries,
scanWorkspaceSkills,
};
}