@xagent-ai/cli 1.0.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 (537) hide show
  1. package/.eslintrc.js +25 -0
  2. package/.gitmodules +3 -0
  3. package/.prettierrc.json +8 -0
  4. package/CONTRIBUTING.md +167 -0
  5. package/LICENSE +21 -0
  6. package/README.md +280 -0
  7. package/README_CN.md +280 -0
  8. package/dist/agents.d.ts +21 -0
  9. package/dist/agents.d.ts.map +1 -0
  10. package/dist/agents.js +463 -0
  11. package/dist/agents.js.map +1 -0
  12. package/dist/ai-client.d.ts +83 -0
  13. package/dist/ai-client.d.ts.map +1 -0
  14. package/dist/ai-client.js +1280 -0
  15. package/dist/ai-client.js.map +1 -0
  16. package/dist/auth.d.ts +25 -0
  17. package/dist/auth.d.ts.map +1 -0
  18. package/dist/auth.js +573 -0
  19. package/dist/auth.js.map +1 -0
  20. package/dist/cancellation.d.ts +46 -0
  21. package/dist/cancellation.d.ts.map +1 -0
  22. package/dist/cancellation.js +154 -0
  23. package/dist/cancellation.js.map +1 -0
  24. package/dist/checkpoint.d.ts +28 -0
  25. package/dist/checkpoint.d.ts.map +1 -0
  26. package/dist/checkpoint.js +186 -0
  27. package/dist/checkpoint.js.map +1 -0
  28. package/dist/cli.d.ts +3 -0
  29. package/dist/cli.d.ts.map +1 -0
  30. package/dist/cli.js +364 -0
  31. package/dist/cli.js.map +1 -0
  32. package/dist/config.d.ts +49 -0
  33. package/dist/config.d.ts.map +1 -0
  34. package/dist/config.js +205 -0
  35. package/dist/config.js.map +1 -0
  36. package/dist/context-compressor.d.ts +51 -0
  37. package/dist/context-compressor.d.ts.map +1 -0
  38. package/dist/context-compressor.js +231 -0
  39. package/dist/context-compressor.js.map +1 -0
  40. package/dist/conversation.d.ts +34 -0
  41. package/dist/conversation.d.ts.map +1 -0
  42. package/dist/conversation.js +221 -0
  43. package/dist/conversation.js.map +1 -0
  44. package/dist/gui-subagent/action-parser/actionParser.d.ts +19 -0
  45. package/dist/gui-subagent/action-parser/actionParser.d.ts.map +1 -0
  46. package/dist/gui-subagent/action-parser/actionParser.js +203 -0
  47. package/dist/gui-subagent/action-parser/actionParser.js.map +1 -0
  48. package/dist/gui-subagent/action-parser/constants.d.ts +8 -0
  49. package/dist/gui-subagent/action-parser/constants.d.ts.map +1 -0
  50. package/dist/gui-subagent/action-parser/constants.js +12 -0
  51. package/dist/gui-subagent/action-parser/constants.js.map +1 -0
  52. package/dist/gui-subagent/action-parser/index.d.ts +3 -0
  53. package/dist/gui-subagent/action-parser/index.d.ts.map +1 -0
  54. package/dist/gui-subagent/action-parser/index.js +6 -0
  55. package/dist/gui-subagent/action-parser/index.js.map +1 -0
  56. package/dist/gui-subagent/action-parser/types.d.ts +24 -0
  57. package/dist/gui-subagent/action-parser/types.d.ts.map +1 -0
  58. package/dist/gui-subagent/action-parser/types.js +12 -0
  59. package/dist/gui-subagent/action-parser/types.js.map +1 -0
  60. package/dist/gui-subagent/agent/gui-agent.d.ts +126 -0
  61. package/dist/gui-subagent/agent/gui-agent.d.ts.map +1 -0
  62. package/dist/gui-subagent/agent/gui-agent.js +820 -0
  63. package/dist/gui-subagent/agent/gui-agent.js.map +1 -0
  64. package/dist/gui-subagent/agent/index.d.ts +5 -0
  65. package/dist/gui-subagent/agent/index.d.ts.map +1 -0
  66. package/dist/gui-subagent/agent/index.js +5 -0
  67. package/dist/gui-subagent/agent/index.js.map +1 -0
  68. package/dist/gui-subagent/index.d.ts +43 -0
  69. package/dist/gui-subagent/index.d.ts.map +1 -0
  70. package/dist/gui-subagent/index.js +96 -0
  71. package/dist/gui-subagent/index.js.map +1 -0
  72. package/dist/gui-subagent/operator/base-operator.d.ts +108 -0
  73. package/dist/gui-subagent/operator/base-operator.d.ts.map +1 -0
  74. package/dist/gui-subagent/operator/base-operator.js +172 -0
  75. package/dist/gui-subagent/operator/base-operator.js.map +1 -0
  76. package/dist/gui-subagent/operator/browser-operator.d.ts +36 -0
  77. package/dist/gui-subagent/operator/browser-operator.d.ts.map +1 -0
  78. package/dist/gui-subagent/operator/browser-operator.js +306 -0
  79. package/dist/gui-subagent/operator/browser-operator.js.map +1 -0
  80. package/dist/gui-subagent/operator/computer-operator.d.ts +31 -0
  81. package/dist/gui-subagent/operator/computer-operator.d.ts.map +1 -0
  82. package/dist/gui-subagent/operator/computer-operator.js +441 -0
  83. package/dist/gui-subagent/operator/computer-operator.js.map +1 -0
  84. package/dist/gui-subagent/operator/desktop-operator.d.ts +55 -0
  85. package/dist/gui-subagent/operator/desktop-operator.d.ts.map +1 -0
  86. package/dist/gui-subagent/operator/desktop-operator.js +527 -0
  87. package/dist/gui-subagent/operator/desktop-operator.js.map +1 -0
  88. package/dist/gui-subagent/operator/index.d.ts +7 -0
  89. package/dist/gui-subagent/operator/index.d.ts.map +1 -0
  90. package/dist/gui-subagent/operator/index.js +6 -0
  91. package/dist/gui-subagent/operator/index.js.map +1 -0
  92. package/dist/gui-subagent/types/actions.d.ts +108 -0
  93. package/dist/gui-subagent/types/actions.d.ts.map +1 -0
  94. package/dist/gui-subagent/types/actions.js +39 -0
  95. package/dist/gui-subagent/types/actions.js.map +1 -0
  96. package/dist/gui-subagent/types/index.d.ts +6 -0
  97. package/dist/gui-subagent/types/index.d.ts.map +1 -0
  98. package/dist/gui-subagent/types/index.js +6 -0
  99. package/dist/gui-subagent/types/index.js.map +1 -0
  100. package/dist/gui-subagent/types/operator.d.ts +95 -0
  101. package/dist/gui-subagent/types/operator.d.ts.map +1 -0
  102. package/dist/gui-subagent/types/operator.js +16 -0
  103. package/dist/gui-subagent/types/operator.js.map +1 -0
  104. package/dist/gui-subagent/utils.d.ts +19 -0
  105. package/dist/gui-subagent/utils.d.ts.map +1 -0
  106. package/dist/gui-subagent/utils.js +42 -0
  107. package/dist/gui-subagent/utils.js.map +1 -0
  108. package/dist/hook.d.ts +73 -0
  109. package/dist/hook.d.ts.map +1 -0
  110. package/dist/hook.js +156 -0
  111. package/dist/hook.js.map +1 -0
  112. package/dist/index.d.ts +19 -0
  113. package/dist/index.d.ts.map +1 -0
  114. package/dist/index.js +19 -0
  115. package/dist/index.js.map +1 -0
  116. package/dist/input-history.d.ts +24 -0
  117. package/dist/input-history.d.ts.map +1 -0
  118. package/dist/input-history.js +94 -0
  119. package/dist/input-history.js.map +1 -0
  120. package/dist/input-processor.d.ts +31 -0
  121. package/dist/input-processor.d.ts.map +1 -0
  122. package/dist/input-processor.js +233 -0
  123. package/dist/input-processor.js.map +1 -0
  124. package/dist/keyboard-manager.d.ts +151 -0
  125. package/dist/keyboard-manager.d.ts.map +1 -0
  126. package/dist/keyboard-manager.js +396 -0
  127. package/dist/keyboard-manager.js.map +1 -0
  128. package/dist/logger.d.ts +75 -0
  129. package/dist/logger.d.ts.map +1 -0
  130. package/dist/logger.js +339 -0
  131. package/dist/logger.js.map +1 -0
  132. package/dist/mcp.d.ts +57 -0
  133. package/dist/mcp.d.ts.map +1 -0
  134. package/dist/mcp.js +483 -0
  135. package/dist/mcp.js.map +1 -0
  136. package/dist/memory.d.ts +25 -0
  137. package/dist/memory.d.ts.map +1 -0
  138. package/dist/memory.js +250 -0
  139. package/dist/memory.js.map +1 -0
  140. package/dist/print-system-prompt.d.ts +2 -0
  141. package/dist/print-system-prompt.d.ts.map +1 -0
  142. package/dist/print-system-prompt.js +40 -0
  143. package/dist/print-system-prompt.js.map +1 -0
  144. package/dist/session-manager.d.ts +41 -0
  145. package/dist/session-manager.d.ts.map +1 -0
  146. package/dist/session-manager.js +234 -0
  147. package/dist/session-manager.js.map +1 -0
  148. package/dist/session.d.ts +77 -0
  149. package/dist/session.d.ts.map +1 -0
  150. package/dist/session.js +1081 -0
  151. package/dist/session.js.map +1 -0
  152. package/dist/skill-invoker.d.ts +177 -0
  153. package/dist/skill-invoker.d.ts.map +1 -0
  154. package/dist/skill-invoker.js +1643 -0
  155. package/dist/skill-invoker.js.map +1 -0
  156. package/dist/skill-loader.d.ts +76 -0
  157. package/dist/skill-loader.d.ts.map +1 -0
  158. package/dist/skill-loader.js +407 -0
  159. package/dist/skill-loader.js.map +1 -0
  160. package/dist/slash-commands.d.ts +60 -0
  161. package/dist/slash-commands.d.ts.map +1 -0
  162. package/dist/slash-commands.js +1021 -0
  163. package/dist/slash-commands.js.map +1 -0
  164. package/dist/smart-approval.d.ts +137 -0
  165. package/dist/smart-approval.d.ts.map +1 -0
  166. package/dist/smart-approval.js +512 -0
  167. package/dist/smart-approval.js.map +1 -0
  168. package/dist/system-prompt-generator.d.ts +35 -0
  169. package/dist/system-prompt-generator.d.ts.map +1 -0
  170. package/dist/system-prompt-generator.js +729 -0
  171. package/dist/system-prompt-generator.js.map +1 -0
  172. package/dist/test-boundary-conditions.d.ts.map +1 -0
  173. package/dist/test-boundary-conditions.js.map +1 -0
  174. package/dist/test-cancellation-fix.d.ts.map +1 -0
  175. package/dist/test-cancellation-fix.js.map +1 -0
  176. package/dist/test-input-history.d.ts.map +1 -0
  177. package/dist/test-input-history.js.map +1 -0
  178. package/dist/test-interaction-flow.d.ts.map +1 -0
  179. package/dist/test-interaction-flow.js.map +1 -0
  180. package/dist/test-quick.d.ts.map +1 -0
  181. package/dist/test-quick.js.map +1 -0
  182. package/dist/test-user-interaction.d.ts.map +1 -0
  183. package/dist/test-user-interaction.js.map +1 -0
  184. package/dist/theme.d.ts +353 -0
  185. package/dist/theme.d.ts.map +1 -0
  186. package/dist/theme.js +383 -0
  187. package/dist/theme.js.map +1 -0
  188. package/dist/tools.d.ts +373 -0
  189. package/dist/tools.d.ts.map +1 -0
  190. package/dist/tools.js +2906 -0
  191. package/dist/tools.js.map +1 -0
  192. package/dist/types.d.ts +180 -0
  193. package/dist/types.d.ts.map +1 -0
  194. package/dist/types.js +23 -0
  195. package/dist/types.js.map +1 -0
  196. package/dist/unified-session.d.ts +42 -0
  197. package/dist/unified-session.d.ts.map +1 -0
  198. package/dist/unified-session.js +271 -0
  199. package/dist/unified-session.js.map +1 -0
  200. package/dist/update.d.ts +30 -0
  201. package/dist/update.d.ts.map +1 -0
  202. package/dist/update.js +211 -0
  203. package/dist/update.js.map +1 -0
  204. package/dist/workflow.d.ts +53 -0
  205. package/dist/workflow.d.ts.map +1 -0
  206. package/dist/workflow.js +405 -0
  207. package/dist/workflow.js.map +1 -0
  208. package/docs/architecture/mcp-integration-guide.md +131 -0
  209. package/docs/architecture/overview.md +93 -0
  210. package/docs/architecture/tool-system-design.md +89 -0
  211. package/docs/cli/commands.md +189 -0
  212. package/docs/smart-mode.md +257 -0
  213. package/docs/third-party-models.md +449 -0
  214. package/package.json +85 -0
  215. package/scripts/init-skills-path.js +58 -0
  216. package/skills/.claude-plugin/marketplace.json +45 -0
  217. package/skills/README.md +94 -0
  218. package/skills/THIRD_PARTY_NOTICES.md +405 -0
  219. package/skills/skills/algorithmic-art/LICENSE.txt +202 -0
  220. package/skills/skills/algorithmic-art/SKILL.md +405 -0
  221. package/skills/skills/algorithmic-art/templates/generator_template.js +223 -0
  222. package/skills/skills/algorithmic-art/templates/viewer.html +599 -0
  223. package/skills/skills/brand-guidelines/LICENSE.txt +202 -0
  224. package/skills/skills/brand-guidelines/SKILL.md +73 -0
  225. package/skills/skills/canvas-design/LICENSE.txt +202 -0
  226. package/skills/skills/canvas-design/SKILL.md +130 -0
  227. package/skills/skills/canvas-design/canvas-fonts/ArsenalSC-OFL.txt +93 -0
  228. package/skills/skills/canvas-design/canvas-fonts/ArsenalSC-Regular.ttf +0 -0
  229. package/skills/skills/canvas-design/canvas-fonts/BigShoulders-Bold.ttf +0 -0
  230. package/skills/skills/canvas-design/canvas-fonts/BigShoulders-OFL.txt +93 -0
  231. package/skills/skills/canvas-design/canvas-fonts/BigShoulders-Regular.ttf +0 -0
  232. package/skills/skills/canvas-design/canvas-fonts/Boldonse-OFL.txt +93 -0
  233. package/skills/skills/canvas-design/canvas-fonts/Boldonse-Regular.ttf +0 -0
  234. package/skills/skills/canvas-design/canvas-fonts/BricolageGrotesque-Bold.ttf +0 -0
  235. package/skills/skills/canvas-design/canvas-fonts/BricolageGrotesque-OFL.txt +93 -0
  236. package/skills/skills/canvas-design/canvas-fonts/BricolageGrotesque-Regular.ttf +0 -0
  237. package/skills/skills/canvas-design/canvas-fonts/CrimsonPro-Bold.ttf +0 -0
  238. package/skills/skills/canvas-design/canvas-fonts/CrimsonPro-Italic.ttf +0 -0
  239. package/skills/skills/canvas-design/canvas-fonts/CrimsonPro-OFL.txt +93 -0
  240. package/skills/skills/canvas-design/canvas-fonts/CrimsonPro-Regular.ttf +0 -0
  241. package/skills/skills/canvas-design/canvas-fonts/DMMono-OFL.txt +93 -0
  242. package/skills/skills/canvas-design/canvas-fonts/DMMono-Regular.ttf +0 -0
  243. package/skills/skills/canvas-design/canvas-fonts/EricaOne-OFL.txt +94 -0
  244. package/skills/skills/canvas-design/canvas-fonts/EricaOne-Regular.ttf +0 -0
  245. package/skills/skills/canvas-design/canvas-fonts/GeistMono-Bold.ttf +0 -0
  246. package/skills/skills/canvas-design/canvas-fonts/GeistMono-OFL.txt +93 -0
  247. package/skills/skills/canvas-design/canvas-fonts/GeistMono-Regular.ttf +0 -0
  248. package/skills/skills/canvas-design/canvas-fonts/Gloock-OFL.txt +93 -0
  249. package/skills/skills/canvas-design/canvas-fonts/Gloock-Regular.ttf +0 -0
  250. package/skills/skills/canvas-design/canvas-fonts/IBMPlexMono-Bold.ttf +0 -0
  251. package/skills/skills/canvas-design/canvas-fonts/IBMPlexMono-OFL.txt +93 -0
  252. package/skills/skills/canvas-design/canvas-fonts/IBMPlexMono-Regular.ttf +0 -0
  253. package/skills/skills/canvas-design/canvas-fonts/IBMPlexSerif-Bold.ttf +0 -0
  254. package/skills/skills/canvas-design/canvas-fonts/IBMPlexSerif-BoldItalic.ttf +0 -0
  255. package/skills/skills/canvas-design/canvas-fonts/IBMPlexSerif-Italic.ttf +0 -0
  256. package/skills/skills/canvas-design/canvas-fonts/IBMPlexSerif-Regular.ttf +0 -0
  257. package/skills/skills/canvas-design/canvas-fonts/InstrumentSans-Bold.ttf +0 -0
  258. package/skills/skills/canvas-design/canvas-fonts/InstrumentSans-BoldItalic.ttf +0 -0
  259. package/skills/skills/canvas-design/canvas-fonts/InstrumentSans-Italic.ttf +0 -0
  260. package/skills/skills/canvas-design/canvas-fonts/InstrumentSans-OFL.txt +93 -0
  261. package/skills/skills/canvas-design/canvas-fonts/InstrumentSans-Regular.ttf +0 -0
  262. package/skills/skills/canvas-design/canvas-fonts/InstrumentSerif-Italic.ttf +0 -0
  263. package/skills/skills/canvas-design/canvas-fonts/InstrumentSerif-Regular.ttf +0 -0
  264. package/skills/skills/canvas-design/canvas-fonts/Italiana-OFL.txt +93 -0
  265. package/skills/skills/canvas-design/canvas-fonts/Italiana-Regular.ttf +0 -0
  266. package/skills/skills/canvas-design/canvas-fonts/JetBrainsMono-Bold.ttf +0 -0
  267. package/skills/skills/canvas-design/canvas-fonts/JetBrainsMono-OFL.txt +93 -0
  268. package/skills/skills/canvas-design/canvas-fonts/JetBrainsMono-Regular.ttf +0 -0
  269. package/skills/skills/canvas-design/canvas-fonts/Jura-Light.ttf +0 -0
  270. package/skills/skills/canvas-design/canvas-fonts/Jura-Medium.ttf +0 -0
  271. package/skills/skills/canvas-design/canvas-fonts/Jura-OFL.txt +93 -0
  272. package/skills/skills/canvas-design/canvas-fonts/LibreBaskerville-OFL.txt +93 -0
  273. package/skills/skills/canvas-design/canvas-fonts/LibreBaskerville-Regular.ttf +0 -0
  274. package/skills/skills/canvas-design/canvas-fonts/Lora-Bold.ttf +0 -0
  275. package/skills/skills/canvas-design/canvas-fonts/Lora-BoldItalic.ttf +0 -0
  276. package/skills/skills/canvas-design/canvas-fonts/Lora-Italic.ttf +0 -0
  277. package/skills/skills/canvas-design/canvas-fonts/Lora-OFL.txt +93 -0
  278. package/skills/skills/canvas-design/canvas-fonts/Lora-Regular.ttf +0 -0
  279. package/skills/skills/canvas-design/canvas-fonts/NationalPark-Bold.ttf +0 -0
  280. package/skills/skills/canvas-design/canvas-fonts/NationalPark-OFL.txt +93 -0
  281. package/skills/skills/canvas-design/canvas-fonts/NationalPark-Regular.ttf +0 -0
  282. package/skills/skills/canvas-design/canvas-fonts/NothingYouCouldDo-OFL.txt +93 -0
  283. package/skills/skills/canvas-design/canvas-fonts/NothingYouCouldDo-Regular.ttf +0 -0
  284. package/skills/skills/canvas-design/canvas-fonts/Outfit-Bold.ttf +0 -0
  285. package/skills/skills/canvas-design/canvas-fonts/Outfit-OFL.txt +93 -0
  286. package/skills/skills/canvas-design/canvas-fonts/Outfit-Regular.ttf +0 -0
  287. package/skills/skills/canvas-design/canvas-fonts/PixelifySans-Medium.ttf +0 -0
  288. package/skills/skills/canvas-design/canvas-fonts/PixelifySans-OFL.txt +93 -0
  289. package/skills/skills/canvas-design/canvas-fonts/PoiretOne-OFL.txt +93 -0
  290. package/skills/skills/canvas-design/canvas-fonts/PoiretOne-Regular.ttf +0 -0
  291. package/skills/skills/canvas-design/canvas-fonts/RedHatMono-Bold.ttf +0 -0
  292. package/skills/skills/canvas-design/canvas-fonts/RedHatMono-OFL.txt +93 -0
  293. package/skills/skills/canvas-design/canvas-fonts/RedHatMono-Regular.ttf +0 -0
  294. package/skills/skills/canvas-design/canvas-fonts/Silkscreen-OFL.txt +93 -0
  295. package/skills/skills/canvas-design/canvas-fonts/Silkscreen-Regular.ttf +0 -0
  296. package/skills/skills/canvas-design/canvas-fonts/SmoochSans-Medium.ttf +0 -0
  297. package/skills/skills/canvas-design/canvas-fonts/SmoochSans-OFL.txt +93 -0
  298. package/skills/skills/canvas-design/canvas-fonts/Tektur-Medium.ttf +0 -0
  299. package/skills/skills/canvas-design/canvas-fonts/Tektur-OFL.txt +93 -0
  300. package/skills/skills/canvas-design/canvas-fonts/Tektur-Regular.ttf +0 -0
  301. package/skills/skills/canvas-design/canvas-fonts/WorkSans-Bold.ttf +0 -0
  302. package/skills/skills/canvas-design/canvas-fonts/WorkSans-BoldItalic.ttf +0 -0
  303. package/skills/skills/canvas-design/canvas-fonts/WorkSans-Italic.ttf +0 -0
  304. package/skills/skills/canvas-design/canvas-fonts/WorkSans-OFL.txt +93 -0
  305. package/skills/skills/canvas-design/canvas-fonts/WorkSans-Regular.ttf +0 -0
  306. package/skills/skills/canvas-design/canvas-fonts/YoungSerif-OFL.txt +93 -0
  307. package/skills/skills/canvas-design/canvas-fonts/YoungSerif-Regular.ttf +0 -0
  308. package/skills/skills/doc-coauthoring/SKILL.md +375 -0
  309. package/skills/skills/docx/LICENSE.txt +30 -0
  310. package/skills/skills/docx/SKILL.md +197 -0
  311. package/skills/skills/docx/docx-js.md +350 -0
  312. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
  313. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
  314. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
  315. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
  316. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
  317. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
  318. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
  319. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
  320. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
  321. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
  322. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
  323. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
  324. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
  325. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
  326. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
  327. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
  328. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
  329. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
  330. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
  331. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
  332. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
  333. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
  334. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
  335. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
  336. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
  337. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
  338. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
  339. package/skills/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
  340. package/skills/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
  341. package/skills/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
  342. package/skills/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
  343. package/skills/skills/docx/ooxml/schemas/mce/mc.xsd +75 -0
  344. package/skills/skills/docx/ooxml/schemas/microsoft/wml-2010.xsd +560 -0
  345. package/skills/skills/docx/ooxml/schemas/microsoft/wml-2012.xsd +67 -0
  346. package/skills/skills/docx/ooxml/schemas/microsoft/wml-2018.xsd +14 -0
  347. package/skills/skills/docx/ooxml/schemas/microsoft/wml-cex-2018.xsd +20 -0
  348. package/skills/skills/docx/ooxml/schemas/microsoft/wml-cid-2016.xsd +13 -0
  349. package/skills/skills/docx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
  350. package/skills/skills/docx/ooxml/schemas/microsoft/wml-symex-2015.xsd +8 -0
  351. package/skills/skills/docx/ooxml/scripts/pack.py +159 -0
  352. package/skills/skills/docx/ooxml/scripts/unpack.py +29 -0
  353. package/skills/skills/docx/ooxml/scripts/validate.py +69 -0
  354. package/skills/skills/docx/ooxml/scripts/validation/__init__.py +15 -0
  355. package/skills/skills/docx/ooxml/scripts/validation/base.py +951 -0
  356. package/skills/skills/docx/ooxml/scripts/validation/docx.py +274 -0
  357. package/skills/skills/docx/ooxml/scripts/validation/pptx.py +315 -0
  358. package/skills/skills/docx/ooxml/scripts/validation/redlining.py +279 -0
  359. package/skills/skills/docx/ooxml.md +610 -0
  360. package/skills/skills/docx/scripts/__init__.py +1 -0
  361. package/skills/skills/docx/scripts/document.py +1276 -0
  362. package/skills/skills/docx/scripts/templates/comments.xml +3 -0
  363. package/skills/skills/docx/scripts/templates/commentsExtended.xml +3 -0
  364. package/skills/skills/docx/scripts/templates/commentsExtensible.xml +3 -0
  365. package/skills/skills/docx/scripts/templates/commentsIds.xml +3 -0
  366. package/skills/skills/docx/scripts/templates/people.xml +3 -0
  367. package/skills/skills/docx/scripts/utilities.py +374 -0
  368. package/skills/skills/frontend-design/LICENSE.txt +177 -0
  369. package/skills/skills/frontend-design/SKILL.md +42 -0
  370. package/skills/skills/internal-comms/LICENSE.txt +202 -0
  371. package/skills/skills/internal-comms/SKILL.md +32 -0
  372. package/skills/skills/internal-comms/examples/3p-updates.md +47 -0
  373. package/skills/skills/internal-comms/examples/company-newsletter.md +65 -0
  374. package/skills/skills/internal-comms/examples/faq-answers.md +30 -0
  375. package/skills/skills/internal-comms/examples/general-comms.md +16 -0
  376. package/skills/skills/mcp-builder/LICENSE.txt +202 -0
  377. package/skills/skills/mcp-builder/SKILL.md +236 -0
  378. package/skills/skills/mcp-builder/reference/evaluation.md +602 -0
  379. package/skills/skills/mcp-builder/reference/mcp_best_practices.md +249 -0
  380. package/skills/skills/mcp-builder/reference/node_mcp_server.md +970 -0
  381. package/skills/skills/mcp-builder/reference/python_mcp_server.md +719 -0
  382. package/skills/skills/mcp-builder/scripts/connections.py +151 -0
  383. package/skills/skills/mcp-builder/scripts/evaluation.py +373 -0
  384. package/skills/skills/mcp-builder/scripts/example_evaluation.xml +22 -0
  385. package/skills/skills/mcp-builder/scripts/requirements.txt +2 -0
  386. package/skills/skills/pdf/LICENSE.txt +30 -0
  387. package/skills/skills/pdf/SKILL.md +294 -0
  388. package/skills/skills/pdf/forms.md +205 -0
  389. package/skills/skills/pdf/reference.md +612 -0
  390. package/skills/skills/pdf/scripts/check_bounding_boxes.py +70 -0
  391. package/skills/skills/pdf/scripts/check_bounding_boxes_test.py +226 -0
  392. package/skills/skills/pdf/scripts/check_fillable_fields.py +12 -0
  393. package/skills/skills/pdf/scripts/convert_pdf_to_images.py +35 -0
  394. package/skills/skills/pdf/scripts/create_validation_image.py +41 -0
  395. package/skills/skills/pdf/scripts/extract_form_field_info.py +152 -0
  396. package/skills/skills/pdf/scripts/fill_fillable_fields.py +114 -0
  397. package/skills/skills/pdf/scripts/fill_pdf_form_with_annotations.py +108 -0
  398. package/skills/skills/pptx/LICENSE.txt +30 -0
  399. package/skills/skills/pptx/SKILL.md +484 -0
  400. package/skills/skills/pptx/html2pptx.md +625 -0
  401. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
  402. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
  403. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
  404. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
  405. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
  406. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
  407. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
  408. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
  409. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
  410. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
  411. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
  412. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
  413. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
  414. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
  415. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
  416. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
  417. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
  418. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
  419. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
  420. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
  421. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
  422. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
  423. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
  424. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
  425. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
  426. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
  427. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
  428. package/skills/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
  429. package/skills/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
  430. package/skills/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
  431. package/skills/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
  432. package/skills/skills/pptx/ooxml/schemas/mce/mc.xsd +75 -0
  433. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-2010.xsd +560 -0
  434. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-2012.xsd +67 -0
  435. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-2018.xsd +14 -0
  436. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-cex-2018.xsd +20 -0
  437. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-cid-2016.xsd +13 -0
  438. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
  439. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-symex-2015.xsd +8 -0
  440. package/skills/skills/pptx/ooxml/scripts/pack.py +159 -0
  441. package/skills/skills/pptx/ooxml/scripts/unpack.py +29 -0
  442. package/skills/skills/pptx/ooxml/scripts/validate.py +69 -0
  443. package/skills/skills/pptx/ooxml/scripts/validation/__init__.py +15 -0
  444. package/skills/skills/pptx/ooxml/scripts/validation/base.py +951 -0
  445. package/skills/skills/pptx/ooxml/scripts/validation/docx.py +274 -0
  446. package/skills/skills/pptx/ooxml/scripts/validation/pptx.py +315 -0
  447. package/skills/skills/pptx/ooxml/scripts/validation/redlining.py +279 -0
  448. package/skills/skills/pptx/ooxml.md +427 -0
  449. package/skills/skills/pptx/scripts/html2pptx.js +979 -0
  450. package/skills/skills/pptx/scripts/inventory.py +1020 -0
  451. package/skills/skills/pptx/scripts/rearrange.py +231 -0
  452. package/skills/skills/pptx/scripts/replace.py +385 -0
  453. package/skills/skills/pptx/scripts/thumbnail.py +450 -0
  454. package/skills/skills/skill-creator/LICENSE.txt +202 -0
  455. package/skills/skills/skill-creator/SKILL.md +356 -0
  456. package/skills/skills/skill-creator/references/output-patterns.md +82 -0
  457. package/skills/skills/skill-creator/references/workflows.md +28 -0
  458. package/skills/skills/skill-creator/scripts/init_skill.py +303 -0
  459. package/skills/skills/skill-creator/scripts/package_skill.py +110 -0
  460. package/skills/skills/skill-creator/scripts/quick_validate.py +95 -0
  461. package/skills/skills/slack-gif-creator/LICENSE.txt +202 -0
  462. package/skills/skills/slack-gif-creator/SKILL.md +254 -0
  463. package/skills/skills/slack-gif-creator/core/easing.py +234 -0
  464. package/skills/skills/slack-gif-creator/core/frame_composer.py +176 -0
  465. package/skills/skills/slack-gif-creator/core/gif_builder.py +269 -0
  466. package/skills/skills/slack-gif-creator/core/validators.py +136 -0
  467. package/skills/skills/slack-gif-creator/requirements.txt +4 -0
  468. package/skills/skills/theme-factory/LICENSE.txt +202 -0
  469. package/skills/skills/theme-factory/SKILL.md +59 -0
  470. package/skills/skills/theme-factory/theme-showcase.pdf +0 -0
  471. package/skills/skills/theme-factory/themes/arctic-frost.md +19 -0
  472. package/skills/skills/theme-factory/themes/botanical-garden.md +19 -0
  473. package/skills/skills/theme-factory/themes/desert-rose.md +19 -0
  474. package/skills/skills/theme-factory/themes/forest-canopy.md +19 -0
  475. package/skills/skills/theme-factory/themes/golden-hour.md +19 -0
  476. package/skills/skills/theme-factory/themes/midnight-galaxy.md +19 -0
  477. package/skills/skills/theme-factory/themes/modern-minimalist.md +19 -0
  478. package/skills/skills/theme-factory/themes/ocean-depths.md +19 -0
  479. package/skills/skills/theme-factory/themes/sunset-boulevard.md +19 -0
  480. package/skills/skills/theme-factory/themes/tech-innovation.md +19 -0
  481. package/skills/skills/web-artifacts-builder/LICENSE.txt +202 -0
  482. package/skills/skills/web-artifacts-builder/SKILL.md +74 -0
  483. package/skills/skills/web-artifacts-builder/scripts/bundle-artifact.sh +54 -0
  484. package/skills/skills/web-artifacts-builder/scripts/init-artifact.sh +322 -0
  485. package/skills/skills/webapp-testing/LICENSE.txt +202 -0
  486. package/skills/skills/webapp-testing/SKILL.md +96 -0
  487. package/skills/skills/webapp-testing/examples/console_logging.py +35 -0
  488. package/skills/skills/webapp-testing/examples/element_discovery.py +40 -0
  489. package/skills/skills/webapp-testing/examples/static_html_automation.py +33 -0
  490. package/skills/skills/webapp-testing/scripts/with_server.py +106 -0
  491. package/skills/skills/xlsx/LICENSE.txt +30 -0
  492. package/skills/skills/xlsx/SKILL.md +289 -0
  493. package/skills/skills/xlsx/recalc.py +178 -0
  494. package/skills/spec/agent-skills-spec.md +3 -0
  495. package/skills/template/SKILL.md +6 -0
  496. package/src/agents.ts +504 -0
  497. package/src/ai-client.ts +1456 -0
  498. package/src/auth.ts +648 -0
  499. package/src/cancellation.ts +176 -0
  500. package/src/checkpoint.ts +219 -0
  501. package/src/cli.ts +384 -0
  502. package/src/config.ts +248 -0
  503. package/src/context-compressor.ts +290 -0
  504. package/src/conversation.ts +288 -0
  505. package/src/gui-subagent/action-parser/actionParser.ts +312 -0
  506. package/src/gui-subagent/action-parser/constants.ts +12 -0
  507. package/src/gui-subagent/action-parser/index.ts +6 -0
  508. package/src/gui-subagent/action-parser/types.ts +31 -0
  509. package/src/gui-subagent/agent/gui-agent.ts +982 -0
  510. package/src/gui-subagent/agent/index.ts +5 -0
  511. package/src/gui-subagent/index.ts +139 -0
  512. package/src/gui-subagent/operator/base-operator.ts +246 -0
  513. package/src/gui-subagent/operator/computer-operator.ts +520 -0
  514. package/src/gui-subagent/operator/index.ts +7 -0
  515. package/src/gui-subagent/types/actions.ts +263 -0
  516. package/src/gui-subagent/types/index.ts +6 -0
  517. package/src/gui-subagent/types/operator.ts +106 -0
  518. package/src/gui-subagent/utils.ts +51 -0
  519. package/src/index.ts +18 -0
  520. package/src/input-processor.ts +282 -0
  521. package/src/logger.ts +438 -0
  522. package/src/mcp.ts +563 -0
  523. package/src/memory.ts +303 -0
  524. package/src/session-manager.ts +308 -0
  525. package/src/session.ts +1280 -0
  526. package/src/skill-invoker.ts +1888 -0
  527. package/src/skill-loader.ts +476 -0
  528. package/src/slash-commands.ts +1150 -0
  529. package/src/smart-approval.ts +595 -0
  530. package/src/system-prompt-generator.ts +786 -0
  531. package/src/theme.ts +455 -0
  532. package/src/tools.ts +3398 -0
  533. package/src/types.ts +198 -0
  534. package/src/update.ts +270 -0
  535. package/src/workflow.ts +508 -0
  536. package/tsconfig.json +22 -0
  537. package/vitest.config.ts +19 -0
