contextos-agents 1.5.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 (310) hide show
  1. package/.agents/AGENTS.md +421 -0
  2. package/.agents/adapters/aider/export.js +137 -0
  3. package/.agents/adapters/claude/export.js +55 -0
  4. package/.agents/adapters/copilot/export.js +107 -0
  5. package/.agents/adapters/cursor/export.js +210 -0
  6. package/.agents/adapters/gemini/export.js +115 -0
  7. package/.agents/adapters/shared.js +119 -0
  8. package/.agents/adapters/zed/export.js +111 -0
  9. package/.agents/core/profiles/backend.yaml +47 -0
  10. package/.agents/core/profiles/enterprise.yaml +46 -0
  11. package/.agents/core/profiles/frontend.yaml +46 -0
  12. package/.agents/core/profiles/hackathon.yaml +45 -0
  13. package/.agents/core/profiles/mvp.yaml +43 -0
  14. package/.agents/core/profiles/startup.yaml +48 -0
  15. package/.agents/core/skills/adapters/EXAMPLES.md +19 -0
  16. package/.agents/core/skills/adapters/SKILL.md +105 -0
  17. package/.agents/core/skills/adapters/TROUBLESHOOTING.md +7 -0
  18. package/.agents/core/skills/adapters/VALIDATION.json +12 -0
  19. package/.agents/core/skills/adapters/skill.yaml +10 -0
  20. package/.agents/core/skills/architecture-diagrams/SKILL.md +108 -0
  21. package/.agents/core/skills/architecture-diagrams/VALIDATION.json +12 -0
  22. package/.agents/core/skills/architecture-diagrams/skill.yaml +8 -0
  23. package/.agents/core/skills/brutalist-design/SKILL.md +150 -0
  24. package/.agents/core/skills/brutalist-design/VALIDATION.json +12 -0
  25. package/.agents/core/skills/brutalist-design/skill.yaml +8 -0
  26. package/.agents/core/skills/context-manager/EXAMPLES.md +19 -0
  27. package/.agents/core/skills/context-manager/SKILL.md +126 -0
  28. package/.agents/core/skills/context-manager/TROUBLESHOOTING.md +7 -0
  29. package/.agents/core/skills/context-manager/VALIDATION.json +12 -0
  30. package/.agents/core/skills/context-manager/skill.yaml +10 -0
  31. package/.agents/core/skills/context-os/EXAMPLES.md +21 -0
  32. package/.agents/core/skills/context-os/SKILL.md +169 -0
  33. package/.agents/core/skills/context-os/TROUBLESHOOTING.md +7 -0
  34. package/.agents/core/skills/context-os/VALIDATION.json +12 -0
  35. package/.agents/core/skills/context-os/packs.yaml +59 -0
  36. package/.agents/core/skills/context-os/references/context-rules.md +68 -0
  37. package/.agents/core/skills/context-os/references/pipeline.md +119 -0
  38. package/.agents/core/skills/context-os/references/project-graph.md +103 -0
  39. package/.agents/core/skills/context-os/rules.yaml +135 -0
  40. package/.agents/core/skills/context-os/skill.yaml +10 -0
  41. package/.agents/core/skills/database/EXAMPLES.md +74 -0
  42. package/.agents/core/skills/database/SKILL.md +101 -0
  43. package/.agents/core/skills/database/TROUBLESHOOTING.md +18 -0
  44. package/.agents/core/skills/database/VALIDATION.json +11 -0
  45. package/.agents/core/skills/database/skill.yaml +25 -0
  46. package/.agents/core/skills/ddd/EXAMPLES.md +42 -0
  47. package/.agents/core/skills/ddd/SKILL.md +247 -0
  48. package/.agents/core/skills/ddd/TROUBLESHOOTING.md +19 -0
  49. package/.agents/core/skills/ddd/VALIDATION.json +12 -0
  50. package/.agents/core/skills/ddd/ddd.md +178 -0
  51. package/.agents/core/skills/ddd/skill.yaml +10 -0
  52. package/.agents/core/skills/decisions/EXAMPLES.md +35 -0
  53. package/.agents/core/skills/decisions/SKILL.md +90 -0
  54. package/.agents/core/skills/decisions/TROUBLESHOOTING.md +13 -0
  55. package/.agents/core/skills/decisions/VALIDATION.json +12 -0
  56. package/.agents/core/skills/decisions/skill.yaml +10 -0
  57. package/.agents/core/skills/docker/EXAMPLES.md +56 -0
  58. package/.agents/core/skills/docker/SKILL.md +63 -0
  59. package/.agents/core/skills/docker/TROUBLESHOOTING.md +18 -0
  60. package/.agents/core/skills/docker/VALIDATION.json +11 -0
  61. package/.agents/core/skills/docker/skill.yaml +23 -0
  62. package/.agents/core/skills/engineering-workflow/EXAMPLES.md +57 -0
  63. package/.agents/core/skills/engineering-workflow/SKILL.md +343 -0
  64. package/.agents/core/skills/engineering-workflow/TROUBLESHOOTING.md +19 -0
  65. package/.agents/core/skills/engineering-workflow/VALIDATION.json +12 -0
  66. package/.agents/core/skills/engineering-workflow/skill.yaml +13 -0
  67. package/.agents/core/skills/fastapi/EXAMPLES.md +36 -0
  68. package/.agents/core/skills/fastapi/SKILL.md +148 -0
  69. package/.agents/core/skills/fastapi/TROUBLESHOOTING.md +19 -0
  70. package/.agents/core/skills/fastapi/VALIDATION.json +12 -0
  71. package/.agents/core/skills/fastapi/fastapi.md +112 -0
  72. package/.agents/core/skills/fastapi/skill.yaml +10 -0
  73. package/.agents/core/skills/gemini-precision/SKILL.md +169 -0
  74. package/.agents/core/skills/gemini-precision/VALIDATION.json +12 -0
  75. package/.agents/core/skills/gemini-precision/skill.yaml +9 -0
  76. package/.agents/core/skills/generators/EXAMPLES.md +19 -0
  77. package/.agents/core/skills/generators/SKILL.md +112 -0
  78. package/.agents/core/skills/generators/TROUBLESHOOTING.md +7 -0
  79. package/.agents/core/skills/generators/VALIDATION.json +12 -0
  80. package/.agents/core/skills/generators/skill.yaml +10 -0
  81. package/.agents/core/skills/generators/templates/API.md +77 -0
  82. package/.agents/core/skills/generators/templates/ARCHITECTURE.md +70 -0
  83. package/.agents/core/skills/generators/templates/DATABASE.md +42 -0
  84. package/.agents/core/skills/generators/templates/DECISION.md +46 -0
  85. package/.agents/core/skills/generators/templates/PRD.md +67 -0
  86. package/.agents/core/skills/generators/templates/PROJECT_GRAPH.md +56 -0
  87. package/.agents/core/skills/generators/templates/ROADMAP.md +51 -0
  88. package/.agents/core/skills/generators/templates/TASKS.md +43 -0
  89. package/.agents/core/skills/generators/templates/UI.md +73 -0
  90. package/.agents/core/skills/graphify/EXAMPLES.md +73 -0
  91. package/.agents/core/skills/graphify/SKILL.md +130 -0
  92. package/.agents/core/skills/graphify/VALIDATION.json +12 -0
  93. package/.agents/core/skills/graphify/skill.yaml +13 -0
  94. package/.agents/core/skills/gstack-roles/EXAMPLES.md +23 -0
  95. package/.agents/core/skills/gstack-roles/SKILL.md +152 -0
  96. package/.agents/core/skills/gstack-roles/TROUBLESHOOTING.md +13 -0
  97. package/.agents/core/skills/gstack-roles/VALIDATION.json +12 -0
  98. package/.agents/core/skills/gstack-roles/skill.yaml +12 -0
  99. package/.agents/core/skills/impeccable-design/EXAMPLES.md +26 -0
  100. package/.agents/core/skills/impeccable-design/SKILL.md +201 -0
  101. package/.agents/core/skills/impeccable-design/TROUBLESHOOTING.md +19 -0
  102. package/.agents/core/skills/impeccable-design/VALIDATION.json +12 -0
  103. package/.agents/core/skills/impeccable-design/skill.yaml +14 -0
  104. package/.agents/core/skills/interview-me/SKILL.md +97 -0
  105. package/.agents/core/skills/interview-me/VALIDATION.json +12 -0
  106. package/.agents/core/skills/interview-me/skill.yaml +8 -0
  107. package/.agents/core/skills/microservices/EXAMPLES.md +38 -0
  108. package/.agents/core/skills/microservices/SKILL.md +164 -0
  109. package/.agents/core/skills/microservices/TROUBLESHOOTING.md +19 -0
  110. package/.agents/core/skills/microservices/VALIDATION.json +12 -0
  111. package/.agents/core/skills/microservices/microservices.md +119 -0
  112. package/.agents/core/skills/microservices/skill.yaml +10 -0
  113. package/.agents/core/skills/minimalist-design/SKILL.md +113 -0
  114. package/.agents/core/skills/minimalist-design/VALIDATION.json +12 -0
  115. package/.agents/core/skills/minimalist-design/skill.yaml +8 -0
  116. package/.agents/core/skills/nestjs/EXAMPLES.md +40 -0
  117. package/.agents/core/skills/nestjs/SKILL.md +139 -0
  118. package/.agents/core/skills/nestjs/TROUBLESHOOTING.md +19 -0
  119. package/.agents/core/skills/nestjs/VALIDATION.json +12 -0
  120. package/.agents/core/skills/nestjs/nestjs.md +103 -0
  121. package/.agents/core/skills/nestjs/skill.yaml +10 -0
  122. package/.agents/core/skills/nextjs/EXAMPLES.md +40 -0
  123. package/.agents/core/skills/nextjs/SKILL.md +163 -0
  124. package/.agents/core/skills/nextjs/TROUBLESHOOTING.md +19 -0
  125. package/.agents/core/skills/nextjs/VALIDATION.json +12 -0
  126. package/.agents/core/skills/nextjs/nextjs.md +67 -0
  127. package/.agents/core/skills/nextjs/skill.yaml +10 -0
  128. package/.agents/core/skills/node/EXAMPLES.md +80 -0
  129. package/.agents/core/skills/node/SKILL.md +128 -0
  130. package/.agents/core/skills/node/TROUBLESHOOTING.md +19 -0
  131. package/.agents/core/skills/node/VALIDATION.json +12 -0
  132. package/.agents/core/skills/node/node.md +87 -0
  133. package/.agents/core/skills/node/skill.yaml +10 -0
  134. package/.agents/core/skills/performance/EXAMPLES.md +30 -0
  135. package/.agents/core/skills/performance/SKILL.md +75 -0
  136. package/.agents/core/skills/performance/TROUBLESHOOTING.md +19 -0
  137. package/.agents/core/skills/performance/VALIDATION.json +12 -0
  138. package/.agents/core/skills/performance/performance.md +52 -0
  139. package/.agents/core/skills/performance/skill.yaml +10 -0
  140. package/.agents/core/skills/ponytail-mindset/EXAMPLES.md +45 -0
  141. package/.agents/core/skills/ponytail-mindset/SKILL.md +193 -0
  142. package/.agents/core/skills/ponytail-mindset/TROUBLESHOOTING.md +19 -0
  143. package/.agents/core/skills/ponytail-mindset/VALIDATION.json +12 -0
  144. package/.agents/core/skills/ponytail-mindset/skill.yaml +14 -0
  145. package/.agents/core/skills/react/EXAMPLES.md +79 -0
  146. package/.agents/core/skills/react/SKILL.md +132 -0
  147. package/.agents/core/skills/react/TROUBLESHOOTING.md +19 -0
  148. package/.agents/core/skills/react/VALIDATION.json +12 -0
  149. package/.agents/core/skills/react/react.md +93 -0
  150. package/.agents/core/skills/react/skill.yaml +10 -0
  151. package/.agents/core/skills/react-best-practices/SKILL.md +155 -0
  152. package/.agents/core/skills/react-best-practices/VALIDATION.json +12 -0
  153. package/.agents/core/skills/react-best-practices/skill.yaml +10 -0
  154. package/.agents/core/skills/redesign-audit/SKILL.md +117 -0
  155. package/.agents/core/skills/redesign-audit/VALIDATION.json +12 -0
  156. package/.agents/core/skills/redesign-audit/skill.yaml +8 -0
  157. package/.agents/core/skills/security/EXAMPLES.md +64 -0
  158. package/.agents/core/skills/security/SKILL.md +158 -0
  159. package/.agents/core/skills/security/TROUBLESHOOTING.md +19 -0
  160. package/.agents/core/skills/security/VALIDATION.json +12 -0
  161. package/.agents/core/skills/security/security.md +106 -0
  162. package/.agents/core/skills/security/skill.yaml +10 -0
  163. package/.agents/core/skills/soft-design/SKILL.md +108 -0
  164. package/.agents/core/skills/soft-design/VALIDATION.json +12 -0
  165. package/.agents/core/skills/soft-design/skill.yaml +8 -0
  166. package/.agents/core/skills/state-management/EXAMPLES.md +56 -0
  167. package/.agents/core/skills/state-management/SKILL.md +48 -0
  168. package/.agents/core/skills/state-management/TROUBLESHOOTING.md +18 -0
  169. package/.agents/core/skills/state-management/VALIDATION.json +11 -0
  170. package/.agents/core/skills/state-management/skill.yaml +22 -0
  171. package/.agents/core/skills/subagent-orchestrator/SKILL.md +100 -0
  172. package/.agents/core/skills/subagent-orchestrator/VALIDATION.json +12 -0
  173. package/.agents/core/skills/subagent-orchestrator/skill.yaml +8 -0
  174. package/.agents/core/skills/system-design/EXAMPLES.md +75 -0
  175. package/.agents/core/skills/system-design/SKILL.md +419 -0
  176. package/.agents/core/skills/system-design/TROUBLESHOOTING.md +19 -0
  177. package/.agents/core/skills/system-design/VALIDATION.json +12 -0
  178. package/.agents/core/skills/system-design/skill.yaml +13 -0
  179. package/.agents/core/skills/system-design/system-design.md +112 -0
  180. package/.agents/core/skills/testing/EXAMPLES.md +71 -0
  181. package/.agents/core/skills/testing/SKILL.md +70 -0
  182. package/.agents/core/skills/testing/TROUBLESHOOTING.md +18 -0
  183. package/.agents/core/skills/testing/VALIDATION.json +11 -0
  184. package/.agents/core/skills/testing/skill.yaml +26 -0
  185. package/.agents/core/skills/typescript/EXAMPLES.md +64 -0
  186. package/.agents/core/skills/typescript/SKILL.md +112 -0
  187. package/.agents/core/skills/typescript/TROUBLESHOOTING.md +19 -0
  188. package/.agents/core/skills/typescript/VALIDATION.json +12 -0
  189. package/.agents/core/skills/typescript/skill.yaml +10 -0
  190. package/.agents/core/skills/typescript/typescript.md +71 -0
  191. package/.agents/core/skills/ui-design/EXAMPLES.md +21 -0
  192. package/.agents/core/skills/ui-design/SKILL.md +124 -0
  193. package/.agents/core/skills/ui-design/TROUBLESHOOTING.md +19 -0
  194. package/.agents/core/skills/ui-design/VALIDATION.json +12 -0
  195. package/.agents/core/skills/ui-design/skill.yaml +10 -0
  196. package/.agents/core/skills/ui-design/ui.md +88 -0
  197. package/.agents/core/skills/ui-ux-pro/EXAMPLES.md +62 -0
  198. package/.agents/core/skills/ui-ux-pro/SKILL.md +375 -0
  199. package/.agents/core/skills/ui-ux-pro/TROUBLESHOOTING.md +19 -0
  200. package/.agents/core/skills/ui-ux-pro/VALIDATION.json +12 -0
  201. package/.agents/core/skills/ui-ux-pro/skill.yaml +13 -0
  202. package/.agents/core/skills/ux-design/EXAMPLES.md +36 -0
  203. package/.agents/core/skills/ux-design/SKILL.md +116 -0
  204. package/.agents/core/skills/ux-design/TROUBLESHOOTING.md +19 -0
  205. package/.agents/core/skills/ux-design/VALIDATION.json +12 -0
  206. package/.agents/core/skills/ux-design/skill.yaml +10 -0
  207. package/.agents/core/skills/ux-design/ux.md +80 -0
  208. package/.agents/core/skills/vercel-optimize/SKILL.md +83 -0
  209. package/.agents/core/skills/vercel-optimize/VALIDATION.json +12 -0
  210. package/.agents/core/skills/vercel-optimize/skill.yaml +10 -0
  211. package/.agents/core/skills/web-accessibility/EXAMPLES.md +39 -0
  212. package/.agents/core/skills/web-accessibility/SKILL.md +170 -0
  213. package/.agents/core/skills/web-accessibility/TROUBLESHOOTING.md +19 -0
  214. package/.agents/core/skills/web-accessibility/VALIDATION.json +12 -0
  215. package/.agents/core/skills/web-accessibility/accessibility.md +63 -0
  216. package/.agents/core/skills/web-accessibility/skill.yaml +10 -0
  217. package/.agents/ctx.js +370 -0
  218. package/.agents/generated/claude/skills/adapters/SKILL.md +126 -0
  219. package/.agents/generated/claude/skills/architecture-diagrams/SKILL.md +101 -0
  220. package/.agents/generated/claude/skills/brutalist-design/SKILL.md +145 -0
  221. package/.agents/generated/claude/skills/context-manager/SKILL.md +147 -0
  222. package/.agents/generated/claude/skills/context-os/SKILL.md +191 -0
  223. package/.agents/generated/claude/skills/database/SKILL.md +191 -0
  224. package/.agents/generated/claude/skills/ddd/SKILL.md +305 -0
  225. package/.agents/generated/claude/skills/decisions/SKILL.md +134 -0
  226. package/.agents/generated/claude/skills/docker/SKILL.md +135 -0
  227. package/.agents/generated/claude/skills/engineering-workflow/SKILL.md +414 -0
  228. package/.agents/generated/claude/skills/fastapi/SKILL.md +200 -0
  229. package/.agents/generated/claude/skills/gemini-precision/SKILL.md +161 -0
  230. package/.agents/generated/claude/skills/generators/SKILL.md +133 -0
  231. package/.agents/generated/claude/skills/graphify/SKILL.md +198 -0
  232. package/.agents/generated/claude/skills/gstack-roles/SKILL.md +184 -0
  233. package/.agents/generated/claude/skills/impeccable-design/SKILL.md +241 -0
  234. package/.agents/generated/claude/skills/interview-me/SKILL.md +90 -0
  235. package/.agents/generated/claude/skills/microservices/SKILL.md +218 -0
  236. package/.agents/generated/claude/skills/minimalist-design/SKILL.md +108 -0
  237. package/.agents/generated/claude/skills/nestjs/SKILL.md +195 -0
  238. package/.agents/generated/claude/skills/nextjs/SKILL.md +219 -0
  239. package/.agents/generated/claude/skills/node/SKILL.md +224 -0
  240. package/.agents/generated/claude/skills/performance/SKILL.md +121 -0
  241. package/.agents/generated/claude/skills/ponytail-mindset/SKILL.md +252 -0
  242. package/.agents/generated/claude/skills/react/SKILL.md +227 -0
  243. package/.agents/generated/claude/skills/react-best-practices/SKILL.md +146 -0
  244. package/.agents/generated/claude/skills/redesign-audit/SKILL.md +112 -0
  245. package/.agents/generated/claude/skills/security/SKILL.md +237 -0
  246. package/.agents/generated/claude/skills/soft-design/SKILL.md +103 -0
  247. package/.agents/generated/claude/skills/state-management/SKILL.md +120 -0
  248. package/.agents/generated/claude/skills/subagent-orchestrator/SKILL.md +93 -0
  249. package/.agents/generated/claude/skills/system-design/SKILL.md +507 -0
  250. package/.agents/generated/claude/skills/testing/SKILL.md +157 -0
  251. package/.agents/generated/claude/skills/typescript/SKILL.md +192 -0
  252. package/.agents/generated/claude/skills/ui-design/SKILL.md +161 -0
  253. package/.agents/generated/claude/skills/ui-ux-pro/SKILL.md +451 -0
  254. package/.agents/generated/claude/skills/ux-design/SKILL.md +168 -0
  255. package/.agents/generated/claude/skills/vercel-optimize/SKILL.md +76 -0
  256. package/.agents/generated/claude/skills/web-accessibility/SKILL.md +225 -0
  257. package/.agents/generated/gemini/skills/adapters/SKILL.md +135 -0
  258. package/.agents/generated/gemini/skills/architecture-diagrams/SKILL.md +107 -0
  259. package/.agents/generated/gemini/skills/brutalist-design/SKILL.md +151 -0
  260. package/.agents/generated/gemini/skills/context-manager/SKILL.md +156 -0
  261. package/.agents/generated/gemini/skills/context-os/SKILL.md +200 -0
  262. package/.agents/generated/gemini/skills/database/SKILL.md +200 -0
  263. package/.agents/generated/gemini/skills/ddd/SKILL.md +314 -0
  264. package/.agents/generated/gemini/skills/decisions/SKILL.md +143 -0
  265. package/.agents/generated/gemini/skills/docker/SKILL.md +144 -0
  266. package/.agents/generated/gemini/skills/engineering-workflow/SKILL.md +423 -0
  267. package/.agents/generated/gemini/skills/fastapi/SKILL.md +209 -0
  268. package/.agents/generated/gemini/skills/gemini-precision/SKILL.md +167 -0
  269. package/.agents/generated/gemini/skills/generators/SKILL.md +142 -0
  270. package/.agents/generated/gemini/skills/graphify/SKILL.md +205 -0
  271. package/.agents/generated/gemini/skills/gstack-roles/SKILL.md +193 -0
  272. package/.agents/generated/gemini/skills/impeccable-design/SKILL.md +250 -0
  273. package/.agents/generated/gemini/skills/interview-me/SKILL.md +96 -0
  274. package/.agents/generated/gemini/skills/microservices/SKILL.md +227 -0
  275. package/.agents/generated/gemini/skills/minimalist-design/SKILL.md +114 -0
  276. package/.agents/generated/gemini/skills/nestjs/SKILL.md +204 -0
  277. package/.agents/generated/gemini/skills/nextjs/SKILL.md +298 -0
  278. package/.agents/generated/gemini/skills/node/SKILL.md +323 -0
  279. package/.agents/generated/gemini/skills/performance/SKILL.md +185 -0
  280. package/.agents/generated/gemini/skills/ponytail-mindset/SKILL.md +261 -0
  281. package/.agents/generated/gemini/skills/react/SKILL.md +332 -0
  282. package/.agents/generated/gemini/skills/react-best-practices/SKILL.md +152 -0
  283. package/.agents/generated/gemini/skills/redesign-audit/SKILL.md +118 -0
  284. package/.agents/generated/gemini/skills/security/SKILL.md +355 -0
  285. package/.agents/generated/gemini/skills/soft-design/SKILL.md +109 -0
  286. package/.agents/generated/gemini/skills/state-management/SKILL.md +129 -0
  287. package/.agents/generated/gemini/skills/subagent-orchestrator/SKILL.md +99 -0
  288. package/.agents/generated/gemini/skills/system-design/SKILL.md +631 -0
  289. package/.agents/generated/gemini/skills/testing/SKILL.md +166 -0
  290. package/.agents/generated/gemini/skills/typescript/SKILL.md +275 -0
  291. package/.agents/generated/gemini/skills/ui-design/SKILL.md +170 -0
  292. package/.agents/generated/gemini/skills/ui-ux-pro/SKILL.md +460 -0
  293. package/.agents/generated/gemini/skills/ux-design/SKILL.md +177 -0
  294. package/.agents/generated/gemini/skills/vercel-optimize/SKILL.md +82 -0
  295. package/.agents/generated/gemini/skills/web-accessibility/SKILL.md +300 -0
  296. package/.agents/mcp/runtime.py +454 -0
  297. package/.agents/mcp/server.mjs +189373 -0
  298. package/.agents/plugins.js +574 -0
  299. package/.agents/profiles.js +267 -0
  300. package/.agents/resolver.js +336 -0
  301. package/.agents/skills-index.json +200 -0
  302. package/.agents/skills.json +6 -0
  303. package/.agents/validate.js +500 -0
  304. package/LICENSE +21 -0
  305. package/README.md +415 -0
  306. package/benchmarks/gemini-issues.js +533 -0
  307. package/bin/index.js +458 -0
  308. package/package.json +70 -0
  309. package/registry.json +53 -0
  310. package/registry.schema.json +32 -0
