@omnidev-ai/cli 0.14.0 → 0.16.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.
Files changed (2) hide show
  1. package/dist/index.js +159 -69
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1243,6 +1243,15 @@ var init_stringify = __esm(() => {
1243
1243
  });
1244
1244
 
1245
1245
  // ../../node_modules/.bun/smol-toml@1.6.0/node_modules/smol-toml/dist/index.js
1246
+ var exports_dist = {};
1247
+ __export(exports_dist, {
1248
+ stringify: () => stringify,
1249
+ parse: () => parse,
1250
+ default: () => dist_default,
1251
+ TomlError: () => TomlError,
1252
+ TomlDate: () => TomlDate
1253
+ });
1254
+ var dist_default;
1246
1255
  var init_dist = __esm(() => {
1247
1256
  init_parse();
1248
1257
  init_stringify();
@@ -1275,6 +1284,7 @@ var init_dist = __esm(() => {
1275
1284
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
1276
1285
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1277
1286
  */
1287
+ dist_default = { parse, stringify, TomlDate, TomlError };
1278
1288
  });
1279
1289
 
1280
1290
  // ../core/src/config/parser.ts
@@ -2791,19 +2801,56 @@ function convertCommandExports(commandExports, capabilityId) {
2791
2801
  return result;
2792
2802
  });
2793
2803
  }