@@ -0,0 +1,1888 @@
1
+ import fs from 'fs/promises';
2
+ import path from 'path';
3
+ import os from 'os';
4
+ import { getSkillLoader, SkillInfo, SkillLoader } from './skill-loader.js';
5
+ import { getToolRegistry } from './tools.js';
6
+ import { ExecutionMode, Tool } from './types.js';
7
+ import { getConfigManager } from './config.js';
8
+
9
+ // Re-export SkillInfo for other modules
10
+ export type { SkillInfo };
11
+
12
+ /**
13
+ * Track skill execution history for tracking failures
14
+ */
15
+ export class SkillExecutionHistory {
16
+ private history: Map<string, number> = new Map();
17
+
18
+ /**
19
+ * Get failure count for a task
20
+ */
21
+ getFailureCount(taskKey: string): number {
22
+ return this.history.get(taskKey) || 0;
23
+ }
24
+
25
+ /**
26
+ * Increment failure count for a task
27
+ */
28
+ incrementFailure(taskKey: string): number {
29
+ const count = this.getFailureCount(taskKey) + 1;
30
+ this.history.set(taskKey, count);
31
+ return count;
32
+ }
33
+
34
+ /**
35
+ * Reset failure count for a task (e.g., after success)
36
+ */
37
+ reset(taskKey: string): void {
38
+ this.history.delete(taskKey);
39
+ }
40
+
41
+ /**
42
+ * Check if threshold reached
43
+ */
44
+ shouldUseFallback(taskKey: string, threshold: number = 2): boolean {
45
+ return this.getFailureCount(taskKey) >= threshold;
46
+ }
47
+ }
48
+
49
+ // Singleton execution history
50
+ const executionHistory = new SkillExecutionHistory();
51
+
52
+ export function getExecutionHistory(): SkillExecutionHistory {
53
+ return executionHistory;
54
+ }
55
+
56
+ export interface SkillExecutionParams {
57
+ skillId: string;
58
+ taskDescription: string;
59
+ inputFile?: string;
60
+ outputFile?: string;
61
+ options?: Record<string, any>;
62
+ /** Task ID for workspace directory naming */
63
+ taskId?: string;
64
+ }
65
+
66
+ /**
67
+ * Execution step interface - tells Agent what to do next
68
+ */
69
+ export interface ExecutionStep {
70
+ step: number;
71
+ action: string;
72
+ description: string;
73
+ command?: string;
74
+ file?: string;
75
+ reason: string;
76
+ }
77
+
78
+ /**
79
+ * Skill execution result - contains guidance and next actions
80
+ */
81
+ export interface SkillExecutionResult {
82
+ success: boolean;
83
+ output?: string;
84
+ error?: string;
85
+ files?: string[];
86
+ /** Tells Agent what to do next */
87
+ nextSteps?: ExecutionStep[];
88
+ /** Skill type for determining if manual execution is needed */
89
+ requiresManualExecution?: boolean;
90
+ /** Workspace directory used, for cleanup */
91
+ workspaceDir?: string;
92
+ /** Files to preserve (relative paths), skipped during cleanup */
93
+ preserveFiles?: string[];
94
+ }
95
+
96
+ export interface SkillMatcherResult {
97
+ skill: SkillInfo;
98
+ confidence: number;
99
+ matchedKeywords: string[];
100
+ category: string;
101
+ }
102
+
103
+ // ============================================================
104
+ // Workspace Utility Functions
105
+ // ============================================================
106
+
107
+ /**
108
+ * Get workspace directory path
109
+ * @param taskId Task ID for creating unique workspace directory
110
+ * @returns Absolute path to workspace directory
111
+ */
112
+ export function getWorkspaceDir(taskId: string): string {
113
+ // Try to get from config first
114
+ try {
115
+ const configManager = getConfigManager();
116
+ const config = configManager.getSettings?.();
117
+ if (config?.workspacePath) {
118
+ return path.join(config.workspacePath, taskId);
119
+ }
120
+ } catch {
121
+ // Config not available, use default
122
+ }
123
+
124
+ // Default to ~/.xagent/workspace
125
+ return path.join(os.homedir(), '.xagent', 'workspace', taskId);
126
+ }
127
+
128
+ /**
129
+ * Get base workspace directory (without task-id)
130
+ */
131
+ export function getBaseWorkspaceDir(): string {
132
+ try {
133
+ const configManager = getConfigManager();
134
+ const config = configManager.getSettings?.();
135
+ if (config?.workspacePath) {
136
+ return config.workspacePath;
137
+ }
138
+ } catch {
139
+ // Config not available, use default
140
+ }
141
+
142
+ return path.join(os.homedir(), '.xagent', 'workspace');
143
+ }
144
+
145
+ /**
146
+ * Get workspace directory description for AI
147
+ * Returns the actual workspace path from config, or default path
148
+ */
149
+ export function getWorkspaceDescription(): string {
150
+ try {
151
+ const configManager = getConfigManager();
152
+ const config = configManager.getSettings?.();
153
+ if (config?.workspacePath) {
154
+ return config.workspacePath;
155
+ }
156
+ } catch {
157
+ // Config not available, use default
158
+ }
159
+
160
+ return path.join(os.homedir(), '.xagent', 'workspace');
161
+ }
162
+
163
+ /**
164
+ * Ensure workspace directory exists
165
+ * @param workspaceDir Workspace directory path
166
+ */
167
+ export async function ensureWorkspaceDir(workspaceDir: string): Promise<void> {
168
+ await fs.mkdir(workspaceDir, { recursive: true });
169
+ }
170
+
171
+ /**
172
+ * Clean up workspace directory
173
+ * @param workspaceDir Workspace directory path
174
+ * @param preserveFiles Files to preserve (relative paths)
175
+ */
176
+ export async function cleanupWorkspace(workspaceDir: string, preserveFiles: string[] = []): Promise<void> {
177
+ try {
178
+ const entries = await fs.readdir(workspaceDir, { withFileTypes: true });
179
+
180
+ for (const entry of entries) {
181
+ const fullPath = path.join(workspaceDir, entry.name);
182
+
183
+ // Skip files to preserve
184
+ if (preserveFiles.includes(entry.name)) {
185
+ continue;
186
+ }
187
+
188
+ if (entry.isDirectory()) {
189
+ // Recursively delete subdirectories
190
+ await fs.rm(fullPath, { recursive: true, force: true });
191
+ } else {
192
+ // Delete files
193
+ await fs.unlink(fullPath);
194
+ }
195
+ }
196
+ } catch (error: any) {
197
+ if (error.code !== 'ENOENT') {
198
+ console.warn(`Workspace cleanup failed: ${error.message}`);
199
+ }
200
+ }
201
+ }
202
+
203
+ /**
204
+ * Determine if workspace should be auto-cleaned based on ExecutionMode
205
+ * @param executionMode Execution mode
206
+ * @returns Whether auto-cleanup should happen
207
+ */
208
+ export function shouldAutoCleanup(executionMode: ExecutionMode): boolean {
209
+ // YOLO mode: fully automatic, clean up directly
210
+ if (executionMode === ExecutionMode.YOLO) {
211
+ return true;
212
+ }
213
+ // Other modes require user confirmation
214
+ return false;
215
+ }
216
+
217
+ /**
218
+ * Generate cleanup prompt message
219
+ * @param workspaceDir Workspace directory path
220
+ */
221
+ export async function getCleanupInfo(workspaceDir: string): Promise<{ files: string[]; totalSize: string }> {
222
+ try {
223
+ const entries = await fs.readdir(workspaceDir, { withFileTypes: true });
224
+ const files: string[] = [];
225
+
226
+ for (const entry of entries) {
227
+ files.push(entry.name);
228
+ }
229
+
230
+ // Calculate total size
231
+ let totalSize = 0;
232
+ for (const entry of entries) {
233
+ if (entry.isFile()) {
234
+ const stats = await fs.stat(path.join(workspaceDir, entry.name));
235
+ totalSize += stats.size;
236
+ }
237
+ }
238
+
239
+ const formatSize = (bytes: number): string => {
240
+ if (bytes < 1024) return `${bytes} B`;
241
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(2)} KB`;
242
+ return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
243
+ };
244
+
245
+ return { files, totalSize: formatSize(totalSize) };
246
+ } catch {
247
+ return { files: [], totalSize: '0 B' };
248
+ }
249
+ }
250
+
251
+ // ============================================================
252
+ // Shared Content Extraction Utilities
253
+ // ============================================================
254
+
255
+ /**
256
+ * Remove Markdown formatting (bold, italic, etc.)
257
+ */
258
+ export function stripMarkdown(text: string): string {
259
+ return text
260
+ .replace(/\*\*(.+?)\*\*/g, '$1') // Remove bold **
261
+ .replace(/\*(.+?)\*/g, '$1') // Remove italic *
262
+ .replace(/`(.+?)`/g, '$1') // Remove inline code `
263
+ .trim();
264
+ }
265
+
266
+ /**
267
+ * Extract content related to keywords (for SKILL.md content matching)
268
+ * @param content SKILL.md full content
269
+ * @param keywords Keyword list
270
+ * @param maxLength Maximum return length
271
+ * @returns Extracted relevant content
272
+ */
273
+ export function extractContent(content: string, keywords: string[], maxLength: number = 5000): string {
274
+ const lines = content.split('\n');
275
+ const relevantLines: string[] = [];
276
+ let inRelevantSection = false;
277
+ let sectionDepth = 0;
278
+ let found = false;
279
+
280
+ for (let i = 0; i < lines.length; i++) {
281
+ const line = lines[i];
282
+
283
+ // Detect headings
284
+ if (line.match(/^#{1,6}\s/)) {
285
+ const strippedLine = stripMarkdown(line);
286
+ const lowerLine = strippedLine.toLowerCase();
287
+
288
+ // Check if contains keywords
289
+ const hasKeyword = keywords.some(kw => lowerLine.includes(kw.toLowerCase()));
290
+
291
+ if (hasKeyword) {
292
+ inRelevantSection = true;
293
+ found = true;
294
+ sectionDepth = line.match(/^(#+)/)?.[1].length || 1;
295
+ } else if (inRelevantSection) {
296
+ // Check if same level or higher heading (end current section)
297
+ const currentDepth = line.match(/^(#+)/)?.[1].length || 1;
298
+ if (currentDepth <= sectionDepth) {
299
+ inRelevantSection = false;
300
+ }
301
+ }
302
+ }
303
+
304
+ if (inRelevantSection || found) {
305
+ relevantLines.push(line);
306
+ }
307
+
308
+ // Limit content length
309
+ if (relevantLines.join('\n').length > maxLength) {
310
+ relevantLines.push('\n...(content truncated for brevity)...');
311
+ break;
312
+ }
313
+ }
314
+
315
+ if (relevantLines.length > 0) {
316
+ return relevantLines.join('\n').trim();
317
+ }
318
+
319
+ // If still not found, return first 100 lines
320
+ return lines.slice(0, 100).join('\n').trim() + '\n\n...(See SKILL.md for full instructions)';
321
+ }
322
+
323
+ /**
324
+ * Read SKILL.md and extract relevant content based on task
325
+ */
326
+ export async function readSkillContent(skillPath: string, keywords: string[], maxLength: number = 5000): Promise<string> {
327
+ const skillMdPath = path.join(skillPath, 'SKILL.md');
328
+ const content = await fs.readFile(skillMdPath, 'utf-8');
329
+ return extractContent(content, keywords, maxLength);
330
+ }
331
+
332
+ // ============================================================
333
+ // SKILL Trigger Keywords Mapping
334
+ // ============================================================
335
+
336
+ const SKILL_TRIGGERS: Record<string, { skillId: string; keywords: string[]; category: string }> = {
337
+ docx: {
338
+ skillId: 'docx',
339
+ keywords: [
340
+ 'word document', 'docx', 'microsoft word', 'create word', 'edit word',
341
+ 'create .docx', '.docx file', 'word file', 'document creation',
342
+ 'word editing', 'tracked changes', 'comments'
343
+ ],
344
+ category: 'Document Processing'
345
+ },
346
+ pdf: {
347
+ skillId: 'pdf',
348
+ keywords: [
349
+ 'pdf', 'create pdf', 'edit pdf', 'pdf document', 'pdf file',
350
+ 'extract pdf', 'merge pdf', 'split pdf', 'pdf form', 'manipulate pdf'
351
+ ],
352
+ category: 'Document Processing'
353
+ },
354
+ pptx: {
355
+ skillId: 'pptx',
356
+ keywords: [
357
+ 'powerpoint', 'ppt', 'pptx', 'presentation', 'slide',
358
+ 'create presentation', 'edit powerpoint', 'create slides',
359
+ 'powerpoint file', 'presentation file'
360
+ ],
361
+ category: 'Document Processing'
362
+ },
363
+ xlsx: {
364
+ skillId: 'xlsx',
365
+ keywords: [
366
+ 'excel', 'spreadsheet', 'xlsx', 'create excel', 'edit spreadsheet',
367
+ 'excel file', 'spreadsheet file', 'formulas', 'data analysis'
368
+ ],
369
+ category: 'Spreadsheet & Data'
370
+ },
371
+ frontend_design: {
372
+ skillId: 'frontend-design',
373
+ keywords: [
374
+ 'web page', 'website', 'web app', 'frontend', 'ui', 'user interface',
375
+ 'create website', 'build website', 'web component', 'html css',
376
+ 'landing page', 'dashboard', 'react', 'vue', 'web interface'
377
+ ],
378
+ category: 'Frontend & Web Development'
379
+ },
380
+ web_artifacts_builder: {
381
+ skillId: 'web-artifacts-builder',
382
+ keywords: [
383
+ 'complex react', 'react artifact', 'stateful artifact', 'routing',
384
+ 'web artifact', 'interactive artifact', 'web-based tool'
385
+ ],
386
+ category: 'Frontend & Web Development'
387
+ },
388
+ webapp_testing: {
389
+ skillId: 'webapp-testing',
390
+ keywords: [
391
+ 'test web', 'web testing', 'browser test', 'playwright', 'e2e test',
392
+ 'frontend test', 'capture screenshot', 'verify web'
393
+ ],
394
+ category: 'Frontend & Web Development'
395
+ },
396
+ canvas_design: {
397
+ skillId: 'canvas-design',
398
+ keywords: [
399
+ 'poster', 'artwork', 'visual art', 'canvas', 'design art',
400
+ 'create poster', 'create artwork', 'visual design', 'graphic art'
401
+ ],
402
+ category: 'Visual & Creative Design'
403
+ },
404
+ algorithmic_art: {
405
+ skillId: 'algorithmic-art',
406
+ keywords: [
407
+ 'generative art', 'algorithmic art', 'p5.js', 'particle system',
408
+ 'flow field', 'creative coding', 'code art'
409
+ ],
410
+ category: 'Visual & Creative Design'
411
+ },
412
+ theme_factory: {
413
+ skillId: 'theme-factory',
414
+ keywords: [
415
+ 'theme', 'color scheme', 'font theme', 'styling theme',
416
+ 'consistent theme', 'apply theme', 'theme colors'
417
+ ],
418
+ category: 'Visual & Creative Design'
419
+ },
420
+ brand_guidelines: {
421
+ skillId: 'brand-guidelines',
422
+ keywords: [
423
+ 'brand colors', 'brand guidelines', 'anthropic brand',
424
+ 'official brand', 'brand styling'
425
+ ],
426
+ category: 'Visual & Creative Design'
427
+ },
428
+ slack_gif_creator: {
429
+ skillId: 'slack-gif-creator',
430
+ keywords: [
431
+ 'slack gif', 'animated gif', 'gif for slack', 'slack animation'
432
+ ],
433
+ category: 'Visual & Creative Design'
434
+ },
435
+ mcp_builder: {
436
+ skillId: 'mcp-builder',
437
+ keywords: [
438
+ 'mcp server', 'model context protocol', 'create mcp',
439
+ 'mcp integration', 'external api integration'
440
+ ],
441
+ category: 'Development & Integration'
442
+ },
443
+ skill_creator: {
444
+ skillId: 'skill-creator',
445
+ keywords: [
446
+ 'create skill', 'new skill', 'skill development',
447
+ 'extend capabilities', 'custom skill'
448
+ ],
449
+ category: 'Development & Integration'
450
+ },
451
+ doc_coauthoring: {
452
+ skillId: 'doc-coauthoring',
453
+ keywords: [
454
+ 'documentation', 'technical docs', 'write documentation',
455
+ 'coauthor', 'doc writing', 'technical writing'
456
+ ],
457
+ category: 'Communication & Documentation'
458
+ },
459
+ internal_comms: {
460
+ skillId: 'internal-comms',
461
+ keywords: [
462
+ 'internal communication', 'status report', 'newsletter',
463
+ 'internal update', 'team communication', 'announcement'
464
+ ],
465
+ category: 'Communication & Documentation'
466
+ }
467
+ };
468
+
469
+ // ============================================================
470
+ // SkillInvoker Main Class
471
+ // ============================================================
472
+
473
+ export class SkillInvoker {
474
+ private skillLoader: SkillLoader;
475
+ private initialized: boolean = false;
476
+ private skillCache: Map<string, SkillInfo> = new Map();
477
+
478
+ constructor(skillLoader?: SkillLoader) {
479
+ this.skillLoader = skillLoader || getSkillLoader();
480
+ }
481
+
482
+ async initialize(): Promise<void> {
483
+ if (this.initialized) return;
484
+
485
+ const skills = await this.skillLoader.loadAllSkills();
486
+ for (const skill of skills) {
487
+ this.skillCache.set(skill.id, skill);
488
+ }
489
+
490
+ this.initialized = true;
491
+ }
492
+
493
+ /**
494
+ * Get list of all available skills
495
+ */
496
+ async listAvailableSkills(): Promise<SkillInfo[]> {
497
+ await this.initialize();
498
+ return this.skillLoader.listSkills();
499
+ }
500
+
501
+ /**
502
+ * Match the most relevant skill based on user input
503
+ */
504
+ async matchSkill(userInput: string): Promise<SkillMatcherResult | null> {
505
+ await this.initialize();
506
+
507
+ const lowerInput = userInput.toLowerCase();
508
+ let bestMatch: SkillMatcherResult | null = null;
509
+
510
+ // First check predefined trigger keywords
511
+ for (const trigger of Object.values(SKILL_TRIGGERS)) {
512
+ const matchedKeywords = trigger.keywords.filter(kw => lowerInput.includes(kw.toLowerCase()));
513
+
514
+ if (matchedKeywords.length > 0) {
515
+ const confidence = matchedKeywords.length / trigger.keywords.length;
516
+ const skill = this.skillCache.get(trigger.skillId);
517
+
518
+ if (skill) {
519
+ const result: SkillMatcherResult = {
520
+ skill,
521
+ confidence,
522
+ matchedKeywords,
523
+ category: trigger.category
524
+ };
525
+
526
+ if (!bestMatch || confidence > bestMatch.confidence) {
527
+ bestMatch = result;
528
+ }
529
+ }
530
+ }
531
+ }
532
+
533
+ return bestMatch;
534
+ }
535
+
536
+ /**
537
+ * Get skill details
538
+ */
539
+ async getSkillDetails(skillId: string): Promise<SkillInfo | null> {
540
+ await this.initialize();
541
+ return this.skillLoader.getSkill(skillId) || null;
542
+ }
543
+
544
+ /**
545
+ * Execute skill
546
+ */
547
+ async executeSkill(params: SkillExecutionParams): Promise<SkillExecutionResult> {
548
+ const skill = this.skillCache.get(params.skillId);
549
+
550
+ if (!skill) {
551
+ return {
552
+ success: false,
553
+ error: `Skill not found: ${params.skillId}`
554
+ };
555
+ }
556
+
557
+ // Generate task ID (if not provided)
558
+ const taskId = params.taskId || `${params.skillId}-${Date.now()}`;
559
+
560
+ try {
561
+ // Execute based on skillId
562
+ const executor = this.getSkillExecutor(skill.id);
563
+ const result = await executor.execute(skill, { ...params, taskId });
564
+
565
+ // Add workspaceDir to result
566
+ if (result.success && result.nextSteps && result.nextSteps.length > 0) {
567
+ result.workspaceDir = getWorkspaceDir(taskId);
568
+ await ensureWorkspaceDir(result.workspaceDir);
569
+ }
570
+
571
+ return result;
572
+ } catch (error: any) {
573
+ return {
574
+ success: false,
575
+ error: error.message
576
+ };
577
+ }
578
+ }
579
+
580
+ /**
581
+ * Clean up workspace based on execution result
582
+ * @param result Skill execution result
583
+ * @param executionMode Execution mode
584
+ * @returns Whether cleanup was performed
585
+ */
586
+ async cleanupAfterExecution(result: SkillExecutionResult, executionMode: ExecutionMode): Promise<boolean> {
587
+ if (!result.workspaceDir) {
588
+ return false;
589
+ }
590
+
591
+ // YOLO mode: auto cleanup
592
+ if (executionMode === ExecutionMode.YOLO) {
593
+ await cleanupWorkspace(result.workspaceDir, result.preserveFiles || []);
594
+ return true;
595
+ }
596
+
597
+ // Other modes: don't auto cleanup, let user decide
598
+ return false;
599
+ }
600
+
601
+ /**
602
+ * Get cleanup prompt (for asking user)
603
+ */
604
+ async getCleanupPrompt(result: SkillExecutionResult): Promise<string | null> {
605
+ if (!result.workspaceDir) {
606
+ return null;
607
+ }
608
+
609
+ const info = await getCleanupInfo(result.workspaceDir);
610
+ if (info.files.length === 0) {
611
+ return null;
612
+ }
613
+
614
+ return `Task completed! Workspace directory contains the following files:\n` +
615
+ `📁 ${result.workspaceDir}\n` +
616
+ `Files: ${info.files.join(', ')}\n` +
617
+ `Size: ${info.totalSize}\n\n` +
618
+ `Do you want to clean up these temporary files?`;
619
+ }
620
+
621
+ /**
622
+ * Get executor for skill
623
+ * Determine which executor to use based on skill.id
624
+ */
625
+ private getSkillExecutor(skillId: string): SkillExecutor {
626
+ const docProcessingSkills = ['docx', 'pdf', 'pptx', 'xlsx'];
627
+ const frontendSkills = ['frontend-design', 'web-artifacts-builder', 'webapp-testing'];
628
+ const visualDesignSkills = ['canvas-design', 'algorithmic-art', 'theme-factory', 'brand-guidelines', 'slack-gif-creator'];
629
+ const docSkills = ['doc-coauthoring', 'internal-comms'];
630
+
631
+ if (docProcessingSkills.includes(skillId)) {
632
+ return new DocumentSkillExecutor();
633
+ }
634
+ if (frontendSkills.includes(skillId)) {
635
+ return new FrontendSkillExecutor();
636
+ }
637
+ if (visualDesignSkills.includes(skillId)) {
638
+ return new VisualDesignSkillExecutor();
639
+ }
640
+ if (docSkills.includes(skillId)) {
641
+ return new DocumentationSkillExecutor();
642
+ }
643
+ return new DefaultSkillExecutor();
644
+ }
645
+
646
+ /**
647
+ * Generate skill invocation instructions (for system prompt)
648
+ */
649
+ generateSkillInstructions(): string {
650
+ const categories = new Map<string, { skillId: string; name: string; description: string }[]>();
651
+
652
+ for (const trigger of Object.values(SKILL_TRIGGERS)) {
653
+ const skill = this.skillCache.get(trigger.skillId);
654
+ if (skill) {
655
+ const existing = categories.get(trigger.category) || [];
656
+ existing.push({
657
+ skillId: trigger.skillId,
658
+ name: skill.name,
659
+ description: skill.description
660
+ });
661
+ categories.set(trigger.category, existing);
662
+ }
663
+ }
664
+
665
+ let instructions = '\n## Available Skills\n\n';
666
+ instructions += 'When users request tasks matching these domains, invoke the "InvokeSkill" tool:\n\n';
667
+
668
+ for (const [category, skills] of categories) {
669
+ instructions += `### ${category}\n`;
670
+ for (const skill of skills) {
671
+ instructions += `**${skill.name}** (${skill.skillId}): ${skill.description}\n`;
672
+ instructions += ` �?Use: InvokeSkill(skillId="${skill.skillId}", taskDescription="...")\n`;
673
+ }
674
+ instructions += '\n';
675
+ }
676
+
677
+ return instructions;
678
+ }
679
+ }
680
+
681
+ // ============================================================
682
+ // Skill Executor Interface and Implementation
683
+ // ============================================================
684
+
685
+ interface SkillExecutor {
686
+ execute(skill: SkillInfo, params: SkillExecutionParams): Promise<SkillExecutionResult>;
687
+ }
688
+
689
+ /**
690
+ * Document Processing Skill Executor
691
+ */
692
+ class DocumentSkillExecutor implements SkillExecutor {
693
+ async execute(skill: SkillInfo, params: SkillExecutionParams): Promise<SkillExecutionResult> {
694
+ const outputMessages: string[] = [];
695
+ const files: string[] = [];
696
+ const nextSteps: ExecutionStep[] = [];
697
+
698
+ outputMessages.push(`## 🧠 ${skill.name} Skill - Autonomous Mode\n`);
699
+
700
+ outputMessages.push(`**Task**: ${params.taskDescription}\n`);
701
+
702
+ try {
703
+ // Generate task ID
704
+ const taskId = params.taskId || `${skill.id}-${Date.now()}`;
705
+
706
+ // Read complete skill documentation
707
+ const skillPath = skill.skillsPath;
708
+ const skillMdPath = path.join(skillPath, 'SKILL.md');
709
+ files.push(skillMdPath);
710
+
711
+ // Read SKILL.md content
712
+ const skillContent = await fs.readFile(skillMdPath, 'utf-8');
713
+
714
+ // Extract relevant content based on task type and generate execution steps
715
+ const taskContent = await this.extractRelevantContent(skill, params, skillContent, nextSteps, taskId);
716
+ outputMessages.push(taskContent);
717
+
718
+ // Add input/output files to list if they exist
719
+ if (params.inputFile) files.push(params.inputFile);
720
+ if (params.outputFile) files.push(params.outputFile);
721
+
722
+ return {
723
+ success: true,
724
+ output: outputMessages.join('\n'),
725
+ files: files,
726
+ nextSteps: nextSteps,
727
+ requiresManualExecution: true
728
+ };
729
+ } catch (error: any) {
730
+ return {
731
+ success: false,
732
+ error: error.message
733
+ };
734
+ }
735
+ }
736
+
737
+ /**
738
+ * Extract relevant skill content based on task type
739
+ */
740
+ private async extractRelevantContent(
741
+ skill: SkillInfo,
742
+ params: SkillExecutionParams,
743
+ fullContent: string,
744
+ nextSteps: ExecutionStep[],
745
+ taskId: string
746
+ ): Promise<string> {
747
+ const taskLower = params.taskDescription.toLowerCase();
748
+ const workspaceBase = getWorkspaceDescription();
749
+ const taskWorkspace = `${workspaceBase}/${taskId}`;
750
+
751
+ // Determine required files based on skill type
752
+ let requiredFiles: string[] = [];
753
+
754
+ switch (skill.id) {
755
+ case 'pptx':
756
+ requiredFiles = ['skills/pptx/SKILL.md', 'skills/pptx/html2pptx.md', 'skills/pptx/scripts/html2pptx.js'];
757
+ break;
758
+ case 'docx':
759
+ requiredFiles = ['skills/docx/SKILL.md', 'skills/docx/docx-js.md', 'skills/docx/ooxml.md'];
760
+ break;
761
+ case 'pdf':
762
+ requiredFiles = ['skills/pdf/SKILL.md', 'skills/pdf/reference.md', 'skills/pdf/forms.md'];
763
+ break;
764
+ case 'xlsx':
765
+ requiredFiles = ['skills/xlsx/SKILL.md', 'skills/xlsx/recalc.py'];
766
+ break;
767
+ case 'frontend-design':
768
+ requiredFiles = ['skills/frontend-design/SKILL.md'];
769
+ break;
770
+ case 'web-artifacts-builder':
771
+ requiredFiles = ['skills/web-artifacts-builder/SKILL.md'];
772
+ break;
773
+ case 'webapp-testing':
774
+ requiredFiles = ['skills/webapp-testing/SKILL.md', 'skills/webapp-testing/examples/'];
775
+ break;
776
+ case 'canvas-design':
777
+ requiredFiles = ['skills/canvas-design/SKILL.md'];
778
+ break;
779
+ case 'algorithmic-art':
780
+ requiredFiles = ['skills/algorithmic-art/SKILL.md', 'skills/algorithmic-art/templates/generator_template.js'];
781
+ break;
782
+ case 'theme-factory':
783
+ requiredFiles = ['skills/theme-factory/SKILL.md', 'skills/theme-factory/themes/'];
784
+ break;
785
+ case 'brand-guidelines':
786
+ requiredFiles = ['skills/brand-guidelines/SKILL.md'];
787
+ break;
788
+ case 'internal-comms':
789
+ requiredFiles = ['skills/internal-comms/SKILL.md', 'skills/internal-comms/examples/'];
790
+ break;
791
+ case 'doc-coauthoring':
792
+ requiredFiles = ['skills/doc-coauthoring/SKILL.md'];
793
+ break;
794
+ case 'mcp-builder':
795
+ requiredFiles = ['skills/mcp-builder/SKILL.md', 'skills/mcp-builder/reference/'];
796
+ break;
797
+ case 'skill-creator':
798
+ requiredFiles = ['skills/skill-creator/SKILL.md'];
799
+ break;
800
+ case 'slack-gif-creator':
801
+ requiredFiles = ['skills/slack-gif-creator/SKILL.md', 'skills/slack-gif-creator/core/'];
802
+ break;
803
+ default:
804
+ requiredFiles = [`skills/${skill.id}/SKILL.md`];
805
+ }
806
+
807
+ nextSteps.push({
808
+ step: 1,
809
+ action: 'Read skill documentation',
810
+ description: `Read: ${requiredFiles.join(', ')}`,
811
+ reason: 'Understand the skill workflow and best practices'
812
+ });
813
+
814
+ nextSteps.push({
815
+ step: 2,
816
+ action: 'Analyze documentation and design approach',
817
+ description: `Based on SKILL.md, determine the best approach for: ${taskWorkspace}`,
818
+ reason: 'Plan your execution based on the documentation'
819
+ });
820
+
821
+ nextSteps.push({
822
+ step: 3,
823
+ action: 'Execute your plan',
824
+ description: 'Create workspace, write code, run scripts, verify output',
825
+ reason: 'Execute the task using your own understanding'
826
+ });
827
+
828
+ return `### Skill Execution\n\n` +
829
+ `**Your task**: ${params.taskDescription}\n\n` +
830
+ `**Read these files first**:\n` +
831
+ requiredFiles.map(f => `- ${f}`).join('\n') + '\n\n' +
832
+ `Then analyze the documentation and create your own execution plan.\n\n` +
833
+ `**Workspace**: \`${taskWorkspace}\`\n\n` +
834
+ `**⚠️ Windows Path Execution**: Use absolute paths, NOT \`cd && command\`:\n` +
835
+ ` - ✅ Correct: \`node "${taskWorkspace}/script.js"\`\n` +
836
+ ` - ❌ Wrong: \`cd "${taskWorkspace}" && node script.js\` (fails in PowerShell 5.1)\n` +
837
+ ` - ✅ Correct: \`python "${taskWorkspace}/script.py"\`\n\n` +
838
+ `**📦 Dependency Reuse**: Check existing libraries before downloading:\n` +
839
+ ` - Node.js: pptxgenjs, playwright, sharp, docx are globally available\n` +
840
+ ` - Python: pypdf, openpyxl, python-pptx, fitz are available\n` +
841
+ ` - Use \`require("pptxgenjs")\` NOT \`npm install pptxgenjs\`\n` +
842
+ ` - Use \`from openpyxl import Workbook\` NOT \`pip install openpyxl\`\n\n` +
843
+ `**🧹 Cleanup**: Delete all intermediate/temporary files when task completes:\n` +
844
+ ` - Remove: all files generated during the task\n` +
845
+ ` - Keep: Only the final output file (output.pptx/docx/xlsx/pdf)\n\n` +
846
+ `**Instructions**: read_file the documentation, understand the API, and create your own execution plan.\n` +
847
+ `**If you encounter issues**: Explain what went wrong and suggest a different approach.\n`;
848
+ }
849
+
850
+ /**
851
+ * Extract PPTX-related content and generate steps
852
+ */
853
+ private extractPptxContent(taskLower: string, fullContent: string, nextSteps: ExecutionStep[], skillPath: string, taskWorkspace: string): string {
854
+ const content = fullContent.replace(/^---\n[\s\S]*?\n---/, '').trim();
855
+ const html2pptxPath = `${skillPath}/scripts/html2pptx.js`;
856
+ const scriptsPath = `${skillPath}/scripts`;
857
+
858
+ // Check if using template
859
+ const useTemplate = taskLower.includes('template') || taskLower.includes('template');
860
+
861
+ if (useTemplate) {
862
+ // Add template usage steps
863
+ nextSteps.push({
864
+ step: 1,
865
+ action: 'Read documentation and script',
866
+ description: `Read pptx/html2pptx.md and ${html2pptxPath} - CRITICAL: Read the USAGE section at the top of html2pptx.js to understand the correct API: const { slide, placeholders } = await html2pptx('slide.html', pptx);`,
867
+ file: html2pptxPath,
868
+ reason: 'Understand html2pptx API - MUST read the usage example in the file header'
869
+ });
870
+ nextSteps.push({
871
+ step: 2,
872
+ action: 'Create workspace directory',
873
+ description: `Create directory: ${taskWorkspace}`,
874
+ reason: 'Create workspace directory for this task'
875
+ });
876
+ nextSteps.push({
877
+ step: 3,
878
+ action: 'Create HTML slide file in workspace',
879
+ description: `Create slide.html inside ${taskWorkspace}/ (720pt × 405pt for 16:9)`,
880
+ reason: 'Create slide HTML file in workspace to avoid polluting target directory'
881
+ });
882
+ nextSteps.push({
883
+ step: 4,
884
+ action: 'Create PPTX conversion script in workspace',
885
+ description: `Create convert.js inside ${taskWorkspace}/ using CommonJS: const { slide, placeholders } = await html2pptx('slide.html', pptx); // slide is already added, use slide.addChart()/addText() for content`,
886
+ reason: 'Write Node.js script - MUST use destructured { slide, placeholders } from html2pptx()'
887
+ });
888
+ nextSteps.push({
889
+ step: 5,
890
+ action: 'Run the script',
891
+ description: `node "${taskWorkspace.replace(/\\/g, '/')}/convert.js"`,
892
+ reason: 'Generate PPTX file using html2pptx (use absolute path for Windows compatibility)'
893
+ });
894
+ nextSteps.push({
895
+ step: 6,
896
+ action: 'Generate thumbnail grid for visual validation',
897
+ description: `Run: python "${scriptsPath}/thumbnail.py" ${taskWorkspace}/output.pptx ${taskWorkspace}/thumbnails --cols 4`,
898
+ reason: 'Create thumbnail grid to verify slide layout and visual quality'
899
+ });
900
+ nextSteps.push({
901
+ step: 7,
902
+ action: 'Copy output to target directory',
903
+ description: `Copy ${taskWorkspace}/output.pptx to target directory`,
904
+ reason: 'Only save final file to specified path, keep workspace clean'
905
+ });
906
+
907
+ const patterns = [
908
+ /##\s*Creating\s*a\s*new\s*PowerPoint\s*presentation\s*\*\*using\s*a\s*template\*\*[\s\S]*?(?=##\s+)/i,
909
+ /##\s*Using\s*a\s*template[\s\S]*?(?=##\s+)/i
910
+ ];
911
+
912
+ for (const pattern of patterns) {
913
+ const match = content.match(pattern);
914
+ if (match) {
915
+ return `### Using a Template\n\n${match[0].trim()}`;
916
+ }
917
+ }
918
+ }
919
+
920
+ // Not using template
921
+ nextSteps.push({
922
+ step: 1,
923
+ action: 'Read documentation and script',
924
+ description: `Read pptx/html2pptx.md and ${html2pptxPath} - CRITICAL: Read the USAGE section at the top of html2pptx.js to understand the correct API: const { slide, placeholders } = await html2pptx('slide.html', pptx);`,
925
+ file: html2pptxPath,
926
+ reason: 'Understand html2pptx API - MUST read the usage example in the file header'
927
+ });
928
+ nextSteps.push({
929
+ step: 2,
930
+ action: 'Create workspace directory',
931
+ description: `Create directory: ${taskWorkspace}`,
932
+ reason: 'Create workspace directory for this task'
933
+ });
934
+ nextSteps.push({
935
+ step: 3,
936
+ action: 'Create HTML slide file in workspace',
937
+ description: `Create slide.html inside ${taskWorkspace}/ (720pt × 405pt for 16:9)`,
938
+ reason: 'Create slide HTML file in workspace to avoid polluting target directory'
939
+ });
940
+ nextSteps.push({
941
+ step: 4,
942
+ action: 'Create PPTX conversion script in workspace',
943
+ description: `Create convert.js inside ${taskWorkspace}/ using CommonJS: const { slide, placeholders } = await html2pptx('slide.html', pptx); // slide is already added, use slide.addChart()/addText() for content`,
944
+ reason: 'Write Node.js script - MUST use destructured { slide, placeholders } from html2pptx()'
945
+ });
946
+ nextSteps.push({
947
+ step: 5,
948
+ action: 'Run the script',
949
+ description: `node "${taskWorkspace.replace(/\\/g, '/')}/convert.js"`,
950
+ reason: 'Generate PPTX file using html2pptx (use absolute path for Windows compatibility)'
951
+ });
952
+ nextSteps.push({
953
+ step: 6,
954
+ action: 'Generate thumbnail grid for visual validation',
955
+ description: `Run: python "${scriptsPath}/thumbnail.py" ${taskWorkspace}/output.pptx ${taskWorkspace}/thumbnails --cols 4`,
956
+ reason: 'Create thumbnail grid to verify slide layout and visual quality'
957
+ });
958
+ nextSteps.push({
959
+ step: 7,
960
+ action: 'Copy output to target directory',
961
+ description: `Copy ${taskWorkspace}/output.pptx to target directory`,
962
+ reason: 'Only save final file to specified path, keep workspace clean'
963
+ });
964
+
965
+ const patterns = [
966
+ /##\s*Creating\s*a\s*new\s*PowerPoint[\s\S]*?(?=##\s+)/i,
967
+ /###\s*Workflow[\s\S]*?(?=###\s+|$)/i
968
+ ];
969
+
970
+ for (const pattern of patterns) {
971
+ const match = content.match(pattern);
972
+ if (match) {
973
+ return `### Creating New Presentation\n\n${match[0].trim()}`;
974
+ }
975
+ }
976
+
977
+ return extractContent(content, ['html2pptx', 'Creating', 'Workflow']);
978
+ }
979
+
980
+ /**
981
+ * Extract DOCX-related content and generate steps
982
+ */
983
+ private extractDocxContent(
984
+ taskLower: string,
985
+ fullContent: string,
986
+ nextSteps: ExecutionStep[],
987
+ params: SkillExecutionParams,
988
+ skillPath: string,
989
+ taskWorkspace: string
990
+ ): string {
991
+ const content = fullContent.replace(/^---\n[\s\S]*?\n---/, '').trim();
992
+ const unpackScript = `${skillPath}/ooxml/scripts/unpack.py`;
993
+ const packScript = `${skillPath}/ooxml/scripts/pack.py`;
994
+ const scriptsPath = `${skillPath}/scripts`;
995
+
996
+ const isNew = taskLower.includes('create') || taskLower.includes('new');
997
+ const isEditing = taskLower.includes('edit') || taskLower.includes('modify') || taskLower.includes('modify');
998
+
999
+ if (isNew) {
1000
+ // Create new document
1001
+ nextSteps.push({
1002
+ step: 1,
1003
+ action: 'Read documentation',
1004
+ description: 'Read docx-js.md for API reference',
1005
+ file: `${skillPath}/docx-js.md`,
1006
+ reason: 'Understand how to use docx-js library to create Word documents'
1007
+ });
1008
+ nextSteps.push({
1009
+ step: 2,
1010
+ action: 'Create script in workspace',
1011
+ description: `Create create_doc.js in ${taskWorkspace}: const { Document, Paragraph, TextRun, Packer } = await import("docx");`,
1012
+ reason: 'Create Word document code using docx library with dynamic import'
1013
+ });
1014
+ nextSteps.push({
1015
+ step: 3,
1016
+ action: 'Run the script',
1017
+ description: `node "${taskWorkspace.replace(/\\/g, '/')}/create_doc.js"`,
1018
+ reason: 'Generate DOCX file in workspace (use absolute path for Windows compatibility)'
1019
+ });
1020
+ nextSteps.push({ step: 4,
1021
+ action: 'Copy output to target directory',
1022
+ description: `Copy ${taskWorkspace}/output.docx to target directory`,
1023
+ reason: 'Only save final file to specified path, keep workspace clean'
1024
+ });
1025
+
1026
+ return extractContent(content, ['Creating', 'docx-js', 'Workflow']);
1027
+ }
1028
+
1029
+ if (isEditing) {
1030
+ // Edit existing document - use existing scripts
1031
+ nextSteps.push({
1032
+ step: 1,
1033
+ action: 'Read documentation',
1034
+ description: 'Read ooxml.md for editing API',
1035
+ file: `${skillPath}/ooxml.md`,
1036
+ reason: 'Understand how to edit existing Word documents'
1037
+ });
1038
+
1039
+ nextSteps.push({
1040
+ step: 2,
1041
+ action: 'Create workspace directory',
1042
+ description: `Create workspace directory: ${taskWorkspace}/`,
1043
+ reason: 'Create workspace directory for intermediate files'
1044
+ });
1045
+
1046
+ if (params.inputFile) {
1047
+ nextSteps.push({
1048
+ step: 3,
1049
+ action: 'Unpack document in workspace',
1050
+ description: `Run: python "${unpackScript}" "${params.inputFile}" ${taskWorkspace}/docx_input`,
1051
+ reason: 'Unpack DOCX file using existing unpack.py script'
1052
+ });
1053
+ }
1054
+
1055
+ nextSteps.push({
1056
+ step: 4,
1057
+ action: 'Create editing script in workspace',
1058
+ description: `Create edit_doc.py in ${taskWorkspace}: from scripts.document import Document; doc = Document("${taskWorkspace}/docx_input");`,
1059
+ reason: 'Create Python editing script using existing Document library'
1060
+ });
1061
+
1062
+ if (params.inputFile || params.outputFile) {
1063
+ nextSteps.push({
1064
+ step: 5,
1065
+ action: 'Pack document',
1066
+ description: `Run: python "${packScript}" ${taskWorkspace}/docx_input ${taskWorkspace}/output.docx`,
1067
+ reason: 'Repack DOCX using existing pack.py script'
1068
+ });
1069
+ }
1070
+
1071
+ nextSteps.push({
1072
+ step: 6,
1073
+ action: 'Copy output to target directory',
1074
+ description: `Copy ${taskWorkspace}/output.docx to target directory`,
1075
+ reason: 'Only save final file to specified path'
1076
+ });
1077
+
1078
+ return extractContent(content, ['Editing', 'redlining', 'ooxml']);
1079
+ }
1080
+
1081
+ // Default case
1082
+ nextSteps.push({
1083
+ step: 1,
1084
+ action: 'Read documentation',
1085
+ description: 'Read ooxml.md or docx-js.md',
1086
+ reason: 'Understand document processing methods'
1087
+ });
1088
+ nextSteps.push({
1089
+ step: 2,
1090
+ action: 'Create or edit document',
1091
+ description: 'Write code using appropriate library',
1092
+ reason: 'Perform document operations'
1093
+ });
1094
+
1095
+ return extractContent(content, ['Creating', 'Editing', 'document', 'docx']);
1096
+ }
1097
+
1098
+ /**
1099
+ * Extract PDF-related content and generate steps
1100
+ */
1101
+ private extractPdfContent(
1102
+ taskLower: string,
1103
+ fullContent: string,
1104
+ nextSteps: ExecutionStep[],
1105
+ params: SkillExecutionParams,
1106
+ skillPath: string,
1107
+ taskWorkspace: string
1108
+ ): string {
1109
+ const content = fullContent.replace(/^---\n[\s\S]*?\n---/, '').trim();
1110
+ const scriptsPath = `${skillPath}/scripts`;
1111
+
1112
+ const isForm = taskLower.includes('form') || taskLower.includes('form');
1113
+ const isExtract = taskLower.includes('extract') || taskLower.includes('extract');
1114
+ const isMerge = taskLower.includes('merge') || taskLower.includes('merge');
1115
+ const isConvert = taskLower.includes('convert') || taskLower.includes('image');
1116
+
1117
+ nextSteps.push({
1118
+ step: 1,
1119
+ action: 'Read documentation',
1120
+ description: 'Read reference.md for PDF operations',
1121
+ file: `${skillPath}/reference.md`,
1122
+ reason: 'Understand PDF operation methods'
1123
+ });
1124
+
1125
+ nextSteps.push({
1126
+ step: 2,
1127
+ action: 'Create workspace directory',
1128
+ description: `Create workspace directory: ${taskWorkspace}/`,
1129
+ reason: 'Create workspace directory for intermediate files'
1130
+ });
1131
+
1132
+ if (isForm) {
1133
+ // Check for fillable fields first
1134
+ nextSteps.push({
1135
+ step: 3,
1136
+ action: 'Check form fields',
1137
+ description: `Run: python "${scriptsPath}/check_fillable_fields.py" <input_pdf>`,
1138
+ reason: 'Check if PDF has fillable form fields'
1139
+ });
1140
+ nextSteps.push({
1141
+ step: 4,
1142
+ action: 'Create PDF form script in workspace',
1143
+ description: `Create form_script.py in ${taskWorkspace}: use "${scriptsPath}/fill_fillable_fields.py" or "${scriptsPath}/fill_pdf_form_with_annotations.py"`,
1144
+ reason: 'Create PDF form processing script using existing scripts'
1145
+ });
1146
+ } else if (isExtract) {
1147
+ nextSteps.push({
1148
+ step: 3,
1149
+ action: 'Create extraction script in workspace',
1150
+ description: `Create extract_script.py in ${taskWorkspace}: use pypdf or pdfplumber for text extraction`,
1151
+ reason: 'Create PDF content extraction script'
1152
+ });
1153
+ } else if (isMerge) {
1154
+ nextSteps.push({
1155
+ step: 3,
1156
+ action: 'Create merge script in workspace',
1157
+ description: `Create merge_script.py in ${taskWorkspace}: use pypdf to combine PDF files`,
1158
+ reason: 'Create PDF merge script'
1159
+ });
1160
+ } else if (isConvert) {
1161
+ nextSteps.push({
1162
+ step: 3,
1163
+ action: 'Convert PDF to images',
1164
+ description: `Run: python "${scriptsPath}/convert_pdf_to_images.py" <input_pdf> ${taskWorkspace}/images`,
1165
+ reason: 'Convert PDF to images using existing script'
1166
+ });
1167
+ } else {
1168
+ nextSteps.push({
1169
+ step: 3,
1170
+ action: 'Create PDF processing script in workspace',
1171
+ description: `Create pdf_script.py in ${taskWorkspace}: use pypdf for desired operations`,
1172
+ reason: 'Create PDF processing script'
1173
+ });
1174
+ }
1175
+
1176
+ nextSteps.push({
1177
+ step: 5,
1178
+ action: 'Run the script',
1179
+ description: `python "${taskWorkspace.replace(/\\/g, '/')}/pdf_script.py"`,
1180
+ reason: 'Execute PDF operation script in workspace (use absolute path for Windows compatibility)'
1181
+ });
1182
+
1183
+ nextSteps.push({
1184
+ step: 6,
1185
+ action: 'Copy output to target directory',
1186
+ description: `Copy ${taskWorkspace}/output.pdf to target directory`,
1187
+ reason: 'Only save final file to specified path'
1188
+ });
1189
+
1190
+ return extractContent(content, ['Creating', 'pdf', 'PDF']);
1191
+ }
1192
+
1193
+ /**
1194
+ * Extract XLSX relevant content and generate steps
1195
+ */
1196
+ private extractXlsxContent(taskLower: string, fullContent: string, nextSteps: ExecutionStep[], skillPath: string, taskWorkspace: string): string {
1197
+ const content = fullContent.replace(/^---\n[\s\S]*?\n---/, '').trim();
1198
+
1199
+ const hasFormulas = taskLower.includes('formula') || taskLower.includes('公式');
1200
+ const hasData = taskLower.includes('data') || taskLower.includes('数据分析');
1201
+
1202
+ nextSteps.push({
1203
+ step: 1,
1204
+ action: 'Read documentation',
1205
+ description: 'Read SKILL.md for Excel operations',
1206
+ file: `${skillPath}/SKILL.md`,
1207
+ reason: 'Understand Excel operation methods'
1208
+ });
1209
+
1210
+ nextSteps.push({
1211
+ step: 2,
1212
+ action: 'Create workspace directory',
1213
+ description: `Create workspace directory: ${taskWorkspace}/`,
1214
+ reason: 'Create workspace directory for intermediate files'
1215
+ });
1216
+
1217
+ if (hasFormulas || hasData) {
1218
+ nextSteps.push({
1219
+ step: 3,
1220
+ action: 'Create spreadsheet script in workspace',
1221
+ description: `Create create_xlsx.py in ${taskWorkspace}: use openpyxl to create workbook with formulas`,
1222
+ reason: 'Create spreadsheet script with formulas in workspace'
1223
+ });
1224
+ } else {
1225
+ nextSteps.push({
1226
+ step: 3,
1227
+ action: 'Create spreadsheet script in workspace',
1228
+ description: `Create create_xlsx.py in ${taskWorkspace}: use openpyxl to create workbook`,
1229
+ reason: 'Create spreadsheet script in workspace'
1230
+ });
1231
+ }
1232
+
1233
+ nextSteps.push({
1234
+ step: 4,
1235
+ action: 'Run the script',
1236
+ description: `python "${taskWorkspace.replace(/\\/g, '/')}/create_xlsx.py"`,
1237
+ reason: 'Generate XLSX file in workspace (use absolute path for Windows compatibility)'
1238
+ });
1239
+
1240
+ if (hasFormulas) {
1241
+ nextSteps.push({
1242
+ step: 5,
1243
+ action: 'Recalculate formulas',
1244
+ description: `Run: python "${skillPath}/recalc.py" ${taskWorkspace}/output.xlsx to recalculate all formulas and check for errors`,
1245
+ reason: 'Recalculate formulas and verify no formula errors (#REF!, #DIV/0!, etc.)'
1246
+ });
1247
+ nextSteps.push({
1248
+ step: 6,
1249
+ action: 'Fix formula errors if any',
1250
+ description: `Check recalc.py output JSON for error locations and fix formula errors in ${taskWorkspace}`,
1251
+ reason: 'Ensure ZERO formula errors before final output'
1252
+ });
1253
+ nextSteps.push({
1254
+ step: 7,
1255
+ action: 'Copy output to target directory',
1256
+ description: `Copy ${taskWorkspace}/output.xlsx to target directory`,
1257
+ reason: 'Only save final file to specified path'
1258
+ });
1259
+ } else {
1260
+ nextSteps.push({
1261
+ step: 5,
1262
+ action: 'Copy output to target directory',
1263
+ description: `Copy ${taskWorkspace}/output.xlsx to target directory`,
1264
+ reason: 'Only save final file to specified path'
1265
+ });
1266
+ }
1267
+
1268
+ return extractContent(content, ['Excel', 'xlsx', 'spreadsheet']);
1269
+ }
1270
+
1271
+ /**
1272
+ * Extract default content
1273
+ */
1274
+ private extractDefaultContent(skill: SkillInfo, fullContent: string, nextSteps: ExecutionStep[]): string {
1275
+ const content = fullContent.replace(/^---\n[\s\S]*?\n---/, '').trim();
1276
+ const firstLines = content.split('\n').slice(0, 100).join('\n');
1277
+
1278
+ nextSteps.push({
1279
+ step: 1,
1280
+ action: 'Read SKILL.md',
1281
+ description: `Read ${skill.id}/SKILL.md for full instructions`,
1282
+ file: `${skill.skillsPath}/SKILL.md`,
1283
+ reason: 'Understand complete execution workflow'
1284
+ });
1285
+
1286
+ return `### ${skill.name}\n\n${firstLines}\n\n(See ${skill.skillsPath}/SKILL.md for full instructions)`;
1287
+ }
1288
+ }
1289
+
1290
+ /**
1291
+ * Frontend Development Skill Executor
1292
+ */
1293
+ class FrontendSkillExecutor implements SkillExecutor {
1294
+ async execute(skill: SkillInfo, params: SkillExecutionParams): Promise<SkillExecutionResult> {
1295
+ const outputMessages: string[] = [];
1296
+ const files: string[] = [];
1297
+ const nextSteps: ExecutionStep[] = [];
1298
+
1299
+ outputMessages.push(`## ${skill.name} Skill - Execution Guide\n`);
1300
+ outputMessages.push(`**Task**: ${params.taskDescription}\n`);
1301
+
1302
+ // Get or generate task ID
1303
+ const taskId = params.taskId || `${skill.id}-${Date.now()}`;
1304
+
1305
+ try {
1306
+ // Read SKILL.md content
1307
+ const skillMdPath = path.join(skill.skillsPath, 'SKILL.md');
1308
+ files.push(skillMdPath);
1309
+ const skillContent = await fs.readFile(skillMdPath, 'utf-8');
1310
+
1311
+ // Generate execution steps
1312
+ const taskContent = await this.extractFrontendContent(skill, params, skillContent, nextSteps, taskId);
1313
+ outputMessages.push(taskContent);
1314
+
1315
+ // Add input/output files to list if they exist
1316
+ if (params.inputFile) files.push(params.inputFile);
1317
+ if (params.outputFile) files.push(params.outputFile);
1318
+
1319
+ return {
1320
+ success: true,
1321
+ output: outputMessages.join('\n'),
1322
+ files: files,
1323
+ nextSteps: nextSteps,
1324
+ requiresManualExecution: true
1325
+ };
1326
+ } catch (error: any) {
1327
+ return {
1328
+ success: false,
1329
+ error: error.message
1330
+ };
1331
+ }
1332
+ }
1333
+
1334
+ /**
1335
+ * Extract relevant content based on frontend skill type and generate steps
1336
+ */
1337
+ private async extractFrontendContent(
1338
+ skill: SkillInfo,
1339
+ params: SkillExecutionParams,
1340
+ fullContent: string,
1341
+ nextSteps: ExecutionStep[],
1342
+ taskId: string
1343
+ ): Promise<string> {
1344
+ const taskLower = params.taskDescription.toLowerCase();
1345
+ const workspaceBase = getWorkspaceDescription();
1346
+ const taskWorkspace = `${workspaceBase}/${taskId}`;
1347
+
1348
+ // Add common steps
1349
+ nextSteps.push({
1350
+ step: 1,
1351
+ action: 'Design Thinking',
1352
+ description: 'Understand requirements, define aesthetic direction',
1353
+ reason: 'Clarify design direction and goals'
1354
+ });
1355
+ nextSteps.push({
1356
+ step: 2,
1357
+ action: 'Create implementation',
1358
+ description: 'Write production-grade HTML/CSS/JS or React code',
1359
+ reason: 'Implement frontend interface'
1360
+ });
1361
+
1362
+ switch (skill.id) {
1363
+ case 'frontend-design':
1364
+ nextSteps.push({
1365
+ step: 3,
1366
+ action: 'Create workspace directory',
1367
+ description: `Create workspace directory: ${taskWorkspace}/`,
1368
+ reason: 'Create workspace directory for frontend files'
1369
+ });
1370
+ nextSteps.push({
1371
+ step: 4,
1372
+ action: 'Create frontend files in workspace',
1373
+ description: `Create index.html, styles.css, app.js in ${taskWorkspace}`,
1374
+ reason: 'Create frontend files in workspace'
1375
+ });
1376
+ if (taskLower.includes('landing')) {
1377
+ nextSteps.push({
1378
+ step: 5,
1379
+ action: 'Focus areas',
1380
+ description: 'Hero section, features, pricing, testimonials, footer',
1381
+ reason: 'Implement landing page sections'
1382
+ });
1383
+ } else if (taskLower.includes('dashboard')) {
1384
+ nextSteps.push({
1385
+ step: 5,
1386
+ action: 'Focus areas',
1387
+ description: 'Charts, data visualization, navigation panels',
1388
+ reason: 'Implement dashboard functionality'
1389
+ });
1390
+ }
1391
+ nextSteps.push({
1392
+ step: 6,
1393
+ action: 'Verify in browser',
1394
+ description: `Open files in ${taskWorkspace} to verify`,
1395
+ reason: 'Verify in browser'
1396
+ });
1397
+ nextSteps.push({
1398
+ step: 7,
1399
+ action: 'Copy files to target directory',
1400
+ description: `Copy frontend files from ${taskWorkspace} to target directory`,
1401
+ reason: 'Only save final files to specified path'
1402
+ });
1403
+ return extractContent(fullContent, ['frontend', 'design', 'web', 'interface']);
1404
+
1405
+ case 'web-artifacts-builder':
1406
+ nextSteps.push({
1407
+ step: 3,
1408
+ action: 'Create workspace directory',
1409
+ description: `Create workspace directory: ${taskWorkspace}/`,
1410
+ reason: 'Create workspace directory for component files'
1411
+ });
1412
+ nextSteps.push({
1413
+ step: 4,
1414
+ action: 'Build React artifact in workspace',
1415
+ description: `Create React component files in ${taskWorkspace} using shadcn/ui`,
1416
+ reason: 'Build React component in workspace'
1417
+ });
1418
+ nextSteps.push({
1419
+ step: 5,
1420
+ action: 'Test artifact',
1421
+ description: `Test the artifact in ${taskWorkspace}`,
1422
+ reason: 'Test component functionality'
1423
+ });
1424
+ nextSteps.push({
1425
+ step: 6,
1426
+ action: 'Copy artifact to target directory',
1427
+ description: `Copy component files from ${taskWorkspace} to target directory`,
1428
+ reason: 'Only save final files to specified path'
1429
+ });
1430
+ return extractContent(fullContent, ['Web Artifacts Builder', 'React', 'Quick Start']);
1431
+
1432
+ case 'webapp-testing':
1433
+ const scriptsPath = `${skill.skillsPath}/scripts`;
1434
+ nextSteps.push({
1435
+ step: 3,
1436
+ action: 'Read documentation and helper script',
1437
+ description: 'Read SKILL.md and scripts/with_server.py',
1438
+ file: `${scriptsPath}/with_server.py`,
1439
+ reason: 'Understand webapp testing workflow and with_server.py usage'
1440
+ });
1441
+ nextSteps.push({
1442
+ step: 4,
1443
+ action: 'Create workspace directory',
1444
+ description: `Create workspace directory: ${taskWorkspace}/`,
1445
+ reason: 'Create workspace directory for test files'
1446
+ });
1447
+ nextSteps.push({
1448
+ step: 5,
1449
+ action: 'Write Playwright tests in workspace',
1450
+ description: `Create test.py in ${taskWorkspace} for web application testing`,
1451
+ reason: 'Write test scripts in workspace'
1452
+ });
1453
+ nextSteps.push({
1454
+ step: 6,
1455
+ action: 'Run tests with server',
1456
+ description: `Run: python "${scriptsPath}/with_server.py" --server "<start_command>" --port <port> -- python ${taskWorkspace}/test.py`,
1457
+ reason: 'Run tests with server using existing with_server.py helper'
1458
+ });
1459
+ nextSteps.push({
1460
+ step: 7,
1461
+ action: 'Copy test reports to target directory',
1462
+ description: `Copy test reports from ${taskWorkspace} to target directory`,
1463
+ reason: 'Only save test reports to specified path'
1464
+ });
1465
+ return extractContent(fullContent, ['test', 'web', 'playwright', 'testing']);
1466
+
1467
+ default:
1468
+ return extractContent(fullContent, ['frontend', 'design', 'web']);
1469
+ }
1470
+ }
1471
+ }
1472
+
1473
+ /**
1474
+ * Visual Design Skill Executor
1475
+ */
1476
+ class VisualDesignSkillExecutor implements SkillExecutor {
1477
+ async execute(skill: SkillInfo, params: SkillExecutionParams): Promise<SkillExecutionResult> {
1478
+ const outputMessages: string[] = [];
1479
+ const files: string[] = [];
1480
+ const nextSteps: ExecutionStep[] = [];
1481
+
1482
+ outputMessages.push(`## ${skill.name} Skill - Execution Guide\n`);
1483
+ outputMessages.push(`**Task**: ${params.taskDescription}\n`);
1484
+
1485
+ // Get or generate task ID
1486
+ const taskId = params.taskId || `${skill.id}-${Date.now()}`;
1487
+
1488
+ try {
1489
+ // Read SKILL.md content
1490
+ const skillMdPath = path.join(skill.skillsPath, 'SKILL.md');
1491
+ files.push(skillMdPath);
1492
+ const skillContent = await fs.readFile(skillMdPath, 'utf-8');
1493
+
1494
+ // Generate execution steps
1495
+ const taskContent = await this.extractVisualContent(skill, params, skillContent, nextSteps, taskId);
1496
+ outputMessages.push(taskContent);
1497
+
1498
+ // Add input/output files to list if they exist
1499
+ if (params.inputFile) files.push(params.inputFile);
1500
+ if (params.outputFile) files.push(params.outputFile);
1501
+
1502
+ return {
1503
+ success: true,
1504
+ output: outputMessages.join('\n'),
1505
+ files: files,
1506
+ nextSteps: nextSteps,
1507
+ requiresManualExecution: true
1508
+ };
1509
+ } catch (error: any) {
1510
+ return {
1511
+ success: false,
1512
+ error: error.message
1513
+ };
1514
+ }
1515
+ }
1516
+
1517
+ /**
1518
+ * Extract relevant content based on visual design skill type and generate steps
1519
+ */
1520
+ private async extractVisualContent(
1521
+ skill: SkillInfo,
1522
+ params: SkillExecutionParams,
1523
+ fullContent: string,
1524
+ nextSteps: ExecutionStep[],
1525
+ taskId: string
1526
+ ): Promise<string> {
1527
+ const taskLower = params.taskDescription.toLowerCase();
1528
+ const workspaceBase = getWorkspaceDescription();
1529
+ const taskWorkspace = `${workspaceBase}/${taskId}`;
1530
+
1531
+ switch (skill.id) {
1532
+ case 'canvas-design':
1533
+ // Canvas Design: Two-step process
1534
+ nextSteps.push({
1535
+ step: 1,
1536
+ action: 'Create workspace directory',
1537
+ description: `Create workspace directory: ${taskWorkspace}/`,
1538
+ reason: 'Create workspace directory for design files'
1539
+ });
1540
+ nextSteps.push({
1541
+ step: 2,
1542
+ action: 'Design Philosophy Creation',
1543
+ description: `Create manifesto/md file in ${taskWorkspace} defining aesthetic movement`,
1544
+ reason: 'Create design philosophy document in workspace'
1545
+ });
1546
+ nextSteps.push({
1547
+ step: 3,
1548
+ action: 'Canvas Creation',
1549
+ description: `Express philosophy visually using PDF/PNG output in ${taskWorkspace}`,
1550
+ reason: 'Express philosophy visually on canvas in workspace'
1551
+ });
1552
+ nextSteps.push({
1553
+ step: 4,
1554
+ action: 'Copy output to target directory',
1555
+ description: `Copy output files from ${taskWorkspace} to target directory`,
1556
+ reason: 'Only save final files to specified path'
1557
+ });
1558
+ return extractContent(fullContent, ['design', 'art', 'visual', 'philosophy']);
1559
+
1560
+ case 'algorithmic-art':
1561
+ // Algorithmic Art
1562
+ nextSteps.push({
1563
+ step: 1,
1564
+ action: 'Create workspace directory',
1565
+ description: `Create workspace directory: ${taskWorkspace}/`,
1566
+ reason: 'Create workspace directory for generative art files'
1567
+ });
1568
+ nextSteps.push({
1569
+ step: 2,
1570
+ action: 'Algorithmic Philosophy',
1571
+ description: `Define generative art philosophy in ${taskWorkspace}`,
1572
+ reason: 'Create generative art philosophy in workspace'
1573
+ });
1574
+ nextSteps.push({
1575
+ step: 3,
1576
+ action: 'P5.js Implementation',
1577
+ description: `Write p5.js code in ${taskWorkspace} for generative art`,
1578
+ reason: 'Implement generative art code in workspace'
1579
+ });
1580
+ nextSteps.push({
1581
+ step: 4,
1582
+ action: 'Generate artwork',
1583
+ description: `Run p5.js code in ${taskWorkspace} to generate artwork`,
1584
+ reason: 'Run generative art code'
1585
+ });
1586
+ nextSteps.push({
1587
+ step: 5,
1588
+ action: 'Copy output to target directory',
1589
+ description: `Copy output files from ${taskWorkspace} to target directory`,
1590
+ reason: 'Only save final files to specified path'
1591
+ });
1592
+ return extractContent(fullContent, ['generative', 'algorithmic', 'art']);
1593
+
1594
+ case 'theme-factory':
1595
+ // Theme Factory
1596
+ nextSteps.push({
1597
+ step: 1,
1598
+ action: 'Create workspace directory',
1599
+ description: `Create workspace directory: ${taskWorkspace}/`,
1600
+ reason: 'Create workspace directory for theme files'
1601
+ });
1602
+ nextSteps.push({
1603
+ step: 2,
1604
+ action: 'Select theme',
1605
+ description: `Choose from available themes or create custom in ${taskWorkspace}`,
1606
+ reason: 'Select or create theme in workspace'
1607
+ });
1608
+ nextSteps.push({
1609
+ step: 3,
1610
+ action: 'Apply theme',
1611
+ description: `Apply colors, fonts to design in ${taskWorkspace}`,
1612
+ reason: 'Apply theme to design in workspace'
1613
+ });
1614
+ nextSteps.push({
1615
+ step: 4,
1616
+ action: 'Copy output to target directory',
1617
+ description: `Copy theme files from ${taskWorkspace} to target directory`,
1618
+ reason: 'Only save final files to specified path'
1619
+ });
1620
+ return extractContent(fullContent, ['Theme Factory', 'Themes', 'apply']);
1621
+
1622
+ case 'brand-guidelines':
1623
+ // Brand Guidelines
1624
+ nextSteps.push({
1625
+ step: 1,
1626
+ action: 'Create workspace directory',
1627
+ description: `Create workspace directory: ${taskWorkspace}/`,
1628
+ reason: 'Create workspace directory for brand files'
1629
+ });
1630
+ nextSteps.push({
1631
+ step: 2,
1632
+ action: 'Apply brand colors',
1633
+ description: `Use Anthropic brand colors and typography in ${taskWorkspace}`,
1634
+ reason: 'Apply brand colors in workspace'
1635
+ });
1636
+ nextSteps.push({
1637
+ step: 3,
1638
+ action: 'Follow guidelines',
1639
+ description: `Apply brand styling consistently in ${taskWorkspace}`,
1640
+ reason: 'Follow brand guidelines in workspace'
1641
+ });
1642
+ nextSteps.push({
1643
+ step: 4,
1644
+ action: 'Copy output to target directory',
1645
+ description: `Copy brand files from ${taskWorkspace} to target directory`,
1646
+ reason: 'Only save final files to specified path'
1647
+ });
1648
+ return extractContent(fullContent, ['Brand Guidelines', 'Colors', 'Typography']);
1649
+
1650
+ default:
1651
+ nextSteps.push({
1652
+ step: 1,
1653
+ action: 'Create workspace directory',
1654
+ description: `Create workspace directory: ${taskWorkspace}/`,
1655
+ reason: 'Create workspace directory for design files'
1656
+ });
1657
+ nextSteps.push({
1658
+ step: 2,
1659
+ action: 'Create visual design',
1660
+ description: `Write design code or use canvas in ${taskWorkspace}`,
1661
+ reason: 'Create visual design in workspace'
1662
+ });
1663
+ nextSteps.push({
1664
+ step: 3,
1665
+ action: 'Copy output to target directory',
1666
+ description: `Copy output files from ${taskWorkspace} to target directory`,
1667
+ reason: 'Only save final files to specified path'
1668
+ });
1669
+ return extractContent(fullContent, ['design', 'art', 'visual']);
1670
+ }
1671
+ }
1672
+ }
1673
+
1674
+ /**
1675
+ * Documentation Skill Executor
1676
+ */
1677
+ class DocumentationSkillExecutor implements SkillExecutor {
1678
+ async execute(skill: SkillInfo, params: SkillExecutionParams): Promise<SkillExecutionResult> {
1679
+ const outputMessages: string[] = [];
1680
+ const files: string[] = [];
1681
+ const nextSteps: ExecutionStep[] = [];
1682
+
1683
+ outputMessages.push(`## ${skill.name} Skill - Execution Guide\n`);
1684
+ outputMessages.push(`**Task**: ${params.taskDescription}\n`);
1685
+
1686
+ // Get or generate task ID
1687
+ const taskId = params.taskId || `${skill.id}-${Date.now()}`;
1688
+
1689
+ try {
1690
+ // Read SKILL.md content
1691
+ const skillMdPath = path.join(skill.skillsPath, 'SKILL.md');
1692
+ files.push(skillMdPath);
1693
+ const skillContent = await fs.readFile(skillMdPath, 'utf-8');
1694
+
1695
+ // Generate execution steps
1696
+ const taskContent = await this.extractDocContent(skill, params, skillContent, nextSteps, taskId);
1697
+ outputMessages.push(taskContent);
1698
+
1699
+ // Add input/output files to list if they exist
1700
+ if (params.inputFile) files.push(params.inputFile);
1701
+ if (params.outputFile) files.push(params.outputFile);
1702
+
1703
+ return {
1704
+ success: true,
1705
+ output: outputMessages.join('\n'),
1706
+ files: files,
1707
+ nextSteps: nextSteps,
1708
+ requiresManualExecution: true
1709
+ };
1710
+ } catch (error: any) {
1711
+ return {
1712
+ success: false,
1713
+ error: error.message
1714
+ };
1715
+ }
1716
+ }
1717
+
1718
+ /**
1719
+ * Extract relevant content based on documentation skill type and generate steps
1720
+ */
1721
+ private async extractDocContent(
1722
+ skill: SkillInfo,
1723
+ params: SkillExecutionParams,
1724
+ fullContent: string,
1725
+ nextSteps: ExecutionStep[],
1726
+ taskId: string
1727
+ ): Promise<string> {
1728
+ const taskLower = params.taskDescription.toLowerCase();
1729
+ const workspaceBase = getWorkspaceDescription();
1730
+ const taskWorkspace = `${workspaceBase}/${taskId}`;
1731
+
1732
+ switch (skill.id) {
1733
+ case 'internal-comms':
1734
+ // Internal Comms
1735
+ if (taskLower.includes('status') || taskLower.includes('report')) {
1736
+ nextSteps.push({
1737
+ step: 1,
1738
+ action: 'Gather information',
1739
+ description: 'Collect progress, plans, problems',
1740
+ reason: 'Gather status information'
1741
+ });
1742
+ nextSteps.push({
1743
+ step: 2,
1744
+ action: 'Write update',
1745
+ description: 'Draft 3P update format',
1746
+ reason: 'Write status update'
1747
+ });
1748
+ } else if (taskLower.includes('newsletter')) {
1749
+ nextSteps.push({
1750
+ step: 1,
1751
+ action: 'Create newsletter',
1752
+ description: 'Write company newsletter content',
1753
+ reason: 'Create company newsletter'
1754
+ });
1755
+ }
1756
+ return extractContent(fullContent, ['documentation', 'writing', 'internal']);
1757
+
1758
+ case 'doc-coauthoring':
1759
+ // Doc Co-Authoring: Three-stage process
1760
+ nextSteps.push({
1761
+ step: 1,
1762
+ action: 'Create workspace directory',
1763
+ description: `Create workspace directory: ${taskWorkspace}/`,
1764
+ reason: 'Create workspace directory for document drafts'
1765
+ });
1766
+ nextSteps.push({
1767
+ step: 2,
1768
+ action: 'Stage 1: Context Gathering',
1769
+ description: 'Gather requirements and initial questions',
1770
+ reason: 'Gather document background and requirements'
1771
+ });
1772
+ nextSteps.push({
1773
+ step: 3,
1774
+ action: 'Stage 2: Refinement',
1775
+ description: `Structure and draft content in ${taskWorkspace}`,
1776
+ reason: 'Structure and draft document in workspace'
1777
+ });
1778
+ nextSteps.push({
1779
+ step: 4,
1780
+ action: 'Stage 3: Reader Testing',
1781
+ description: `Test with fresh Claude and refine in ${taskWorkspace}`,
1782
+ reason: 'Test and refine document in workspace'
1783
+ });
1784
+ nextSteps.push({
1785
+ step: 5,
1786
+ action: 'Copy final document to target directory',
1787
+ description: `Copy final document from ${taskWorkspace} to target directory`,
1788
+ reason: 'Only save final document to specified path'
1789
+ });
1790
+ return extractContent(fullContent, ['documentation', 'coauthor', 'workflow']);
1791
+
1792
+ default:
1793
+ return extractContent(fullContent, ['documentation', 'writing', 'guide']);
1794
+ }
1795
+ }
1796
+ }
1797
+
1798
+ /**
1799
+ * Default Skill Executor
1800
+ */
1801
+ class DefaultSkillExecutor implements SkillExecutor {
1802
+ async execute(skill: SkillInfo, params: SkillExecutionParams): Promise<SkillExecutionResult> {
1803
+ const outputMessages: string[] = [];
1804
+ const files: string[] = [];
1805
+ const nextSteps: ExecutionStep[] = [];
1806
+
1807
+ outputMessages.push(`## ${skill.name} Skill - Execution Guide\n`);
1808
+ outputMessages.push(`**Task**: ${params.taskDescription}\n`);
1809
+
1810
+ try {
1811
+ // Read SKILL.md content
1812
+ const skillMdPath = path.join(skill.skillsPath, 'SKILL.md');
1813
+ files.push(skillMdPath);
1814
+ const skillContent = await fs.readFile(skillMdPath, 'utf-8');
1815
+
1816
+ // Generate execution steps
1817
+ const taskContent = this.extractDefaultContent(skill, skillContent, nextSteps);
1818
+ outputMessages.push(taskContent);
1819
+
1820
+ // Add input/output files to list if they exist
1821
+ if (params.inputFile) files.push(params.inputFile);
1822
+ if (params.outputFile) files.push(params.outputFile);
1823
+
1824
+ return {
1825
+ success: true,
1826
+ output: outputMessages.join('\n'),
1827
+ files: files,
1828
+ nextSteps: nextSteps,
1829
+ requiresManualExecution: true
1830
+ };
1831
+ } catch (error: any) {
1832
+ return {
1833
+ success: false,
1834
+ error: error.message
1835
+ };
1836
+ }
1837
+ }
1838
+
1839
+ /**
1840
+ * Extract default skill content and generate steps
1841
+ */
1842
+ private extractDefaultContent(skill: SkillInfo, fullContent: string, nextSteps: ExecutionStep[]): string {
1843
+ nextSteps.push({
1844
+ step: 1,
1845
+ action: 'Read SKILL.md',
1846
+ description: `Read ${skill.skillsPath}/SKILL.md for full instructions`,
1847
+ reason: 'Understand complete execution workflow'
1848
+ });
1849
+ nextSteps.push({
1850
+ step: 2,
1851
+ action: 'Follow workflow',
1852
+ description: 'Execute according to SKILL.md instructions',
1853
+ reason: 'Follow SKILL.md guidance for execution'
1854
+ });
1855
+
1856
+ return extractContent(fullContent, ['skill', 'guide', 'how to', skill.name]);
1857
+ }
1858
+ }
1859
+
1860
+ // ============================================================
1861
+ // ============================================================
1862
+
1863
+ /**
1864
+ * Execute skill - LLM analyzes SKILL.md and generates its own steps
1865
+ * @param skill Skill to execute
1866
+ * @param params Execution parameters
1867
+ * @returns Execution result with guidance
1868
+ */
1869
+ export async function executeSkill(
1870
+ skill: SkillInfo,
1871
+ params: SkillExecutionParams
1872
+ ): Promise<SkillExecutionResult> {
1873
+ const executor = new DocumentSkillExecutor();
1874
+ return executor.execute(skill, params);
1875
+ }
1876
+
1877
+ // ============================================================
1878
+ // Singleton Instance and Exports
1879
+ // ============================================================
1880
+
1881
+ let skillInvokerInstance: SkillInvoker | null = null;
1882
+
1883
+ export function getSkillInvoker(): SkillInvoker {
1884
+ if (!skillInvokerInstance) {
1885
+ skillInvokerInstance = new SkillInvoker();
1886
+ }
1887
+ return skillInvokerInstance;
1888
+ }