@@ -0,0 +1,574 @@
1
+ /**
2
+ * .agents/plugins.js
3
+ * ContextOS — Skill Plugin Manager
4
+ *
5
+ * Installs third-party skills from:
6
+ * • npm packages (contextos-skill-*)
7
+ * • GitHub repos (owner/repo or owner/repo/path/to/skill)
8
+ *
9
+ * Usage (via ctx.js):
10
+ * node .agents/ctx.js skill add username/my-skill
11
+ * node .agents/ctx.js skill add my-npm-package
12
+ * node .agents/ctx.js skill remove my-skill
13
+ * node .agents/ctx.js skill list
14
+ * node .agents/ctx.js skill search <query>
15
+ *
16
+ * Or via npx:
17
+ * npx contextos-agents --add-skill username/my-skill
18
+ */
19
+
20
+ 'use strict';
21
+
22
+ const fs = require('fs');
23
+ const os = require('os');
24
+ const path = require('path');
25
+ const https = require('https');
26
+ const crypto = require('crypto');
27
+ const { execFileSync } = require('child_process');
28
+
29
+ // ── Paths ─────────────────────────────────────────────────────────────────────
30
+ const ROOT = process.cwd();
31
+ const AGENTS_DIR = path.join(ROOT, '.agents');
32
+ const CORE_SKILLS = path.join(AGENTS_DIR, 'core', 'skills');
33
+ const PLUGINS_DIR = path.join(AGENTS_DIR, 'plugins'); // installed third-party skills
34
+ const PLUGINS_JSON = path.join(AGENTS_DIR, 'plugins.json'); // local lock file
35
+ const REGISTRY_URL = 'https://raw.githubusercontent.com/kok-o/contextos-agents/main/registry.json';
36
+ const MAX_DOWNLOAD_BYTES = 5 * 1024 * 1024;
37
+ const SAFE_SKILL_NAME = /^[a-z0-9](?:[a-z0-9-]{0,62}[a-z0-9])?$/;
38
+
39
+ // ── Prompt Injection Scanner ──────────────────────────────────────────────────
40
+ const PROMPT_INJECTION_PATTERNS = [
41
+ /ignore\s+(all\s+)?previous\s+instructions/i,
42
+ /forget\s+(all\s+)?previous/i,
43
+ /you\s+are\s+now/i,
44
+ /system\s*:\s*/i,
45
+ /\[SYSTEM\]/i,
46
+ ];
47
+
48
+ function scanForPromptInjection(content) {
49
+ if (typeof content !== 'string') return false;
50
+ const found = PROMPT_INJECTION_PATTERNS.filter(p => p.test(content));
51
+ if (found.length > 0) {
52
+ console.warn(c.yellow(' ⚠️ Potential prompt injection detected in downloaded skill'));
53
+ console.warn(c.yellow(` Patterns: ${found.map(p => p.source).join(', ')}`));
54
+ return true;
55
+ }
56
+ return false;
57
+ }
58
+
59
+ // ── ANSI helpers ──────────────────────────────────────────────────────────────
60
+ const NO_COLOR = process.env.NO_COLOR || !process.stdout.isTTY;
61
+ const c = {
62
+ green: (s) => NO_COLOR ? s : `\x1b[32m${s}\x1b[0m`,
63
+ red: (s) => NO_COLOR ? s : `\x1b[31m${s}\x1b[0m`,
64
+ yellow: (s) => NO_COLOR ? s : `\x1b[33m${s}\x1b[0m`,
65
+ cyan: (s) => NO_COLOR ? s : `\x1b[36m${s}\x1b[0m`,
66
+ bold: (s) => NO_COLOR ? s : `\x1b[1m${s}\x1b[0m`,
67
+ dim: (s) => NO_COLOR ? s : `\x1b[2m${s}\x1b[0m`,
68
+ };
69
+
70
+ // ── plugins.json lock file ─────────────────────────────────────────────────────
71
+ function readLock() {
72
+ if (!fs.existsSync(PLUGINS_JSON)) return { plugins: [] };
73
+ try {
74
+ return JSON.parse(fs.readFileSync(PLUGINS_JSON, 'utf8'));
75
+ } catch {
76
+ return { plugins: [] };
77
+ }
78
+ }
79
+
80
+ function writeLock(lock) {
81
+ fs.mkdirSync(AGENTS_DIR, { recursive: true });
82
+ fs.writeFileSync(PLUGINS_JSON, JSON.stringify(lock, null, 2) + '\n');
83
+ }
84
+
85
+ // ── HTTP fetch helper (no deps) ───────────────────────────────────────────────
86
+ function fetchText(url) {
87
+ return new Promise((resolve, reject) => {
88
+ const request = https.get(url, { headers: { 'User-Agent': 'contextos-agents' } }, (res) => {
89
+ if (res.statusCode === 301 || res.statusCode === 302) {
90
+ const redirect = new URL(res.headers.location, url);
91
+ if (redirect.protocol !== 'https:' || redirect.hostname !== 'raw.githubusercontent.com') {
92
+ return reject(new Error('Refusing redirect outside raw.githubusercontent.com'));
93
+ }
94
+ return fetchText(redirect.toString()).then(resolve).catch(reject);
95
+ }
96
+ if (res.statusCode !== 200) {
97
+ return reject(new Error(`HTTP ${res.statusCode} for ${url}`));
98
+ }
99
+ let data = '';
100
+ let bytes = 0;
101
+ res.on('data', chunk => {
102
+ bytes += chunk.length;
103
+ if (bytes > MAX_DOWNLOAD_BYTES) {
104
+ request.destroy(new Error(`Download exceeds ${MAX_DOWNLOAD_BYTES} bytes`));
105
+ return;
106
+ }
107
+ data += chunk;
108
+ });
109
+ res.on('end', () => resolve(data));
110
+ });
111
+ request.setTimeout(15_000, () => request.destroy(new Error('Download timed out')));
112
+ request.on('error', reject);
113
+ });
114
+ }
115
+
116
+ // ── Source resolver ──────────────────────────────────────────────────────────
117
+ /**
118
+ * Parse a skill reference into a structured descriptor.
119
+ *
120
+ * Supported formats:
121
+ * username/repo → GitHub: fetch /SKILL.md from repo root
122
+ * username/repo/path/to/skill → GitHub: fetch /path/to/skill/SKILL.md
123
+ * my-npm-package → npm: install package, copy skill dir
124
+ */
125
+ function isValidNpmPackage(name) {
126
+ if (typeof name !== 'string' || !name.trim()) return false;
127
+ if (name.startsWith('-') || name.includes('/-')) return false;
128
+ return /^(?:@[a-z0-9_.-]+\/)?[a-z0-9_.-]+$/.test(name);
129
+ }
130
+
131
+ function parseRef(ref) {
132
+ if (typeof ref !== 'string' || !ref.trim()) {
133
+ throw new Error('A plugin reference is required');
134
+ }
135
+
136
+ // Scoped packages contain a slash but are npm packages, not GitHub refs.
137
+ if (ref.startsWith('@')) {
138
+ if (!isValidNpmPackage(ref)) {
139
+ throw new Error(`Invalid scoped npm package name: '${ref}'`);
140
+ }
141
+ return { type: 'npm', package: ref, raw: ref };
142
+ }
143
+
144
+ // GitHub: contains a slash
145
+ if (ref.includes('/')) {
146
+ const parts = ref.split('/');
147
+ const owner = parts[0];
148
+ const repoRef = parts[1];
149
+ const subPath = parts.slice(2).join('/'); // may be empty
150
+ const [repo, gitRef = 'main'] = repoRef.split('@');
151
+ const safeSegment = /^[A-Za-z0-9._-]+$/;
152
+
153
+ const isSafePathPart = part => part !== '.' && part !== '..' && safeSegment.test(part);
154
+ if (!owner || !repo || !isSafePathPart(owner) || !isSafePathPart(repo) ||
155
+ !isSafePathPart(gitRef) || parts.slice(2).some(part => !isSafePathPart(part))) {
156
+ throw new Error('Invalid GitHub plugin reference');
157
+ }
158
+
159
+ return { type: 'github', owner, repo, gitRef, isPinned: repoRef.includes('@'), subPath, raw: ref };
160
+ }
161
+ // npm package
162
+ if (!isValidNpmPackage(ref)) {
163
+ throw new Error(`Invalid npm package name: '${ref}'`);
164
+ }
165
+ return { type: 'npm', package: ref, raw: ref };
166
+ }
167
+
168
+ // ── GitHub installer ──────────────────────────────────────────────────────────
169
+ async function installFromGitHub(descriptor, skillName, dryRun, checksum) {
170
+ const { owner, repo, gitRef, isPinned, subPath } = descriptor;
171
+ const skillPath = subPath || '';
172
+ const base = `https://raw.githubusercontent.com/${owner}/${repo}/${gitRef}`;
173
+ const skillMdUrl = skillPath
174
+ ? `${base}/${skillPath}/SKILL.md`
175
+ : `${base}/SKILL.md`;
176
+
177
+ console.log(c.dim(` Fetching: ${skillMdUrl}`));
178
+ if (!isPinned) {
179
+ console.log(c.yellow(' [WARN] Unpinned GitHub ref: prefer owner/repo@<commit> for reproducible installs.'));
180
+ }
181
+
182
+ let skillMdContent;
183
+ try {
184
+ skillMdContent = await fetchText(skillMdUrl);
185
+ } catch (err) {
186
+ if (gitRef !== 'main') throw err;
187
+ // Try /master branch fallback only for the legacy default branch behavior.
188
+ const masterUrl = skillMdUrl.replace('/main/', '/master/');
189
+ console.log(c.dim(` Retrying on master branch: ${masterUrl}`));
190
+ skillMdContent = await fetchText(masterUrl);
191
+ }
192
+
193
+ if (!skillMdContent || skillMdContent.length < 50) {
194
+ throw new Error('Fetched SKILL.md appears empty or invalid');
195
+ }
196
+
197
+ const sha256 = crypto.createHash('sha256').update(skillMdContent).digest('hex');
198
+ if (checksum && sha256.toLowerCase() !== checksum.toLowerCase()) {
199
+ throw new Error(`Checksum mismatch for ${skillName}: expected ${checksum}, got ${sha256}`);
200
+ }
201
+ scanForPromptInjection(skillMdContent);
202
+
203
+ // Optionally fetch skill.yaml if it exists
204
+ const yamlUrl = skillPath
205
+ ? `${base}/${skillPath}/skill.yaml`
206
+ : `${base}/skill.yaml`;
207
+
208
+ let yamlContent = null;
209
+ try {
210
+ yamlContent = await fetchText(yamlUrl);
211
+ } catch {
212
+ // Optional — not all skills have skill.yaml
213
+ }
214
+
215
+ const targetDir = path.join(PLUGINS_DIR, skillName);
216
+
217
+ if (dryRun) {
218
+ console.log(c.yellow(` [DRY-RUN] Would install to: ${targetDir}`));
219
+ console.log(c.yellow(` [DRY-RUN] SKILL.md size: ${skillMdContent.length} bytes (sha256: ${sha256})`));
220
+ return sha256;
221
+ }
222
+
223
+ fs.mkdirSync(targetDir, { recursive: true });
224
+ fs.writeFileSync(path.join(targetDir, 'SKILL.md'), skillMdContent);
225
+ if (yamlContent) {
226
+ fs.writeFileSync(path.join(targetDir, 'skill.yaml'), yamlContent);
227
+ }
228
+
229
+ // Write a source marker so we know where to update from
230
+ fs.writeFileSync(path.join(targetDir, '.source'), JSON.stringify({
231
+ type: 'github',
232
+ owner,
233
+ repo,
234
+ gitRef,
235
+ subPath: skillPath,
236
+ ref: descriptor.raw,
237
+ sha256,
238
+ installedAt: new Date().toISOString(),
239
+ }, null, 2));
240
+
241
+ console.log(c.green(` ✓ Installed SKILL.md (${skillMdContent.length} bytes, sha256: ${sha256.slice(0, 12)}...)`));
242
+ if (yamlContent) console.log(c.green(` ✓ Installed skill.yaml`));
243
+ return sha256;
244
+ }
245
+
246
+ // ── npm installer ─────────────────────────────────────────────────────────────
247
+ function installFromNpm(descriptor, skillName, dryRun, checksum) {
248
+ const pkgName = descriptor.package;
249
+
250
+ if (dryRun) {
251
+ console.log(c.yellow(` [DRY-RUN] Would run: npm install ${pkgName}`));
252
+ console.log(c.yellow(` [DRY-RUN] Would copy skill to: ${path.join(PLUGINS_DIR, skillName)}`));
253
+ return null;
254
+ }
255
+
256
+ console.log(c.dim(` Installing npm package: ${pkgName}`));
257
+ const npm = process.platform === 'win32' ? 'npm.cmd' : 'npm';
258
+ const temporaryPrefix = fs.mkdtempSync(path.join(os.tmpdir(), 'contextos-plugin-'));
259
+
260
+ let sha256 = null;
261
+ try {
262
+ // `--prefix` keeps both node_modules and npm metadata outside the user's
263
+ // project. Lifecycle scripts remain disabled for untrusted packages.
264
+ execFileSync(npm, [
265
+ 'install', '--prefix', temporaryPrefix, '--no-save', '--ignore-scripts',
266
+ '--package-lock=false', '--no-audit', '--no-fund', pkgName,
267
+ ], { cwd: temporaryPrefix, stdio: 'pipe' });
268
+
269
+ const nmPath = path.join(temporaryPrefix, 'node_modules', pkgName);
270
+ const skillSrc = fs.existsSync(path.join(nmPath, 'SKILL.md'))
271
+ ? nmPath
272
+ : path.join(nmPath, 'skill'); // try skill/ subfolder
273
+
274
+ if (!fs.existsSync(path.join(skillSrc, 'SKILL.md'))) {
275
+ throw new Error(`Package '${pkgName}' does not contain a SKILL.md at its root or skill/ subdirectory`);
276
+ }
277
+
278
+ const skillMdContent = fs.readFileSync(path.join(skillSrc, 'SKILL.md'), 'utf8');
279
+ sha256 = crypto.createHash('sha256').update(skillMdContent).digest('hex');
280
+ if (checksum && sha256.toLowerCase() !== checksum.toLowerCase()) {
281
+ throw new Error(`Checksum mismatch for ${skillName}: expected ${checksum}, got ${sha256}`);
282
+ }
283
+ scanForPromptInjection(skillMdContent);
284
+
285
+ const targetDir = path.join(PLUGINS_DIR, skillName);
286
+ fs.rmSync(targetDir, { recursive: true, force: true });
287
+ fs.mkdirSync(targetDir, { recursive: true });
288
+ fs.cpSync(skillSrc, targetDir, { recursive: true, force: true });
289
+
290
+ // Write source marker
291
+ fs.writeFileSync(path.join(targetDir, '.source'), JSON.stringify({
292
+ type: 'npm',
293
+ package: pkgName,
294
+ ref: descriptor.raw,
295
+ sha256,
296
+ installedAt: new Date().toISOString(),
297
+ }, null, 2));
298
+ } finally {
299
+ fs.rmSync(temporaryPrefix, { recursive: true, force: true });
300
+ }
301
+
302
+ console.log(c.green(` ✓ Installed from npm: ${pkgName} (sha256: ${sha256 ? sha256.slice(0, 12) + '...' : 'unknown'})`));
303
+ return sha256;
304
+ }
305
+
306
+ // ── Derive skill name from ref ────────────────────────────────────────────────
307
+ function deriveSkillName(ref) {
308
+ // username/repo/path/to/my-skill → my-skill
309
+ // username/my-skill → my-skill
310
+ // my-npm-package → my-npm-package
311
+ const parts = ref.replace(/\.git$/, '').split('/');
312
+ return parts[parts.length - 1].toLowerCase().replace(/[^a-z0-9-]/g, '-');
313
+ }
314
+
315
+ function isSafeSkillName(skillName) {
316
+ return typeof skillName === 'string' && SAFE_SKILL_NAME.test(skillName);
317
+ }
318
+
319
+ // ═════════════════════════════════════════════════════════════════════════════
320
+ // COMMANDS
321
+ // ═════════════════════════════════════════════════════════════════════════════
322
+
323
+ /**
324
+ * skill add <ref> [--dry-run] [--checksum <sha256>]
325
+ */
326
+ async function add(ref, { dryRun = false, checksum } = {}) {
327
+ if (!ref) {
328
+ console.error(c.red('Usage: ctx.js skill add <ref> [--checksum <sha256>]'));
329
+ console.error(' ref can be: username/repo, username/repo/path/to/skill, or npm-package-name');
330
+ process.exit(1);
331
+ }
332
+
333
+ const descriptor = parseRef(ref);
334
+ const skillName = deriveSkillName(ref);
335
+
336
+ if (!isSafeSkillName(skillName)) {
337
+ throw new Error(`Invalid plugin name derived from reference: '${skillName}'`);
338
+ }
339
+
340
+ console.log('');
341
+ console.log(c.bold(`Installing skill: ${c.cyan(skillName)}`));
342
+ console.log(c.dim(` Source: ${ref} (${descriptor.type})`));
343
+
344
+ // Check for conflict with builtin skills
345
+ const builtinPath = path.join(CORE_SKILLS, skillName);
346
+ if (fs.existsSync(builtinPath)) {
347
+ console.error(c.red(`\n[ERROR] '${skillName}' conflicts with a built-in skill.`));
348
+ console.error(c.red(' Built-in skills cannot be overridden via --add-skill.'));
349
+ console.error(c.dim(' To customize a built-in skill, fork the repo and submit a PR.'));
350
+ process.exit(1);
351
+ }
352
+
353
+ // Check if already installed
354
+ const lock = readLock();
355
+ const existing = lock.plugins.find(p => p.name === skillName);
356
+ if (existing && !dryRun) {
357
+ console.log(c.yellow(`\n[WARN] '${skillName}' is already installed (from: ${existing.ref})`));
358
+ console.log(c.yellow(' Re-installing will overwrite it. Continuing...'));
359
+ }
360
+
361
+ let installedSha256 = null;
362
+ try {
363
+ if (descriptor.type === 'github') {
364
+ installedSha256 = await installFromGitHub(descriptor, skillName, dryRun, checksum);
365
+ } else {
366
+ installedSha256 = installFromNpm(descriptor, skillName, dryRun, checksum);
367
+ }
368
+ } catch (err) {
369
+ console.error(c.red(`\n[ERROR] Failed to install '${skillName}': ${err.message}`));
370
+ process.exit(1);
371
+ }
372
+
373
+ if (!dryRun) {
374
+ // Update lock file
375
+ const idx = lock.plugins.findIndex(p => p.name === skillName);
376
+ const entry = {
377
+ name: skillName,
378
+ ref,
379
+ type: descriptor.type,
380
+ sha256: installedSha256,
381
+ installedAt: new Date().toISOString(),
382
+ };
383
+ if (idx >= 0) lock.plugins[idx] = entry;
384
+ else lock.plugins.push(entry);
385
+ writeLock(lock);
386
+
387
+ console.log('');
388
+ console.log(c.green(c.bold('✓ Skill installed successfully!')));
389
+ console.log(c.dim(` Location: .agents/plugins/${skillName}/`));
390
+ console.log('');
391
+ console.log(' Next steps:');
392
+ console.log(` node .agents/ctx.js export all # recompile with new skill`);
393
+ console.log(` node .agents/ctx.js validate # verify everything is consistent`);
394
+ console.log('');
395
+ }
396
+ }
397
+
398
+ /**
399
+ * skill remove <name>
400
+ */
401
+ function remove(skillName) {
402
+ if (!skillName) {
403
+ console.error(c.red('Usage: ctx.js skill remove <name>'));
404
+ process.exit(1);
405
+ }
406
+
407
+ if (!isSafeSkillName(skillName)) {
408
+ console.error(c.red(`[ERROR] Invalid plugin name: '${skillName}'`));
409
+ process.exit(1);
410
+ }
411
+
412
+ const lock = readLock();
413
+ const entry = lock.plugins.find(p => p.name === skillName);
414
+ const skillDir = path.join(PLUGINS_DIR, skillName);
415
+
416
+ if (!entry && !fs.existsSync(skillDir)) {
417
+ console.error(c.red(`[ERROR] Plugin '${skillName}' is not installed.`));
418
+ console.log(c.dim(' Run: node .agents/ctx.js skill list'));
419
+ process.exit(1);
420
+ }
421
+
422
+ // Protect builtins
423
+ const builtinPath = path.join(CORE_SKILLS, skillName);
424
+ if (fs.existsSync(builtinPath)) {
425
+ console.error(c.red(`[ERROR] '${skillName}' is a built-in skill and cannot be removed.`));
426
+ process.exit(1);
427
+ }
428
+
429
+ if (fs.existsSync(skillDir)) {
430
+ fs.rmSync(skillDir, { recursive: true, force: true });
431
+ }
432
+
433
+ lock.plugins = lock.plugins.filter(p => p.name !== skillName);
434
+ writeLock(lock);
435
+
436
+ console.log(c.green(`✓ Removed plugin: ${skillName}`));
437
+ console.log(c.dim(' Run: node .agents/ctx.js export all (to recompile)'));
438
+ }
439
+
440
+ /**
441
+ * skill list
442
+ */
443
+ function list() {
444
+ const lock = readLock();
445
+
446
+ // Builtin skills
447
+ const builtins = fs.existsSync(CORE_SKILLS)
448
+ ? fs.readdirSync(CORE_SKILLS).filter(n => fs.statSync(path.join(CORE_SKILLS, n)).isDirectory())
449
+ : [];
450
+
451
+ // Plugin skills
452
+ const plugins = lock.plugins;
453
+
454
+ console.log('');
455
+ console.log(c.bold('ContextOS Skills'));
456
+ console.log('');
457
+
458
+ // Built-ins
459
+ console.log(c.bold(` Built-in (${builtins.length})`));
460
+ for (const name of builtins) {
461
+ console.log(` ${c.cyan('●')} ${name} ${c.dim('(core)')}`);
462
+ }
463
+
464
+ // Plugins
465
+ console.log('');
466
+ if (plugins.length === 0) {
467
+ console.log(c.bold(' Plugins (0)'));
468
+ console.log(c.dim(' No plugins installed yet.'));
469
+ console.log(c.dim(' Install one: node .agents/ctx.js skill add username/my-skill'));
470
+ } else {
471
+ console.log(c.bold(` Plugins (${plugins.length})`));
472
+ for (const p of plugins) {
473
+ const when = p.installedAt ? new Date(p.installedAt).toLocaleDateString() : '?';
474
+ console.log(` ${c.green('●')} ${p.name} ${c.dim(`← ${p.ref} (installed ${when})`)}`);
475
+ }
476
+ }
477
+
478
+ console.log('');
479
+ }
480
+
481
+ /**
482
+ * skill search <query> — searches the hosted registry.json
483
+ */
484
+ async function search(query) {
485
+ console.log(c.dim(`\nFetching registry from: ${REGISTRY_URL}\n`));
486
+
487
+ let registry;
488
+ try {
489
+ const raw = await fetchText(REGISTRY_URL);
490
+ registry = JSON.parse(raw);
491
+ } catch (err) {
492
+ console.error(c.red(`[ERROR] Could not fetch registry: ${err.message}`));
493
+ console.error(c.dim(' Check your internet connection or try again later.'));
494
+ process.exit(1);
495
+ }
496
+
497
+ const q = (query || '').toLowerCase();
498
+ const results = registry.skills.filter(s =>
499
+ !q ||
500
+ s.name.includes(q) ||
501
+ s.description.toLowerCase().includes(q) ||
502
+ (s.tags || []).some(t => t.includes(q)) ||
503
+ s.author.includes(q)
504
+ );
505
+
506
+ if (results.length === 0) {
507
+ console.log(c.yellow(`No skills found matching "${query}".`));
508
+ console.log(c.dim(` Browse all: ${registry.contributing}`));
509
+ return;
510
+ }
511
+
512
+ console.log(c.bold(`Found ${results.length} skill(s)${q ? ` matching "${query}"` : ''}:\n`));
513
+
514
+ for (const s of results) {
515
+ const installRef = s.builtin
516
+ ? c.dim('(built-in)')
517
+ : c.cyan(s.github ? `${s.github}${s.path ? '/' + s.path : ''}` : s.npm);
518
+
519
+ const builtinBadge = s.builtin ? c.dim(' [built-in]') : '';
520
+ console.log(` ${c.bold(s.name)}${builtinBadge}`);
521
+ console.log(` ${s.description}`);
522
+ console.log(` ${c.dim('author:')} ${s.author} ${c.dim('tags:')} ${(s.tags || []).join(', ')}`);
523
+ console.log(` ${c.dim('install:')} node .agents/ctx.js skill add ${installRef}`);
524
+ console.log('');
525
+ }
526
+
527
+ console.log(c.dim(`To publish your skill: ${registry.contributing}`));
528
+ }
529
+
530
+ // ═════════════════════════════════════════════════════════════════════════════
531
+ // Plugin-aware skill collection (used by adapters)
532
+ // ═════════════════════════════════════════════════════════════════════════════
533
+
534
+ /**
535
+ * Returns an array of all skill source directories:
536
+ * both core (builtin) and plugins.
537
+ * Adapters call this instead of reading CORE_SKILLS directly.
538
+ */
539
+ function collectAllSkillDirs() {
540
+ const dirs = [];
541
+
542
+ // Core skills
543
+ if (fs.existsSync(CORE_SKILLS)) {
544
+ for (const name of fs.readdirSync(CORE_SKILLS)) {
545
+ const d = path.join(CORE_SKILLS, name);
546
+ if (fs.statSync(d).isDirectory()) dirs.push(d);
547
+ }
548
+ }
549
+
550
+ // Plugin skills
551
+ if (fs.existsSync(PLUGINS_DIR)) {
552
+ for (const name of fs.readdirSync(PLUGINS_DIR)) {
553
+ const d = path.join(PLUGINS_DIR, name);
554
+ if (fs.statSync(d).isDirectory()) dirs.push(d);
555
+ }
556
+ }
557
+
558
+ return dirs;
559
+ }
560
+
561
+ module.exports = {
562
+ add,
563
+ remove,
564
+ list,
565
+ search,
566
+ collectAllSkillDirs,
567
+ readLock,
568
+ parseRef,
569
+ deriveSkillName,
570
+ isSafeSkillName,
571
+ scanForPromptInjection,
572
+ PROMPT_INJECTION_PATTERNS,
573
+ PLUGINS_DIR,
574
+ };