oneagent 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +469 -175
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1387,6 +1387,9 @@ function timeAgo(date) {
|
|
|
1387
1387
|
return `${months}mo ago`;
|
|
1388
1388
|
return `${Math.floor(months / 12)}y ago`;
|
|
1389
1389
|
}
|
|
1390
|
+
|
|
1391
|
+
// ../core/src/constants.ts
|
|
1392
|
+
var ONEAGENT_DIR = ".oneagent";
|
|
1390
1393
|
// ../core/src/agents.ts
|
|
1391
1394
|
var AGENT_DEFINITIONS;
|
|
1392
1395
|
var init_agents = __esm(() => {
|
|
@@ -1436,7 +1439,7 @@ var init_agents = __esm(() => {
|
|
|
1436
1439
|
target: "copilot",
|
|
1437
1440
|
displayName: "GitHub Copilot",
|
|
1438
1441
|
hint: ".github/instructions/*.instructions.md",
|
|
1439
|
-
detectIndicators: [".github/copilot-instructions.md", ".github"],
|
|
1442
|
+
detectIndicators: [".github/copilot-instructions.md", ".github/instructions"],
|
|
1440
1443
|
mainFile: ".github/copilot-instructions.md",
|
|
1441
1444
|
skillsDir: ".github/skills"
|
|
1442
1445
|
}
|
|
@@ -8415,9 +8418,10 @@ async function writeConfig(root, config) {
|
|
|
8415
8418
|
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
8416
8419
|
await fs.writeFile(filePath, $stringify(config));
|
|
8417
8420
|
}
|
|
8418
|
-
var CONFIG_REL
|
|
8421
|
+
var CONFIG_REL, ALL_AGENT_TARGETS;
|
|
8419
8422
|
var init_config = __esm(() => {
|
|
8420
8423
|
init_dist4();
|
|
8424
|
+
CONFIG_REL = `${ONEAGENT_DIR}/config.yml`;
|
|
8421
8425
|
ALL_AGENT_TARGETS = ["claude", "cursor", "windsurf", "opencode", "copilot"];
|
|
8422
8426
|
});
|
|
8423
8427
|
|
|
@@ -8431,7 +8435,7 @@ async function readDetectedFile(root, rel) {
|
|
|
8431
8435
|
if (stat.isSymbolicLink()) {
|
|
8432
8436
|
const linkTarget = await fs2.readlink(absolutePath);
|
|
8433
8437
|
const resolved = path2.resolve(path2.dirname(absolutePath), linkTarget);
|
|
8434
|
-
if (resolved.startsWith(path2.join(root,
|
|
8438
|
+
if (resolved.startsWith(path2.join(root, ONEAGENT_DIR)))
|
|
8435
8439
|
return null;
|
|
8436
8440
|
}
|
|
8437
8441
|
const content = await fs2.readFile(absolutePath, "utf-8");
|
|
@@ -8483,7 +8487,7 @@ var init_detect = __esm(() => {
|
|
|
8483
8487
|
import path3 from "path";
|
|
8484
8488
|
import fs3 from "fs/promises";
|
|
8485
8489
|
async function readRules(root) {
|
|
8486
|
-
const rulesDir = path3.join(root, "
|
|
8490
|
+
const rulesDir = path3.join(root, ONEAGENT_DIR, "rules");
|
|
8487
8491
|
try {
|
|
8488
8492
|
const files = await fs3.readdir(rulesDir);
|
|
8489
8493
|
return files.filter((f) => f.endsWith(".md")).map((f) => ({ name: path3.basename(f, ".md"), path: path3.join(rulesDir, f) })).sort((a, b) => a.name.localeCompare(b.name));
|
|
@@ -8518,7 +8522,7 @@ async function readSkillFile(filePath) {
|
|
|
8518
8522
|
return { name: path4.basename(filePath, ".md"), path: filePath, description, mode, content };
|
|
8519
8523
|
}
|
|
8520
8524
|
async function readSkills(root) {
|
|
8521
|
-
const skillsDir = path4.join(root, "
|
|
8525
|
+
const skillsDir = path4.join(root, ONEAGENT_DIR, "skills");
|
|
8522
8526
|
try {
|
|
8523
8527
|
const files = await fs4.readdir(skillsDir);
|
|
8524
8528
|
const mdFiles = files.filter((f) => f.endsWith(".md"));
|
|
@@ -8542,15 +8546,26 @@ async function ensureDir(dirPath) {
|
|
|
8542
8546
|
async function createSymlink(symlinkPath, target) {
|
|
8543
8547
|
await ensureDir(path5.dirname(symlinkPath));
|
|
8544
8548
|
try {
|
|
8545
|
-
await fs5.
|
|
8549
|
+
const stat = await fs5.lstat(symlinkPath);
|
|
8550
|
+
if (stat.isSymbolicLink() && await fs5.readlink(symlinkPath) === target)
|
|
8551
|
+
return;
|
|
8546
8552
|
} catch {}
|
|
8547
|
-
|
|
8553
|
+
for (let attempt = 0;attempt < 3; attempt++) {
|
|
8554
|
+
await fs5.rm(symlinkPath, { recursive: true, force: true });
|
|
8555
|
+
try {
|
|
8556
|
+
await fs5.symlink(target, symlinkPath);
|
|
8557
|
+
return;
|
|
8558
|
+
} catch (err) {
|
|
8559
|
+
if (err.code !== "EEXIST" || attempt === 2)
|
|
8560
|
+
throw err;
|
|
8561
|
+
}
|
|
8562
|
+
}
|
|
8548
8563
|
}
|
|
8549
8564
|
function relativeTarget(symlinkPath, targetAbsPath) {
|
|
8550
8565
|
return path5.relative(path5.dirname(symlinkPath), targetAbsPath);
|
|
8551
8566
|
}
|
|
8552
8567
|
function buildMainSymlinks(root, targets) {
|
|
8553
|
-
const instructionsAbs = path5.join(root, "
|
|
8568
|
+
const instructionsAbs = path5.join(root, ONEAGENT_DIR, "instructions.md");
|
|
8554
8569
|
const seen = new Map;
|
|
8555
8570
|
for (const target of targets) {
|
|
8556
8571
|
const def = AGENT_DEFINITIONS.find((d2) => d2.target === target);
|
|
@@ -8566,21 +8581,21 @@ function buildMainSymlinks(root, targets) {
|
|
|
8566
8581
|
return Array.from(seen.values());
|
|
8567
8582
|
}
|
|
8568
8583
|
function buildRulesSymlinks(root, targets) {
|
|
8569
|
-
const targetAbs = path5.join(root, "
|
|
8584
|
+
const targetAbs = path5.join(root, ONEAGENT_DIR, "rules");
|
|
8570
8585
|
return AGENT_DEFINITIONS.filter((d2) => targets.includes(d2.target) && d2.rulesDir).map((d2) => {
|
|
8571
8586
|
const symlinkPath = path5.join(root, d2.rulesDir);
|
|
8572
8587
|
return { symlinkPath, target: relativeTarget(symlinkPath, targetAbs), label: d2.rulesDir };
|
|
8573
8588
|
});
|
|
8574
8589
|
}
|
|
8575
8590
|
function buildSkillSymlinks(root, targets) {
|
|
8576
|
-
const targetAbs = path5.join(root, "
|
|
8591
|
+
const targetAbs = path5.join(root, ONEAGENT_DIR, "skills");
|
|
8577
8592
|
return AGENT_DEFINITIONS.filter((d2) => targets.includes(d2.target) && d2.skillsDir).map((d2) => {
|
|
8578
8593
|
const symlinkPath = path5.join(root, d2.skillsDir);
|
|
8579
8594
|
return { symlinkPath, target: relativeTarget(symlinkPath, targetAbs), label: d2.skillsDir };
|
|
8580
8595
|
});
|
|
8581
8596
|
}
|
|
8582
8597
|
function buildCommandSymlinks(root, targets) {
|
|
8583
|
-
const targetAbs = path5.join(root, "
|
|
8598
|
+
const targetAbs = path5.join(root, ONEAGENT_DIR, "commands");
|
|
8584
8599
|
return AGENT_DEFINITIONS.filter((d2) => targets.includes(d2.target) && d2.commandsDir).map((d2) => {
|
|
8585
8600
|
const symlinkPath = path5.join(root, d2.commandsDir);
|
|
8586
8601
|
return { symlinkPath, target: relativeTarget(symlinkPath, targetAbs), label: d2.commandsDir };
|
|
@@ -8588,7 +8603,7 @@ function buildCommandSymlinks(root, targets) {
|
|
|
8588
8603
|
}
|
|
8589
8604
|
function buildAgentsDirSymlinks(root) {
|
|
8590
8605
|
const symlinkPath = path5.join(root, ".agents/skills");
|
|
8591
|
-
const targetAbs = path5.join(root, "
|
|
8606
|
+
const targetAbs = path5.join(root, ONEAGENT_DIR, "skills");
|
|
8592
8607
|
return [{ symlinkPath, target: relativeTarget(symlinkPath, targetAbs), label: ".agents/skills" }];
|
|
8593
8608
|
}
|
|
8594
8609
|
async function migrateFilesFromDir(srcDir, destDir, root) {
|
|
@@ -8600,9 +8615,22 @@ async function migrateFilesFromDir(srcDir, destDir, root) {
|
|
|
8600
8615
|
return;
|
|
8601
8616
|
}
|
|
8602
8617
|
for (const entry of entries) {
|
|
8603
|
-
if (!entry.isFile())
|
|
8604
|
-
continue;
|
|
8605
8618
|
const srcFile = path5.join(srcDir, entry.name);
|
|
8619
|
+
const fileStat = await fs5.lstat(srcFile);
|
|
8620
|
+
if (fileStat.isSymbolicLink())
|
|
8621
|
+
continue;
|
|
8622
|
+
if (fileStat.isDirectory()) {
|
|
8623
|
+
const destSub = path5.join(destDir, entry.name);
|
|
8624
|
+
try {
|
|
8625
|
+
await fs5.access(destSub);
|
|
8626
|
+
} catch {
|
|
8627
|
+
await fs5.mkdir(destDir, { recursive: true });
|
|
8628
|
+
await fs5.rename(srcFile, destSub);
|
|
8629
|
+
}
|
|
8630
|
+
continue;
|
|
8631
|
+
}
|
|
8632
|
+
if (!fileStat.isFile())
|
|
8633
|
+
continue;
|
|
8606
8634
|
const destFile = path5.join(destDir, entry.name);
|
|
8607
8635
|
let destExists = false;
|
|
8608
8636
|
try {
|
|
@@ -8615,7 +8643,7 @@ async function migrateFilesFromDir(srcDir, destDir, root) {
|
|
|
8615
8643
|
fs5.readFile(destFile, "utf-8")
|
|
8616
8644
|
]);
|
|
8617
8645
|
if (srcContent !== destContent) {
|
|
8618
|
-
const backupDir = path5.join(root, "
|
|
8646
|
+
const backupDir = path5.join(root, ONEAGENT_DIR, "backup");
|
|
8619
8647
|
await fs5.mkdir(backupDir, { recursive: true });
|
|
8620
8648
|
const safeName = path5.relative(root, srcFile).replace(/\//g, "_");
|
|
8621
8649
|
await fs5.writeFile(path5.join(backupDir, safeName), srcContent);
|
|
@@ -8639,21 +8667,75 @@ async function migrateAndRemoveDir(src, dest, root) {
|
|
|
8639
8667
|
await fs5.rm(src, { recursive: true, force: true });
|
|
8640
8668
|
}
|
|
8641
8669
|
async function migrateRuleAndSkillFiles(root) {
|
|
8642
|
-
const destRules = path5.join(root, "
|
|
8643
|
-
const destSkills = path5.join(root, "
|
|
8644
|
-
const destCommands = path5.join(root, "
|
|
8670
|
+
const destRules = path5.join(root, ONEAGENT_DIR, "rules");
|
|
8671
|
+
const destSkills = path5.join(root, ONEAGENT_DIR, "skills");
|
|
8672
|
+
const destCommands = path5.join(root, ONEAGENT_DIR, "commands");
|
|
8645
8673
|
for (const def of AGENT_DEFINITIONS) {
|
|
8646
8674
|
if (def.rulesDir)
|
|
8647
8675
|
await migrateAndRemoveDir(path5.join(root, def.rulesDir), destRules, root);
|
|
8648
8676
|
}
|
|
8677
|
+
for (const def of AGENT_DEFINITIONS) {
|
|
8678
|
+
if (def.skillsDir)
|
|
8679
|
+
await migrateAndRemoveDir(path5.join(root, def.skillsDir), destSkills, root);
|
|
8680
|
+
}
|
|
8649
8681
|
await migrateAndRemoveDir(path5.join(root, ".agents/skills"), destSkills, root);
|
|
8650
8682
|
for (const def of AGENT_DEFINITIONS) {
|
|
8651
8683
|
if (def.commandsDir)
|
|
8652
8684
|
await migrateAndRemoveDir(path5.join(root, def.commandsDir), destCommands, root);
|
|
8653
8685
|
}
|
|
8654
8686
|
}
|
|
8687
|
+
async function backupDirRecursive(srcDir, backupDir, prefix) {
|
|
8688
|
+
let entries;
|
|
8689
|
+
try {
|
|
8690
|
+
entries = await fs5.readdir(srcDir, { withFileTypes: true });
|
|
8691
|
+
} catch {
|
|
8692
|
+
return;
|
|
8693
|
+
}
|
|
8694
|
+
for (const entry of entries) {
|
|
8695
|
+
const srcPath = path5.join(srcDir, entry.name);
|
|
8696
|
+
const lstat = await fs5.lstat(srcPath);
|
|
8697
|
+
if (lstat.isSymbolicLink())
|
|
8698
|
+
continue;
|
|
8699
|
+
if (lstat.isDirectory()) {
|
|
8700
|
+
await backupDirRecursive(srcPath, backupDir, `${prefix}_${entry.name}`);
|
|
8701
|
+
} else if (lstat.isFile()) {
|
|
8702
|
+
await fs5.mkdir(backupDir, { recursive: true });
|
|
8703
|
+
await fs5.copyFile(srcPath, path5.join(backupDir, `${prefix}_${entry.name}`));
|
|
8704
|
+
}
|
|
8705
|
+
}
|
|
8706
|
+
}
|
|
8707
|
+
async function cleanupAgentDir(root, target) {
|
|
8708
|
+
const def = AGENT_DEFINITIONS.find((d2) => d2.target === target);
|
|
8709
|
+
const backupDir = path5.join(root, ONEAGENT_DIR, "backup");
|
|
8710
|
+
const agentDir = [def.rulesDir, def.skillsDir, def.commandsDir].filter(Boolean).map((d2) => d2.split("/")[0]).find((d2) => d2 !== ".github");
|
|
8711
|
+
if (agentDir) {
|
|
8712
|
+
const agentDirAbs = path5.join(root, agentDir);
|
|
8713
|
+
let stat;
|
|
8714
|
+
try {
|
|
8715
|
+
stat = await fs5.lstat(agentDirAbs);
|
|
8716
|
+
} catch {}
|
|
8717
|
+
if (stat && stat.isDirectory() && !stat.isSymbolicLink()) {
|
|
8718
|
+
await backupDirRecursive(agentDirAbs, backupDir, agentDir);
|
|
8719
|
+
await fs5.rm(agentDirAbs, { recursive: true, force: true });
|
|
8720
|
+
}
|
|
8721
|
+
}
|
|
8722
|
+
if (target === "opencode") {
|
|
8723
|
+
const opPath = path5.join(root, "opencode.json");
|
|
8724
|
+
try {
|
|
8725
|
+
const content = await fs5.readFile(opPath, "utf-8");
|
|
8726
|
+
await fs5.mkdir(backupDir, { recursive: true });
|
|
8727
|
+
await fs5.writeFile(path5.join(backupDir, "opencode.json"), content);
|
|
8728
|
+
} catch {}
|
|
8729
|
+
try {
|
|
8730
|
+
await fs5.unlink(opPath);
|
|
8731
|
+
} catch {}
|
|
8732
|
+
}
|
|
8733
|
+
}
|
|
8655
8734
|
async function createAllSymlinks(entries) {
|
|
8656
|
-
|
|
8735
|
+
const deduped = new Map;
|
|
8736
|
+
for (const e2 of entries)
|
|
8737
|
+
deduped.set(e2.symlinkPath, e2);
|
|
8738
|
+
for (const e2 of deduped.values()) {
|
|
8657
8739
|
await createSymlink(e2.symlinkPath, e2.target);
|
|
8658
8740
|
}
|
|
8659
8741
|
}
|
|
@@ -8722,7 +8804,7 @@ async function readOpencode(root) {
|
|
|
8722
8804
|
function buildOpencodeConfig(existing) {
|
|
8723
8805
|
return {
|
|
8724
8806
|
...existing,
|
|
8725
|
-
instructions:
|
|
8807
|
+
instructions: `${ONEAGENT_DIR}/instructions.md`
|
|
8726
8808
|
};
|
|
8727
8809
|
}
|
|
8728
8810
|
async function addOpenCodePlugin(root, id) {
|
|
@@ -8846,7 +8928,7 @@ async function checkOpencodeStatus(root, _rules) {
|
|
|
8846
8928
|
const existing = await readOpencode(root);
|
|
8847
8929
|
if (!existing)
|
|
8848
8930
|
return { exists: false, valid: false };
|
|
8849
|
-
return { exists: true, valid: existing["instructions"] ===
|
|
8931
|
+
return { exists: true, valid: existing["instructions"] === `${ONEAGENT_DIR}/instructions.md` };
|
|
8850
8932
|
}
|
|
8851
8933
|
async function checkCopilotPrompt(root, skill) {
|
|
8852
8934
|
const filePath = copilotPromptFilePath(root, skill.name);
|
|
@@ -8895,9 +8977,11 @@ function parseTemplateYaml(yamlText, fallbackName = "custom") {
|
|
|
8895
8977
|
const name = nameMatch?.[1]?.trim() ?? fallbackName;
|
|
8896
8978
|
const descMatch = yamlText.match(/^description:\s*(.+)$/m);
|
|
8897
8979
|
const description = descMatch?.[1]?.trim() ?? "";
|
|
8980
|
+
const extendsMatch = yamlText.match(/^extends:\s*(.+)$/m);
|
|
8981
|
+
const extendsValue = extendsMatch?.[1]?.trim();
|
|
8898
8982
|
const skills = parseSkillsFromYaml(yamlText);
|
|
8899
8983
|
const plugins = parsePluginsFromYaml(yamlText);
|
|
8900
|
-
return { name, description, skills, plugins };
|
|
8984
|
+
return { name, description, skills, plugins, ...extendsValue ? { extends: extendsValue } : {} };
|
|
8901
8985
|
}
|
|
8902
8986
|
function parseSkillsFromYaml(yamlText) {
|
|
8903
8987
|
const skills = [];
|
|
@@ -8934,8 +9018,31 @@ function parsePluginsFromYaml(yamlText) {
|
|
|
8934
9018
|
}
|
|
8935
9019
|
return plugins;
|
|
8936
9020
|
}
|
|
9021
|
+
async function resolveExtends(child, resolveBuiltin) {
|
|
9022
|
+
if (!child.extends)
|
|
9023
|
+
return child;
|
|
9024
|
+
let parent;
|
|
9025
|
+
if (child.extends.startsWith("https://")) {
|
|
9026
|
+
parent = await fetchTemplateFromGitHub(child.extends);
|
|
9027
|
+
} else if (resolveBuiltin) {
|
|
9028
|
+
const resolved = await resolveBuiltin(child.extends);
|
|
9029
|
+
if (!resolved)
|
|
9030
|
+
throw new Error(`Unknown builtin template: "${child.extends}"`);
|
|
9031
|
+
parent = resolved;
|
|
9032
|
+
} else {
|
|
9033
|
+
throw new Error(`Cannot resolve extends: "${child.extends}"`);
|
|
9034
|
+
}
|
|
9035
|
+
return {
|
|
9036
|
+
name: child.name,
|
|
9037
|
+
description: child.description,
|
|
9038
|
+
instructions: child.instructions,
|
|
9039
|
+
skills: [...parent.skills, ...child.skills],
|
|
9040
|
+
plugins: [...parent.plugins, ...child.plugins],
|
|
9041
|
+
rules: [...parent.rules, ...child.rules]
|
|
9042
|
+
};
|
|
9043
|
+
}
|
|
8937
9044
|
async function applyTemplateFiles(root, template) {
|
|
8938
|
-
const oneagentDir = path9.join(root,
|
|
9045
|
+
const oneagentDir = path9.join(root, ONEAGENT_DIR);
|
|
8939
9046
|
await fs10.mkdir(path9.join(oneagentDir, "rules"), { recursive: true });
|
|
8940
9047
|
await fs10.mkdir(path9.join(oneagentDir, "skills"), { recursive: true });
|
|
8941
9048
|
await fs10.writeFile(path9.join(oneagentDir, "instructions.md"), template.instructions);
|
|
@@ -8944,19 +9051,26 @@ async function applyTemplateFiles(root, template) {
|
|
|
8944
9051
|
}
|
|
8945
9052
|
}
|
|
8946
9053
|
async function installTemplateSkills(root, template) {
|
|
8947
|
-
const
|
|
9054
|
+
const installed = [];
|
|
9055
|
+
const failed = [];
|
|
9056
|
+
for (const entry of template.skills) {
|
|
8948
9057
|
try {
|
|
8949
9058
|
await execFileAsync("npx", ["skills", "add", entry.repo, "--skill", entry.skill, "--agent", "universal", "--yes"], { cwd: root });
|
|
8950
|
-
|
|
9059
|
+
installed.push(entry);
|
|
8951
9060
|
} catch (err) {
|
|
8952
9061
|
const reason = err instanceof Error ? err.message : String(err);
|
|
8953
|
-
|
|
9062
|
+
failed.push({ entry, reason });
|
|
8954
9063
|
}
|
|
8955
|
-
}
|
|
8956
|
-
return {
|
|
8957
|
-
|
|
8958
|
-
|
|
8959
|
-
|
|
9064
|
+
}
|
|
9065
|
+
return { installed, failed };
|
|
9066
|
+
}
|
|
9067
|
+
async function installBuiltinSkill(root) {
|
|
9068
|
+
try {
|
|
9069
|
+
await execFileAsync("npx", ["skills", "add", BUILTIN_SKILL_REPO, "--skill", BUILTIN_SKILL_NAME, "--agent", "universal", "--yes"], { cwd: root });
|
|
9070
|
+
return true;
|
|
9071
|
+
} catch {
|
|
9072
|
+
return false;
|
|
9073
|
+
}
|
|
8960
9074
|
}
|
|
8961
9075
|
async function installTemplatePlugins(root, template, activeTargets2) {
|
|
8962
9076
|
const installed = [];
|
|
@@ -8993,14 +9107,31 @@ async function installTemplatePlugins(root, template, activeTargets2) {
|
|
|
8993
9107
|
return { installed, manual, failed };
|
|
8994
9108
|
}
|
|
8995
9109
|
async function fetchTemplateFromGitHub(url) {
|
|
8996
|
-
const
|
|
9110
|
+
const { owner, repo, branch, subdir } = parseGitHubUrl(url);
|
|
9111
|
+
const branchExplicit = url.includes("/tree/");
|
|
9112
|
+
const resolvedBranch = branchExplicit ? branch : await fetchDefaultBranch(owner, repo);
|
|
9113
|
+
const rawBase = `https://raw.githubusercontent.com/${owner}/${repo}/${resolvedBranch}${subdir ? `/${subdir}` : ""}`;
|
|
8997
9114
|
const [yamlText, instructions] = await Promise.all([
|
|
8998
9115
|
fetchText(`${rawBase}/template.yml`),
|
|
8999
9116
|
fetchText(`${rawBase}/instructions.md`)
|
|
9000
9117
|
]);
|
|
9001
|
-
const
|
|
9118
|
+
const parsed = parseTemplateYaml(yamlText);
|
|
9002
9119
|
const rules = await fetchGitHubRules(url);
|
|
9003
|
-
|
|
9120
|
+
const base = { ...parsed, instructions, rules };
|
|
9121
|
+
return resolveExtends(base);
|
|
9122
|
+
}
|
|
9123
|
+
async function fetchDefaultBranch(owner, repo) {
|
|
9124
|
+
try {
|
|
9125
|
+
const response = await fetch(`https://api.github.com/repos/${owner}/${repo}`, {
|
|
9126
|
+
headers: { Accept: "application/vnd.github.v3+json" }
|
|
9127
|
+
});
|
|
9128
|
+
if (!response.ok)
|
|
9129
|
+
return "main";
|
|
9130
|
+
const data = await response.json();
|
|
9131
|
+
return data.default_branch ?? "main";
|
|
9132
|
+
} catch {
|
|
9133
|
+
return "main";
|
|
9134
|
+
}
|
|
9004
9135
|
}
|
|
9005
9136
|
async function fetchText(url) {
|
|
9006
9137
|
const response = await fetch(url);
|
|
@@ -9017,11 +9148,6 @@ function parseGitHubUrl(url) {
|
|
|
9017
9148
|
const [, owner, repo, branch = "main", subdir = ""] = match;
|
|
9018
9149
|
return { owner, repo, branch, subdir };
|
|
9019
9150
|
}
|
|
9020
|
-
function githubUrlToRawBase(url) {
|
|
9021
|
-
const { owner, repo, branch, subdir } = parseGitHubUrl(url);
|
|
9022
|
-
const base = `https://raw.githubusercontent.com/${owner}/${repo}/${branch}`;
|
|
9023
|
-
return subdir ? `${base}/${subdir}` : base;
|
|
9024
|
-
}
|
|
9025
9151
|
async function fetchGitHubRules(repoUrl) {
|
|
9026
9152
|
const { owner, repo, branch, subdir } = parseGitHubUrl(repoUrl);
|
|
9027
9153
|
const rulesPath = subdir ? `${subdir}/rules` : "rules";
|
|
@@ -9043,7 +9169,7 @@ async function fetchGitHubRules(repoUrl) {
|
|
|
9043
9169
|
return [];
|
|
9044
9170
|
}
|
|
9045
9171
|
}
|
|
9046
|
-
var execFileAsync;
|
|
9172
|
+
var execFileAsync, BUILTIN_SKILL_REPO = "https://github.com/moskalakamil/oneagent", BUILTIN_SKILL_NAME = "oneagent";
|
|
9047
9173
|
var init_apply_template = __esm(() => {
|
|
9048
9174
|
init_opencode();
|
|
9049
9175
|
execFileAsync = promisify(execFile);
|
|
@@ -9075,7 +9201,7 @@ async function loadTemplate(name) {
|
|
|
9075
9201
|
fs11.readFile(path10.join(templateDir, "template.yml"), "utf-8"),
|
|
9076
9202
|
fs11.readFile(path10.join(templateDir, "instructions.md"), "utf-8")
|
|
9077
9203
|
]);
|
|
9078
|
-
const
|
|
9204
|
+
const parsed = parseTemplateYaml(yamlText, name);
|
|
9079
9205
|
const rulesDir = path10.join(templateDir, "rules");
|
|
9080
9206
|
let rules2 = [];
|
|
9081
9207
|
try {
|
|
@@ -9085,7 +9211,8 @@ async function loadTemplate(name) {
|
|
|
9085
9211
|
content: await fs11.readFile(path10.join(rulesDir, f), "utf-8")
|
|
9086
9212
|
})));
|
|
9087
9213
|
} catch {}
|
|
9088
|
-
|
|
9214
|
+
const base = { ...parsed, instructions, rules: rules2 };
|
|
9215
|
+
return resolveExtends(base, (n) => resolveBuiltinTemplate(n));
|
|
9089
9216
|
}
|
|
9090
9217
|
async function resolveBuiltinTemplate(name) {
|
|
9091
9218
|
if (!TEMPLATE_NAMES.includes(name))
|
|
@@ -9105,98 +9232,6 @@ var init_src2 = __esm(() => {
|
|
|
9105
9232
|
];
|
|
9106
9233
|
});
|
|
9107
9234
|
|
|
9108
|
-
// src/assets/about-oneagent.ts
|
|
9109
|
-
var ABOUT_ONEAGENT_CONTENT = `---
|
|
9110
|
-
name: about-oneagent
|
|
9111
|
-
description: Explains how AI configuration is managed in this project using oneagent. Use when working with the .oneagent/ directory, adding or modifying rules or skills, or when files like CLAUDE.md, AGENTS.md, .cursor/rules/, or .github/instructions/ are mentioned.
|
|
9112
|
-
applyTo: "**"
|
|
9113
|
-
globs: "**"
|
|
9114
|
-
alwaysApply: true
|
|
9115
|
-
---
|
|
9116
|
-
# Project AI Configuration — oneagent
|
|
9117
|
-
|
|
9118
|
-
This project uses [oneagent](https://github.com/moskalakamil/oneagent) to manage AI agent configuration.
|
|
9119
|
-
Rules, skills, and instructions are maintained in a single source of truth and automatically distributed to all configured AI agents (Claude, Cursor, Windsurf, OpenCode, Copilot).
|
|
9120
|
-
|
|
9121
|
-
## Directory Structure
|
|
9122
|
-
|
|
9123
|
-
\`\`\`
|
|
9124
|
-
.oneagent/
|
|
9125
|
-
instructions.md # Main project instructions (source for CLAUDE.md, AGENTS.md, etc.)
|
|
9126
|
-
rules/ # Rules distributed to all configured agents
|
|
9127
|
-
skills/ # Skills distributed as slash commands / agent tools
|
|
9128
|
-
\`\`\`
|
|
9129
|
-
|
|
9130
|
-
> Do NOT edit files in \`.claude/\`, \`.cursor/\`, \`.windsurf/\`, \`.opencode/\`, \`.github/instructions/\` directly.
|
|
9131
|
-
> These are auto-generated or symlinked from \`.oneagent/\` and will be overwritten on next \`oneagent generate\`.
|
|
9132
|
-
|
|
9133
|
-
## Adding a Rule
|
|
9134
|
-
|
|
9135
|
-
Create a \`.md\` file in \`.oneagent/rules/\`. Each agent reads frontmatter differently — use all relevant fields:
|
|
9136
|
-
|
|
9137
|
-
**Rule that applies to all files (recommended for general guidelines):**
|
|
9138
|
-
|
|
9139
|
-
\`\`\`md
|
|
9140
|
-
---
|
|
9141
|
-
name: rule-name
|
|
9142
|
-
description: What this rule does and when to use it (used by Cursor and Copilot).
|
|
9143
|
-
applyTo: "**"
|
|
9144
|
-
alwaysApply: true
|
|
9145
|
-
---
|
|
9146
|
-
# Rule Title
|
|
9147
|
-
|
|
9148
|
-
Rule content here.
|
|
9149
|
-
\`\`\`
|
|
9150
|
-
|
|
9151
|
-
**Rule scoped to specific files:**
|
|
9152
|
-
|
|
9153
|
-
\`\`\`md
|
|
9154
|
-
---
|
|
9155
|
-
name: rule-name
|
|
9156
|
-
description: What this rule does (used by Cursor and Copilot to decide when to apply it).
|
|
9157
|
-
applyTo: "**/*.ts"
|
|
9158
|
-
globs: "**/*.ts"
|
|
9159
|
-
---
|
|
9160
|
-
# Rule Title
|
|
9161
|
-
|
|
9162
|
-
Rule content here.
|
|
9163
|
-
\`\`\`
|
|
9164
|
-
|
|
9165
|
-
**Frontmatter fields by agent:**
|
|
9166
|
-
|
|
9167
|
-
| Field | Agent | Purpose |
|
|
9168
|
-
|-------|-------|---------|
|
|
9169
|
-
| \`applyTo\` | Claude Code, Copilot | Glob pattern scoping the rule to matching files |
|
|
9170
|
-
| \`globs\` | Cursor | Glob pattern for file-scoped rules ("Apply to Specific Files" mode) |
|
|
9171
|
-
| \`alwaysApply: true\` | Cursor | Apply to every session regardless of files ("Always Apply" mode) |
|
|
9172
|
-
| \`description\` | Cursor, Copilot | Used by the agent to decide when/whether to apply the rule |
|
|
9173
|
-
| \`name\` | All | Rule identifier |
|
|
9174
|
-
|
|
9175
|
-
> Windsurf and OpenCode ignore frontmatter — the rule body is used as-is.
|
|
9176
|
-
|
|
9177
|
-
Then run \`oneagent generate\` to distribute the rule to all configured agents.
|
|
9178
|
-
|
|
9179
|
-
## Adding a Skill
|
|
9180
|
-
|
|
9181
|
-
Create a \`.md\` file in \`.oneagent/skills/\`:
|
|
9182
|
-
|
|
9183
|
-
\`\`\`md
|
|
9184
|
-
---
|
|
9185
|
-
mode: agent # ask | edit | agent
|
|
9186
|
-
description: Short description shown in agent menus
|
|
9187
|
-
---
|
|
9188
|
-
Skill instructions here.
|
|
9189
|
-
\`\`\`
|
|
9190
|
-
|
|
9191
|
-
Then run \`oneagent generate\` to distribute the skill.
|
|
9192
|
-
|
|
9193
|
-
## Commands
|
|
9194
|
-
|
|
9195
|
-
- \`oneagent generate\` — sync all rules and skills to agent-specific directories
|
|
9196
|
-
- \`oneagent status\` — verify that all symlinks and generated files are up to date
|
|
9197
|
-
- \`oneagent init\` — initialize oneagent in a project (run once)
|
|
9198
|
-
`;
|
|
9199
|
-
|
|
9200
9235
|
// src/commands/init.ts
|
|
9201
9236
|
var exports_init = {};
|
|
9202
9237
|
__export(exports_init, {
|
|
@@ -9213,20 +9248,12 @@ async function chooseContent(detected) {
|
|
|
9213
9248
|
return "";
|
|
9214
9249
|
if (detected.length === 1) {
|
|
9215
9250
|
const file = detected[0];
|
|
9216
|
-
|
|
9217
|
-
|
|
9218
|
-
});
|
|
9219
|
-
if (Ct(result2))
|
|
9220
|
-
cancelAndExit();
|
|
9221
|
-
return result2 ? file.content : "";
|
|
9251
|
+
R2.info(`Found ${file.relativePath} (${timeAgo(file.modifiedAt)}) — importing into ${ONEAGENT_DIR}/instructions.md`);
|
|
9252
|
+
return file.content;
|
|
9222
9253
|
}
|
|
9223
9254
|
if (filesHaveSameContent(detected)) {
|
|
9224
|
-
|
|
9225
|
-
|
|
9226
|
-
});
|
|
9227
|
-
if (Ct(result2))
|
|
9228
|
-
cancelAndExit();
|
|
9229
|
-
return result2 ? detected[0].content : "";
|
|
9255
|
+
R2.info(`Found ${detected.length} files with identical content — importing into ${ONEAGENT_DIR}/instructions.md`);
|
|
9256
|
+
return detected[0].content;
|
|
9230
9257
|
}
|
|
9231
9258
|
Ve(detected.map((f) => ` • ${f.relativePath} ${timeAgo(f.modifiedAt)}`).join(`
|
|
9232
9259
|
`), "Multiple files with different content found");
|
|
@@ -9282,13 +9309,19 @@ async function pickTargets(initialValues) {
|
|
|
9282
9309
|
async function backupFiles(root, files) {
|
|
9283
9310
|
if (files.length === 0)
|
|
9284
9311
|
return;
|
|
9285
|
-
const backupDir = path11.join(root, "
|
|
9312
|
+
const backupDir = path11.join(root, ONEAGENT_DIR, "backup");
|
|
9286
9313
|
await fs12.mkdir(backupDir, { recursive: true });
|
|
9287
9314
|
for (const file of files) {
|
|
9288
9315
|
const safeName = file.relativePath.replace(/\//g, "_");
|
|
9289
9316
|
await fs12.writeFile(path11.join(backupDir, safeName), file.content);
|
|
9290
9317
|
}
|
|
9291
9318
|
}
|
|
9319
|
+
async function cleanupUnselectedAgentDirs(root, presentTargets, selectedTargets) {
|
|
9320
|
+
const unselected = presentTargets.filter((t) => !selectedTargets.includes(t));
|
|
9321
|
+
for (const target of unselected) {
|
|
9322
|
+
await cleanupAgentDir(root, target);
|
|
9323
|
+
}
|
|
9324
|
+
}
|
|
9292
9325
|
async function pickTemplateInteractively() {
|
|
9293
9326
|
const result = await Je({
|
|
9294
9327
|
message: "Which template would you like to use?",
|
|
@@ -9339,6 +9372,12 @@ var init_init = __esm(() => {
|
|
|
9339
9372
|
template: {
|
|
9340
9373
|
type: "string",
|
|
9341
9374
|
description: `Template to use: builtin name (${BUILTIN_TEMPLATE_NAMES.join("/")}) or GitHub URL`
|
|
9375
|
+
},
|
|
9376
|
+
yes: {
|
|
9377
|
+
type: "boolean",
|
|
9378
|
+
alias: "y",
|
|
9379
|
+
description: "Skip prompts: auto-import detected files and select detected agents",
|
|
9380
|
+
default: false
|
|
9342
9381
|
}
|
|
9343
9382
|
},
|
|
9344
9383
|
async run({ args }) {
|
|
@@ -9367,19 +9406,26 @@ var init_init = __esm(() => {
|
|
|
9367
9406
|
Ve(message, "Error");
|
|
9368
9407
|
process.exit(1);
|
|
9369
9408
|
}
|
|
9409
|
+
} else if (args.yes) {
|
|
9410
|
+
if (detected.length > 0) {
|
|
9411
|
+
const newest = detected.toSorted((a, b) => b.modifiedAt.getTime() - a.modifiedAt.getTime())[0];
|
|
9412
|
+
importedContent = newest.content;
|
|
9413
|
+
R2.info(`Auto-importing content from ${newest.relativePath}`);
|
|
9414
|
+
}
|
|
9370
9415
|
} else {
|
|
9371
9416
|
importedContent = await chooseContent(detected);
|
|
9372
9417
|
}
|
|
9373
9418
|
const presentTargets = await detectPresentTargets(root);
|
|
9374
|
-
const selectedTargets = await pickTargets(presentTargets);
|
|
9419
|
+
const selectedTargets = args.yes ? presentTargets.length > 0 ? presentTargets : ALL_AGENT_TARGETS.slice(0, 1) : await pickTargets(presentTargets);
|
|
9375
9420
|
const s = bt2();
|
|
9376
|
-
s.start(
|
|
9377
|
-
await fs12.mkdir(path11.join(root, "
|
|
9378
|
-
await fs12.mkdir(path11.join(root, "
|
|
9379
|
-
await fs12.mkdir(path11.join(root, "
|
|
9421
|
+
s.start(`Setting up ${ONEAGENT_DIR}/ directory...`);
|
|
9422
|
+
await fs12.mkdir(path11.join(root, ONEAGENT_DIR, "rules"), { recursive: true });
|
|
9423
|
+
await fs12.mkdir(path11.join(root, ONEAGENT_DIR, "skills"), { recursive: true });
|
|
9424
|
+
await fs12.mkdir(path11.join(root, ONEAGENT_DIR, "commands"), { recursive: true });
|
|
9380
9425
|
await backupFiles(root, detected);
|
|
9381
9426
|
await removeDeprecatedFiles(root);
|
|
9382
9427
|
await migrateRuleAndSkillFiles(root);
|
|
9428
|
+
await cleanupUnselectedAgentDirs(root, presentTargets, selectedTargets);
|
|
9383
9429
|
const config2 = { version: 1, targets: makeTargets(...selectedTargets) };
|
|
9384
9430
|
await writeConfig(root, config2);
|
|
9385
9431
|
if (template) {
|
|
@@ -9389,30 +9435,37 @@ var init_init = __esm(() => {
|
|
|
9389
9435
|
|
|
9390
9436
|
Add your AI instructions here.
|
|
9391
9437
|
`;
|
|
9392
|
-
await fs12.writeFile(path11.join(root, "
|
|
9438
|
+
await fs12.writeFile(path11.join(root, ONEAGENT_DIR, "instructions.md"), instructionsContent);
|
|
9393
9439
|
}
|
|
9394
|
-
await fs12.writeFile(path11.join(root, ".oneagent/rules/about-oneagent.md"), ABOUT_ONEAGENT_CONTENT, "utf-8");
|
|
9395
9440
|
s.stop("Directory structure created.");
|
|
9396
|
-
const commandFiles = await fs12.readdir(path11.join(root, "
|
|
9441
|
+
const commandFiles = await fs12.readdir(path11.join(root, ONEAGENT_DIR, "commands")).catch(() => []);
|
|
9397
9442
|
if (commandFiles.some((f) => f.endsWith(".md"))) {
|
|
9398
|
-
R2.warn(
|
|
9443
|
+
R2.warn(`Commands detected in ${ONEAGENT_DIR}/commands/. Consider migrating to ${ONEAGENT_DIR}/skills/ — skills are distributed to more agents and support richer features.`);
|
|
9399
9444
|
}
|
|
9400
9445
|
if (commandFiles.some((f) => f.endsWith(".md"))) {
|
|
9401
9446
|
const commandsSupported = new Set(AGENT_DEFINITIONS.filter((d2) => d2.commandsDir).map((d2) => d2.target));
|
|
9402
9447
|
const unsupported = selectedTargets.filter((t) => !commandsSupported.has(t));
|
|
9403
9448
|
if (unsupported.length > 0) {
|
|
9404
9449
|
const names = unsupported.map((t) => AGENT_DEFINITIONS.find((d2) => d2.target === t).displayName).join(", ");
|
|
9405
|
-
R2.warn(`Commands in
|
|
9450
|
+
R2.warn(`Commands in ${ONEAGENT_DIR}/commands/ will not be available in: ${names} — these agents do not support custom slash commands.`);
|
|
9406
9451
|
}
|
|
9407
9452
|
}
|
|
9408
9453
|
const s2 = bt2();
|
|
9409
9454
|
s2.start("Generating symlinks and agent files...");
|
|
9410
9455
|
await generate(root, config2);
|
|
9411
9456
|
s2.stop("Done.");
|
|
9457
|
+
const sSkill = bt2();
|
|
9458
|
+
sSkill.start("Installing oneagent skill...");
|
|
9459
|
+
const builtinInstalled = await installBuiltinSkill(root);
|
|
9460
|
+
if (builtinInstalled) {
|
|
9461
|
+
sSkill.stop("Installed oneagent skill.");
|
|
9462
|
+
} else {
|
|
9463
|
+
sSkill.stop("Could not install oneagent skill (skipped).");
|
|
9464
|
+
}
|
|
9412
9465
|
let skillResult = { installed: [], failed: [] };
|
|
9413
9466
|
if (template && template.skills.length > 0) {
|
|
9414
9467
|
const s3 = bt2();
|
|
9415
|
-
s3.start("Installing skills...");
|
|
9468
|
+
s3.start("Installing template skills...");
|
|
9416
9469
|
skillResult = await installTemplateSkills(root, template);
|
|
9417
9470
|
s3.stop(`Installed ${skillResult.installed.length} skill(s).`);
|
|
9418
9471
|
for (const f of skillResult.failed) {
|
|
@@ -9435,10 +9488,10 @@ Add your AI instructions here.
|
|
|
9435
9488
|
...skillResult.installed.length > 0 ? [`Installed ${skillResult.installed.length} skill(s): ${skillResult.installed.map((s3) => s3.skill).join(", ")}`] : [],
|
|
9436
9489
|
...template.rules.length > 0 ? [`Added ${template.rules.length} rule(s) from template`] : [],
|
|
9437
9490
|
...pluginResult.installed.length > 0 ? [`Installed ${pluginResult.installed.length} plugin(s): ${pluginResult.installed.map((p) => p.id).join(", ")}`] : []
|
|
9438
|
-
] : [
|
|
9439
|
-
|
|
9491
|
+
] : [`Created ${ONEAGENT_DIR}/instructions.md`],
|
|
9492
|
+
...builtinInstalled ? [`Installed oneagent skill`] : [],
|
|
9440
9493
|
...selectedTargets.map((t) => `Configured: ${t}`),
|
|
9441
|
-
...detected.length > 0 ? [`Backed up ${detected.length} file(s) to
|
|
9494
|
+
...detected.length > 0 ? [`Backed up ${detected.length} file(s) to ${ONEAGENT_DIR}/backup/`] : []
|
|
9442
9495
|
];
|
|
9443
9496
|
Ve(lines.map((l) => ` • ${l}`).join(`
|
|
9444
9497
|
`), "Setup complete");
|
|
@@ -9471,18 +9524,25 @@ var init_generate2 = __esm(() => {
|
|
|
9471
9524
|
name: "generate",
|
|
9472
9525
|
description: "Generate symlinks and agent-specific files"
|
|
9473
9526
|
},
|
|
9474
|
-
|
|
9527
|
+
args: {
|
|
9528
|
+
yes: {
|
|
9529
|
+
type: "boolean",
|
|
9530
|
+
alias: "y",
|
|
9531
|
+
description: "Skip confirmation prompts and auto-migrate colliding files"
|
|
9532
|
+
}
|
|
9533
|
+
},
|
|
9534
|
+
async run({ args }) {
|
|
9475
9535
|
const root = process.cwd();
|
|
9476
9536
|
let config2;
|
|
9477
9537
|
try {
|
|
9478
9538
|
config2 = await readConfig(root);
|
|
9479
9539
|
} catch {
|
|
9480
|
-
console.error(
|
|
9540
|
+
console.error(`Error: No ${ONEAGENT_DIR}/config.yml found. Run \`oneagent init\` first.`);
|
|
9481
9541
|
process.exit(1);
|
|
9482
9542
|
}
|
|
9483
9543
|
const { mainFiles, ruleSkillFiles } = await detectGenerateCollisions(root, config2);
|
|
9484
9544
|
if (mainFiles.length > 0) {
|
|
9485
|
-
const backupDir = path12.join(root, "
|
|
9545
|
+
const backupDir = path12.join(root, ONEAGENT_DIR, "backup");
|
|
9486
9546
|
await fs13.mkdir(backupDir, { recursive: true });
|
|
9487
9547
|
for (const file of mainFiles) {
|
|
9488
9548
|
const safeName = file.relativePath.replace(/\//g, "_");
|
|
@@ -9490,16 +9550,20 @@ var init_generate2 = __esm(() => {
|
|
|
9490
9550
|
}
|
|
9491
9551
|
}
|
|
9492
9552
|
if (ruleSkillFiles.length > 0) {
|
|
9493
|
-
|
|
9494
|
-
|
|
9495
|
-
|
|
9496
|
-
|
|
9497
|
-
|
|
9498
|
-
|
|
9499
|
-
|
|
9500
|
-
|
|
9553
|
+
if (args.yes) {
|
|
9554
|
+
await migrateRuleAndSkillFiles(root);
|
|
9555
|
+
} else {
|
|
9556
|
+
Ve(ruleSkillFiles.map((f) => ` • ${f.relativePath}`).join(`
|
|
9557
|
+
`), "These rule/skill files are not oneagent symlinks");
|
|
9558
|
+
const proceed = await Re({
|
|
9559
|
+
message: `Move them to ${ONEAGENT_DIR}/ and replace with symlinks?`
|
|
9560
|
+
});
|
|
9561
|
+
if (Ct(proceed) || !proceed) {
|
|
9562
|
+
Le("Aborted.");
|
|
9563
|
+
process.exit(0);
|
|
9564
|
+
}
|
|
9565
|
+
await migrateRuleAndSkillFiles(root);
|
|
9501
9566
|
}
|
|
9502
|
-
await migrateRuleAndSkillFiles(root);
|
|
9503
9567
|
}
|
|
9504
9568
|
const s = bt2();
|
|
9505
9569
|
s.start("Generating...");
|
|
@@ -9535,7 +9599,7 @@ var init_status2 = __esm(() => {
|
|
|
9535
9599
|
try {
|
|
9536
9600
|
config2 = await readConfig(root);
|
|
9537
9601
|
} catch {
|
|
9538
|
-
console.error(
|
|
9602
|
+
console.error(`Error: No ${ONEAGENT_DIR}/config.yml found. Run \`oneagent init\` first.`);
|
|
9539
9603
|
process.exit(1);
|
|
9540
9604
|
}
|
|
9541
9605
|
const status2 = await checkStatus(root, config2);
|
|
@@ -9568,6 +9632,233 @@ OpenCode:
|
|
|
9568
9632
|
});
|
|
9569
9633
|
});
|
|
9570
9634
|
|
|
9635
|
+
// src/commands/targets.ts
|
|
9636
|
+
var exports_targets = {};
|
|
9637
|
+
__export(exports_targets, {
|
|
9638
|
+
default: () => targets_default
|
|
9639
|
+
});
|
|
9640
|
+
import path13 from "path";
|
|
9641
|
+
import fs14 from "fs/promises";
|
|
9642
|
+
function cancelAndExit2() {
|
|
9643
|
+
Le("Cancelled.");
|
|
9644
|
+
process.exit(0);
|
|
9645
|
+
}
|
|
9646
|
+
async function detectPresentTargets2(root) {
|
|
9647
|
+
const results = await Promise.all(AGENT_DEFINITIONS.map(async (def) => {
|
|
9648
|
+
for (const indicator of def.detectIndicators) {
|
|
9649
|
+
try {
|
|
9650
|
+
await fs14.access(path13.join(root, indicator));
|
|
9651
|
+
return def.target;
|
|
9652
|
+
} catch {}
|
|
9653
|
+
}
|
|
9654
|
+
return null;
|
|
9655
|
+
}));
|
|
9656
|
+
return results.filter((t) => t !== null);
|
|
9657
|
+
}
|
|
9658
|
+
var targets_default;
|
|
9659
|
+
var init_targets = __esm(() => {
|
|
9660
|
+
init_dist();
|
|
9661
|
+
init_dist3();
|
|
9662
|
+
init_src();
|
|
9663
|
+
targets_default = defineCommand2({
|
|
9664
|
+
meta: {
|
|
9665
|
+
name: "targets",
|
|
9666
|
+
description: "Add or remove AI agent targets"
|
|
9667
|
+
},
|
|
9668
|
+
async run() {
|
|
9669
|
+
const root = process.cwd();
|
|
9670
|
+
let config2;
|
|
9671
|
+
try {
|
|
9672
|
+
config2 = await readConfig(root);
|
|
9673
|
+
} catch {
|
|
9674
|
+
console.error(`Error: No ${ONEAGENT_DIR}/config.yml found. Run \`oneagent init\` first.`);
|
|
9675
|
+
process.exit(1);
|
|
9676
|
+
}
|
|
9677
|
+
const current = activeTargets(config2);
|
|
9678
|
+
const presentTargets = await detectPresentTargets2(root);
|
|
9679
|
+
const initialValues = [...new Set([...current, ...presentTargets])];
|
|
9680
|
+
Ve(current.map((t) => ` • ${AGENT_DEFINITIONS.find((d2) => d2.target === t).displayName}`).join(`
|
|
9681
|
+
`), "Currently configured targets");
|
|
9682
|
+
const result = await je({
|
|
9683
|
+
message: `Which AI agents do you want to support?
|
|
9684
|
+
\x1B[90m · Space to toggle · Enter to confirm\x1B[39m`,
|
|
9685
|
+
options: AGENT_DEFINITIONS.map((d2) => ({ value: d2.target, label: d2.displayName, hint: d2.hint })),
|
|
9686
|
+
initialValues,
|
|
9687
|
+
required: true
|
|
9688
|
+
});
|
|
9689
|
+
if (Ct(result))
|
|
9690
|
+
cancelAndExit2();
|
|
9691
|
+
const selected = result;
|
|
9692
|
+
const removed = current.filter((t) => !selected.includes(t));
|
|
9693
|
+
const added = selected.filter((t) => !current.includes(t));
|
|
9694
|
+
if (removed.length === 0 && added.length === 0) {
|
|
9695
|
+
Le("No changes.");
|
|
9696
|
+
return;
|
|
9697
|
+
}
|
|
9698
|
+
const s = bt2();
|
|
9699
|
+
s.start("Updating targets...");
|
|
9700
|
+
for (const target of removed) {
|
|
9701
|
+
await cleanupAgentDir(root, target);
|
|
9702
|
+
}
|
|
9703
|
+
config2.targets = makeTargets(...selected);
|
|
9704
|
+
await writeConfig(root, config2);
|
|
9705
|
+
await generate(root, config2);
|
|
9706
|
+
s.stop("Done.");
|
|
9707
|
+
const lines = [
|
|
9708
|
+
...added.length > 0 ? [`Added: ${added.map((t) => AGENT_DEFINITIONS.find((d2) => d2.target === t).displayName).join(", ")}`] : [],
|
|
9709
|
+
...removed.length > 0 ? [`Removed: ${removed.map((t) => AGENT_DEFINITIONS.find((d2) => d2.target === t).displayName).join(", ")}`] : []
|
|
9710
|
+
];
|
|
9711
|
+
Ve(lines.map((l) => ` • ${l}`).join(`
|
|
9712
|
+
`), "Targets updated");
|
|
9713
|
+
if (removed.length > 0) {
|
|
9714
|
+
R2.info(`Removed agent files backed up to ${ONEAGENT_DIR}/backup/`);
|
|
9715
|
+
}
|
|
9716
|
+
Le("Run `oneagent status` to verify your setup.");
|
|
9717
|
+
}
|
|
9718
|
+
});
|
|
9719
|
+
});
|
|
9720
|
+
|
|
9721
|
+
// src/commands/add.ts
|
|
9722
|
+
var exports_add = {};
|
|
9723
|
+
__export(exports_add, {
|
|
9724
|
+
default: () => add_default
|
|
9725
|
+
});
|
|
9726
|
+
var add_default;
|
|
9727
|
+
var init_add = __esm(() => {
|
|
9728
|
+
init_dist();
|
|
9729
|
+
init_dist3();
|
|
9730
|
+
init_src();
|
|
9731
|
+
add_default = defineCommand2({
|
|
9732
|
+
meta: {
|
|
9733
|
+
name: "add",
|
|
9734
|
+
description: "Add an AI agent target"
|
|
9735
|
+
},
|
|
9736
|
+
args: {
|
|
9737
|
+
target: {
|
|
9738
|
+
type: "positional",
|
|
9739
|
+
description: "Agent to add (claude, cursor, windsurf, opencode, copilot)",
|
|
9740
|
+
required: false
|
|
9741
|
+
}
|
|
9742
|
+
},
|
|
9743
|
+
async run({ args }) {
|
|
9744
|
+
const root = process.cwd();
|
|
9745
|
+
let config2;
|
|
9746
|
+
try {
|
|
9747
|
+
config2 = await readConfig(root);
|
|
9748
|
+
} catch {
|
|
9749
|
+
console.error(`Error: No ${ONEAGENT_DIR}/config.yml found. Run \`oneagent init\` first.`);
|
|
9750
|
+
process.exit(1);
|
|
9751
|
+
}
|
|
9752
|
+
const current = activeTargets(config2);
|
|
9753
|
+
const available = ALL_AGENT_TARGETS.filter((t) => !current.includes(t));
|
|
9754
|
+
if (available.length === 0) {
|
|
9755
|
+
R2.info("All agents are already configured.");
|
|
9756
|
+
return;
|
|
9757
|
+
}
|
|
9758
|
+
let target;
|
|
9759
|
+
if (args.target) {
|
|
9760
|
+
if (!ALL_AGENT_TARGETS.includes(args.target)) {
|
|
9761
|
+
console.error(`Unknown target "${args.target}". Available: ${ALL_AGENT_TARGETS.join(", ")}`);
|
|
9762
|
+
process.exit(1);
|
|
9763
|
+
}
|
|
9764
|
+
target = args.target;
|
|
9765
|
+
if (current.includes(target)) {
|
|
9766
|
+
R2.info(`${AGENT_DEFINITIONS.find((d2) => d2.target === target).displayName} is already configured.`);
|
|
9767
|
+
return;
|
|
9768
|
+
}
|
|
9769
|
+
} else {
|
|
9770
|
+
const result = await Je({
|
|
9771
|
+
message: "Which agent do you want to add?",
|
|
9772
|
+
options: available.map((t) => {
|
|
9773
|
+
const def = AGENT_DEFINITIONS.find((d2) => d2.target === t);
|
|
9774
|
+
return { value: t, label: def.displayName, hint: def.hint };
|
|
9775
|
+
})
|
|
9776
|
+
});
|
|
9777
|
+
if (Ct(result)) {
|
|
9778
|
+
Le("Cancelled.");
|
|
9779
|
+
process.exit(0);
|
|
9780
|
+
}
|
|
9781
|
+
target = result;
|
|
9782
|
+
}
|
|
9783
|
+
config2.targets[target] = true;
|
|
9784
|
+
await writeConfig(root, config2);
|
|
9785
|
+
await generate(root, config2);
|
|
9786
|
+
R2.success(`Added ${AGENT_DEFINITIONS.find((d2) => d2.target === target).displayName}`);
|
|
9787
|
+
}
|
|
9788
|
+
});
|
|
9789
|
+
});
|
|
9790
|
+
|
|
9791
|
+
// src/commands/remove.ts
|
|
9792
|
+
var exports_remove = {};
|
|
9793
|
+
__export(exports_remove, {
|
|
9794
|
+
default: () => remove_default
|
|
9795
|
+
});
|
|
9796
|
+
var remove_default;
|
|
9797
|
+
var init_remove = __esm(() => {
|
|
9798
|
+
init_dist();
|
|
9799
|
+
init_dist3();
|
|
9800
|
+
init_src();
|
|
9801
|
+
remove_default = defineCommand2({
|
|
9802
|
+
meta: {
|
|
9803
|
+
name: "remove",
|
|
9804
|
+
description: "Remove an AI agent target"
|
|
9805
|
+
},
|
|
9806
|
+
args: {
|
|
9807
|
+
target: {
|
|
9808
|
+
type: "positional",
|
|
9809
|
+
description: "Agent to remove (claude, cursor, windsurf, opencode, copilot)",
|
|
9810
|
+
required: false
|
|
9811
|
+
}
|
|
9812
|
+
},
|
|
9813
|
+
async run({ args }) {
|
|
9814
|
+
const root = process.cwd();
|
|
9815
|
+
let config2;
|
|
9816
|
+
try {
|
|
9817
|
+
config2 = await readConfig(root);
|
|
9818
|
+
} catch {
|
|
9819
|
+
console.error(`Error: No ${ONEAGENT_DIR}/config.yml found. Run \`oneagent init\` first.`);
|
|
9820
|
+
process.exit(1);
|
|
9821
|
+
}
|
|
9822
|
+
const current = activeTargets(config2);
|
|
9823
|
+
if (current.length === 1) {
|
|
9824
|
+
console.error("Cannot remove the last target. At least one agent must be configured.");
|
|
9825
|
+
process.exit(1);
|
|
9826
|
+
}
|
|
9827
|
+
let target;
|
|
9828
|
+
if (args.target) {
|
|
9829
|
+
if (!ALL_AGENT_TARGETS.includes(args.target)) {
|
|
9830
|
+
console.error(`Unknown target "${args.target}". Available: ${ALL_AGENT_TARGETS.join(", ")}`);
|
|
9831
|
+
process.exit(1);
|
|
9832
|
+
}
|
|
9833
|
+
target = args.target;
|
|
9834
|
+
if (!current.includes(target)) {
|
|
9835
|
+
R2.info(`${AGENT_DEFINITIONS.find((d2) => d2.target === target).displayName} is not configured.`);
|
|
9836
|
+
return;
|
|
9837
|
+
}
|
|
9838
|
+
} else {
|
|
9839
|
+
const result = await Je({
|
|
9840
|
+
message: "Which agent do you want to remove?",
|
|
9841
|
+
options: current.map((t) => {
|
|
9842
|
+
const def = AGENT_DEFINITIONS.find((d2) => d2.target === t);
|
|
9843
|
+
return { value: t, label: def.displayName, hint: def.hint };
|
|
9844
|
+
})
|
|
9845
|
+
});
|
|
9846
|
+
if (Ct(result)) {
|
|
9847
|
+
Le("Cancelled.");
|
|
9848
|
+
process.exit(0);
|
|
9849
|
+
}
|
|
9850
|
+
target = result;
|
|
9851
|
+
}
|
|
9852
|
+
await cleanupAgentDir(root, target);
|
|
9853
|
+
config2.targets[target] = false;
|
|
9854
|
+
await writeConfig(root, config2);
|
|
9855
|
+
await generate(root, config2);
|
|
9856
|
+
R2.success(`Removed ${AGENT_DEFINITIONS.find((d2) => d2.target === target).displayName}`);
|
|
9857
|
+
R2.info(`Files backed up to ${ONEAGENT_DIR}/backup/`);
|
|
9858
|
+
}
|
|
9859
|
+
});
|
|
9860
|
+
});
|
|
9861
|
+
|
|
9571
9862
|
// ../../node_modules/.bun/citty@0.2.1/node_modules/citty/dist/index.mjs
|
|
9572
9863
|
init_scule();
|
|
9573
9864
|
import { parseArgs as parseArgs$1 } from "node:util";
|
|
@@ -9922,7 +10213,10 @@ var main = defineCommand({
|
|
|
9922
10213
|
subCommands: {
|
|
9923
10214
|
init: () => Promise.resolve().then(() => (init_init(), exports_init)).then((r) => r.default),
|
|
9924
10215
|
generate: () => Promise.resolve().then(() => (init_generate2(), exports_generate)).then((r) => r.default),
|
|
9925
|
-
status: () => Promise.resolve().then(() => (init_status2(), exports_status)).then((r) => r.default)
|
|
10216
|
+
status: () => Promise.resolve().then(() => (init_status2(), exports_status)).then((r) => r.default),
|
|
10217
|
+
targets: () => Promise.resolve().then(() => (init_targets(), exports_targets)).then((r) => r.default),
|
|
10218
|
+
add: () => Promise.resolve().then(() => (init_add(), exports_add)).then((r) => r.default),
|
|
10219
|
+
remove: () => Promise.resolve().then(() => (init_remove(), exports_remove)).then((r) => r.default)
|
|
9926
10220
|
}
|
|
9927
10221
|
});
|
|
9928
10222
|
runMain(main);
|
package/package.json
CHANGED