@xagent-ai/cli 1.2.2 → 1.3.1

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 (602) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +38 -38
  2. package/.github/ISSUE_TEMPLATE/feature_request.md +20 -20
  3. package/.github/release.yml +76 -0
  4. package/.github/workflows/ci.yml +75 -0
  5. package/.github/workflows/release.yml +103 -0
  6. package/.gitmodules +3 -3
  7. package/README.md +326 -280
  8. package/README_CN.md +325 -279
  9. package/dist/agents.d.ts.map +1 -1
  10. package/dist/agents.js +7 -3
  11. package/dist/agents.js.map +1 -1
  12. package/dist/ai-client/factory.d.ts +40 -0
  13. package/dist/ai-client/factory.d.ts.map +1 -0
  14. package/dist/ai-client/factory.js +100 -0
  15. package/dist/ai-client/factory.js.map +1 -0
  16. package/dist/ai-client/index.d.ts +20 -0
  17. package/dist/ai-client/index.d.ts.map +1 -0
  18. package/dist/ai-client/index.js +49 -0
  19. package/dist/ai-client/index.js.map +1 -0
  20. package/dist/ai-client/providers/anthropic.d.ts +57 -0
  21. package/dist/ai-client/providers/anthropic.d.ts.map +1 -0
  22. package/dist/ai-client/providers/anthropic.js +406 -0
  23. package/dist/ai-client/providers/anthropic.js.map +1 -0
  24. package/dist/ai-client/providers/openai.d.ts +57 -0
  25. package/dist/ai-client/providers/openai.d.ts.map +1 -0
  26. package/dist/ai-client/providers/openai.js +290 -0
  27. package/dist/ai-client/providers/openai.js.map +1 -0
  28. package/dist/ai-client/providers/remote.d.ts +110 -0
  29. package/dist/ai-client/providers/remote.d.ts.map +1 -0
  30. package/dist/ai-client/providers/remote.js +352 -0
  31. package/dist/ai-client/providers/remote.js.map +1 -0
  32. package/dist/ai-client/registry.d.ts +51 -0
  33. package/dist/ai-client/registry.d.ts.map +1 -0
  34. package/dist/ai-client/registry.js +81 -0
  35. package/dist/ai-client/registry.js.map +1 -0
  36. package/dist/ai-client/types.d.ts +274 -0
  37. package/dist/ai-client/types.d.ts.map +1 -0
  38. package/dist/ai-client/types.js +90 -0
  39. package/dist/ai-client/types.js.map +1 -0
  40. package/dist/ai-client-factory.d.ts +62 -0
  41. package/dist/ai-client-factory.d.ts.map +1 -0
  42. package/dist/ai-client-factory.js +157 -0
  43. package/dist/ai-client-factory.js.map +1 -0
  44. package/dist/auth.d.ts +23 -1
  45. package/dist/auth.d.ts.map +1 -1
  46. package/dist/auth.js +164 -174
  47. package/dist/auth.js.map +1 -1
  48. package/dist/cancellation.d.ts +5 -4
  49. package/dist/cancellation.d.ts.map +1 -1
  50. package/dist/cancellation.js +53 -32
  51. package/dist/cancellation.js.map +1 -1
  52. package/dist/checkpoint.d.ts +2 -1
  53. package/dist/checkpoint.d.ts.map +1 -1
  54. package/dist/checkpoint.js +39 -6
  55. package/dist/checkpoint.js.map +1 -1
  56. package/dist/cli.js +742 -29
  57. package/dist/cli.js.map +1 -1
  58. package/dist/config.d.ts +10 -4
  59. package/dist/config.d.ts.map +1 -1
  60. package/dist/config.js +62 -25
  61. package/dist/config.js.map +1 -1
  62. package/dist/context-compressor.d.ts +82 -18
  63. package/dist/context-compressor.d.ts.map +1 -1
  64. package/dist/context-compressor.js +718 -154
  65. package/dist/context-compressor.js.map +1 -1
  66. package/dist/conversation.d.ts +1 -1
  67. package/dist/conversation.d.ts.map +1 -1
  68. package/dist/conversation.js +8 -7
  69. package/dist/conversation.js.map +1 -1
  70. package/dist/gui-subagent/action-parser/actionParser.d.ts.map +1 -1
  71. package/dist/gui-subagent/action-parser/actionParser.js +6 -4
  72. package/dist/gui-subagent/action-parser/actionParser.js.map +1 -1
  73. package/dist/gui-subagent/agent/gui-agent.d.ts +39 -2
  74. package/dist/gui-subagent/agent/gui-agent.d.ts.map +1 -1
  75. package/dist/gui-subagent/agent/gui-agent.js +189 -74
  76. package/dist/gui-subagent/agent/gui-agent.js.map +1 -1
  77. package/dist/gui-subagent/index.d.ts +23 -1
  78. package/dist/gui-subagent/index.d.ts.map +1 -1
  79. package/dist/gui-subagent/index.js +6 -0
  80. package/dist/gui-subagent/index.js.map +1 -1
  81. package/dist/gui-subagent/operator/base-operator.d.ts.map +1 -1
  82. package/dist/gui-subagent/operator/base-operator.js +0 -1
  83. package/dist/gui-subagent/operator/base-operator.js.map +1 -1
  84. package/dist/gui-subagent/operator/computer-operator.d.ts.map +1 -1
  85. package/dist/gui-subagent/operator/computer-operator.js +31 -8
  86. package/dist/gui-subagent/operator/computer-operator.js.map +1 -1
  87. package/dist/gui-subagent/types/actions.d.ts +1 -1
  88. package/dist/gui-subagent/types/actions.d.ts.map +1 -1
  89. package/dist/gui-subagent/types/actions.js +0 -1
  90. package/dist/gui-subagent/types/actions.js.map +1 -1
  91. package/dist/gui-subagent/types/operator.d.ts +1 -1
  92. package/dist/gui-subagent/types/operator.d.ts.map +1 -1
  93. package/dist/index.d.ts +1 -2
  94. package/dist/index.d.ts.map +1 -1
  95. package/dist/index.js +1 -2
  96. package/dist/index.js.map +1 -1
  97. package/dist/input-processor.d.ts.map +1 -1
  98. package/dist/input-processor.js +8 -5
  99. package/dist/input-processor.js.map +1 -1
  100. package/dist/logger.d.ts.map +1 -1
  101. package/dist/logger.js +1 -1
  102. package/dist/logger.js.map +1 -1
  103. package/dist/mcp.d.ts +7 -1
  104. package/dist/mcp.d.ts.map +1 -1
  105. package/dist/mcp.js +157 -49
  106. package/dist/mcp.js.map +1 -1
  107. package/dist/memory.d.ts.map +1 -1
  108. package/dist/memory.js +3 -3
  109. package/dist/memory.js.map +1 -1
  110. package/dist/output-util.d.ts +27 -0
  111. package/dist/output-util.d.ts.map +1 -0
  112. package/dist/output-util.js +74 -0
  113. package/dist/output-util.js.map +1 -0
  114. package/dist/retry.js +1 -1
  115. package/dist/retry.js.map +1 -1
  116. package/dist/ripgrep.d.ts +29 -0
  117. package/dist/ripgrep.d.ts.map +1 -0
  118. package/dist/ripgrep.js +294 -0
  119. package/dist/ripgrep.js.map +1 -0
  120. package/dist/sdk-output-adapter.d.ts +34 -1
  121. package/dist/sdk-output-adapter.d.ts.map +1 -1
  122. package/dist/sdk-output-adapter.js +67 -2
  123. package/dist/sdk-output-adapter.js.map +1 -1
  124. package/dist/sdk-session.d.ts.map +1 -1
  125. package/dist/sdk-session.js +2 -0
  126. package/dist/sdk-session.js.map +1 -1
  127. package/dist/session-manager.js +3 -3
  128. package/dist/session-manager.js.map +1 -1
  129. package/dist/session.d.ts +116 -6
  130. package/dist/session.d.ts.map +1 -1
  131. package/dist/session.js +1416 -448
  132. package/dist/session.js.map +1 -1
  133. package/dist/shell.d.ts +33 -0
  134. package/dist/shell.d.ts.map +1 -0
  135. package/dist/shell.js +126 -0
  136. package/dist/shell.js.map +1 -0
  137. package/dist/skill-installer.d.ts +38 -0
  138. package/dist/skill-installer.d.ts.map +1 -0
  139. package/dist/skill-installer.js +447 -0
  140. package/dist/skill-installer.js.map +1 -0
  141. package/dist/skill-invoker.d.ts +8 -2
  142. package/dist/skill-invoker.d.ts.map +1 -1
  143. package/dist/skill-invoker.js +36 -15
  144. package/dist/skill-invoker.js.map +1 -1
  145. package/dist/skill-loader.d.ts +8 -3
  146. package/dist/skill-loader.d.ts.map +1 -1
  147. package/dist/skill-loader.js +51 -48
  148. package/dist/skill-loader.js.map +1 -1
  149. package/dist/skill-manager.d.ts +85 -0
  150. package/dist/skill-manager.d.ts.map +1 -0
  151. package/dist/skill-manager.js +341 -0
  152. package/dist/skill-manager.js.map +1 -0
  153. package/dist/slash-commands.d.ts +39 -2
  154. package/dist/slash-commands.d.ts.map +1 -1
  155. package/dist/slash-commands.js +934 -305
  156. package/dist/slash-commands.js.map +1 -1
  157. package/dist/smart-approval.d.ts +20 -1
  158. package/dist/smart-approval.d.ts.map +1 -1
  159. package/dist/smart-approval.js +125 -56
  160. package/dist/smart-approval.js.map +1 -1
  161. package/dist/system-prompt-generator.d.ts +6 -0
  162. package/dist/system-prompt-generator.d.ts.map +1 -1
  163. package/dist/system-prompt-generator.js +86 -36
  164. package/dist/system-prompt-generator.js.map +1 -1
  165. package/dist/terminal.d.ts +28 -0
  166. package/dist/terminal.d.ts.map +1 -0
  167. package/dist/terminal.js +82 -0
  168. package/dist/terminal.js.map +1 -0
  169. package/dist/theme.d.ts.map +1 -1
  170. package/dist/theme.js +8 -7
  171. package/dist/theme.js.map +1 -1
  172. package/dist/tools.d.ts +38 -7
  173. package/dist/tools.d.ts.map +1 -1
  174. package/dist/tools.js +1249 -617
  175. package/dist/tools.js.map +1 -1
  176. package/dist/truncate.d.ts +55 -0
  177. package/dist/truncate.d.ts.map +1 -0
  178. package/dist/truncate.js +130 -0
  179. package/dist/truncate.js.map +1 -0
  180. package/dist/types.d.ts +84 -9
  181. package/dist/types.d.ts.map +1 -1
  182. package/dist/types.js +49 -0
  183. package/dist/types.js.map +1 -1
  184. package/dist/update.d.ts.map +1 -1
  185. package/dist/update.js +28 -36
  186. package/dist/update.js.map +1 -1
  187. package/dist/workflow.d.ts +5 -1
  188. package/dist/workflow.d.ts.map +1 -1
  189. package/dist/workflow.js +61 -49
  190. package/dist/workflow.js.map +1 -1
  191. package/docs/architecture/mcp-integration-guide.md +304 -194
  192. package/docs/architecture/overview.md +169 -169
  193. package/docs/architecture/tool-system-design.md +134 -134
  194. package/docs/cli/commands.md +349 -238
  195. package/docs/smart-mode.md +281 -281
  196. package/docs/third-party-models.md +440 -439
  197. package/find-skills/SKILL.md +133 -0
  198. package/package.json +91 -90
  199. package/scripts/install-ripgrep.js +241 -0
  200. package/src/agents.ts +7 -3
  201. package/src/ai-client/factory.ts +116 -0
  202. package/src/ai-client/index.ts +61 -0
  203. package/src/ai-client/providers/anthropic.ts +475 -0
  204. package/src/ai-client/providers/openai.ts +348 -0
  205. package/src/ai-client/providers/remote.ts +439 -0
  206. package/src/ai-client/registry.ts +97 -0
  207. package/src/ai-client/types.ts +364 -0
  208. package/src/ai-client-factory.ts +204 -0
  209. package/src/auth.ts +661 -614
  210. package/src/cancellation.ts +202 -176
  211. package/src/checkpoint.ts +255 -219
  212. package/src/cli.ts +1523 -743
  213. package/src/config.ts +341 -297
  214. package/src/context-compressor.ts +987 -290
  215. package/src/conversation.ts +290 -288
  216. package/src/gui-subagent/action-parser/actionParser.ts +318 -315
  217. package/src/gui-subagent/action-parser/constants.ts +14 -14
  218. package/src/gui-subagent/action-parser/index.ts +8 -8
  219. package/src/gui-subagent/action-parser/types.ts +31 -31
  220. package/src/gui-subagent/agent/gui-agent.ts +1234 -1089
  221. package/src/gui-subagent/agent/index.ts +5 -5
  222. package/src/gui-subagent/index.ts +185 -163
  223. package/src/gui-subagent/operator/base-operator.ts +244 -245
  224. package/src/gui-subagent/operator/computer-operator.ts +541 -520
  225. package/src/gui-subagent/operator/index.ts +6 -6
  226. package/src/gui-subagent/types/actions.ts +260 -262
  227. package/src/gui-subagent/types/index.ts +6 -6
  228. package/src/gui-subagent/types/operator.ts +106 -106
  229. package/src/gui-subagent/utils.ts +51 -51
  230. package/src/index.ts +17 -18
  231. package/src/input-processor.ts +8 -5
  232. package/src/logger.ts +436 -438
  233. package/src/mcp.ts +793 -682
  234. package/src/memory.ts +343 -344
  235. package/src/output-util.ts +80 -0
  236. package/src/retry.ts +1 -1
  237. package/src/ripgrep.ts +370 -0
  238. package/src/sdk-output-adapter.ts +842 -0
  239. package/src/sdk-session.ts +62 -0
  240. package/src/session-manager.ts +308 -308
  241. package/src/session.ts +1775 -573
  242. package/src/shell.ts +134 -0
  243. package/src/skill-installer.ts +518 -0
  244. package/src/skill-invoker.ts +959 -935
  245. package/src/skill-loader.ts +501 -496
  246. package/src/skill-manager.ts +385 -0
  247. package/src/slash-commands.ts +2189 -1389
  248. package/src/smart-approval.ts +193 -74
  249. package/src/system-prompt-generator.ts +91 -36
  250. package/src/terminal.ts +96 -0
  251. package/src/theme.ts +739 -738
  252. package/src/tools.ts +1790 -931
  253. package/src/truncate.ts +173 -0
  254. package/src/types.ts +337 -198
  255. package/src/update.ts +33 -40
  256. package/src/workflow.ts +521 -508
  257. package/test/cli-launch.test.ts +279 -0
  258. package/tsconfig.json +22 -22
  259. package/vitest.config.ts +21 -19
  260. package/dist/ai-client.d.ts +0 -86
  261. package/dist/ai-client.d.ts.map +0 -1
  262. package/dist/ai-client.js +0 -1372
  263. package/dist/ai-client.js.map +0 -1
  264. package/dist/gui-subagent/operator/browser-operator.d.ts +0 -36
  265. package/dist/gui-subagent/operator/browser-operator.d.ts.map +0 -1
  266. package/dist/gui-subagent/operator/browser-operator.js +0 -306
  267. package/dist/gui-subagent/operator/browser-operator.js.map +0 -1
  268. package/dist/gui-subagent/operator/desktop-operator.d.ts +0 -55
  269. package/dist/gui-subagent/operator/desktop-operator.d.ts.map +0 -1
  270. package/dist/gui-subagent/operator/desktop-operator.js +0 -527
  271. package/dist/gui-subagent/operator/desktop-operator.js.map +0 -1
  272. package/dist/hook.d.ts +0 -73
  273. package/dist/hook.d.ts.map +0 -1
  274. package/dist/hook.js +0 -156
  275. package/dist/hook.js.map +0 -1
  276. package/dist/input-history.d.ts +0 -24
  277. package/dist/input-history.d.ts.map +0 -1
  278. package/dist/input-history.js +0 -94
  279. package/dist/input-history.js.map +0 -1
  280. package/dist/keyboard-manager.d.ts +0 -151
  281. package/dist/keyboard-manager.d.ts.map +0 -1
  282. package/dist/keyboard-manager.js +0 -396
  283. package/dist/keyboard-manager.js.map +0 -1
  284. package/dist/print-system-prompt.d.ts +0 -2
  285. package/dist/print-system-prompt.d.ts.map +0 -1
  286. package/dist/print-system-prompt.js +0 -40
  287. package/dist/print-system-prompt.js.map +0 -1
  288. package/dist/remote-ai-client.d.ts +0 -104
  289. package/dist/remote-ai-client.d.ts.map +0 -1
  290. package/dist/remote-ai-client.js +0 -552
  291. package/dist/remote-ai-client.js.map +0 -1
  292. package/dist/sdk-session-v2.d.ts +0 -13
  293. package/dist/sdk-session-v2.d.ts.map +0 -1
  294. package/dist/sdk-session-v2.js +0 -46
  295. package/dist/sdk-session-v2.js.map +0 -1
  296. package/dist/test-boundary-conditions.d.ts.map +0 -1
  297. package/dist/test-boundary-conditions.js.map +0 -1
  298. package/dist/test-cancellation-fix.d.ts.map +0 -1
  299. package/dist/test-cancellation-fix.js.map +0 -1
  300. package/dist/test-input-history.d.ts.map +0 -1
  301. package/dist/test-input-history.js.map +0 -1
  302. package/dist/test-interaction-flow.d.ts.map +0 -1
  303. package/dist/test-interaction-flow.js.map +0 -1
  304. package/dist/test-quick.d.ts.map +0 -1
  305. package/dist/test-quick.js.map +0 -1
  306. package/dist/test-user-interaction.d.ts.map +0 -1
  307. package/dist/test-user-interaction.js.map +0 -1
  308. package/dist/tools/edit-diff.d.ts +0 -32
  309. package/dist/tools/edit-diff.d.ts.map +0 -1
  310. package/dist/tools/edit-diff.js +0 -185
  311. package/dist/tools/edit-diff.js.map +0 -1
  312. package/dist/tools/edit.d.ts +0 -11
  313. package/dist/tools/edit.d.ts.map +0 -1
  314. package/dist/tools/edit.js +0 -129
  315. package/dist/tools/edit.js.map +0 -1
  316. package/dist/unified-session.d.ts +0 -42
  317. package/dist/unified-session.d.ts.map +0 -1
  318. package/dist/unified-session.js +0 -271
  319. package/dist/unified-session.js.map +0 -1
  320. package/skills/.claude-plugin/marketplace.json +0 -45
  321. package/skills/README.md +0 -94
  322. package/skills/THIRD_PARTY_NOTICES.md +0 -405
  323. package/skills/skills/algorithmic-art/LICENSE.txt +0 -202
  324. package/skills/skills/algorithmic-art/SKILL.md +0 -405
  325. package/skills/skills/algorithmic-art/templates/generator_template.js +0 -223
  326. package/skills/skills/algorithmic-art/templates/viewer.html +0 -599
  327. package/skills/skills/brand-guidelines/LICENSE.txt +0 -202
  328. package/skills/skills/brand-guidelines/SKILL.md +0 -73
  329. package/skills/skills/canvas-design/LICENSE.txt +0 -202
  330. package/skills/skills/canvas-design/SKILL.md +0 -130
  331. package/skills/skills/canvas-design/canvas-fonts/ArsenalSC-OFL.txt +0 -93
  332. package/skills/skills/canvas-design/canvas-fonts/ArsenalSC-Regular.ttf +0 -0
  333. package/skills/skills/canvas-design/canvas-fonts/BigShoulders-Bold.ttf +0 -0
  334. package/skills/skills/canvas-design/canvas-fonts/BigShoulders-OFL.txt +0 -93
  335. package/skills/skills/canvas-design/canvas-fonts/BigShoulders-Regular.ttf +0 -0
  336. package/skills/skills/canvas-design/canvas-fonts/Boldonse-OFL.txt +0 -93
  337. package/skills/skills/canvas-design/canvas-fonts/Boldonse-Regular.ttf +0 -0
  338. package/skills/skills/canvas-design/canvas-fonts/BricolageGrotesque-Bold.ttf +0 -0
  339. package/skills/skills/canvas-design/canvas-fonts/BricolageGrotesque-OFL.txt +0 -93
  340. package/skills/skills/canvas-design/canvas-fonts/BricolageGrotesque-Regular.ttf +0 -0
  341. package/skills/skills/canvas-design/canvas-fonts/CrimsonPro-Bold.ttf +0 -0
  342. package/skills/skills/canvas-design/canvas-fonts/CrimsonPro-Italic.ttf +0 -0
  343. package/skills/skills/canvas-design/canvas-fonts/CrimsonPro-OFL.txt +0 -93
  344. package/skills/skills/canvas-design/canvas-fonts/CrimsonPro-Regular.ttf +0 -0
  345. package/skills/skills/canvas-design/canvas-fonts/DMMono-OFL.txt +0 -93
  346. package/skills/skills/canvas-design/canvas-fonts/DMMono-Regular.ttf +0 -0
  347. package/skills/skills/canvas-design/canvas-fonts/EricaOne-OFL.txt +0 -94
  348. package/skills/skills/canvas-design/canvas-fonts/EricaOne-Regular.ttf +0 -0
  349. package/skills/skills/canvas-design/canvas-fonts/GeistMono-Bold.ttf +0 -0
  350. package/skills/skills/canvas-design/canvas-fonts/GeistMono-OFL.txt +0 -93
  351. package/skills/skills/canvas-design/canvas-fonts/GeistMono-Regular.ttf +0 -0
  352. package/skills/skills/canvas-design/canvas-fonts/Gloock-OFL.txt +0 -93
  353. package/skills/skills/canvas-design/canvas-fonts/Gloock-Regular.ttf +0 -0
  354. package/skills/skills/canvas-design/canvas-fonts/IBMPlexMono-Bold.ttf +0 -0
  355. package/skills/skills/canvas-design/canvas-fonts/IBMPlexMono-OFL.txt +0 -93
  356. package/skills/skills/canvas-design/canvas-fonts/IBMPlexMono-Regular.ttf +0 -0
  357. package/skills/skills/canvas-design/canvas-fonts/IBMPlexSerif-Bold.ttf +0 -0
  358. package/skills/skills/canvas-design/canvas-fonts/IBMPlexSerif-BoldItalic.ttf +0 -0
  359. package/skills/skills/canvas-design/canvas-fonts/IBMPlexSerif-Italic.ttf +0 -0
  360. package/skills/skills/canvas-design/canvas-fonts/IBMPlexSerif-Regular.ttf +0 -0
  361. package/skills/skills/canvas-design/canvas-fonts/InstrumentSans-Bold.ttf +0 -0
  362. package/skills/skills/canvas-design/canvas-fonts/InstrumentSans-BoldItalic.ttf +0 -0
  363. package/skills/skills/canvas-design/canvas-fonts/InstrumentSans-Italic.ttf +0 -0
  364. package/skills/skills/canvas-design/canvas-fonts/InstrumentSans-OFL.txt +0 -93
  365. package/skills/skills/canvas-design/canvas-fonts/InstrumentSans-Regular.ttf +0 -0
  366. package/skills/skills/canvas-design/canvas-fonts/InstrumentSerif-Italic.ttf +0 -0
  367. package/skills/skills/canvas-design/canvas-fonts/InstrumentSerif-Regular.ttf +0 -0
  368. package/skills/skills/canvas-design/canvas-fonts/Italiana-OFL.txt +0 -93
  369. package/skills/skills/canvas-design/canvas-fonts/Italiana-Regular.ttf +0 -0
  370. package/skills/skills/canvas-design/canvas-fonts/JetBrainsMono-Bold.ttf +0 -0
  371. package/skills/skills/canvas-design/canvas-fonts/JetBrainsMono-OFL.txt +0 -93
  372. package/skills/skills/canvas-design/canvas-fonts/JetBrainsMono-Regular.ttf +0 -0
  373. package/skills/skills/canvas-design/canvas-fonts/Jura-Light.ttf +0 -0
  374. package/skills/skills/canvas-design/canvas-fonts/Jura-Medium.ttf +0 -0
  375. package/skills/skills/canvas-design/canvas-fonts/Jura-OFL.txt +0 -93
  376. package/skills/skills/canvas-design/canvas-fonts/LibreBaskerville-OFL.txt +0 -93
  377. package/skills/skills/canvas-design/canvas-fonts/LibreBaskerville-Regular.ttf +0 -0
  378. package/skills/skills/canvas-design/canvas-fonts/Lora-Bold.ttf +0 -0
  379. package/skills/skills/canvas-design/canvas-fonts/Lora-BoldItalic.ttf +0 -0
  380. package/skills/skills/canvas-design/canvas-fonts/Lora-Italic.ttf +0 -0
  381. package/skills/skills/canvas-design/canvas-fonts/Lora-OFL.txt +0 -93
  382. package/skills/skills/canvas-design/canvas-fonts/Lora-Regular.ttf +0 -0
  383. package/skills/skills/canvas-design/canvas-fonts/NationalPark-Bold.ttf +0 -0
  384. package/skills/skills/canvas-design/canvas-fonts/NationalPark-OFL.txt +0 -93
  385. package/skills/skills/canvas-design/canvas-fonts/NationalPark-Regular.ttf +0 -0
  386. package/skills/skills/canvas-design/canvas-fonts/NothingYouCouldDo-OFL.txt +0 -93
  387. package/skills/skills/canvas-design/canvas-fonts/NothingYouCouldDo-Regular.ttf +0 -0
  388. package/skills/skills/canvas-design/canvas-fonts/Outfit-Bold.ttf +0 -0
  389. package/skills/skills/canvas-design/canvas-fonts/Outfit-OFL.txt +0 -93
  390. package/skills/skills/canvas-design/canvas-fonts/Outfit-Regular.ttf +0 -0
  391. package/skills/skills/canvas-design/canvas-fonts/PixelifySans-Medium.ttf +0 -0
  392. package/skills/skills/canvas-design/canvas-fonts/PixelifySans-OFL.txt +0 -93
  393. package/skills/skills/canvas-design/canvas-fonts/PoiretOne-OFL.txt +0 -93
  394. package/skills/skills/canvas-design/canvas-fonts/PoiretOne-Regular.ttf +0 -0
  395. package/skills/skills/canvas-design/canvas-fonts/RedHatMono-Bold.ttf +0 -0
  396. package/skills/skills/canvas-design/canvas-fonts/RedHatMono-OFL.txt +0 -93
  397. package/skills/skills/canvas-design/canvas-fonts/RedHatMono-Regular.ttf +0 -0
  398. package/skills/skills/canvas-design/canvas-fonts/Silkscreen-OFL.txt +0 -93
  399. package/skills/skills/canvas-design/canvas-fonts/Silkscreen-Regular.ttf +0 -0
  400. package/skills/skills/canvas-design/canvas-fonts/SmoochSans-Medium.ttf +0 -0
  401. package/skills/skills/canvas-design/canvas-fonts/SmoochSans-OFL.txt +0 -93
  402. package/skills/skills/canvas-design/canvas-fonts/Tektur-Medium.ttf +0 -0
  403. package/skills/skills/canvas-design/canvas-fonts/Tektur-OFL.txt +0 -93
  404. package/skills/skills/canvas-design/canvas-fonts/Tektur-Regular.ttf +0 -0
  405. package/skills/skills/canvas-design/canvas-fonts/WorkSans-Bold.ttf +0 -0
  406. package/skills/skills/canvas-design/canvas-fonts/WorkSans-BoldItalic.ttf +0 -0
  407. package/skills/skills/canvas-design/canvas-fonts/WorkSans-Italic.ttf +0 -0
  408. package/skills/skills/canvas-design/canvas-fonts/WorkSans-OFL.txt +0 -93
  409. package/skills/skills/canvas-design/canvas-fonts/WorkSans-Regular.ttf +0 -0
  410. package/skills/skills/canvas-design/canvas-fonts/YoungSerif-OFL.txt +0 -93
  411. package/skills/skills/canvas-design/canvas-fonts/YoungSerif-Regular.ttf +0 -0
  412. package/skills/skills/doc-coauthoring/SKILL.md +0 -375
  413. package/skills/skills/docx/LICENSE.txt +0 -30
  414. package/skills/skills/docx/SKILL.md +0 -197
  415. package/skills/skills/docx/docx-js.md +0 -350
  416. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -1499
  417. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -146
  418. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -1085
  419. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -11
  420. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -3081
  421. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -23
  422. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -185
  423. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -287
  424. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -1676
  425. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -28
  426. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -144
  427. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -174
  428. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -25
  429. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -18
  430. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -59
  431. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -56
  432. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -195
  433. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -582
  434. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -25
  435. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -4439
  436. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -570
  437. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -509
  438. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -12
  439. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -108
  440. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -96
  441. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -3646
  442. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -116
  443. package/skills/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -42
  444. package/skills/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -50
  445. package/skills/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -49
  446. package/skills/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -33
  447. package/skills/skills/docx/ooxml/schemas/mce/mc.xsd +0 -75
  448. package/skills/skills/docx/ooxml/schemas/microsoft/wml-2010.xsd +0 -560
  449. package/skills/skills/docx/ooxml/schemas/microsoft/wml-2012.xsd +0 -67
  450. package/skills/skills/docx/ooxml/schemas/microsoft/wml-2018.xsd +0 -14
  451. package/skills/skills/docx/ooxml/schemas/microsoft/wml-cex-2018.xsd +0 -20
  452. package/skills/skills/docx/ooxml/schemas/microsoft/wml-cid-2016.xsd +0 -13
  453. package/skills/skills/docx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -4
  454. package/skills/skills/docx/ooxml/schemas/microsoft/wml-symex-2015.xsd +0 -8
  455. package/skills/skills/docx/ooxml/scripts/pack.py +0 -159
  456. package/skills/skills/docx/ooxml/scripts/unpack.py +0 -29
  457. package/skills/skills/docx/ooxml/scripts/validate.py +0 -69
  458. package/skills/skills/docx/ooxml/scripts/validation/__init__.py +0 -15
  459. package/skills/skills/docx/ooxml/scripts/validation/base.py +0 -951
  460. package/skills/skills/docx/ooxml/scripts/validation/docx.py +0 -274
  461. package/skills/skills/docx/ooxml/scripts/validation/pptx.py +0 -315
  462. package/skills/skills/docx/ooxml/scripts/validation/redlining.py +0 -279
  463. package/skills/skills/docx/ooxml.md +0 -610
  464. package/skills/skills/docx/scripts/__init__.py +0 -1
  465. package/skills/skills/docx/scripts/document.py +0 -1276
  466. package/skills/skills/docx/scripts/templates/comments.xml +0 -3
  467. package/skills/skills/docx/scripts/templates/commentsExtended.xml +0 -3
  468. package/skills/skills/docx/scripts/templates/commentsExtensible.xml +0 -3
  469. package/skills/skills/docx/scripts/templates/commentsIds.xml +0 -3
  470. package/skills/skills/docx/scripts/templates/people.xml +0 -3
  471. package/skills/skills/docx/scripts/utilities.py +0 -374
  472. package/skills/skills/frontend-design/LICENSE.txt +0 -177
  473. package/skills/skills/frontend-design/SKILL.md +0 -42
  474. package/skills/skills/internal-comms/LICENSE.txt +0 -202
  475. package/skills/skills/internal-comms/SKILL.md +0 -32
  476. package/skills/skills/internal-comms/examples/3p-updates.md +0 -47
  477. package/skills/skills/internal-comms/examples/company-newsletter.md +0 -65
  478. package/skills/skills/internal-comms/examples/faq-answers.md +0 -30
  479. package/skills/skills/internal-comms/examples/general-comms.md +0 -16
  480. package/skills/skills/mcp-builder/LICENSE.txt +0 -202
  481. package/skills/skills/mcp-builder/SKILL.md +0 -236
  482. package/skills/skills/mcp-builder/reference/evaluation.md +0 -602
  483. package/skills/skills/mcp-builder/reference/mcp_best_practices.md +0 -249
  484. package/skills/skills/mcp-builder/reference/node_mcp_server.md +0 -970
  485. package/skills/skills/mcp-builder/reference/python_mcp_server.md +0 -719
  486. package/skills/skills/mcp-builder/scripts/connections.py +0 -151
  487. package/skills/skills/mcp-builder/scripts/evaluation.py +0 -373
  488. package/skills/skills/mcp-builder/scripts/example_evaluation.xml +0 -22
  489. package/skills/skills/mcp-builder/scripts/requirements.txt +0 -2
  490. package/skills/skills/pdf/LICENSE.txt +0 -30
  491. package/skills/skills/pdf/SKILL.md +0 -294
  492. package/skills/skills/pdf/forms.md +0 -205
  493. package/skills/skills/pdf/reference.md +0 -612
  494. package/skills/skills/pdf/scripts/check_bounding_boxes.py +0 -70
  495. package/skills/skills/pdf/scripts/check_bounding_boxes_test.py +0 -226
  496. package/skills/skills/pdf/scripts/check_fillable_fields.py +0 -12
  497. package/skills/skills/pdf/scripts/convert_pdf_to_images.py +0 -35
  498. package/skills/skills/pdf/scripts/create_validation_image.py +0 -41
  499. package/skills/skills/pdf/scripts/extract_form_field_info.py +0 -152
  500. package/skills/skills/pdf/scripts/fill_fillable_fields.py +0 -114
  501. package/skills/skills/pdf/scripts/fill_pdf_form_with_annotations.py +0 -108
  502. package/skills/skills/pptx/LICENSE.txt +0 -30
  503. package/skills/skills/pptx/SKILL.md +0 -484
  504. package/skills/skills/pptx/html2pptx.md +0 -625
  505. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -1499
  506. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -146
  507. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -1085
  508. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -11
  509. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -3081
  510. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -23
  511. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -185
  512. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -287
  513. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -1676
  514. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -28
  515. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -144
  516. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -174
  517. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -25
  518. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -18
  519. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -59
  520. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -56
  521. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -195
  522. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -582
  523. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -25
  524. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -4439
  525. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -570
  526. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -509
  527. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -12
  528. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -108
  529. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -96
  530. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -3646
  531. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -116
  532. package/skills/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -42
  533. package/skills/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -50
  534. package/skills/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -49
  535. package/skills/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -33
  536. package/skills/skills/pptx/ooxml/schemas/mce/mc.xsd +0 -75
  537. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-2010.xsd +0 -560
  538. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-2012.xsd +0 -67
  539. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-2018.xsd +0 -14
  540. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-cex-2018.xsd +0 -20
  541. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-cid-2016.xsd +0 -13
  542. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -4
  543. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-symex-2015.xsd +0 -8
  544. package/skills/skills/pptx/ooxml/scripts/pack.py +0 -159
  545. package/skills/skills/pptx/ooxml/scripts/unpack.py +0 -29
  546. package/skills/skills/pptx/ooxml/scripts/validate.py +0 -69
  547. package/skills/skills/pptx/ooxml/scripts/validation/__init__.py +0 -15
  548. package/skills/skills/pptx/ooxml/scripts/validation/base.py +0 -951
  549. package/skills/skills/pptx/ooxml/scripts/validation/docx.py +0 -274
  550. package/skills/skills/pptx/ooxml/scripts/validation/pptx.py +0 -315
  551. package/skills/skills/pptx/ooxml/scripts/validation/redlining.py +0 -279
  552. package/skills/skills/pptx/ooxml.md +0 -427
  553. package/skills/skills/pptx/scripts/html2pptx.js +0 -979
  554. package/skills/skills/pptx/scripts/inventory.py +0 -1020
  555. package/skills/skills/pptx/scripts/rearrange.py +0 -231
  556. package/skills/skills/pptx/scripts/replace.py +0 -385
  557. package/skills/skills/pptx/scripts/thumbnail.py +0 -450
  558. package/skills/skills/skill-creator/LICENSE.txt +0 -202
  559. package/skills/skills/skill-creator/SKILL.md +0 -356
  560. package/skills/skills/skill-creator/references/output-patterns.md +0 -82
  561. package/skills/skills/skill-creator/references/workflows.md +0 -28
  562. package/skills/skills/skill-creator/scripts/init_skill.py +0 -303
  563. package/skills/skills/skill-creator/scripts/package_skill.py +0 -110
  564. package/skills/skills/skill-creator/scripts/quick_validate.py +0 -95
  565. package/skills/skills/slack-gif-creator/LICENSE.txt +0 -202
  566. package/skills/skills/slack-gif-creator/SKILL.md +0 -254
  567. package/skills/skills/slack-gif-creator/core/easing.py +0 -234
  568. package/skills/skills/slack-gif-creator/core/frame_composer.py +0 -176
  569. package/skills/skills/slack-gif-creator/core/gif_builder.py +0 -269
  570. package/skills/skills/slack-gif-creator/core/validators.py +0 -136
  571. package/skills/skills/slack-gif-creator/requirements.txt +0 -4
  572. package/skills/skills/theme-factory/LICENSE.txt +0 -202
  573. package/skills/skills/theme-factory/SKILL.md +0 -59
  574. package/skills/skills/theme-factory/theme-showcase.pdf +0 -0
  575. package/skills/skills/theme-factory/themes/arctic-frost.md +0 -19
  576. package/skills/skills/theme-factory/themes/botanical-garden.md +0 -19
  577. package/skills/skills/theme-factory/themes/desert-rose.md +0 -19
  578. package/skills/skills/theme-factory/themes/forest-canopy.md +0 -19
  579. package/skills/skills/theme-factory/themes/golden-hour.md +0 -19
  580. package/skills/skills/theme-factory/themes/midnight-galaxy.md +0 -19
  581. package/skills/skills/theme-factory/themes/modern-minimalist.md +0 -19
  582. package/skills/skills/theme-factory/themes/ocean-depths.md +0 -19
  583. package/skills/skills/theme-factory/themes/sunset-boulevard.md +0 -19
  584. package/skills/skills/theme-factory/themes/tech-innovation.md +0 -19
  585. package/skills/skills/web-artifacts-builder/LICENSE.txt +0 -202
  586. package/skills/skills/web-artifacts-builder/SKILL.md +0 -74
  587. package/skills/skills/web-artifacts-builder/scripts/bundle-artifact.sh +0 -54
  588. package/skills/skills/web-artifacts-builder/scripts/init-artifact.sh +0 -322
  589. package/skills/skills/webapp-testing/LICENSE.txt +0 -202
  590. package/skills/skills/webapp-testing/SKILL.md +0 -96
  591. package/skills/skills/webapp-testing/examples/console_logging.py +0 -35
  592. package/skills/skills/webapp-testing/examples/element_discovery.py +0 -40
  593. package/skills/skills/webapp-testing/examples/static_html_automation.py +0 -33
  594. package/skills/skills/webapp-testing/scripts/with_server.py +0 -106
  595. package/skills/skills/xlsx/LICENSE.txt +0 -30
  596. package/skills/skills/xlsx/SKILL.md +0 -289
  597. package/skills/skills/xlsx/recalc.py +0 -178
  598. package/skills/spec/agent-skills-spec.md +0 -3
  599. package/skills/template/SKILL.md +0 -6
  600. package/src/ai-client.ts +0 -1560
  601. package/src/remote-ai-client.ts +0 -664
  602. /package/{.eslintrc.js → .eslintrc.cjs} +0 -0
