oneagent 0.2.4 → 0.2.6

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.
Files changed (2) hide show
  1. package/dist/index.js +178 -83
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1290,6 +1290,59 @@ var init_dist3 = __esm(() => {
1290
1290
  zt = { light: C("─", "-"), heavy: C("━", "="), block: C("█", "#") };
1291
1291
  Qt = `${import_picocolors2.default.gray(d)} `;
1292
1292
  });
1293
+ // ../core/src/agents.ts
1294
+ var AGENT_DEFINITIONS;
1295
+ var init_agents = __esm(() => {
1296
+ AGENT_DEFINITIONS = [
1297
+ {
1298
+ target: "claude",
1299
+ displayName: "Claude Code",
1300
+ hint: "CLAUDE.md + .claude/rules/",
1301
+ detectIndicators: ["CLAUDE.md", ".claude"],
1302
+ mainFile: "CLAUDE.md",
1303
+ rulesDir: ".claude/rules",
1304
+ skillsDir: ".claude/skills"
1305
+ },
1306
+ {
1307
+ target: "cursor",
1308
+ displayName: "Cursor",
1309
+ hint: "AGENTS.md + .cursor/rules/",
1310
+ detectIndicators: [".cursor", ".cursorrules"],
1311
+ mainFile: "AGENTS.md",
1312
+ rulesDir: ".cursor/rules",
1313
+ skillsDir: ".cursor/skills",
1314
+ deprecatedFiles: [".cursorrules"]
1315
+ },
1316
+ {
1317
+ target: "windsurf",
1318
+ displayName: "Windsurf",
1319
+ hint: "AGENTS.md + .windsurf/rules/",
1320
+ detectIndicators: [".windsurf", ".windsurfrules"],
1321
+ mainFile: "AGENTS.md",
1322
+ rulesDir: ".windsurf/rules",
1323
+ skillsDir: ".windsurf/skills",
1324
+ deprecatedFiles: [".windsurfrules"]
1325
+ },
1326
+ {
1327
+ target: "opencode",
1328
+ displayName: "OpenCode",
1329
+ hint: "AGENTS.md + .opencode/",
1330
+ detectIndicators: ["opencode.json", ".opencode"],
1331
+ mainFile: "AGENTS.md",
1332
+ rulesDir: ".opencode/rules",
1333
+ skillsDir: ".opencode/skills"
1334
+ },
1335
+ {
1336
+ target: "copilot",
1337
+ displayName: "GitHub Copilot",
1338
+ hint: ".github/instructions/*.instructions.md",
1339
+ detectIndicators: [".github/copilot-instructions.md", ".github"],
1340
+ mainFile: ".github/copilot-instructions.md",
1341
+ skillsDir: ".github/skills"
1342
+ }
1343
+ ];
1344
+ });
1345
+
1293
1346
  // ../../node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/nodes/identity.js
