98 lines
2.9 KiB
JavaScript
98 lines
2.9 KiB
JavaScript
import fs from "fs";
|
||
import path from "path";
|
||
|
||
const AGENT_ROOT_MAP = {
|
||
agents: ".agents",
|
||
claudecode: ".claude",
|
||
opencode: ".opencode",
|
||
codex: ".codex",
|
||
};
|
||
|
||
const ALL_AGENT_TYPES = Object.keys(AGENT_ROOT_MAP);
|
||
const PRIMARY_AGENT_TYPE = "agents";
|
||
|
||
async function removePathIfExists(targetPath) {
|
||
if (!fs.existsSync(targetPath)) return;
|
||
await fs.promises.rm(targetPath, { recursive: true, force: true });
|
||
}
|
||
|
||
async function ensureDir(dirPath) {
|
||
if (fs.existsSync(dirPath)) return;
|
||
await fs.promises.mkdir(dirPath, { recursive: true });
|
||
}
|
||
|
||
async function copyDirectory(srcDir, destDir) {
|
||
const stat = await fs.promises.lstat(srcDir);
|
||
if (stat.isDirectory()) {
|
||
await ensureDir(destDir);
|
||
const entries = await fs.promises.readdir(srcDir);
|
||
for (const entry of entries) {
|
||
await copyDirectory(path.join(srcDir, entry), path.join(destDir, entry));
|
||
}
|
||
} else {
|
||
await ensureDir(path.dirname(destDir));
|
||
await fs.promises.copyFile(srcDir, destDir);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 仅确保主 agent(.claude)目录存在,业务逻辑只写这一份
|
||
*/
|
||
async function ensurePrimaryAgentDirs(workspaceRoot) {
|
||
const rootDir = path.join(workspaceRoot, AGENT_ROOT_MAP[PRIMARY_AGENT_TYPE]);
|
||
const skillsDir = path.join(rootDir, "skills");
|
||
const agentsDir = path.join(rootDir, "agents");
|
||
await ensureDir(rootDir);
|
||
await ensureDir(skillsDir);
|
||
await ensureDir(agentsDir);
|
||
return { rootDir, skillsDir, agentsDir, agentTypes: ALL_AGENT_TYPES };
|
||
}
|
||
|
||
/**
|
||
* 将主 agent 目录内容同步到其他 agent 目录
|
||
*/
|
||
async function syncAgents(workspaceRoot) {
|
||
const primary = await ensurePrimaryAgentDirs(workspaceRoot);
|
||
|
||
for (const agentType of ALL_AGENT_TYPES) {
|
||
if (agentType === PRIMARY_AGENT_TYPE) continue;
|
||
const targetRoot = path.join(workspaceRoot, AGENT_ROOT_MAP[agentType]);
|
||
const targetSkills = path.join(targetRoot, "skills");
|
||
const targetAgents = path.join(targetRoot, "agents");
|
||
await ensureDir(targetRoot);
|
||
|
||
await removePathIfExists(targetSkills);
|
||
await ensureDir(targetSkills);
|
||
if (fs.existsSync(primary.skillsDir)) {
|
||
const entries = await fs.promises.readdir(primary.skillsDir, {
|
||
withFileTypes: true,
|
||
});
|
||
for (const entry of entries) {
|
||
const srcPath = path.join(primary.skillsDir, entry.name);
|
||
const dstPath = path.join(targetSkills, entry.name);
|
||
await copyDirectory(srcPath, dstPath);
|
||
}
|
||
}
|
||
|
||
await removePathIfExists(targetAgents);
|
||
await ensureDir(targetAgents);
|
||
if (fs.existsSync(primary.agentsDir)) {
|
||
const entries = await fs.promises.readdir(primary.agentsDir, {
|
||
withFileTypes: true,
|
||
});
|
||
for (const entry of entries) {
|
||
const srcPath = path.join(primary.agentsDir, entry.name);
|
||
const dstPath = path.join(targetAgents, entry.name);
|
||
await copyDirectory(srcPath, dstPath);
|
||
}
|
||
}
|
||
}
|
||
|
||
return { agentTypes: ALL_AGENT_TYPES };
|
||
}
|
||
|
||
export {
|
||
ensurePrimaryAgentDirs,
|
||
syncAgents,
|
||
};
|