@@ -1,497 +1,502 @@
1
- import fs from 'fs/promises';
2
- import fsSync from 'fs';
3
- import path from 'path';
4
- import { fileURLToPath } from 'url';
5
- import { WorkflowConfig } from './workflow.js';
6
- import { getConfigManager } from './config.js';
7
-
8
- export interface SkillInfo {
9
- id: string;
10
- name: string;
11
- description: string;
12
- license: string;
13
- version: string;
14
- author: string;
15
- category: string;
16
- markdown: string;
17
- skillsPath: string;
18
- }
19
-
20
- export interface SkillLoaderConfig {
21
- skillsRootPath?: string;
22
- onError?: (error: SkillLoadError) => void;
23
- onWarning?: (warning: SkillLoadWarning) => void;
24
- }
25
-
26
- export interface SkillLoadError {
27
- skillId?: string;
28
- path: string;
29
- error: Error;
30
- phase: 'directory_read' | 'file_read' | 'parse_markdown';
31
- }
32
-
33
- export interface SkillLoadWarning {
34
- skillId?: string;
35
- path: string;
36
- warning: string;
37
- reason?: string;
38
- }
39
-
40
- export class SkillLoader {
41
- private skillsRootPath: string;
42
- private loadedSkills: Map<string, SkillInfo> = new Map();
43
- private skillDirectories: Map<string, string> = new Map(); // skillId -> path mapping
44
- private errorCallback?: (error: SkillLoadError) => void;
45
- private warningCallback?: (warning: SkillLoadWarning) => void;
46
- private loadStats: {
47
- totalFound: number;
48
- successfullyLoaded: number;
49
- failed: number;
50
- errors: SkillLoadError[];
51
- } = { totalFound: 0, successfullyLoaded: 0, failed: 0, errors: [] };
52
-
53
- constructor(config?: SkillLoaderConfig) {
54
- if (config?.skillsRootPath) {
55
- // Explicit path provided
56
- this.skillsRootPath = config.skillsRootPath;
57
- } else {
58
- // Try to get from config first
59
- const configManager = getConfigManager();
60
- const configuredPath = configManager.getSkillsPath();
61
-
62
- if (configuredPath) {
63
- this.skillsRootPath = configuredPath;
64
- } else {
65
- // Fallback: auto-detect from script location
66
- this.skillsRootPath = this.detectSkillsPath();
67
- }
68
- }
69
-
70
- // Set error and warning callbacks
71
- this.errorCallback = config?.onError;
72
- this.warningCallback = config?.onWarning;
73
- }
74
-
75
- private detectSkillsPath(): string {
76
- // Skills folder is always at {xagent_root}/skills/skills
77
- return path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', 'skills', 'skills');
78
- }
79
-
80
- async loadAllSkills(): Promise<SkillInfo[]> {
81
- const skills: SkillInfo[] = [];
82
-
83
- // Reset stats
84
- this.loadStats = { totalFound: 0, successfullyLoaded: 0, failed: 0, errors: [] };
85
-
86
- try {
87
- const categories = await fs.readdir(this.skillsRootPath, { withFileTypes: true });
88
-
89
- // First pass: discover all skill directories
90
- const skillDirs: { path: string; category: string }[] = [];
91
- for (const category of categories) {
92
- if (category.isDirectory()) {
93
- const categoryPath = path.join(this.skillsRootPath, category.name);
94
- skillDirs.push({ path: categoryPath, category: category.name });
95
- this.loadStats.totalFound++;
96
- }
97
- }
98
-
99
- // Second pass: load skills (can be parallelized)
100
- const loadPromises = skillDirs.map(async ({ path: skillPath, category }) => {
101
- const skillInfo = await this.loadSkillFromPath(skillPath, category);
102
- if (skillInfo) {
103
- this.loadedSkills.set(skillInfo.id, skillInfo);
104
- this.skillDirectories.set(skillInfo.id, skillPath);
105
- this.loadStats.successfullyLoaded++;
106
- return skillInfo;
107
- } else {
108
- this.loadStats.failed++;
109
- return null;
110
- }
111
- });
112
-
113
- const results = await Promise.all(loadPromises);
114
- for (const skill of results) {
115
- if (skill) skills.push(skill);
116
- }
117
-
118
- // Log summary if there were errors
119
- if (this.loadStats.failed > 0) {
120
- const errorMsg = `Loaded ${this.loadStats.successfullyLoaded}/${this.loadStats.totalFound} skills, ${this.loadStats.failed} failed`;
121
- if (this.warningCallback) {
122
- this.warningCallback({
123
- skillId: undefined,
124
- path: this.skillsRootPath,
125
- warning: errorMsg,
126
- reason: `${this.loadStats.errors.length} parsing errors`
127
- });
128
- } else {
129
- console.warn(`[SkillLoader] ${errorMsg}`);
130
- }
131
- }
132
-
133
- } catch (error) {
134
- const loadError: SkillLoadError = {
135
- skillId: undefined,
136
- path: this.skillsRootPath,
137
- error: error as Error,
138
- phase: 'directory_read'
139
- };
140
- this.loadStats.errors.push(loadError);
141
-
142
- if (this.errorCallback) {
143
- this.errorCallback(loadError);
144
- } else {
145
- console.error(`[SkillLoader] Failed to load skills from ${this.skillsRootPath}:`, error);
146
- }
147
- }
148
-
149
- return skills;
150
- }
151
-
152
- /**
153
- * Lazy load a single skill by ID - only loads when needed
154
- * This is the key optimization for on-demand loading
155
- */
156
- async loadSkill(skillId: string): Promise<SkillInfo | null> {
157
- // Return from cache if already loaded
158
- const cached = this.loadedSkills.get(skillId);
159
- if (cached) return cached;
160
-
161
- // Try to find and load the specific skill
162
- const skillPath = this.skillDirectories.get(skillId);
163
- if (skillPath) {
164
- const skillInfo = await this.loadSkillFromPath(skillPath, '');
165
- if (skillInfo) {
166
- this.loadedSkills.set(skillInfo.id, skillInfo);
167
- return skillInfo;
168
- }
169
- }
170
-
171
- // Fallback: search in skills root directory
172
- return this.loadSkillBySearching(skillId);
173
- }
174
-
175
- /**
176
- * Search for a skill by ID in the skills root directory
177
- */
178
- private async loadSkillBySearching(skillId: string): Promise<SkillInfo | null> {
179
- try {
180
- const categories = await fs.readdir(this.skillsRootPath, { withFileTypes: true });
181
-
182
- for (const category of categories) {
183
- if (category.isDirectory()) {
184
- const categoryPath = path.join(this.skillsRootPath, category.name);
185
- const skillMdPath = path.join(categoryPath, 'SKILL.md');
186
-
187
- try {
188
- const content = await fs.readFile(skillMdPath, 'utf-8');
189
- const parsed = this._parseSkillMarkdown(content);
190
-
191
- if (parsed.name === skillId) {
192
- this.skillDirectories.set(skillId, categoryPath);
193
- const skillInfo: SkillInfo = {
194
- id: parsed.name,
195
- name: parsed.name,
196
- description: parsed.description,
197
- license: parsed.license || 'Unknown',
198
- version: parsed.version || '1.0.0',
199
- author: parsed.author || 'Anonymous',
200
- category: category.name,
201
- markdown: content,
202
- skillsPath: categoryPath
203
- };
204
- this.loadedSkills.set(skillId, skillInfo);
205
- return skillInfo;
206
- }
207
- } catch {
208
- // Continue searching
209
- continue;
210
- }
211
- }
212
- }
213
- } catch (error) {
214
- const loadError: SkillLoadError = {
215
- skillId,
216
- path: this.skillsRootPath,
217
- error: error as Error,
218
- phase: 'directory_read'
219
- };
220
- this.handleError(loadError);
221
- }
222
-
223
- return null;
224
- }
225
-
226
- /**
227
- * Pre-discover skill directories without loading content
228
- * This allows faster subsequent lazy loading
229
- */
230
- async discoverSkills(): Promise<string[]> {
231
- const skillIds: string[] = [];
232
-
233
- try {
234
- const categories = await fs.readdir(this.skillsRootPath, { withFileTypes: true });
235
-
236
- for (const category of categories) {
237
- if (category.isDirectory()) {
238
- const categoryPath = path.join(this.skillsRootPath, category.name);
239
- const skillMdPath = path.join(categoryPath, 'SKILL.md');
240
-
241
- try {
242
- const content = await fs.readFile(skillMdPath, 'utf-8');
243
- const parsed = this._parseSkillMarkdown(content);
244
-
245
- if (parsed.name) {
246
- this.skillDirectories.set(parsed.name, categoryPath);
247
-
248
- // Also populate loadedSkills so getSkill() can find it
249
- const skillInfo: SkillInfo = {
250
- id: parsed.name,
251
- name: parsed.name,
252
- description: parsed.description || '',
253
- license: parsed.license || 'Unknown',
254
- version: parsed.version || '1.0.0',
255
- author: parsed.author || 'Anonymous',
256
- category: category.name,
257
- markdown: content,
258
- skillsPath: categoryPath
259
- };
260
- this.loadedSkills.set(parsed.name, skillInfo);
261
-
262
- skillIds.push(parsed.name);
263
- }
264
- } catch (error) {
265
- const loadError: SkillLoadError = {
266
- skillId: undefined,
267
- path: categoryPath,
268
- error: error as Error,
269
- phase: 'file_read'
270
- };
271
- this.handleError(loadError);
272
- }
273
- }
274
- }
275
- } catch (error) {
276
- const loadError: SkillLoadError = {
277
- skillId: undefined,
278
- path: this.skillsRootPath,
279
- error: error as Error,
280
- phase: 'directory_read'
281
- };
282
- this.handleError(loadError);
283
- }
284
-
285
- return skillIds;
286
- }
287
-
288
- /**
289
- * Get load statistics
290
- */
291
- getLoadStats(): { totalFound: number; successfullyLoaded: number; failed: number; errors: SkillLoadError[] } {
292
- return { ...this.loadStats };
293
- }
294
-
295
- /**
296
- * Handle error with callback or console
297
- */
298
- private handleError(error: SkillLoadError): void {
299
- this.loadStats.errors.push(error);
300
-
301
- if (this.errorCallback) {
302
- this.errorCallback(error);
303
- } else {
304
- console.error(`[SkillLoader] Error loading skill from ${error.path}:`, error.error.message);
305
- }
306
- }
307
-
308
- private async loadSkillFromPath(skillPath: string, category: string): Promise<SkillInfo | null> {
309
- const skillMdPath = path.join(skillPath, 'SKILL.md');
310
-
311
- try {
312
- const content = await fs.readFile(skillMdPath, 'utf-8');
313
- const parsed = this._parseSkillMarkdown(content);
314
-
315
- if (!parsed.name) {
316
- const warning: SkillLoadWarning = {
317
- skillId: undefined,
318
- path: skillPath,
319
- warning: 'SKILL.md missing required "name" field',
320
- reason: 'Cannot determine skill ID'
321
- };
322
- if (this.warningCallback) {
323
- this.warningCallback(warning);
324
- } else {
325
- console.warn(`[SkillLoader] Warning: ${warning.warning} in ${skillPath}`);
326
- }
327
- return null;
328
- }
329
-
330
- return {
331
- id: parsed.name,
332
- name: parsed.name,
333
- description: parsed.description,
334
- license: parsed.license || 'Unknown',
335
- version: parsed.version || '1.0.0',
336
- author: parsed.author || 'Anonymous',
337
- category: category,
338
- markdown: content,
339
- skillsPath: skillPath
340
- };
341
- } catch (error) {
342
- const loadError: SkillLoadError = {
343
- skillId: undefined,
344
- path: skillPath,
345
- error: error as Error,
346
- phase: 'file_read'
347
- };
348
- this.handleError(loadError);
349
- return null;
350
- }
351
- }
352
-
353
- private _parseSkillMarkdown(content: string): { name: string; description: string; license?: string; version?: string; author?: string } {
354
- const result = {
355
- name: '',
356
- description: '',
357
- license: undefined as string | undefined,
358
- version: undefined as string | undefined,
359
- author: undefined as string | undefined
360
- };
361
-
362
- // Normalize line endings to LF for consistent parsing
363
- const normalizedContent = content.replace(/\r\n/g, '\n');
364
-
365
- // Try to extract frontmatter - support both formats:
366
- // 1. Standard YAML: ---name: docx...--- 2. No opening ---: name: docx...
367
- let frontmatter = '';
368
- let contentStart = 0;
369
-
370
- const frontmatterMatch = normalizedContent.match(/^---\n([\s\S]*?)\n---/);
371
- if (frontmatterMatch) {
372
- // Standard format with --- at start and end
373
- frontmatter = frontmatterMatch[1];
374
- contentStart = frontmatterMatch[0].length;
375
- } else {
376
- // Check for format without opening --- (just YAML at the start)
377
- const yamlMatch = normalizedContent.match(/^([\s\S]*?)\n---/);
378
- if (yamlMatch) {
379
- frontmatter = yamlMatch[1];
380
- contentStart = yamlMatch[0].length;
381
- }
382
- }
383
-
384
- if (frontmatter) {
385
- const lines = frontmatter.split('\n');
386
-
387
- let currentKey = '';
388
- let currentValue = '';
389
-
390
- for (const line of lines) {
391
- const keyValueMatch = line.match(/^(\w+):\s*(.*)$/);
392
-
393
- if (keyValueMatch) {
394
- // Save previous key-value pair
395
- if (currentKey) {
396
- let value = currentValue.trim();
397
- // Remove quotes if present
398
- value = value.replace(/^["']|["']$/g, '');
399
-
400
- if (currentKey === 'name') result.name = value;
401
- else if (currentKey === 'description') result.description = value;
402
- else if (currentKey === 'license') result.license = value;
403
- else if (currentKey === 'version') result.version = value;
404
- else if (currentKey === 'author') result.author = value;
405
- }
406
-
407
- currentKey = keyValueMatch[1];
408
- currentValue = keyValueMatch[2];
409
- } else if (currentKey && line.trim()) {
410
- // Continuation of previous value
411
- currentValue += ' ' + line.trim();
412
- }
413
- }
414
-
415
- // Save last key-value pair
416
- if (currentKey) {
417
- let value = currentValue.trim();
418
- value = value.replace(/^["']|["']$/g, '');
419
-
420
- if (currentKey === 'name') result.name = value;
421
- else if (currentKey === 'description') result.description = value;
422
- else if (currentKey === 'license') result.license = value;
423
- else if (currentKey === 'version') result.version = value;
424
- else if (currentKey === 'author') result.author = value;
425
- }
426
- }
427
-
428
- return result;
429
- }
430
-
431
- getSkill(skillId: string): SkillInfo | undefined {
432
- return this.loadedSkills.get(skillId);
433
- }
434
-
435
- /**
436
- * Get the directory path for a skill
437
- */
438
- getSkillDirectory(skillId: string): string | undefined {
439
- return this.skillDirectories.get(skillId);
440
- }
441
-
442
- /**
443
- * Public method to parse skill markdown frontmatter
444
- */
445
- parseSkillMarkdown(content: string): { name: string; description: string; license?: string; version?: string; author?: string } {
446
- return this._parseSkillMarkdown(content);
447
- }
448
-
449
- listSkills(): SkillInfo[] {
450
- return Array.from(this.loadedSkills.values());
451
- }
452
-
453
- async convertToWorkflow(skillId: string): Promise<WorkflowConfig | null> {
454
- const skill = this.getSkill(skillId);
455
- if (!skill) return null;
456
-
457
- return {
458
- id: skill.id,
459
- name: skill.name,
460
- description: skill.description,
461
- version: skill.version,
462
- author: skill.author,
463
- agents: [],
464
- commands: {},
465
- mcpServers: {},
466
- xagentMd: skill.markdown,
467
- files: {}
468
- };
469
- }
470
-
471
- async convertAllToWorkflows(): Promise<WorkflowConfig[]> {
472
- const workflows: WorkflowConfig[] = [];
473
-
474
- for (const skill of this.loadedSkills.values()) {
475
- const workflow = await this.convertToWorkflow(skill.id);
476
- if (workflow) {
477
- workflows.push(workflow);
478
- }
479
- }
480
-
481
- return workflows;
482
- }
483
- }
484
-
485
- let skillLoaderInstance: SkillLoader | null = null;
486
-
487
- export function getSkillLoader(config?: SkillLoaderConfig): SkillLoader {
488
- if (!skillLoaderInstance) {
489
- skillLoaderInstance = new SkillLoader(config);
490
- }
491
- return skillLoaderInstance;
492
- }
493
-
494
- export async function loadSkillsFromFolder(skillsPath: string): Promise<SkillInfo[]> {
495
- const loader = new SkillLoader({ skillsRootPath: skillsPath });
496
- return await loader.loadAllSkills();
1
+ import fs from 'fs/promises';
2
+ import _fsSync from 'fs';
3
+ import path from 'path';
4
+ import os from 'os';
5
+ import { WorkflowConfig } from './workflow.js';
6
+ import { getConfigManager } from './config.js';
7
+
8
+ export interface SkillInfo {
9
+ id: string;
10
+ name: string;
11
+ description: string;
12
+ license: string;
13
+ version: string;
14
+ author: string;
15
+ category: string;
16
+ markdown: string;
17
+ skillsPath: string;
18
+ }
19
+
20
+ export interface SkillLoaderConfig {
21
+ /** User-installed skills path (~/.xagent/skills) */
22
+ userSkillsRootPath?: string;
23
+ onError?: (error: SkillLoadError) => void;
24
+ onWarning?: (warning: SkillLoadWarning) => void;
25
+ }
26
+
27
+ export interface SkillLoadError {
28
+ skillId?: string;
29
+ path: string;
30
+ error: Error;
31
+ phase: 'directory_read' | 'file_read' | 'parse_markdown';
32
+ }
33
+
34
+ export interface SkillLoadWarning {
35
+ skillId?: string;
36
+ path: string;
37
+ warning: string;
38
+ reason?: string;
39
+ }
40
+
41
+ export class SkillLoader {
42
+ private skillsRootPath: string;
43
+ private loadedSkills: Map<string, SkillInfo> = new Map();
44
+ private skillDirectories: Map<string, string> = new Map(); // skillId -> path mapping
45
+ private errorCallback?: (error: SkillLoadError) => void;
46
+ private warningCallback?: (warning: SkillLoadWarning) => void;
47
+ private loadStats: {
48
+ totalFound: number;
49
+ successfullyLoaded: number;
50
+ failed: number;
51
+ errors: SkillLoadError[];
52
+ } = { totalFound: 0, successfullyLoaded: 0, failed: 0, errors: [] };
53
+
54
+ constructor(config?: SkillLoaderConfig) {
55
+ // All skills are loaded from user directory (default: ~/.xagent/skills)
56
+ // Built-in skills are copied to user directory during initialization
57
+ if (config?.userSkillsRootPath) {
58
+ this.skillsRootPath = config.userSkillsRootPath;
59
+ } else {
60
+ const configManager = getConfigManager();
61
+ const userPath = configManager.getUserSkillsPath();
62
+ this.skillsRootPath = userPath || path.join(os.homedir(), '.xagent', 'skills');
63
+ }
64
+ }
65
+ async loadAllSkills(): Promise<SkillInfo[]> {
66
+ const skills: SkillInfo[] = [];
67
+
68
+ // Reset stats
69
+ this.loadStats = { totalFound: 0, successfullyLoaded: 0, failed: 0, errors: [] };
70
+
71
+ try {
72
+ const categories = await fs.readdir(this.skillsRootPath, { withFileTypes: true });
73
+
74
+ // First pass: discover all skill directories
75
+ const skillDirs: { path: string; category: string }[] = [];
76
+ for (const category of categories) {
77
+ if (category.isDirectory()) {
78
+ const categoryPath = path.join(this.skillsRootPath, category.name);
79
+ skillDirs.push({ path: categoryPath, category: category.name });
80
+ this.loadStats.totalFound++;
81
+ }
82
+ }
83
+
84
+ // Second pass: load skills (can be parallelized)
85
+ const loadPromises = skillDirs.map(async ({ path: skillPath, category }) => {
86
+ const skillInfo = await this.loadSkillFromPath(skillPath, category);
87
+ if (skillInfo) {
88
+ this.loadedSkills.set(skillInfo.id, skillInfo);
89
+ this.skillDirectories.set(skillInfo.id, skillPath);
90
+ this.loadStats.successfullyLoaded++;
91
+ return skillInfo;
92
+ } else {
93
+ this.loadStats.failed++;
94
+ return null;
95
+ }
96
+ });
97
+
98
+ const results = await Promise.all(loadPromises);
99
+ for (const skill of results) {
100
+ if (skill) skills.push(skill);
101
+ }
102
+
103
+ } catch (error) {
104
+ const loadError: SkillLoadError = {
105
+ skillId: undefined,
106
+ path: this.skillsRootPath,
107
+ error: error as Error,
108
+ phase: 'directory_read'
109
+ };
110
+ this.loadStats.errors.push(loadError);
111
+
112
+ if (this.errorCallback) {
113
+ this.errorCallback(loadError);
114
+ } else {
115
+ console.error(`[SkillLoader] Failed to load skills from ${this.skillsRootPath}:`, error);
116
+ }
117
+ }
118
+
119
+ // Log summary if there were errors
120
+ if (this.loadStats.failed > 0) {
121
+ const errorMsg = `Loaded ${this.loadStats.successfullyLoaded}/${this.loadStats.totalFound} skills, ${this.loadStats.failed} failed`;
122
+ if (this.warningCallback) {
123
+ this.warningCallback({
124
+ skillId: undefined,
125
+ path: this.skillsRootPath,
126
+ warning: errorMsg,
127
+ reason: `${this.loadStats.errors.length} parsing errors`
128
+ });
129
+ } else {
130
+ console.warn(`[SkillLoader] ${errorMsg}`);
131
+ }
132
+ }
133
+
134
+ return skills;
135
+ }
136
+
137
+ /**
138
+ * Lazy load a single skill by ID - only loads when needed
139
+ * This is the key optimization for on-demand loading
140
+ */
141
+ async loadSkill(skillId: string): Promise<SkillInfo | null> {
142
+ // Return from cache if already loaded
143
+ const cached = this.loadedSkills.get(skillId);
144
+ if (cached) return cached;
145
+
146
+ // Try to find and load the specific skill
147
+ const skillPath = this.skillDirectories.get(skillId);
148
+ if (skillPath) {
149
+ const skillInfo = await this.loadSkillFromPath(skillPath, '');
150
+ if (skillInfo) {
151
+ this.loadedSkills.set(skillInfo.id, skillInfo);
152
+ return skillInfo;
153
+ }
154
+ }
155
+
156
+ // Fallback: search in skills root directory
157
+ return this.loadSkillBySearching(skillId);
158
+ }
159
+
160
+ /**
161
+ * Search for a skill by ID in the skills root directories
162
+ */
163
+ private async loadSkillBySearching(skillId: string): Promise<SkillInfo | null> {
164
+ // Unified approach: only search in user skills directory
165
+ const skillsRootPath = this.skillsRootPath;
166
+
167
+ try {
168
+ const categories = await fs.readdir(skillsRootPath, { withFileTypes: true });
169
+
170
+ for (const category of categories) {
171
+ if (category.isDirectory()) {
172
+ const categoryPath = path.join(skillsRootPath, category.name);
173
+ const skillMdPath = path.join(categoryPath, 'SKILL.md');
174
+
175
+ try {
176
+ const content = await fs.readFile(skillMdPath, 'utf-8');
177
+ const parsed = this._parseSkillMarkdown(content);
178
+
179
+ if (parsed.name === skillId) {
180
+ this.skillDirectories.set(skillId, categoryPath);
181
+ const skillInfo: SkillInfo = {
182
+ id: parsed.name,
183
+ name: parsed.name,
184
+ description: parsed.description,
185
+ license: parsed.license || 'Unknown',
186
+ version: parsed.version || '1.0.0',
187
+ author: parsed.author || 'Anonymous',
188
+ category: category.name,
189
+ markdown: content,
190
+ skillsPath: categoryPath
191
+ };
192
+ this.loadedSkills.set(skillId, skillInfo);
193
+ return skillInfo;
194
+ }
195
+ } catch {
196
+ // Continue searching
197
+ continue;
198
+ }
199
+ }
200
+ }
201
+ } catch (error) {
202
+ const loadError: SkillLoadError = {
203
+ skillId,
204
+ path: skillsRootPath,
205
+ error: error as Error,
206
+ phase: 'directory_read'
207
+ };
208
+ this.handleError(loadError);
209
+ }
210
+
211
+ return null;
212
+ }
213
+
214
+ /**
215
+ * Pre-discover skill directories without loading content
216
+ * This allows faster subsequent lazy loading
217
+ */
218
+ async discoverSkills(): Promise<string[]> {
219
+ const skillIds: string[] = [];
220
+
221
+ // Unified approach: only scan user skills directory
222
+ const skillsRootPath = this.skillsRootPath;
223
+
224
+ try {
225
+ const categories = await fs.readdir(skillsRootPath, { withFileTypes: true });
226
+
227
+ for (const category of categories) {
228
+ if (category.isDirectory()) {
229
+ const categoryPath = path.join(skillsRootPath, category.name);
230
+ const skillMdPath = path.join(categoryPath, 'SKILL.md');
231
+
232
+ try {
233
+ const content = await fs.readFile(skillMdPath, 'utf-8');
234
+ const parsed = this._parseSkillMarkdown(content);
235
+
236
+ if (parsed.name) {
237
+ this.skillDirectories.set(parsed.name, categoryPath);
238
+
239
+ // Also populate loadedSkills so getSkill() can find it
240
+ const skillInfo: SkillInfo = {
241
+ id: parsed.name,
242
+ name: parsed.name,
243
+ description: parsed.description || '',
244
+ license: parsed.license || 'Unknown',
245
+ version: parsed.version || '1.0.0',
246
+ author: parsed.author || 'Anonymous',
247
+ category: category.name,
248
+ markdown: content,
249
+ skillsPath: categoryPath
250
+ };
251
+ this.loadedSkills.set(parsed.name, skillInfo);
252
+
253
+ skillIds.push(parsed.name);
254
+ }
255
+ } catch (error) {
256
+ const loadError: SkillLoadError = {
257
+ skillId: undefined,
258
+ path: categoryPath,
259
+ error: error as Error,
260
+ phase: 'file_read'
261
+ };
262
+ this.handleError(loadError);
263
+ }
264
+ }
265
+ }
266
+ } catch (error) {
267
+ const loadError: SkillLoadError = {
268
+ skillId: undefined,
269
+ path: skillsRootPath,
270
+ error: error as Error,
271
+ phase: 'directory_read'
272
+ };
273
+ this.handleError(loadError);
274
+ }
275
+
276
+ return skillIds;
277
+ }
278
+
279
+ /**
280
+ * Get load statistics
281
+ */
282
+ getLoadStats(): { totalFound: number; successfullyLoaded: number; failed: number; errors: SkillLoadError[] } {
283
+ return { ...this.loadStats };
284
+ }
285
+
286
+ /**
287
+ * Handle error with callback or console
288
+ */
289
+ private handleError(error: SkillLoadError): void {
290
+ this.loadStats.errors.push(error);
291
+
292
+ if (this.errorCallback) {
293
+ this.errorCallback(error);
294
+ } else {
295
+ console.error(`[SkillLoader] Error loading skill from ${error.path}:`, error.error.message);
296
+ }
297
+ }
298
+
299
+ private async loadSkillFromPath(skillPath: string, category: string): Promise<SkillInfo | null> {
300
+ const skillMdPath = path.join(skillPath, 'SKILL.md');
301
+
302
+ try {
303
+ const content = await fs.readFile(skillMdPath, 'utf-8');
304
+ const parsed = this._parseSkillMarkdown(content);
305
+
306
+ if (!parsed.name) {
307
+ const warning: SkillLoadWarning = {
308
+ skillId: undefined,
309
+ path: skillPath,
310
+ warning: 'SKILL.md missing required "name" field',
311
+ reason: 'Cannot determine skill ID'
312
+ };
313
+ if (this.warningCallback) {
314
+ this.warningCallback(warning);
315
+ } else {
316
+ console.warn(`[SkillLoader] Warning: ${warning.warning} in ${skillPath}`);
317
+ }
318
+ return null;
319
+ }
320
+
321
+ return {
322
+ id: parsed.name,
323
+ name: parsed.name,
324
+ description: parsed.description,
325
+ license: parsed.license || 'Unknown',
326
+ version: parsed.version || '1.0.0',
327
+ author: parsed.author || 'Anonymous',
328
+ category: category,
329
+ markdown: content,
330
+ skillsPath: skillPath
331
+ };
332
+ } catch (error) {
333
+ const loadError: SkillLoadError = {
334
+ skillId: undefined,
335
+ path: skillPath,
336
+ error: error as Error,
337
+ phase: 'file_read'
338
+ };
339
+ this.handleError(loadError);
340
+ return null;
341
+ }
342
+ }
343
+
344
+ private _parseSkillMarkdown(content: string): { name: string; description: string; license?: string; version?: string; author?: string } {
345
+ const result = {
346
+ name: '',
347
+ description: '',
348
+ license: undefined as string | undefined,
349
+ version: undefined as string | undefined,
350
+ author: undefined as string | undefined
351
+ };
352
+
353
+ // Normalize line endings to LF for consistent parsing
354
+ const normalizedContent = content.replace(/\r\n/g, '\n');
355
+
356
+ // Try to extract frontmatter - support both formats:
357
+ // 1. Standard YAML: ---name: docx...--- 2. No opening ---: name: docx...
358
+ let frontmatter = '';
359
+ let _contentStart = 0;
360
+
361
+ const frontmatterMatch = normalizedContent.match(/^---([\s\S]*?)\n---/);
362
+ if (frontmatterMatch) {
363
+ // Standard format with --- at start and end
364
+ frontmatter = frontmatterMatch[1];
365
+ _contentStart = frontmatterMatch[0].length;
366
+ } else {
367
+ // Check for format without opening --- (just YAML at the start)
368
+ const yamlMatch = normalizedContent.match(/^([\s\S]*?)\n---/);
369
+ if (yamlMatch) {
370
+ frontmatter = yamlMatch[1];
371
+ _contentStart = yamlMatch[0].length;
372
+ }
373
+ }
374
+
375
+ if (frontmatter) {
376
+ const lines = frontmatter.split('\n');
377
+
378
+ let currentKey = '';
379
+ let currentValue = '';
380
+
381
+ for (const line of lines) {
382
+ const keyValueMatch = line.match(/^(\w+):\s*(.*)$/);
383
+
384
+ if (keyValueMatch) {
385
+ // Save previous key-value pair
386
+ if (currentKey) {
387
+ let value = currentValue.trim();
388
+ // Remove quotes if present
389
+ value = value.replace(/^["']|["']$/g, '');
390
+
391
+ if (currentKey === 'name') result.name = value;
392
+ else if (currentKey === 'description') result.description = value;
393
+ else if (currentKey === 'license') result.license = value;
394
+ else if (currentKey === 'version') result.version = value;
395
+ else if (currentKey === 'author') result.author = value;
396
+ }
397
+
398
+ currentKey = keyValueMatch[1];
399
+ currentValue = keyValueMatch[2];
400
+ } else if (currentKey && line.trim()) {
401
+ // Continuation of previous value
402
+ currentValue += ' ' + line.trim();
403
+ }
404
+ }
405
+
406
+ // Save last key-value pair
407
+ if (currentKey) {
408
+ let value = currentValue.trim();
409
+ value = value.replace(/^["']|["']$/g, '');
410
+
411
+ if (currentKey === 'name') result.name = value;
412
+ else if (currentKey === 'description') result.description = value;
413
+ else if (currentKey === 'license') result.license = value;
414
+ else if (currentKey === 'version') result.version = value;
415
+ else if (currentKey === 'author') result.author = value;
416
+ }
417
+ }
418
+
419
+ return result;
420
+ }
421
+
422
+ getSkill(skillId: string): SkillInfo | undefined {
423
+ return this.loadedSkills.get(skillId);
424
+ }
425
+
426
+ /**
427
+ * Get the directory path for a skill
428
+ */
429
+ getSkillDirectory(skillId: string): string | undefined {
430
+ return this.skillDirectories.get(skillId);
431
+ }
432
+
433
+ /**
434
+ * Public method to parse skill markdown frontmatter
435
+ */
436
+ parseSkillMarkdown(content: string): { name: string; description: string; license?: string; version?: string; author?: string } {
437
+ return this._parseSkillMarkdown(content);
438
+ }
439
+
440
+ listSkills(): SkillInfo[] {
441
+ return Array.from(this.loadedSkills.values());
442
+ }
443
+
444
+ async convertToWorkflow(skillId: string): Promise<WorkflowConfig | null> {
445
+ const skill = this.getSkill(skillId);
446
+ if (!skill) return null;
447
+
448
+ return {
449
+ id: skill.id,
450
+ name: skill.name,
451
+ description: skill.description,
452
+ version: skill.version,
453
+ author: skill.author,
454
+ agents: [],
455
+ commands: {},
456
+ mcpServers: {},
457
+ xagentMd: skill.markdown,
458
+ files: {}
459
+ };
460
+ }
461
+
462
+ async convertAllToWorkflows(): Promise<WorkflowConfig[]> {
463
+ const workflows: WorkflowConfig[] = [];
464
+
465
+ for (const skill of this.loadedSkills.values()) {
466
+ const workflow = await this.convertToWorkflow(skill.id);
467
+ if (workflow) {
468
+ workflows.push(workflow);
469
+ }
470
+ }
471
+
472
+ return workflows;
473
+ }
474
+ }
475
+
476
+ let skillLoaderInstance: SkillLoader | null = null;
477
+
478
+ export function getSkillLoader(config?: SkillLoaderConfig): SkillLoader {
479
+ // Always use the same user skills directory to avoid cache pollution
480
+ // Built-in skills are copied to user directory during initialization
481
+ const unifiedConfig: SkillLoaderConfig = {
482
+ userSkillsRootPath: config?.userSkillsRootPath
483
+ };
484
+
485
+ if (!skillLoaderInstance) {
486
+ skillLoaderInstance = new SkillLoader(unifiedConfig);
487
+ }
488
+ return skillLoaderInstance;
489
+ }
490
+
491
+ /**
492
+ * Force reset the skill loader instance (for testing or critical reload)
493
+ * WARNING: This clears all cached skills!
494
+ */
495
+ export function resetSkillLoader(): void {
496
+ skillLoaderInstance = null;
497
+ }
498
+
499
+ export async function loadSkillsFromFolder(skillsPath: string): Promise<SkillInfo[]> {
500
+ const loader = new SkillLoader({ userSkillsRootPath: skillsPath });
501
+ return await loader.loadAllSkills();
497
502
  }