2804
+ function mergeByName(fileBased, programmatic) {
2805
+ const byName = new Map;
2806
+ for (const item of fileBased) {
2807
+ byName.set(item.name, item);
2808
+ }
2809
+ for (const item of programmatic) {
2810
+ byName.set(item.name, item);
2811
+ }
2812
+ return Array.from(byName.values());
2813
+ }
2794
2814
  async function loadCapability(capabilityPath) {
2795
2815
  const config = await loadCapabilityConfig(capabilityPath);
2796
2816
  const id = config.capability.id;
2797
2817
  const exports = await importCapabilityExports(capabilityPath);
2798
2818
  const exportsAny = exports;
2799
- const skills = "skills" in exports && Array.isArray(exportsAny.skills) ? convertSkillExports(exportsAny.skills, id) : await loadSkills(capabilityPath, id);
2800
- const rules = "rules" in exports && Array.isArray(exportsAny.rules) ? convertRuleExports(exportsAny.rules, id) : await loadRules(capabilityPath, id);
2801
- const docs = "docs" in exports && Array.isArray(exportsAny.docs) ? convertDocExports(exportsAny.docs, id) : await loadDocs(capabilityPath, id);
2802
- const subagents = "subagents" in exports && Array.isArray(exportsAny.subagents) ? convertSubagentExports(exportsAny.subagents, id) : await loadSubagents(capabilityPath, id);
2803
- const commands = "commands" in exports && Array.isArray(exportsAny.commands) ? convertCommandExports(exportsAny.commands, id) : await loadCommands(capabilityPath, id);
2804
- const typeDefinitionsFromExports = "typeDefinitions" in exports && typeof exportsAny.typeDefinitions === "string" ? exportsAny.typeDefinitions : undefined;
2819
+ const defaultExport = exportsAny.default ?? {};
2820
+ const getExportValue = (key) => {
2821
+ if (key in exports && exports[key] !== undefined) {
2822
+ return exportsAny[key];
2823
+ }
2824
+ if (key in defaultExport && defaultExport[key] !== undefined) {
2825
+ return defaultExport[key];
2826
+ }
2827
+ return;
2828
+ };
2829
+ const skillsExport = getExportValue("skills");
2830
+ const programmaticSkills = Array.isArray(skillsExport) ? convertSkillExports(skillsExport, id) : [];
2831
+ const fileSkills = await loadSkills(capabilityPath, id);
2832
+ const skills = mergeByName(fileSkills, programmaticSkills);
2833
+ const rulesExport = getExportValue("rules");
2834
+ const programmaticRules = Array.isArray(rulesExport) ? convertRuleExports(rulesExport, id) : [];
2835
+ const fileRules = await loadRules(capabilityPath, id);
2836
+ const rules = mergeByName(fileRules, programmaticRules);
2837
+ const docsExport = getExportValue("docs");
2838
+ const programmaticDocs = Array.isArray(docsExport) ? convertDocExports(docsExport, id) : [];
2839
+ const fileDocs = await loadDocs(capabilityPath, id);
2840
+ const docs = mergeByName(fileDocs, programmaticDocs);
2841
+ const subagentsExport = getExportValue("subagents");
2842
+ const programmaticSubagents = Array.isArray(subagentsExport) ? convertSubagentExports(subagentsExport, id) : [];
2843
+ const fileSubagents = await loadSubagents(capabilityPath, id);
2844
+ const subagents = mergeByName(fileSubagents, programmaticSubagents);
2845
+ const commandsExport = getExportValue("commands");
2846
+ const programmaticCommands = Array.isArray(commandsExport) ? convertCommandExports(commandsExport, id) : [];
2847
+ const fileCommands = await loadCommands(capabilityPath, id);
2848
+ const commands = mergeByName(fileCommands, programmaticCommands);
2849
+ const typeDefinitionsExport = getExportValue("typeDefinitions");
2850
+ const typeDefinitionsFromExports = typeof typeDefinitionsExport === "string" ? typeDefinitionsExport : undefined;
2805
2851
  const typeDefinitions = typeDefinitionsFromExports !== undefined ? typeDefinitionsFromExports : await loadTypeDefinitions(capabilityPath);
2806
- const gitignore = "gitignore" in exports && Array.isArray(exportsAny.gitignore) ? exportsAny.gitignore : undefined;
2852
+ const gitignoreExport = getExportValue("gitignore");
2853
+ const gitignore = Array.isArray(gitignoreExport) ? gitignoreExport : undefined;
2807
2854
  const hooks = loadCapabilityHooks(id, capabilityPath, { resolveCapabilityRoot: true });
2808
2855
  const result = {
2809
2856
  id,
@@ -3528,6 +3575,9 @@ function shortCommit(commit) {
3528
3575
  function shortContentHash(hash) {
3529
3576
  return hash.substring(0, 12);
3530
3577
  }
3578
+ function escapeTomlString(value) {
3579
+ return value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"").replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t");
3580
+ }
3531
3581
  async function computeContentHash(dirPath, excludePatterns = CONTENT_HASH_EXCLUDES) {
3532
3582
  const hash = createHash("sha256");
3533
3583
  const files = [];
@@ -3734,27 +3784,48 @@ async function cloneRepo(gitUrl, targetPath, ref) {
3734
3784
  }
3735
3785
  }
3736
3786
  async function fetchRepo(repoPath, ref) {
3737
- const fetchResult = await spawnCapture("git", ["fetch", "--depth", "1", "origin"], {
3787
+ const fetchArgs = ["fetch", "--depth", "1", "origin"];
3788
+ if (ref) {
3789
+ fetchArgs.push(ref);
3790
+ }
3791
+ const fetchResult = await spawnCapture("git", fetchArgs, {
3738
3792
  cwd: repoPath
3739
3793
  });
3740
3794
  if (fetchResult.exitCode !== 0) {
3741
3795
  throw new Error(`Failed to fetch in ${repoPath}: ${fetchResult.stderr.trim()}`);
3742
3796
  }
3743
3797
  const currentCommit = await getRepoCommit(repoPath);
3744
- const targetRef = ref || "HEAD";
3745
- const lsResult = await spawnCapture("git", ["ls-remote", "origin", targetRef], {
3798
+ let resetTarget;
3799
+ if (ref) {
3800
+ resetTarget = "FETCH_HEAD";
3801
+ } else {
3802
+ const remoteShowResult = await spawnCapture("git", ["remote", "show", "origin"], {
3803
+ cwd: repoPath
3804
+ });
3805
+ let defaultBranch = "main";
3806
+ if (remoteShowResult.exitCode === 0) {
3807
+ const match = remoteShowResult.stdout.match(/HEAD branch:\s*(\S+)/);
3808
+ if (match?.[1]) {
3809
+ defaultBranch = match[1];
3810
+ }
3811
+ }
3812
+ resetTarget = `origin/${defaultBranch}`;
3813
+ }
3814
+ const revParseResult = await spawnCapture("git", ["rev-parse", resetTarget], {
3746
3815
  cwd: repoPath
3747
3816
  });
3748
- if (lsResult.exitCode !== 0) {
3749
- throw new Error(`Failed to ls-remote in ${repoPath}: ${lsResult.stderr.trim()}`);
3817
+ if (revParseResult.exitCode !== 0) {
3818
+ throw new Error(`Failed to resolve ${resetTarget} in ${repoPath}: ${revParseResult.stderr.trim()}`);
3750
3819
  }
3751
- const remoteCommit = lsResult.stdout.split("\t")[0];
3752
- if (currentCommit === remoteCommit) {
3820
+ const targetCommit = revParseResult.stdout.trim();
3821
+ if (currentCommit === targetCommit) {
3753
3822
  return false;
3754
3823
  }
3755
- const pullResult = await spawnCapture("git", ["pull", "--ff-only"], { cwd: repoPath });
3756
- if (pullResult.exitCode !== 0) {
3757
- throw new Error(`Failed to pull in ${repoPath}: ${pullResult.stderr.trim()}`);
3824
+ const resetResult = await spawnCapture("git", ["reset", "--hard", resetTarget], {
3825
+ cwd: repoPath
3826
+ });
3827
+ if (resetResult.exitCode !== 0) {
3828
+ throw new Error(`Failed to reset in ${repoPath}: ${resetResult.stderr.trim()}`);
3758
3829
  }
3759
3830
  return true;
3760
3831
  }
@@ -3952,27 +4023,27 @@ async function generateCapabilityToml(id, repoPath, source, commit, content) {
3952
4023
  # This capability was wrapped from an external repository
3953
4024
 
3954
4025
  [capability]
3955
- id = "${id}"
3956
- name = "${name}"
3957
- version = "${version}"
3958
- description = "${description}"
4026
+ id = "${escapeTomlString(id)}"
4027
+ name = "${escapeTomlString(name)}"
4028
+ version = "${escapeTomlString(version)}"
4029
+ description = "${escapeTomlString(description)}"
3959
4030
  `;
3960
4031
  if (pluginMeta?.author?.name || pluginMeta?.author?.email) {
3961
4032
  tomlContent += `
3962
4033
  [capability.author]
3963
4034
  `;
3964
4035
  if (pluginMeta.author.name) {
3965
- tomlContent += `name = "${pluginMeta.author.name}"
4036
+ tomlContent += `name = "${escapeTomlString(pluginMeta.author.name)}"
3966
4037
  `;
3967
4038
  }
3968
4039
  if (pluginMeta.author.email) {
3969
- tomlContent += `email = "${pluginMeta.author.email}"
4040
+ tomlContent += `email = "${escapeTomlString(pluginMeta.author.email)}"
3970
4041
  `;
3971
4042
  }
3972
4043
  }
3973
4044
  tomlContent += `
3974
4045
  [capability.metadata]
3975
- repository = "${repoUrl}"
4046
+ repository = "${escapeTomlString(repoUrl)}"
3976
4047
  wrapped = true
3977
4048
  commit = "${commit}"
3978
4049
  `;
@@ -4138,28 +4209,28 @@ async function generateFileSourceCapabilityToml(id, source, hashVersion, content
4138
4209
  # This capability was wrapped from a local directory
4139
4210
 
4140
4211
  [capability]
4141
- id = "${id}"
4142
- name = "${name}"
4143
- version = "${version}"
4144
- description = "${description}"
4212
+ id = "${escapeTomlString(id)}"
4213
+ name = "${escapeTomlString(name)}"
4214
+ version = "${escapeTomlString(version)}"
4215
+ description = "${escapeTomlString(description)}"
4145
4216
  `;
4146
4217
  if (pluginMeta?.author?.name || pluginMeta?.author?.email) {
4147
4218
  tomlContent += `
4148
4219
  [capability.author]
4149
4220
  `;
4150
4221
  if (pluginMeta.author.name) {
4151
- tomlContent += `name = "${pluginMeta.author.name}"
4222
+ tomlContent += `name = "${escapeTomlString(pluginMeta.author.name)}"
4152
4223
  `;
4153
4224
  }
4154
4225
  if (pluginMeta.author.email) {
4155
- tomlContent += `email = "${pluginMeta.author.email}"
4226
+ tomlContent += `email = "${escapeTomlString(pluginMeta.author.email)}"
4156
4227
  `;
4157
4228
  }
4158
4229
  }
4159
4230
  tomlContent += `
4160
4231
  [capability.metadata]
4161
4232
  wrapped = true
4162
- source = "${source}"
4233
+ source = "${escapeTomlString(source)}"
4163
4234
  `;
4164
4235
  await writeFile3(join8(targetPath, "capability.toml"), tomlContent, "utf-8");
4165
4236
  }
@@ -5076,6 +5147,7 @@ import { mkdirSync as mkdirSync5 } from "node:fs";
5076
5147
  async function installCapabilityDependencies(silent) {
5077
5148
  const { existsSync: existsSync19, readdirSync: readdirSync7, readFileSync: readFileSync3 } = await import("node:fs");
5078
5149
  const { join: join9 } = await import("node:path");
5150
+ const { parse: parse2 } = await Promise.resolve().then(() => (init_dist(), exports_dist));
5079
5151
  const capabilitiesDir = ".omni/capabilities";
5080
5152
  if (!existsSync19(capabilitiesDir)) {
5081
5153
  return;
@@ -5099,43 +5171,24 @@ async function installCapabilityDependencies(silent) {
5099
5171
  }
5100
5172
  const capabilityPath = join9(capabilitiesDir, entry.name);
5101
5173
  const packageJsonPath = join9(capabilityPath, "package.json");
5174
+ const capabilityTomlPath = join9(capabilityPath, "capability.toml");
5102
5175
  if (!existsSync19(packageJsonPath)) {
5103
5176
  continue;
5104
5177
  }
5105
- await new Promise((resolve2, reject) => {
5106
- const useNpmCi = hasNpm && existsSync19(join9(capabilityPath, "package-lock.json"));
5107
- const cmd = hasBun ? "bun" : "npm";
5108
- const args = hasBun ? ["install"] : useNpmCi ? ["ci"] : ["install"];
5109
- const proc = spawn2(cmd, args, {
5110
- cwd: capabilityPath,
5111
- stdio: "pipe"
5112
- });
5113
- let stderr = "";
5114
- proc.stderr?.on("data", (data) => {
5115
- stderr += data.toString();
5116
- });
5117
- proc.on("close", (code) => {
5118
- if (code === 0) {
5119
- resolve2();
5120
- } else {
5121
- reject(new Error(`Failed to install dependencies for ${capabilityPath}:
5122
- ${stderr}`));
5178
+ if (existsSync19(capabilityTomlPath)) {
5179
+ try {
5180
+ const tomlContent = readFileSync3(capabilityTomlPath, "utf-8");
5181
+ const parsed = parse2(tomlContent);
5182
+ if (parsed.capability?.metadata?.wrapped === true) {
5183
+ continue;
5123
5184
  }
5124
- });
5125
- proc.on("error", (error) => {
5126
- reject(error);
5127
- });
5128
- });
5129
- const hasIndexTs = existsSync19(join9(capabilityPath, "index.ts"));
5130
- let hasBuildScript = false;
5185
+ } catch {}
5186
+ }
5131
5187
  try {
5132
- const pkgJson = JSON.parse(readFileSync3(packageJsonPath, "utf-8"));
5133
- hasBuildScript = Boolean(pkgJson.scripts?.build);
5134
- } catch {}
5135
- if (hasBuildScript) {
5136
5188
  await new Promise((resolve2, reject) => {
5189
+ const useNpmCi = hasNpm && existsSync19(join9(capabilityPath, "package-lock.json"));
5137
5190
  const cmd = hasBun ? "bun" : "npm";
5138
- const args = ["run", "build"];
5191
+ const args = hasBun ? ["install"] : useNpmCi ? ["ci"] : ["install"];
5139
5192
  const proc = spawn2(cmd, args, {
5140
5193
  cwd: capabilityPath,
5141
5194
  stdio: "pipe"
@@ -5148,7 +5201,7 @@ ${stderr}`));
5148
5201
  if (code === 0) {
5149
5202
  resolve2();
5150
5203
  } else {
5151
- reject(new Error(`Failed to build capability ${capabilityPath}:
5204
+ reject(new Error(`Failed to install dependencies for ${capabilityPath}:
5152
5205
  ${stderr}`));
5153
5206
  }
5154
5207
  });
@@ -5156,12 +5209,46 @@ ${stderr}`));
5156
5209
  reject(error);
5157
5210
  });
5158
5211
  });
5159
- } else if (hasIndexTs && !silent) {
5160
- const hasBuiltIndex = existsSync19(join9(capabilityPath, "dist", "index.js"));
5161
- if (!hasBuiltIndex) {
5162
- console.warn(`Warning: Capability at ${capabilityPath} has index.ts but no build script.
5212
+ const hasIndexTs = existsSync19(join9(capabilityPath, "index.ts"));
5213
+ let hasBuildScript = false;
5214
+ try {
5215
+ const pkgJson = JSON.parse(readFileSync3(packageJsonPath, "utf-8"));
5216
+ hasBuildScript = Boolean(pkgJson.scripts?.build);
5217
+ } catch {}
5218
+ if (hasBuildScript) {
5219
+ await new Promise((resolve2, reject) => {
5220
+ const cmd = hasBun ? "bun" : "npm";
5221
+ const args = ["run", "build"];
5222
+ const proc = spawn2(cmd, args, {
5223
+ cwd: capabilityPath,
5224
+ stdio: "pipe"
5225
+ });
5226
+ let stderr = "";
5227
+ proc.stderr?.on("data", (data) => {
5228
+ stderr += data.toString();
5229
+ });
5230
+ proc.on("close", (code) => {
5231
+ if (code === 0) {
5232
+ resolve2();
5233
+ } else {
5234
+ reject(new Error(`Failed to build capability ${capabilityPath}:
5235
+ ${stderr}`));
5236
+ }
5237
+ });
5238
+ proc.on("error", (error) => {
5239
+ reject(error);
5240
+ });
5241
+ });
5242
+ } else if (hasIndexTs && !silent) {
5243
+ const hasBuiltIndex = existsSync19(join9(capabilityPath, "dist", "index.js"));
5244
+ if (!hasBuiltIndex) {
5245
+ console.warn(`Warning: Capability at ${capabilityPath} has index.ts but no build script.
5163
5246
  Add a "build" script to package.json (e.g., "build": "tsc") to compile TypeScript.`);
5247
+ }
5164
5248
  }
5249
+ } catch (error) {
5250
+ const errorMessage = error instanceof Error ? error.message : String(error);
5251
+ console.warn(`Warning: ${errorMessage}`);
5165
5252
  }
5166
5253
  }
5167
5254
  }
@@ -5720,13 +5807,16 @@ function generateAgentsTemplate() {
5720
5807
  }
5721
5808
 
5722
5809
  // ../core/src/templates/capability.ts
5810
+ function escapeTomlString2(value) {
5811
+ return value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"").replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t");
5812
+ }
5723
5813
  function generateCapabilityToml2(options) {
5724
5814
  const description = options.description || "TODO: Add a description for your capability";
5725
5815
  return `[capability]
5726
- id = "${options.id}"
5727
- name = "${options.name}"
5816
+ id = "${escapeTomlString2(options.id)}"
5817
+ name = "${escapeTomlString2(options.name)}"
5728
5818
  version = "0.1.0"
5729
- description = "${description}"
5819
+ description = "${escapeTomlString2(description)}"
5730
5820
 
5731
5821
  # Optional author information
5732
5822
  # [capability.author]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@omnidev-ai/cli",
3
- "version": "0.14.0",
3
+ "version": "0.16.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "imports": {