1294
1347
  var require_identity = __commonJS((exports) => {
1295
1348
  var ALIAS = Symbol.for("yaml.alias");
@@ -8324,6 +8377,7 @@ async function detectDeprecatedCommandFiles(root) {
8324
8377
  }
8325
8378
  var AGENT_FILES, DEPRECATED_FILES;
8326
8379
  var init_detect = __esm(() => {
8380
+ init_agents();
8327
8381
  AGENT_FILES = [
8328
8382
  "CLAUDE.md",
8329
8383
  "AGENTS.md",
@@ -8331,7 +8385,7 @@ var init_detect = __esm(() => {
8331
8385
  ".windsurfrules",
8332
8386
  ".github/copilot-instructions.md"
8333
8387
  ];
8334
- DEPRECATED_FILES = [".cursorrules"];
8388
+ DEPRECATED_FILES = AGENT_DEFINITIONS.flatMap((d2) => d2.deprecatedFiles ?? []);
8335
8389
  });
8336
8390
 
8337
8391
  // ../core/src/rules.ts
@@ -8411,7 +8465,7 @@ async function ensureDir(dirPath) {
8411
8465
  async function createSymlink(symlinkPath, target) {
8412
8466
  await ensureDir(path5.dirname(symlinkPath));
8413
8467
  try {
8414
- await fs5.unlink(symlinkPath);
8468
+ await fs5.rm(symlinkPath, { recursive: true });
8415
8469
  } catch {}
8416
8470
  await fs5.symlink(target, symlinkPath);
8417
8471
  }
@@ -8422,24 +8476,8 @@ function buildMainSymlinks(root, targets) {
8422
8476
  const instructionsAbs = path5.join(root, ".oneagent/instructions.md");
8423
8477
  const seen = new Map;
8424
8478
  for (const target of targets) {
8425
- let symlinkPath;
8426
- switch (target) {
8427
- case "claude":
8428
- symlinkPath = path5.join(root, "CLAUDE.md");
8429
- break;
8430
- case "cursor":
8431
- symlinkPath = path5.join(root, "AGENTS.md");
8432
- break;
8433
- case "windsurf":
8434
- symlinkPath = path5.join(root, ".windsurfrules");
8435
- break;
8436
- case "opencode":
8437
- symlinkPath = path5.join(root, "AGENTS.md");
8438
- break;
8439
- case "copilot":
8440
- symlinkPath = path5.join(root, ".github/copilot-instructions.md");
8441
- break;
8442
- }
8479
+ const def = AGENT_DEFINITIONS.find((d2) => d2.target === target);
8480
+ const symlinkPath = path5.join(root, def.mainFile);
8443
8481
  if (!seen.has(symlinkPath)) {
8444
8482
  seen.set(symlinkPath, {
8445
8483
  symlinkPath,
@@ -8450,51 +8488,19 @@ function buildMainSymlinks(root, targets) {
8450
8488
  }
8451
8489
  return Array.from(seen.values());
8452
8490
  }
8453
- function buildRulesSymlinks(root, targets, rules) {
8454
- const entries = [];
8455
- for (const target of targets) {
8456
- let rulesDir = null;
8457
- switch (target) {
8458
- case "claude":
8459
- rulesDir = path5.join(root, ".claude/rules");
8460
- break;
8461
- case "cursor":
8462
- rulesDir = path5.join(root, ".cursor/rules");
8463
- break;
8464
- case "windsurf":
8465
- rulesDir = path5.join(root, ".windsurf/rules");
8466
- break;
8467
- case "opencode":
8468
- case "copilot":
8469
- rulesDir = null;
8470
- break;
8471
- }
8472
- if (!rulesDir)
8473
- continue;
8474
- for (const rule of rules) {
8475
- const symlinkPath = path5.join(rulesDir, `${rule.name}.md`);
8476
- entries.push({
8477
- symlinkPath,
8478
- target: relativeTarget(symlinkPath, rule.path),
8479
- label: path5.relative(root, symlinkPath)
8480
- });
8481
- }
8482
- }
8483
- return entries;
8491
+ function buildRulesSymlinks(root, targets) {
8492
+ const targetAbs = path5.join(root, ".oneagent/rules");
8493
+ return AGENT_DEFINITIONS.filter((d2) => targets.includes(d2.target) && d2.rulesDir).map((d2) => {
8494
+ const symlinkPath = path5.join(root, d2.rulesDir);
8495
+ return { symlinkPath, target: relativeTarget(symlinkPath, targetAbs), label: d2.rulesDir };
8496
+ });
8484
8497
  }
8485
8498
  function buildSkillSymlinks(root, targets) {
8486
8499
  const targetAbs = path5.join(root, ".oneagent/skills");
8487
- const agentDirs = {
8488
- claude: path5.join(root, ".claude/skills"),
8489
- cursor: path5.join(root, ".cursor/skills"),
8490
- windsurf: path5.join(root, ".windsurf/skills"),
8491
- copilot: path5.join(root, ".github/skills")
8492
- };
8493
- return Object.entries(agentDirs).filter(([target]) => targets.includes(target)).map(([, dir]) => ({
8494
- symlinkPath: dir,
8495
- target: relativeTarget(dir, targetAbs),
8496
- label: path5.relative(root, dir)
8497
- }));
8500
+ return AGENT_DEFINITIONS.filter((d2) => targets.includes(d2.target) && d2.skillsDir).map((d2) => {
8501
+ const symlinkPath = path5.join(root, d2.skillsDir);
8502
+ return { symlinkPath, target: relativeTarget(symlinkPath, targetAbs), label: d2.skillsDir };
8503
+ });
8498
8504
  }
8499
8505
  function buildAgentsDirSymlinks(root) {
8500
8506
  const symlinkPath = path5.join(root, ".agents/skills");
@@ -8551,9 +8557,10 @@ async function migrateAndRemoveDir(src, dest, root) {
8551
8557
  async function migrateRuleAndSkillFiles(root) {
8552
8558
  const destRules = path5.join(root, ".oneagent/rules");
8553
8559
  const destSkills = path5.join(root, ".oneagent/skills");
8554
- await migrateFilesFromDir(path5.join(root, ".cursor/rules"), destRules, root);
8555
- await migrateFilesFromDir(path5.join(root, ".claude/rules"), destRules, root);
8556
- await migrateFilesFromDir(path5.join(root, ".windsurf/rules"), destRules, root);
8560
+ await migrateAndRemoveDir(path5.join(root, ".cursor/rules"), destRules, root);
8561
+ await migrateAndRemoveDir(path5.join(root, ".claude/rules"), destRules, root);
8562
+ await migrateAndRemoveDir(path5.join(root, ".windsurf/rules"), destRules, root);
8563
+ await migrateAndRemoveDir(path5.join(root, ".opencode/rules"), destRules, root);
8557
8564
  await migrateAndRemoveDir(path5.join(root, ".agents/skills"), destSkills, root);
8558
8565
  }
8559
8566
  async function createAllSymlinks(entries) {
@@ -8571,7 +8578,9 @@ async function checkSymlink(entry) {
8571
8578
  return { ...entry, exists: false, valid: false };
8572
8579
  }
8573
8580
  }
8574
- var init_symlinks = () => {};
8581
+ var init_symlinks = __esm(() => {
8582
+ init_agents();
8583
+ });
8575
8584
 
8576
8585
  // ../core/src/copilot.ts
8577
8586
  import path6 from "path";
@@ -8631,6 +8640,21 @@ function buildOpencodeConfig(existing) {
8631
8640
  instructions: ".oneagent/instructions.md"
8632
8641
  };
8633
8642
  }
8643
+ async function addOpenCodePlugin(root, id) {
8644
+ const filePath = path7.join(root, "opencode.json");
8645
+ let existing;
8646
+ try {
8647
+ existing = JSON.parse(await fs7.readFile(filePath, "utf-8"));
8648
+ } catch {
8649
+ return;
8650
+ }
8651
+ const current = Array.isArray(existing.plugin) ? existing.plugin : [];
8652
+ if (current.includes(id))
8653
+ return;
8654
+ existing.plugin = [...current, id];
8655
+ await fs7.writeFile(filePath, JSON.stringify(existing, null, 2) + `
8656
+ `);
8657
+ }
8634
8658
  async function writeOpencode(root, _rules) {
8635
8659
  const existing = await readOpencode(root);
8636
8660
  const config = buildOpencodeConfig(existing);
@@ -8647,7 +8671,7 @@ async function detectGenerateCollisions(root, config) {
8647
8671
  const targets = activeTargets(config);
8648
8672
  const mainEntries = buildMainSymlinks(root, targets);
8649
8673
  const ruleSkillEntries = [
8650
- ...buildRulesSymlinks(root, targets, rules),
8674
+ ...buildRulesSymlinks(root, targets),
8651
8675
  ...buildSkillSymlinks(root, targets)
8652
8676
  ];
8653
8677
  const [mainCollisions, ruleSkillSymlinkCollisions] = await Promise.all([
@@ -8694,7 +8718,7 @@ async function generate(root, config) {
8694
8718
  const targets = activeTargets(config);
8695
8719
  await migrateRuleAndSkillFiles(root);
8696
8720
  const mainSymlinks = buildMainSymlinks(root, targets);
8697
- const rulesSymlinks = buildRulesSymlinks(root, targets, rules);
8721
+ const rulesSymlinks = buildRulesSymlinks(root, targets);
8698
8722
  const skillSymlinks = await buildSkillSymlinks(root, targets);
8699
8723
  await createAllSymlinks([...mainSymlinks, ...rulesSymlinks, ...skillSymlinks, ...buildAgentsDirSymlinks(root)]);
8700
8724
  if (targets.includes("copilot")) {
@@ -8747,7 +8771,7 @@ async function checkStatus(root, config) {
8747
8771
  const targets = activeTargets(config);
8748
8772
  const allEntries = [
8749
8773
  ...buildMainSymlinks(root, targets),
8750
- ...buildRulesSymlinks(root, targets, rules),
8774
+ ...buildRulesSymlinks(root, targets),
8751
8775
  ...buildSkillSymlinks(root, targets),
8752
8776
  ...buildAgentsDirSymlinks(root)
8753
8777
  ];
@@ -8773,6 +8797,25 @@ import path9 from "path";
8773
8797
  import fs10 from "fs/promises";
8774
8798
  import { execFile } from "child_process";
8775
8799
  import { promisify } from "util";
8800
+ function parsePluginsFromYaml(yamlText) {
8801
+ const plugins = [];
8802
+ const section = yamlText.match(/^plugins:\s*\n((?:(?: -.+|\s{4}.+)\n?)*)/m);
8803
+ if (!section)
8804
+ return plugins;
8805
+ const block = section[1];
8806
+ const entries = block.split(/\n(?= -)/);
8807
+ for (const entry of entries) {
8808
+ const targetMatch = entry.match(/target:\s*(\S+)/);
8809
+ const idMatch = entry.match(/id:\s*(.+)/);
8810
+ if (targetMatch && idMatch) {
8811
+ plugins.push({
8812
+ target: targetMatch[1].trim(),
8813
+ id: idMatch[1].trim()
8814
+ });
8815
+ }
8816
+ }
8817
+ return plugins;
8818
+ }
8776
8819
  async function applyTemplateFiles(root, template) {
8777
8820
  const oneagentDir = path9.join(root, ".oneagent");
8778
8821
  await fs10.mkdir(path9.join(oneagentDir, "rules"), { recursive: true });
@@ -8793,6 +8836,37 @@ async function installTemplateSkills(root, template, onSkillInstalled) {
8793
8836
  }
8794
8837
  }
8795
8838
  }
8839
+ async function installTemplatePlugins(root, template, activeTargets2, onPluginInstalled) {
8840
+ const installed = [];
8841
+ const manual = [];
8842
+ for (const plugin of template.plugins) {
8843
+ if (!activeTargets2.includes(plugin.target))
8844
+ continue;
8845
+ switch (plugin.target) {
8846
+ case "claude":
8847
+ await execFileAsync("claude", ["plugin", "install", plugin.id], { cwd: root });
8848
+ installed.push(plugin);
8849
+ onPluginInstalled?.(plugin);
8850
+ break;
8851
+ case "copilot":
8852
+ await execFileAsync("copilot", ["plugin", "install", plugin.id], { cwd: root });
8853
+ installed.push(plugin);
8854
+ onPluginInstalled?.(plugin);
8855
+ break;
8856
+ case "opencode":
8857
+ await addOpenCodePlugin(root, plugin.id);
8858
+ installed.push(plugin);
8859
+ onPluginInstalled?.(plugin);
8860
+ break;
8861
+ case "cursor":
8862
+ manual.push(plugin);
8863
+ break;
8864
+ case "windsurf":
8865
+ break;
8866
+ }
8867
+ }
8868
+ return { installed, manual };
8869
+ }
8796
8870
  async function fetchTemplateFromGitHub(url) {
8797
8871
  const rawBase = githubUrlToRawBase(url);
8798
8872
  const [yamlText, instructions] = await Promise.all([
@@ -8814,8 +8888,9 @@ async function fetchTemplateFromGitHub(url) {
8814
8888
  skills.push(skill);
8815
8889
  }
8816
8890
  }
8891
+ const plugins = parsePluginsFromYaml(yamlText);
8817
8892
  const rules = await fetchGitHubRules(url);
8818
- return { name, description, skills, instructions, rules };
8893
+ return { name, description, skills, plugins, instructions, rules };
8819
8894
  }
8820
8895
  async function fetchText(url) {
8821
8896
  const response = await fetch(url);
@@ -8857,11 +8932,13 @@ async function fetchGitHubRules(repoUrl) {
8857
8932
  }
8858
8933
  var execFileAsync;
8859
8934
  var init_apply_template = __esm(() => {
8935
+ init_opencode();
8860
8936
  execFileAsync = promisify(execFile);
8861
8937
  });
8862
8938
 
8863
8939
  // ../core/src/index.ts
8864
8940
  var init_src = __esm(() => {
8941
+ init_agents();
8865
8942
  init_config();
8866
8943
  init_detect();
8867
8944
  init_rules();
@@ -8930,6 +9007,7 @@ async function loadTemplate(name) {
8930
9007
  skills2.push(skill);
8931
9008
  }
8932
9009
  }
9010
+ const plugins = parsePluginsFromYaml(yamlText);
8933
9011
  const rulesDir = path10.join(templateDir, "rules");
8934
9012
  let rules2 = [];
8935
9013
  try {
@@ -8939,7 +9017,7 @@ async function loadTemplate(name) {
8939
9017
  content: await fs11.readFile(path10.join(rulesDir, f), "utf-8")
8940
9018
  })));
8941
9019
  } catch {}
8942
- return { name, description, skills: skills2, instructions, rules: rules2 };
9020
+ return { name, description, skills: skills2, plugins, instructions, rules: rules2 };
8943
9021
  }
8944
9022
  async function resolveBuiltinTemplate(name) {
8945
9023
  if (!TEMPLATE_NAMES.includes(name))
@@ -8948,6 +9026,7 @@ async function resolveBuiltinTemplate(name) {
8948
9026
  }
8949
9027
  var __dirname2, TEMPLATE_NAMES, BUILTIN_TEMPLATE_NAMES;
8950
9028
  var init_src2 = __esm(() => {
9029
+ init_src();
8951
9030
  __dirname2 = path10.dirname(fileURLToPath(import.meta.url));
8952
9031
  TEMPLATE_NAMES = ["default", "react", "react-native"];
8953
9032
  BUILTIN_TEMPLATE_NAMES = TEMPLATE_NAMES;
@@ -9011,18 +9090,24 @@ async function chooseContent(detected) {
9011
9090
  const index = parseInt(result.replace("file:", ""), 10);
9012
9091
  return detected[index].content;
9013
9092
  }
9014
- async function pickTargets() {
9093
+ async function detectPresentTargets(root) {
9094
+ const results = await Promise.all(AGENT_DEFINITIONS.map(async (def) => {
9095
+ for (const indicator of def.detectIndicators) {
9096
+ try {
9097
+ await fs12.access(path11.join(root, indicator));
9098
+ return def.target;
9099
+ } catch {}
9100
+ }
9101
+ return null;
9102
+ }));
9103
+ return results.filter((t) => t !== null);
9104
+ }
9105
+ async function pickTargets(initialValues) {
9015
9106
  const result = await je({
9016
9107
  message: `Which AI agents do you want to support?
9017
9108
  \x1B[90m · Space to toggle · Enter to confirm\x1B[39m`,
9018
- options: [
9019
- { value: "claude", label: "Claude Code", hint: "CLAUDE.md + .claude/rules/" },
9020
- { value: "cursor", label: "Cursor", hint: "AGENTS.md + .cursor/rules/" },
9021
- { value: "windsurf", label: "Windsurf", hint: ".windsurfrules + .windsurf/rules/" },
9022
- { value: "opencode", label: "OpenCode", hint: "AGENTS.md + opencode.json" },
9023
- { value: "copilot", label: "GitHub Copilot", hint: ".github/instructions/*.instructions.md" }
9024
- ],
9025
- initialValues: ["claude"],
9109
+ options: AGENT_DEFINITIONS.map((d2) => ({ value: d2.target, label: d2.displayName, hint: d2.hint })),
9110
+ initialValues,
9026
9111
  required: true
9027
9112
  });
9028
9113
  if (Ct(result))
@@ -9113,14 +9198,14 @@ var init_init = __esm(() => {
9113
9198
  } else {
9114
9199
  importedContent = await chooseContent(detected);
9115
9200
  }
9116
- const selectedTargets = await pickTargets();
9201
+ const presentTargets = await detectPresentTargets(root);
9202
+ const selectedTargets = await pickTargets(presentTargets);
9117
9203
  const s = bt2();
9118
9204
  s.start("Setting up .oneagent/ directory...");
9119
9205
  await fs12.mkdir(path11.join(root, ".oneagent/rules"), { recursive: true });
9120
9206
  await fs12.mkdir(path11.join(root, ".oneagent/skills"), { recursive: true });
9121
9207
  await backupFiles(root, detected);
9122
9208
  await removeDeprecatedFiles(root);
9123
- await warnDeprecatedCommandFiles(root);
9124
9209
  await migrateRuleAndSkillFiles(root);
9125
9210
  const config2 = { version: 1, targets: makeTargets(...selectedTargets) };
9126
9211
  await writeConfig(root, config2);
@@ -9135,6 +9220,7 @@ Add your AI instructions here.
9135
9220
  }
9136
9221
  await fs12.writeFile(path11.join(root, ".oneagent/rules/oneagent.md"), DOTAI_META_RULE);
9137
9222
  s.stop("Directory structure created.");
9223
+ await warnDeprecatedCommandFiles(root);
9138
9224
  const s2 = bt2();
9139
9225
  s2.start("Generating symlinks and agent files...");
9140
9226
  await generate(root, config2);
@@ -9146,11 +9232,20 @@ Add your AI instructions here.
9146
9232
  await installTemplateSkills(root, template, (id) => fetchedSkills.push(id));
9147
9233
  s3.stop(`Installed ${fetchedSkills.length} skill(s).`);
9148
9234
  }
9235
+ let pluginResult = { installed: [], manual: [] };
9236
+ if (template && template.plugins.length > 0) {
9237
+ const s4 = bt2();
9238
+ s4.start("Installing plugins...");
9239
+ pluginResult = await installTemplatePlugins(root, template, selectedTargets);
9240
+ s4.stop(`Installed ${pluginResult.installed.length} plugin(s).`);
9241
+ }
9149
9242
  const lines = [
9150
9243
  ...template ? [
9151
9244
  `Template: ${template.name} — ${template.description}`,
9152
9245
  ...fetchedSkills.length > 0 ? [`Fetched ${fetchedSkills.length} skill(s): ${fetchedSkills.join(", ")}`] : [],
9153
- ...template.rules.length > 0 ? [`Added ${template.rules.length} rule(s) from template`] : []
9246
+ ...template.rules.length > 0 ? [`Added ${template.rules.length} rule(s) from template`] : [],
9247
+ ...pluginResult.installed.length > 0 ? [`Installed ${pluginResult.installed.length} plugin(s): ${pluginResult.installed.map((p) => p.id).join(", ")}`] : [],
9248
+ ...pluginResult.manual.map((p) => `Run in Cursor chat: /add-plugin ${p.id}`)
9154
9249
  ] : ["Created .oneagent/instructions.md"],
9155
9250
  "Created .oneagent/rules/oneagent.md",
9156
9251
  ...selectedTargets.map((t) => `Configured: ${t}`),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oneagent",
3
- "version": "0.2.4",
3
+ "version": "0.2.6",
4
4
  "type": "module",
5
5
  "description": "One source of truth for AI agent rules — distributed via symlinks to Claude, Cursor, Windsurf, Copilot, OpenCode",
6
6
  "license": "MIT",