Merge branch 'worktree-agent-afbb9437'

This commit is contained in:
ZacharyZhang-NY committed 2026-03-28 03:26:56 -04:00
commit 2ed952f19c
90 files changed
+270701 -32

No files matched your search

+7
View File
@@ -1182,6 +1182,13 @@ export class AppDatabase {
return row ? { ...row, isPrimary: toBoolean(row.isPrimary) } : null;
}
listWorkspaceLocalPaths(companyId: string): string[] {
const rows = this.db
.prepare("select local_path as localPath from workspaces where company_id = ? and local_path is not null")
.all(companyId) as Array<{ localPath: string }>;
return rows.map((r) => r.localPath).filter(Boolean);
}
getAnyCompanyWorkspace(companyId: string): WorkspaceRecord | null {
const row = this.db
.prepare(
+5 -1
View File
@@ -8,6 +8,7 @@ import {
dialog,
Menu,
nativeImage,
nativeTheme,
net,
protocol,
session,
@@ -206,7 +207,7 @@ export function createDesktopShellService({
y: savedWindowState.bounds.y,
minWidth: 1180,
minHeight: 760,
backgroundColor: "#13110f",
backgroundColor: "#ffffff",
titleBarStyle: process.platform === "darwin" ? "hiddenInset" : "default",
webPreferences: {
preload: preloadPath,
@@ -220,6 +221,9 @@ export function createDesktopShellService({
},
});
// Sync native theme with app to ensure Windows title bar matches content
nativeTheme.themeSource = "light";
if (isDev && devServerUrl) {
await mainWindow.loadURL(devServerUrl);
} else {
+7 -1
View File
@@ -50,13 +50,19 @@ export function registerSkillHandlers({
return result;
});
// ---- List all skills for a company ----
// ---- List all skills for a company (also scans workspace .agents/skills/) ----
registerHandle(IPC_CHANNELS.listSkills, async (_event, payload) => {
const parsed = listSkillsSchema.parse(payload);
const companyError = ensureCompanyExists(parsed.companyId);
if (companyError) return companyError;
const serviceError = requireSkillService();
if (serviceError) return serviceError;
// Scan workspace .agents/skills/ directories for new skills before listing
try {
await skillService!.scanWorkspaceSkills(parsed.companyId);
} catch {
// Non-fatal: scan failure should not block listing existing skills
}
return ok(skillService!.listForCompany(parsed.companyId));
});
+61
View File
@@ -701,6 +701,66 @@ 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 allResults: SkillImportResult[] = [];
// 1. Scan user home directories: ~/.agents/skills/ and ~/.claude/skills/
const homeDir = process.env.HOME || process.env.USERPROFILE || "";
if (homeDir) {
const homeScanDirs = [
join(homeDir, ".agents", "skills"),
join(homeDir, ".claude", "skills"),
];
for (const scanDir of homeScanDirs) {
if (!existsSync(scanDir)) continue;
try {
const stat = statSync(scanDir);
if (!stat.isDirectory()) continue;
const results = await importFromLocal(companyId, scanDir);
allResults.push(...results);
logger.info(`Scanned home skills: ${scanDir} — imported ${results.length} skill(s)`);
} catch (err) {
const message = err instanceof Error ? err.message : String(err);
logger.warn(`Failed to scan home skills at ${scanDir}: ${message}`);
}
}
}
// 2. Scan workspace .agents/skills/ directories
const workspacePaths = db.listWorkspaceLocalPaths(companyId);
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 +775,6 @@ export function createSkillService({ db, profileDir, logger }: SkillServiceDepen
removeFromAgent,
checkUpdateStatus,
listRuntimeSkillEntries,
scanWorkspaceSkills,
};
}