@kody-ade/kody-engine-lite 0.1.134 → 0.1.135

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/bin/cli.js +115 -87
  2. package/package.json +1 -1
package/dist/bin/cli.js CHANGED
@@ -7795,74 +7795,80 @@ function detectToolsForBootstrap(cwd) {
7795
7795
  (tool) => tool.detect.some((pattern) => fs8.existsSync(path7.join(cwd, pattern)))
7796
7796
  );
7797
7797
  }
7798
- var FRAMEWORK_SKILL_RULES = [
7799
- {
7800
- detect: (deps) => "next" in deps,
7801
- skills: [
7802
- { skill: "vercel-labs/agent-skills@vercel-react-best-practices", label: "React best practices" },
7803
- { skill: "wshobson/agents@nextjs-app-router-patterns", label: "Next.js App Router patterns" }
7804
- ]
7805
- },
7806
- {
7807
- detect: (deps) => "react" in deps && !("next" in deps),
7808
- skills: [
7809
- { skill: "vercel-labs/agent-skills@vercel-react-best-practices", label: "React best practices" }
7810
- ]
7811
- },
7812
- {
7813
- detect: (deps) => "vue" in deps,
7814
- skills: [
7815
- { skill: "antfu/skills@vue", label: "Vue best practices" }
7816
- ]
7817
- },
7818
- {
7819
- detect: (deps) => "svelte" in deps || "@sveltejs/kit" in deps,
7820
- skills: [
7821
- { skill: "ejirocodes/agent-skills@svelte5-best-practices", label: "Svelte best practices" }
7822
- ]
7823
- },
7824
- {
7825
- detect: (deps) => "@angular/core" in deps,
7826
- skills: [
7827
- { skill: "analogjs/angular-skills@angular-component", label: "Angular component patterns" }
7828
- ]
7829
- },
7830
- {
7831
- detect: (deps) => "payload" in deps,
7832
- skills: [
7833
- { skill: "payloadcms/skills@payload", label: "Payload CMS patterns" }
7834
- ]
7835
- },
7836
- {
7837
- detect: (deps) => "tailwindcss" in deps,
7838
- skills: [
7839
- { skill: "wshobson/agents@tailwind-design-system", label: "Tailwind design system" }
7840
- ]
7841
- }
7842
- ];
7843
- function detectFrameworkSkills(cwd) {
7798
+ var FRAMEWORK_KEYWORDS = {
7799
+ next: "nextjs",
7800
+ react: "react",
7801
+ vue: "vue",
7802
+ svelte: "svelte",
7803
+ "@angular/core": "angular",
7804
+ payload: "payload cms",
7805
+ tailwindcss: "tailwind",
7806
+ nuxt: "nuxt",
7807
+ astro: "astro",
7808
+ "solid-js": "solidjs",
7809
+ express: "express",
7810
+ fastify: "fastify",
7811
+ prisma: "prisma"
7812
+ };
7813
+ function parseSkillsSearchOutput(output) {
7814
+ const stripped = output.replace(/\x1b\[[0-9;]*m/g, "");
7815
+ const results = [];
7816
+ for (const line of stripped.split("\n")) {
7817
+ const match = line.match(/^([a-zA-Z0-9._-]+\/[a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+)\s+([\d.]+)([KM]?)\s+installs/);
7818
+ if (!match) continue;
7819
+ const ref = match[1];
7820
+ const name = ref.split("@").pop() ?? "";
7821
+ let installs = parseFloat(match[2]);
7822
+ if (match[3] === "K") installs *= 1e3;
7823
+ if (match[3] === "M") installs *= 1e6;
7824
+ results.push({ ref, name, installs });
7825
+ }
7826
+ return results;
7827
+ }
7828
+ function detectProjectKeywords(cwd) {
7844
7829
  const pkgPath = path7.join(cwd, "package.json");
7845
7830
  if (!fs8.existsSync(pkgPath)) return [];
7846
7831
  try {
7847
7832
  const pkg = JSON.parse(fs8.readFileSync(pkgPath, "utf-8"));
7848
7833
  const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
7849
- const seen = /* @__PURE__ */ new Set();
7850
- const skills = [];
7851
- for (const rule of FRAMEWORK_SKILL_RULES) {
7852
- if (rule.detect(allDeps)) {
7853
- for (const skill of rule.skills) {
7854
- if (!seen.has(skill.skill)) {
7855
- seen.add(skill.skill);
7856
- skills.push(skill);
7857
- }
7858
- }
7859
- }
7834
+ const keywords = [];
7835
+ for (const [dep, keyword] of Object.entries(FRAMEWORK_KEYWORDS)) {
7836
+ if (dep in allDeps) keywords.push(keyword);
7860
7837
  }
7861
- return skills;
7838
+ return keywords;
7862
7839
  } catch {
7863
7840
  return [];
7864
7841
  }
7865
7842
  }
7843
+ function searchSkills(keywords, exclude, limit) {
7844
+ const allResults = [];
7845
+ const seen = /* @__PURE__ */ new Set();
7846
+ for (const keyword of keywords) {
7847
+ try {
7848
+ const output = execFileSync4("npx", ["skills", "find", keyword], {
7849
+ encoding: "utf-8",
7850
+ timeout: 15e3,
7851
+ stdio: ["pipe", "pipe", "pipe"]
7852
+ });
7853
+ for (const skill of parseSkillsSearchOutput(output)) {
7854
+ if (!seen.has(skill.ref) && !exclude.has(skill.name)) {
7855
+ seen.add(skill.ref);
7856
+ allResults.push(skill);
7857
+ }
7858
+ }
7859
+ } catch {
7860
+ }
7861
+ }
7862
+ return allResults.sort((a, b) => b.installs - a.installs).slice(0, limit);
7863
+ }
7864
+ function collectSkillPaths(cwd, skillName, paths) {
7865
+ for (const dir of [".claude/skills", ".agents/skills"]) {
7866
+ const skillPath = path7.join(dir, skillName);
7867
+ if (fs8.existsSync(path7.join(cwd, skillPath))) {
7868
+ paths.push(skillPath);
7869
+ }
7870
+ }
7871
+ }
7866
7872
  function bootstrapCommand(opts, pkgRoot) {
7867
7873
  const cwd = process.cwd();
7868
7874
  setConfigDir(cwd);
@@ -8319,44 +8325,66 @@ ${entries}
8319
8325
  }
8320
8326
  console.log("\n\u2500\u2500 Skills \u2500\u2500");
8321
8327
  const installedSkillPaths = [];
8322
- const allSkills = [];
8323
- const seen = /* @__PURE__ */ new Set();
8328
+ const excludeSkills = /* @__PURE__ */ new Set();
8329
+ const claudeSkillsDir = path7.join(cwd, ".claude", "skills");
8330
+ if (fs8.existsSync(claudeSkillsDir)) {
8331
+ try {
8332
+ for (const entry of fs8.readdirSync(claudeSkillsDir, { withFileTypes: true })) {
8333
+ if (entry.isDirectory() || entry.isSymbolicLink()) excludeSkills.add(entry.name);
8334
+ }
8335
+ } catch {
8336
+ }
8337
+ }
8324
8338
  for (const tool of detectToolsForBootstrap(cwd)) {
8325
- if (tool.skill && !seen.has(tool.skill)) {
8326
- seen.add(tool.skill);
8327
- allSkills.push({ skill: tool.skill, label: `${tool.name} CLI` });
8339
+ if (tool.skill) {
8340
+ const toolSkillName = tool.skill.split("@").pop() ?? "";
8341
+ excludeSkills.add(toolSkillName);
8328
8342
  }
8329
8343
  }
8330
- for (const mapping of detectFrameworkSkills(cwd)) {
8331
- if (!seen.has(mapping.skill)) {
8332
- seen.add(mapping.skill);
8333
- allSkills.push(mapping);
8344
+ for (const tool of detectToolsForBootstrap(cwd)) {
8345
+ if (!tool.skill) continue;
8346
+ const skillName = tool.skill.split("@").pop() ?? "";
8347
+ if (excludeSkills.has(skillName) && fs8.existsSync(path7.join(claudeSkillsDir, skillName))) continue;
8348
+ try {
8349
+ console.log(` Installing: ${tool.name} CLI (${tool.skill})`);
8350
+ execFileSync4("npx", ["skills", "add", tool.skill, "--yes"], {
8351
+ cwd,
8352
+ encoding: "utf-8",
8353
+ timeout: 6e4,
8354
+ stdio: ["pipe", "pipe", "pipe"]
8355
+ });
8356
+ collectSkillPaths(cwd, skillName, installedSkillPaths);
8357
+ excludeSkills.add(skillName);
8358
+ console.log(` \u2713 ${tool.name} CLI`);
8359
+ } catch {
8360
+ console.log(` \u2717 ${tool.name} CLI \u2014 failed to install`);
8334
8361
  }
8335
8362
  }
8336
- if (allSkills.length > 0) {
8337
- for (const { skill, label } of allSkills) {
8338
- try {
8339
- console.log(` Installing: ${label} (${skill})`);
8340
- execFileSync4("npx", ["skills", "add", skill, "--yes"], {
8341
- cwd,
8342
- encoding: "utf-8",
8343
- timeout: 6e4,
8344
- stdio: ["pipe", "pipe", "pipe"]
8345
- });
8346
- const skillName = skill.split("@").pop() ?? "";
8347
- for (const dir of [".claude/skills", ".agents/skills"]) {
8348
- const skillPath = path7.join(dir, skillName);
8349
- if (fs8.existsSync(path7.join(cwd, skillPath))) {
8350
- installedSkillPaths.push(skillPath);
8351
- }
8363
+ const keywords = detectProjectKeywords(cwd);
8364
+ if (keywords.length > 0) {
8365
+ console.log(` Searching skills.sh for: ${keywords.join(", ")}`);
8366
+ const found = searchSkills(keywords, excludeSkills, 5);
8367
+ if (found.length > 0) {
8368
+ for (const skill of found) {
8369
+ try {
8370
+ console.log(` Installing: ${skill.name} (${skill.ref})`);
8371
+ execFileSync4("npx", ["skills", "add", skill.ref, "--yes"], {
8372
+ cwd,
8373
+ encoding: "utf-8",
8374
+ timeout: 6e4,
8375
+ stdio: ["pipe", "pipe", "pipe"]
8376
+ });
8377
+ collectSkillPaths(cwd, skill.name, installedSkillPaths);
8378
+ console.log(` \u2713 ${skill.name}`);
8379
+ } catch {
8380
+ console.log(` \u2717 ${skill.name} \u2014 failed to install`);
8352
8381
  }
8353
- console.log(` \u2713 ${label}`);
8354
- } catch {
8355
- console.log(` \u2717 ${label} \u2014 failed to install`);
8356
8382
  }
8383
+ } else {
8384
+ console.log(" \u25CB No matching skills found on skills.sh");
8357
8385
  }
8358
8386
  } else {
8359
- console.log(" \u25CB No skills to install (no frameworks detected)");
8387
+ console.log(" \u25CB No frameworks detected \u2014 skipping skill search");
8360
8388
  }
8361
8389
  if (fs8.existsSync(path7.join(cwd, "skills-lock.json"))) {
8362
8390
  installedSkillPaths.push("skills-lock.json");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kody-ade/kody-engine-lite",
3
- "version": "0.1.134",
3
+ "version": "0.1.135",
4
4
  "description": "Autonomous SDLC pipeline: Kody orchestration + Claude Code + LiteLLM",
5
5
  "license": "MIT",
6
6
  "type": "module",