@xagent-ai/cli 1.2.2 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (568) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +38 -38
  2. package/.github/ISSUE_TEMPLATE/feature_request.md +20 -20
  3. package/.github/workflows/ci.yml +72 -0
  4. package/.github/workflows/release.yml +109 -0
  5. package/.gitmodules +3 -3
  6. package/README.md +326 -280
  7. package/README_CN.md +325 -279
  8. package/dist/ai-client/factory.d.ts +52 -0
  9. package/dist/ai-client/factory.d.ts.map +1 -0
  10. package/dist/ai-client/factory.js +132 -0
  11. package/dist/ai-client/factory.js.map +1 -0
  12. package/dist/ai-client/index.d.ts +20 -0
  13. package/dist/ai-client/index.d.ts.map +1 -0
  14. package/dist/ai-client/index.js +49 -0
  15. package/dist/ai-client/index.js.map +1 -0
  16. package/dist/ai-client/providers/anthropic.d.ts +57 -0
  17. package/dist/ai-client/providers/anthropic.d.ts.map +1 -0
  18. package/dist/ai-client/providers/anthropic.js +400 -0
  19. package/dist/ai-client/providers/anthropic.js.map +1 -0
  20. package/dist/ai-client/providers/openai.d.ts +57 -0
  21. package/dist/ai-client/providers/openai.d.ts.map +1 -0
  22. package/dist/ai-client/providers/openai.js +286 -0
  23. package/dist/ai-client/providers/openai.js.map +1 -0
  24. package/dist/ai-client/providers/remote.d.ts +111 -0
  25. package/dist/ai-client/providers/remote.d.ts.map +1 -0
  26. package/dist/ai-client/providers/remote.js +351 -0
  27. package/dist/ai-client/providers/remote.js.map +1 -0
  28. package/dist/ai-client/registry.d.ts +51 -0
  29. package/dist/ai-client/registry.d.ts.map +1 -0
  30. package/dist/ai-client/registry.js +81 -0
  31. package/dist/ai-client/registry.js.map +1 -0
  32. package/dist/ai-client/types.d.ts +260 -0
  33. package/dist/ai-client/types.d.ts.map +1 -0
  34. package/dist/ai-client/types.js +73 -0
  35. package/dist/ai-client/types.js.map +1 -0
  36. package/dist/ai-client-factory.d.ts +62 -0
  37. package/dist/ai-client-factory.d.ts.map +1 -0
  38. package/dist/ai-client-factory.js +157 -0
  39. package/dist/ai-client-factory.js.map +1 -0
  40. package/dist/auth.d.ts +23 -1
  41. package/dist/auth.d.ts.map +1 -1
  42. package/dist/auth.js +160 -168
  43. package/dist/auth.js.map +1 -1
  44. package/dist/cancellation.d.ts +5 -4
  45. package/dist/cancellation.d.ts.map +1 -1
  46. package/dist/cancellation.js +55 -32
  47. package/dist/cancellation.js.map +1 -1
  48. package/dist/checkpoint.d.ts +1 -1
  49. package/dist/checkpoint.d.ts.map +1 -1
  50. package/dist/checkpoint.js +2 -2
  51. package/dist/checkpoint.js.map +1 -1
  52. package/dist/cli.js +626 -13
  53. package/dist/cli.js.map +1 -1
  54. package/dist/config.d.ts +10 -4
  55. package/dist/config.d.ts.map +1 -1
  56. package/dist/config.js +62 -25
  57. package/dist/config.js.map +1 -1
  58. package/dist/context-compressor.d.ts +81 -16
  59. package/dist/context-compressor.d.ts.map +1 -1
  60. package/dist/context-compressor.js +712 -153
  61. package/dist/context-compressor.js.map +1 -1
  62. package/dist/gui-subagent/action-parser/actionParser.d.ts.map +1 -1
  63. package/dist/gui-subagent/action-parser/actionParser.js +4 -2
  64. package/dist/gui-subagent/action-parser/actionParser.js.map +1 -1
  65. package/dist/gui-subagent/agent/gui-agent.d.ts +29 -2
  66. package/dist/gui-subagent/agent/gui-agent.d.ts.map +1 -1
  67. package/dist/gui-subagent/agent/gui-agent.js +87 -45
  68. package/dist/gui-subagent/agent/gui-agent.js.map +1 -1
  69. package/dist/gui-subagent/index.d.ts +16 -1
  70. package/dist/gui-subagent/index.d.ts.map +1 -1
  71. package/dist/gui-subagent/index.js +4 -0
  72. package/dist/gui-subagent/index.js.map +1 -1
  73. package/dist/gui-subagent/operator/base-operator.d.ts.map +1 -1
  74. package/dist/gui-subagent/operator/base-operator.js +0 -1
  75. package/dist/gui-subagent/operator/base-operator.js.map +1 -1
  76. package/dist/gui-subagent/operator/computer-operator.d.ts.map +1 -1
  77. package/dist/gui-subagent/operator/computer-operator.js +29 -8
  78. package/dist/gui-subagent/operator/computer-operator.js.map +1 -1
  79. package/dist/gui-subagent/types/actions.d.ts +1 -1
  80. package/dist/gui-subagent/types/actions.d.ts.map +1 -1
  81. package/dist/gui-subagent/types/actions.js +0 -1
  82. package/dist/gui-subagent/types/actions.js.map +1 -1
  83. package/dist/gui-subagent/types/operator.d.ts +1 -1
  84. package/dist/gui-subagent/types/operator.d.ts.map +1 -1
  85. package/dist/index.d.ts +1 -2
  86. package/dist/index.d.ts.map +1 -1
  87. package/dist/index.js +1 -2
  88. package/dist/index.js.map +1 -1
  89. package/dist/input-processor.d.ts.map +1 -1
  90. package/dist/input-processor.js +6 -3
  91. package/dist/input-processor.js.map +1 -1
  92. package/dist/mcp.d.ts +5 -0
  93. package/dist/mcp.d.ts.map +1 -1
  94. package/dist/mcp.js +81 -35
  95. package/dist/mcp.js.map +1 -1
  96. package/dist/ripgrep.d.ts +29 -0
  97. package/dist/ripgrep.d.ts.map +1 -0
  98. package/dist/ripgrep.js +292 -0
  99. package/dist/ripgrep.js.map +1 -0
  100. package/dist/session.d.ts +23 -7
  101. package/dist/session.d.ts.map +1 -1
  102. package/dist/session.js +624 -243
  103. package/dist/session.js.map +1 -1
  104. package/dist/shell.d.ts +33 -0
  105. package/dist/shell.d.ts.map +1 -0
  106. package/dist/shell.js +125 -0
  107. package/dist/shell.js.map +1 -0
  108. package/dist/skill-installer.d.ts +38 -0
  109. package/dist/skill-installer.d.ts.map +1 -0
  110. package/dist/skill-installer.js +447 -0
  111. package/dist/skill-installer.js.map +1 -0
  112. package/dist/skill-invoker.d.ts +7 -1
  113. package/dist/skill-invoker.d.ts.map +1 -1
  114. package/dist/skill-invoker.js +34 -13
  115. package/dist/skill-invoker.js.map +1 -1
  116. package/dist/skill-loader.d.ts +8 -3
  117. package/dist/skill-loader.d.ts.map +1 -1
  118. package/dist/skill-loader.js +46 -44
  119. package/dist/skill-loader.js.map +1 -1
  120. package/dist/skill-manager.d.ts +85 -0
  121. package/dist/skill-manager.d.ts.map +1 -0
  122. package/dist/skill-manager.js +340 -0
  123. package/dist/skill-manager.js.map +1 -0
  124. package/dist/slash-commands.d.ts +38 -1
  125. package/dist/slash-commands.d.ts.map +1 -1
  126. package/dist/slash-commands.js +912 -296
  127. package/dist/slash-commands.js.map +1 -1
  128. package/dist/smart-approval.d.ts.map +1 -1
  129. package/dist/smart-approval.js +67 -55
  130. package/dist/smart-approval.js.map +1 -1
  131. package/dist/system-prompt-generator.d.ts +6 -0
  132. package/dist/system-prompt-generator.d.ts.map +1 -1
  133. package/dist/system-prompt-generator.js +84 -34
  134. package/dist/system-prompt-generator.js.map +1 -1
  135. package/dist/terminal.d.ts +28 -0
  136. package/dist/terminal.d.ts.map +1 -0
  137. package/dist/terminal.js +82 -0
  138. package/dist/terminal.js.map +1 -0
  139. package/dist/tools.d.ts +23 -7
  140. package/dist/tools.d.ts.map +1 -1
  141. package/dist/tools.js +797 -437
  142. package/dist/tools.js.map +1 -1
  143. package/dist/truncate.d.ts +55 -0
  144. package/dist/truncate.d.ts.map +1 -0
  145. package/dist/truncate.js +130 -0
  146. package/dist/truncate.js.map +1 -0
  147. package/dist/types.d.ts +27 -9
  148. package/dist/types.d.ts.map +1 -1
  149. package/dist/update.d.ts.map +1 -1
  150. package/dist/update.js +17 -28
  151. package/dist/update.js.map +1 -1
  152. package/dist/workflow.d.ts +5 -1
  153. package/dist/workflow.d.ts.map +1 -1
  154. package/dist/workflow.js +60 -47
  155. package/dist/workflow.js.map +1 -1
  156. package/docs/architecture/mcp-integration-guide.md +304 -194
  157. package/docs/architecture/overview.md +169 -169
  158. package/docs/architecture/tool-system-design.md +134 -134
  159. package/docs/cli/commands.md +349 -238
  160. package/docs/smart-mode.md +281 -281
  161. package/docs/third-party-models.md +439 -439
  162. package/find-skills/SKILL.md +133 -0
  163. package/package.json +89 -90
  164. package/scripts/install-ripgrep.js +241 -0
  165. package/src/ai-client/factory.ts +151 -0
  166. package/src/ai-client/index.ts +61 -0
  167. package/src/ai-client/providers/anthropic.ts +466 -0
  168. package/src/ai-client/providers/openai.ts +342 -0
  169. package/src/ai-client/providers/remote.ts +436 -0
  170. package/src/ai-client/registry.ts +97 -0
  171. package/src/ai-client/types.ts +345 -0
  172. package/src/ai-client-factory.ts +204 -0
  173. package/src/auth.ts +663 -614
  174. package/src/cancellation.ts +205 -176
  175. package/src/checkpoint.ts +219 -219
  176. package/src/cli.ts +1406 -743
  177. package/src/config.ts +341 -297
  178. package/src/context-compressor.ts +982 -290
  179. package/src/conversation.ts +288 -288
  180. package/src/gui-subagent/action-parser/actionParser.ts +318 -315
  181. package/src/gui-subagent/action-parser/constants.ts +14 -14
  182. package/src/gui-subagent/action-parser/index.ts +8 -8
  183. package/src/gui-subagent/action-parser/types.ts +31 -31
  184. package/src/gui-subagent/agent/gui-agent.ts +1151 -1089
  185. package/src/gui-subagent/agent/index.ts +5 -5
  186. package/src/gui-subagent/index.ts +177 -163
  187. package/src/gui-subagent/operator/base-operator.ts +244 -245
  188. package/src/gui-subagent/operator/computer-operator.ts +540 -520
  189. package/src/gui-subagent/operator/index.ts +6 -6
  190. package/src/gui-subagent/types/actions.ts +260 -262
  191. package/src/gui-subagent/types/index.ts +6 -6
  192. package/src/gui-subagent/types/operator.ts +106 -106
  193. package/src/gui-subagent/utils.ts +51 -51
  194. package/src/index.ts +17 -18
  195. package/src/input-processor.ts +6 -3
  196. package/src/logger.ts +438 -438
  197. package/src/mcp.ts +730 -682
  198. package/src/memory.ts +344 -344
  199. package/src/ripgrep.ts +368 -0
  200. package/src/session-manager.ts +308 -308
  201. package/src/session.ts +948 -386
  202. package/src/shell.ts +133 -0
  203. package/src/skill-installer.ts +518 -0
  204. package/src/skill-invoker.ts +960 -935
  205. package/src/skill-loader.ts +501 -496
  206. package/src/skill-manager.ts +384 -0
  207. package/src/slash-commands.ts +2181 -1389
  208. package/src/smart-approval.ts +117 -73
  209. package/src/system-prompt-generator.ts +89 -34
  210. package/src/terminal.ts +96 -0
  211. package/src/theme.ts +738 -738
  212. package/src/tools.ts +1336 -773
  213. package/src/truncate.ts +173 -0
  214. package/src/types.ts +219 -198
  215. package/src/update.ts +22 -32
  216. package/src/workflow.ts +523 -508
  217. package/tsconfig.json +22 -22
  218. package/vitest.config.ts +19 -19
  219. package/dist/ai-client.d.ts +0 -86
  220. package/dist/ai-client.d.ts.map +0 -1
  221. package/dist/ai-client.js +0 -1372
  222. package/dist/ai-client.js.map +0 -1
  223. package/dist/gui-subagent/operator/browser-operator.d.ts +0 -36
  224. package/dist/gui-subagent/operator/browser-operator.d.ts.map +0 -1
  225. package/dist/gui-subagent/operator/browser-operator.js +0 -306
  226. package/dist/gui-subagent/operator/browser-operator.js.map +0 -1
  227. package/dist/gui-subagent/operator/desktop-operator.d.ts +0 -55
  228. package/dist/gui-subagent/operator/desktop-operator.d.ts.map +0 -1
  229. package/dist/gui-subagent/operator/desktop-operator.js +0 -527
  230. package/dist/gui-subagent/operator/desktop-operator.js.map +0 -1
  231. package/dist/hook.d.ts +0 -73
  232. package/dist/hook.d.ts.map +0 -1
  233. package/dist/hook.js +0 -156
  234. package/dist/hook.js.map +0 -1
  235. package/dist/input-history.d.ts +0 -24
  236. package/dist/input-history.d.ts.map +0 -1
  237. package/dist/input-history.js +0 -94
  238. package/dist/input-history.js.map +0 -1
  239. package/dist/keyboard-manager.d.ts +0 -151
  240. package/dist/keyboard-manager.d.ts.map +0 -1
  241. package/dist/keyboard-manager.js +0 -396
  242. package/dist/keyboard-manager.js.map +0 -1
  243. package/dist/print-system-prompt.d.ts +0 -2
  244. package/dist/print-system-prompt.d.ts.map +0 -1
  245. package/dist/print-system-prompt.js +0 -40
  246. package/dist/print-system-prompt.js.map +0 -1
  247. package/dist/remote-ai-client.d.ts +0 -104
  248. package/dist/remote-ai-client.d.ts.map +0 -1
  249. package/dist/remote-ai-client.js +0 -552
  250. package/dist/remote-ai-client.js.map +0 -1
  251. package/dist/sdk-output-adapter.d.ts +0 -232
  252. package/dist/sdk-output-adapter.d.ts.map +0 -1
  253. package/dist/sdk-output-adapter.js +0 -636
  254. package/dist/sdk-output-adapter.js.map +0 -1
  255. package/dist/sdk-session-v2.d.ts +0 -13
  256. package/dist/sdk-session-v2.d.ts.map +0 -1
  257. package/dist/sdk-session-v2.js +0 -46
  258. package/dist/sdk-session-v2.js.map +0 -1
  259. package/dist/sdk-session.d.ts +0 -13
  260. package/dist/sdk-session.d.ts.map +0 -1
  261. package/dist/sdk-session.js +0 -48
  262. package/dist/sdk-session.js.map +0 -1
  263. package/dist/test-boundary-conditions.d.ts.map +0 -1
  264. package/dist/test-boundary-conditions.js.map +0 -1
  265. package/dist/test-cancellation-fix.d.ts.map +0 -1
  266. package/dist/test-cancellation-fix.js.map +0 -1
  267. package/dist/test-input-history.d.ts.map +0 -1
  268. package/dist/test-input-history.js.map +0 -1
  269. package/dist/test-interaction-flow.d.ts.map +0 -1
  270. package/dist/test-interaction-flow.js.map +0 -1
  271. package/dist/test-quick.d.ts.map +0 -1
  272. package/dist/test-quick.js.map +0 -1
  273. package/dist/test-user-interaction.d.ts.map +0 -1
  274. package/dist/test-user-interaction.js.map +0 -1
  275. package/dist/tools/edit-diff.d.ts +0 -32
  276. package/dist/tools/edit-diff.d.ts.map +0 -1
  277. package/dist/tools/edit-diff.js +0 -185
  278. package/dist/tools/edit-diff.js.map +0 -1
  279. package/dist/tools/edit.d.ts +0 -11
  280. package/dist/tools/edit.d.ts.map +0 -1
  281. package/dist/tools/edit.js +0 -129
  282. package/dist/tools/edit.js.map +0 -1
  283. package/dist/unified-session.d.ts +0 -42
  284. package/dist/unified-session.d.ts.map +0 -1
  285. package/dist/unified-session.js +0 -271
  286. package/dist/unified-session.js.map +0 -1
  287. package/skills/.claude-plugin/marketplace.json +0 -45
  288. package/skills/README.md +0 -94
  289. package/skills/THIRD_PARTY_NOTICES.md +0 -405
  290. package/skills/skills/algorithmic-art/LICENSE.txt +0 -202
  291. package/skills/skills/algorithmic-art/SKILL.md +0 -405
  292. package/skills/skills/algorithmic-art/templates/generator_template.js +0 -223
  293. package/skills/skills/algorithmic-art/templates/viewer.html +0 -599
  294. package/skills/skills/brand-guidelines/LICENSE.txt +0 -202
  295. package/skills/skills/brand-guidelines/SKILL.md +0 -73
  296. package/skills/skills/canvas-design/LICENSE.txt +0 -202
  297. package/skills/skills/canvas-design/SKILL.md +0 -130
  298. package/skills/skills/canvas-design/canvas-fonts/ArsenalSC-OFL.txt +0 -93
  299. package/skills/skills/canvas-design/canvas-fonts/ArsenalSC-Regular.ttf +0 -0
  300. package/skills/skills/canvas-design/canvas-fonts/BigShoulders-Bold.ttf +0 -0
  301. package/skills/skills/canvas-design/canvas-fonts/BigShoulders-OFL.txt +0 -93
  302. package/skills/skills/canvas-design/canvas-fonts/BigShoulders-Regular.ttf +0 -0
  303. package/skills/skills/canvas-design/canvas-fonts/Boldonse-OFL.txt +0 -93
  304. package/skills/skills/canvas-design/canvas-fonts/Boldonse-Regular.ttf +0 -0
  305. package/skills/skills/canvas-design/canvas-fonts/BricolageGrotesque-Bold.ttf +0 -0
  306. package/skills/skills/canvas-design/canvas-fonts/BricolageGrotesque-OFL.txt +0 -93
  307. package/skills/skills/canvas-design/canvas-fonts/BricolageGrotesque-Regular.ttf +0 -0
  308. package/skills/skills/canvas-design/canvas-fonts/CrimsonPro-Bold.ttf +0 -0
  309. package/skills/skills/canvas-design/canvas-fonts/CrimsonPro-Italic.ttf +0 -0
  310. package/skills/skills/canvas-design/canvas-fonts/CrimsonPro-OFL.txt +0 -93
  311. package/skills/skills/canvas-design/canvas-fonts/CrimsonPro-Regular.ttf +0 -0
  312. package/skills/skills/canvas-design/canvas-fonts/DMMono-OFL.txt +0 -93
  313. package/skills/skills/canvas-design/canvas-fonts/DMMono-Regular.ttf +0 -0
  314. package/skills/skills/canvas-design/canvas-fonts/EricaOne-OFL.txt +0 -94
  315. package/skills/skills/canvas-design/canvas-fonts/EricaOne-Regular.ttf +0 -0
  316. package/skills/skills/canvas-design/canvas-fonts/GeistMono-Bold.ttf +0 -0
  317. package/skills/skills/canvas-design/canvas-fonts/GeistMono-OFL.txt +0 -93
  318. package/skills/skills/canvas-design/canvas-fonts/GeistMono-Regular.ttf +0 -0
  319. package/skills/skills/canvas-design/canvas-fonts/Gloock-OFL.txt +0 -93
  320. package/skills/skills/canvas-design/canvas-fonts/Gloock-Regular.ttf +0 -0
  321. package/skills/skills/canvas-design/canvas-fonts/IBMPlexMono-Bold.ttf +0 -0
  322. package/skills/skills/canvas-design/canvas-fonts/IBMPlexMono-OFL.txt +0 -93
  323. package/skills/skills/canvas-design/canvas-fonts/IBMPlexMono-Regular.ttf +0 -0
  324. package/skills/skills/canvas-design/canvas-fonts/IBMPlexSerif-Bold.ttf +0 -0
  325. package/skills/skills/canvas-design/canvas-fonts/IBMPlexSerif-BoldItalic.ttf +0 -0
  326. package/skills/skills/canvas-design/canvas-fonts/IBMPlexSerif-Italic.ttf +0 -0
  327. package/skills/skills/canvas-design/canvas-fonts/IBMPlexSerif-Regular.ttf +0 -0
  328. package/skills/skills/canvas-design/canvas-fonts/InstrumentSans-Bold.ttf +0 -0
  329. package/skills/skills/canvas-design/canvas-fonts/InstrumentSans-BoldItalic.ttf +0 -0
  330. package/skills/skills/canvas-design/canvas-fonts/InstrumentSans-Italic.ttf +0 -0
  331. package/skills/skills/canvas-design/canvas-fonts/InstrumentSans-OFL.txt +0 -93
  332. package/skills/skills/canvas-design/canvas-fonts/InstrumentSans-Regular.ttf +0 -0
  333. package/skills/skills/canvas-design/canvas-fonts/InstrumentSerif-Italic.ttf +0 -0
  334. package/skills/skills/canvas-design/canvas-fonts/InstrumentSerif-Regular.ttf +0 -0
  335. package/skills/skills/canvas-design/canvas-fonts/Italiana-OFL.txt +0 -93
  336. package/skills/skills/canvas-design/canvas-fonts/Italiana-Regular.ttf +0 -0
  337. package/skills/skills/canvas-design/canvas-fonts/JetBrainsMono-Bold.ttf +0 -0
  338. package/skills/skills/canvas-design/canvas-fonts/JetBrainsMono-OFL.txt +0 -93
  339. package/skills/skills/canvas-design/canvas-fonts/JetBrainsMono-Regular.ttf +0 -0
  340. package/skills/skills/canvas-design/canvas-fonts/Jura-Light.ttf +0 -0
  341. package/skills/skills/canvas-design/canvas-fonts/Jura-Medium.ttf +0 -0
  342. package/skills/skills/canvas-design/canvas-fonts/Jura-OFL.txt +0 -93
  343. package/skills/skills/canvas-design/canvas-fonts/LibreBaskerville-OFL.txt +0 -93
  344. package/skills/skills/canvas-design/canvas-fonts/LibreBaskerville-Regular.ttf +0 -0
  345. package/skills/skills/canvas-design/canvas-fonts/Lora-Bold.ttf +0 -0
  346. package/skills/skills/canvas-design/canvas-fonts/Lora-BoldItalic.ttf +0 -0
  347. package/skills/skills/canvas-design/canvas-fonts/Lora-Italic.ttf +0 -0
  348. package/skills/skills/canvas-design/canvas-fonts/Lora-OFL.txt +0 -93
  349. package/skills/skills/canvas-design/canvas-fonts/Lora-Regular.ttf +0 -0
  350. package/skills/skills/canvas-design/canvas-fonts/NationalPark-Bold.ttf +0 -0
  351. package/skills/skills/canvas-design/canvas-fonts/NationalPark-OFL.txt +0 -93
  352. package/skills/skills/canvas-design/canvas-fonts/NationalPark-Regular.ttf +0 -0
  353. package/skills/skills/canvas-design/canvas-fonts/NothingYouCouldDo-OFL.txt +0 -93
  354. package/skills/skills/canvas-design/canvas-fonts/NothingYouCouldDo-Regular.ttf +0 -0
  355. package/skills/skills/canvas-design/canvas-fonts/Outfit-Bold.ttf +0 -0
  356. package/skills/skills/canvas-design/canvas-fonts/Outfit-OFL.txt +0 -93
  357. package/skills/skills/canvas-design/canvas-fonts/Outfit-Regular.ttf +0 -0
  358. package/skills/skills/canvas-design/canvas-fonts/PixelifySans-Medium.ttf +0 -0
  359. package/skills/skills/canvas-design/canvas-fonts/PixelifySans-OFL.txt +0 -93
  360. package/skills/skills/canvas-design/canvas-fonts/PoiretOne-OFL.txt +0 -93
  361. package/skills/skills/canvas-design/canvas-fonts/PoiretOne-Regular.ttf +0 -0
  362. package/skills/skills/canvas-design/canvas-fonts/RedHatMono-Bold.ttf +0 -0
  363. package/skills/skills/canvas-design/canvas-fonts/RedHatMono-OFL.txt +0 -93
  364. package/skills/skills/canvas-design/canvas-fonts/RedHatMono-Regular.ttf +0 -0
  365. package/skills/skills/canvas-design/canvas-fonts/Silkscreen-OFL.txt +0 -93
  366. package/skills/skills/canvas-design/canvas-fonts/Silkscreen-Regular.ttf +0 -0
  367. package/skills/skills/canvas-design/canvas-fonts/SmoochSans-Medium.ttf +0 -0
  368. package/skills/skills/canvas-design/canvas-fonts/SmoochSans-OFL.txt +0 -93
  369. package/skills/skills/canvas-design/canvas-fonts/Tektur-Medium.ttf +0 -0
  370. package/skills/skills/canvas-design/canvas-fonts/Tektur-OFL.txt +0 -93
  371. package/skills/skills/canvas-design/canvas-fonts/Tektur-Regular.ttf +0 -0
  372. package/skills/skills/canvas-design/canvas-fonts/WorkSans-Bold.ttf +0 -0
  373. package/skills/skills/canvas-design/canvas-fonts/WorkSans-BoldItalic.ttf +0 -0
  374. package/skills/skills/canvas-design/canvas-fonts/WorkSans-Italic.ttf +0 -0
  375. package/skills/skills/canvas-design/canvas-fonts/WorkSans-OFL.txt +0 -93
  376. package/skills/skills/canvas-design/canvas-fonts/WorkSans-Regular.ttf +0 -0
  377. package/skills/skills/canvas-design/canvas-fonts/YoungSerif-OFL.txt +0 -93
  378. package/skills/skills/canvas-design/canvas-fonts/YoungSerif-Regular.ttf +0 -0
  379. package/skills/skills/doc-coauthoring/SKILL.md +0 -375
  380. package/skills/skills/docx/LICENSE.txt +0 -30
  381. package/skills/skills/docx/SKILL.md +0 -197
  382. package/skills/skills/docx/docx-js.md +0 -350
  383. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -1499
  384. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -146
  385. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -1085
  386. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -11
  387. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -3081
  388. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -23
  389. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -185
  390. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -287
  391. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -1676
  392. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -28
  393. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -144
  394. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -174
  395. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -25
  396. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -18
  397. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -59
  398. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -56
  399. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -195
  400. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -582
  401. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -25
  402. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -4439
  403. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -570
  404. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -509
  405. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -12
  406. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -108
  407. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -96
  408. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -3646
  409. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -116
  410. package/skills/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -42
  411. package/skills/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -50
  412. package/skills/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -49
  413. package/skills/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -33
  414. package/skills/skills/docx/ooxml/schemas/mce/mc.xsd +0 -75
  415. package/skills/skills/docx/ooxml/schemas/microsoft/wml-2010.xsd +0 -560
  416. package/skills/skills/docx/ooxml/schemas/microsoft/wml-2012.xsd +0 -67
  417. package/skills/skills/docx/ooxml/schemas/microsoft/wml-2018.xsd +0 -14
  418. package/skills/skills/docx/ooxml/schemas/microsoft/wml-cex-2018.xsd +0 -20
  419. package/skills/skills/docx/ooxml/schemas/microsoft/wml-cid-2016.xsd +0 -13
  420. package/skills/skills/docx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -4
  421. package/skills/skills/docx/ooxml/schemas/microsoft/wml-symex-2015.xsd +0 -8
  422. package/skills/skills/docx/ooxml/scripts/pack.py +0 -159
  423. package/skills/skills/docx/ooxml/scripts/unpack.py +0 -29
  424. package/skills/skills/docx/ooxml/scripts/validate.py +0 -69
  425. package/skills/skills/docx/ooxml/scripts/validation/__init__.py +0 -15
  426. package/skills/skills/docx/ooxml/scripts/validation/base.py +0 -951
  427. package/skills/skills/docx/ooxml/scripts/validation/docx.py +0 -274
  428. package/skills/skills/docx/ooxml/scripts/validation/pptx.py +0 -315
  429. package/skills/skills/docx/ooxml/scripts/validation/redlining.py +0 -279
  430. package/skills/skills/docx/ooxml.md +0 -610
  431. package/skills/skills/docx/scripts/__init__.py +0 -1
  432. package/skills/skills/docx/scripts/document.py +0 -1276
  433. package/skills/skills/docx/scripts/templates/comments.xml +0 -3
  434. package/skills/skills/docx/scripts/templates/commentsExtended.xml +0 -3
  435. package/skills/skills/docx/scripts/templates/commentsExtensible.xml +0 -3
  436. package/skills/skills/docx/scripts/templates/commentsIds.xml +0 -3
  437. package/skills/skills/docx/scripts/templates/people.xml +0 -3
  438. package/skills/skills/docx/scripts/utilities.py +0 -374
  439. package/skills/skills/frontend-design/LICENSE.txt +0 -177
  440. package/skills/skills/frontend-design/SKILL.md +0 -42
  441. package/skills/skills/internal-comms/LICENSE.txt +0 -202
  442. package/skills/skills/internal-comms/SKILL.md +0 -32
  443. package/skills/skills/internal-comms/examples/3p-updates.md +0 -47
  444. package/skills/skills/internal-comms/examples/company-newsletter.md +0 -65
  445. package/skills/skills/internal-comms/examples/faq-answers.md +0 -30
  446. package/skills/skills/internal-comms/examples/general-comms.md +0 -16
  447. package/skills/skills/mcp-builder/LICENSE.txt +0 -202
  448. package/skills/skills/mcp-builder/SKILL.md +0 -236
  449. package/skills/skills/mcp-builder/reference/evaluation.md +0 -602
  450. package/skills/skills/mcp-builder/reference/mcp_best_practices.md +0 -249
  451. package/skills/skills/mcp-builder/reference/node_mcp_server.md +0 -970
  452. package/skills/skills/mcp-builder/reference/python_mcp_server.md +0 -719
  453. package/skills/skills/mcp-builder/scripts/connections.py +0 -151
  454. package/skills/skills/mcp-builder/scripts/evaluation.py +0 -373
  455. package/skills/skills/mcp-builder/scripts/example_evaluation.xml +0 -22
  456. package/skills/skills/mcp-builder/scripts/requirements.txt +0 -2
  457. package/skills/skills/pdf/LICENSE.txt +0 -30
  458. package/skills/skills/pdf/SKILL.md +0 -294
  459. package/skills/skills/pdf/forms.md +0 -205
  460. package/skills/skills/pdf/reference.md +0 -612
  461. package/skills/skills/pdf/scripts/check_bounding_boxes.py +0 -70
  462. package/skills/skills/pdf/scripts/check_bounding_boxes_test.py +0 -226
  463. package/skills/skills/pdf/scripts/check_fillable_fields.py +0 -12
  464. package/skills/skills/pdf/scripts/convert_pdf_to_images.py +0 -35
  465. package/skills/skills/pdf/scripts/create_validation_image.py +0 -41
  466. package/skills/skills/pdf/scripts/extract_form_field_info.py +0 -152
  467. package/skills/skills/pdf/scripts/fill_fillable_fields.py +0 -114
  468. package/skills/skills/pdf/scripts/fill_pdf_form_with_annotations.py +0 -108
  469. package/skills/skills/pptx/LICENSE.txt +0 -30
  470. package/skills/skills/pptx/SKILL.md +0 -484
  471. package/skills/skills/pptx/html2pptx.md +0 -625
  472. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -1499
  473. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -146
  474. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -1085
  475. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -11
  476. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -3081
  477. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -23
  478. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -185
  479. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -287
  480. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -1676
  481. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -28
  482. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -144
  483. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -174
  484. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -25
  485. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -18
  486. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -59
  487. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -56
  488. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -195
  489. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -582
  490. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -25
  491. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -4439
  492. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -570
  493. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -509
  494. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -12
  495. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -108
  496. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -96
  497. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -3646
  498. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -116
  499. package/skills/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -42
  500. package/skills/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -50
  501. package/skills/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -49
  502. package/skills/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -33
  503. package/skills/skills/pptx/ooxml/schemas/mce/mc.xsd +0 -75
  504. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-2010.xsd +0 -560
  505. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-2012.xsd +0 -67
  506. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-2018.xsd +0 -14
  507. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-cex-2018.xsd +0 -20
  508. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-cid-2016.xsd +0 -13
  509. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -4
  510. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-symex-2015.xsd +0 -8
  511. package/skills/skills/pptx/ooxml/scripts/pack.py +0 -159
  512. package/skills/skills/pptx/ooxml/scripts/unpack.py +0 -29
  513. package/skills/skills/pptx/ooxml/scripts/validate.py +0 -69
  514. package/skills/skills/pptx/ooxml/scripts/validation/__init__.py +0 -15
  515. package/skills/skills/pptx/ooxml/scripts/validation/base.py +0 -951
  516. package/skills/skills/pptx/ooxml/scripts/validation/docx.py +0 -274
  517. package/skills/skills/pptx/ooxml/scripts/validation/pptx.py +0 -315
  518. package/skills/skills/pptx/ooxml/scripts/validation/redlining.py +0 -279
  519. package/skills/skills/pptx/ooxml.md +0 -427
  520. package/skills/skills/pptx/scripts/html2pptx.js +0 -979
  521. package/skills/skills/pptx/scripts/inventory.py +0 -1020
  522. package/skills/skills/pptx/scripts/rearrange.py +0 -231
  523. package/skills/skills/pptx/scripts/replace.py +0 -385
  524. package/skills/skills/pptx/scripts/thumbnail.py +0 -450
  525. package/skills/skills/skill-creator/LICENSE.txt +0 -202
  526. package/skills/skills/skill-creator/SKILL.md +0 -356
  527. package/skills/skills/skill-creator/references/output-patterns.md +0 -82
  528. package/skills/skills/skill-creator/references/workflows.md +0 -28
  529. package/skills/skills/skill-creator/scripts/init_skill.py +0 -303
  530. package/skills/skills/skill-creator/scripts/package_skill.py +0 -110
  531. package/skills/skills/skill-creator/scripts/quick_validate.py +0 -95
  532. package/skills/skills/slack-gif-creator/LICENSE.txt +0 -202
  533. package/skills/skills/slack-gif-creator/SKILL.md +0 -254
  534. package/skills/skills/slack-gif-creator/core/easing.py +0 -234
  535. package/skills/skills/slack-gif-creator/core/frame_composer.py +0 -176
  536. package/skills/skills/slack-gif-creator/core/gif_builder.py +0 -269
  537. package/skills/skills/slack-gif-creator/core/validators.py +0 -136
  538. package/skills/skills/slack-gif-creator/requirements.txt +0 -4
  539. package/skills/skills/theme-factory/LICENSE.txt +0 -202
  540. package/skills/skills/theme-factory/SKILL.md +0 -59
  541. package/skills/skills/theme-factory/theme-showcase.pdf +0 -0
  542. package/skills/skills/theme-factory/themes/arctic-frost.md +0 -19
  543. package/skills/skills/theme-factory/themes/botanical-garden.md +0 -19
  544. package/skills/skills/theme-factory/themes/desert-rose.md +0 -19
  545. package/skills/skills/theme-factory/themes/forest-canopy.md +0 -19
  546. package/skills/skills/theme-factory/themes/golden-hour.md +0 -19
  547. package/skills/skills/theme-factory/themes/midnight-galaxy.md +0 -19
  548. package/skills/skills/theme-factory/themes/modern-minimalist.md +0 -19
  549. package/skills/skills/theme-factory/themes/ocean-depths.md +0 -19
  550. package/skills/skills/theme-factory/themes/sunset-boulevard.md +0 -19
  551. package/skills/skills/theme-factory/themes/tech-innovation.md +0 -19
  552. package/skills/skills/web-artifacts-builder/LICENSE.txt +0 -202
  553. package/skills/skills/web-artifacts-builder/SKILL.md +0 -74
  554. package/skills/skills/web-artifacts-builder/scripts/bundle-artifact.sh +0 -54
  555. package/skills/skills/web-artifacts-builder/scripts/init-artifact.sh +0 -322
  556. package/skills/skills/webapp-testing/LICENSE.txt +0 -202
  557. package/skills/skills/webapp-testing/SKILL.md +0 -96
  558. package/skills/skills/webapp-testing/examples/console_logging.py +0 -35
  559. package/skills/skills/webapp-testing/examples/element_discovery.py +0 -40
  560. package/skills/skills/webapp-testing/examples/static_html_automation.py +0 -33
  561. package/skills/skills/webapp-testing/scripts/with_server.py +0 -106
  562. package/skills/skills/xlsx/LICENSE.txt +0 -30
  563. package/skills/skills/xlsx/SKILL.md +0 -289
  564. package/skills/skills/xlsx/recalc.py +0 -178
  565. package/skills/spec/agent-skills-spec.md +0 -3
  566. package/skills/template/SKILL.md +0 -6
  567. package/src/ai-client.ts +0 -1560
  568. package/src/remote-ai-client.ts +0 -664
package/src/cli.ts CHANGED
@@ -1,743 +1,1406 @@
1
- #!/usr/bin/env node
2
-
3
- import { Command } from 'commander';
4
- import chalk from 'chalk';
5
- import { startInteractiveSession } from './session.js';
6
- import { getConfigManager } from './config.js';
7
- import { AuthService, selectAuthType } from './auth.js';
8
- import { getAgentManager } from './agents.js';
9
- import { getMCPManager } from './mcp.js';
10
- import { getLogger, setConfigProvider } from './logger.js';
11
- import { theme, icons, colors } from './theme.js';
12
- import { getCancellationManager } from './cancellation.js';
13
- import { readFileSync, promises as fs } from 'fs';
14
- import path from 'path';
15
- import { dirname, join } from 'path';
16
- import { fileURLToPath } from 'url';
17
- import { glob } from 'glob';
18
-
19
- // Get current directory
20
- const __filename = fileURLToPath(import.meta.url);
21
- const __dirname = dirname(__filename);
22
-
23
- // Read package.json
24
- const packageJsonPath = join(__dirname, '../package.json');
25
- const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
26
-
27
- const logger = getLogger();
28
-
29
- // Initialize CancellationManager early to set up ESC handler
30
- getCancellationManager();
31
-
32
- // Set up config provider for logger to read loggerLevel
33
- setConfigProvider(() => {
34
- const configManager = getConfigManager();
35
- return {
36
- getLoggerLevel: () => configManager.getLoggerLevel()
37
- };
38
- });
39
-
40
- const program = new Command();
41
-
42
- /**
43
- * Format error message for user-friendly display
44
- */
45
- function formatError(error: unknown): { message: string; suggestion: string } {
46
- const errorMessage = error instanceof Error ? error.message : String(error);
47
-
48
- // Network errors
49
- if (errorMessage.includes('ENOTFOUND') || errorMessage.includes('ECONNREFUSED')) {
50
- return {
51
- message: 'Unable to connect to the server',
52
- suggestion: 'Please check your network connection and try again.'
53
- };
54
- }
55
- if (errorMessage.includes('ETIMEDOUT') || errorMessage.includes('ECONNRESET')) {
56
- return {
57
- message: 'Connection timed out',
58
- suggestion: 'The server may be busy. Please wait a moment and try again.'
59
- };
60
- }
61
- // Authentication errors
62
- if (errorMessage.includes('401') || errorMessage.includes('Unauthorized') || errorMessage.includes('invalid token')) {
63
- return {
64
- message: 'Authentication failed',
65
- suggestion: 'Please login again using: xagent auth'
66
- };
67
- }
68
- // Token expired
69
- if (errorMessage.includes('token') && errorMessage.includes('expired')) {
70
- return {
71
- message: 'Session expired',
72
- suggestion: 'Please login again using: xagent auth'
73
- };
74
- }
75
- // Permission errors
76
- if (errorMessage.includes('EACCES') || errorMessage.includes('permission denied')) {
77
- return {
78
- message: 'Permission denied',
79
- suggestion: 'Please check your file permissions or run with appropriate privileges.'
80
- };
81
- }
82
- // File not found
83
- if (errorMessage.includes('ENOENT') || errorMessage.includes('not found')) {
84
- return {
85
- message: 'File or resource not found',
86
- suggestion: 'Please check the path and try again.'
87
- };
88
- }
89
- // Invalid JSON
90
- if (errorMessage.includes('JSON') || errorMessage.includes('parse')) {
91
- return {
92
- message: 'Invalid data format',
93
- suggestion: 'The configuration file may be corrupted. Please check the file content.'
94
- };
95
- }
96
-
97
- // Default friendly message
98
- return {
99
- message: 'An error occurred',
100
- suggestion: 'Please try again. If the problem persists, check your configuration.'
101
- };
102
- }
103
-
104
- program
105
- .name('xagent')
106
- .description('AI-powered command-line assistant')
107
- .version(packageJson.version)
108
- .option('-h, --help', 'Show help');
109
-
110
- program
111
- .command('start')
112
- .description('Start the xAgent CLI interactive session')
113
- .option('--approval-mode <mode>', 'Set approval mode (yolo, accept_edits, plan, default, smart)')
114
- .action(async (options) => {
115
- if (options.approvalMode) {
116
- const { getConfigManager } = await import('./config.js');
117
- const { ExecutionMode } = await import('./types.js');
118
- const configManager = getConfigManager();
119
-
120
- const validModes = Object.values(ExecutionMode) as string[];
121
- if (!validModes.includes(options.approvalMode)) {
122
- console.log('');
123
- console.log(colors.error(`Invalid approval mode: ${options.approvalMode}`));
124
- console.log(colors.textMuted(`Valid modes: ${validModes.join(', ')}`));
125
- console.log('');
126
- process.exit(1);
127
- }
128
-
129
- configManager.setApprovalMode(options.approvalMode as any);
130
- await configManager.save('global');
131
- console.log('');
132
- console.log(colors.success(`✅ Approval mode set to: ${options.approvalMode}`));
133
- console.log('');
134
- }
135
- await startInteractiveSession();
136
- });
137
-
138
- program
139
- .command('auth')
140
- .description('Configure authentication for xAgent CLI')
141
- .action(async () => {
142
- const separator = icons.separator.repeat(40);
143
- console.log('');
144
- console.log(colors.primaryBright(`${icons.lock} Authentication Management`));
145
- console.log(colors.border(separator));
146
- console.log('');
147
-
148
- const authType = await selectAuthType();
149
- const configManager = getConfigManager();
150
- configManager.set('selectedAuthType', authType);
151
-
152
- const authService = new AuthService({
153
- type: authType,
154
- apiKey: '',
155
- baseUrl: '',
156
- modelName: ''
157
- });
158
-
159
- const success = await authService.authenticate();
160
-
161
- if (success) {
162
- const authConfig = authService.getAuthConfig();
163
- await configManager.setAuthConfig(authConfig);
164
-
165
- console.log('');
166
- console.log(colors.success('Authentication configured successfully!'));
167
- console.log(colors.textMuted('You can now run "xagent start" to begin'));
168
- console.log('');
169
- } else {
170
- console.log('');
171
- console.log(colors.error('Authentication failed. Please try again.'));
172
- console.log(colors.textMuted('Run "xagent auth" to retry'));
173
- console.log('');
174
- process.exit(1);
175
- }
176
- });
177
-
178
- program
179
- .command('agent')
180
- .description('Add, list, or remove SubAgents')
181
- .option('-l, --list', 'List all agents')
182
- .option('-a, --add <name>', 'Add a new agent')
183
- .option('-r, --remove <name>', 'Remove an agent')
184
- .option('--scope <scope>', 'Scope (global or project)', 'global')
185
- .action(async (options) => {
186
- const agentManager = getAgentManager(process.cwd());
187
- await agentManager.loadAgents();
188
-
189
- if (options.list) {
190
- const agents = agentManager.getAllAgents();
191
-
192
- if (agents.length === 0) {
193
- console.log('');
194
- console.log(colors.warning('No agents configured'));
195
- console.log(colors.textMuted('Use /agents install in interactive mode to add agents'));
196
- console.log('');
197
- } else {
198
- const separator = icons.separator.repeat(40);
199
- console.log('');
200
- console.log(colors.primaryBright(`${icons.robot} Available Agents`));
201
- console.log(colors.border(separator));
202
- console.log('');
203
-
204
- agents.forEach((agent, index) => {
205
- console.log(` ${colors.primaryBright(`${index + 1}. ${agent.agentType}`)}`);
206
- console.log(` ${colors.textDim(` ${agent.whenToUse}`)}`);
207
- console.log('');
208
- });
209
- }
210
- } else if (options.add) {
211
- console.log('');
212
- console.log(colors.warning('Agent creation wizard not implemented yet'));
213
- console.log(colors.textMuted('Use /agents install in interactive mode'));
214
- console.log('');
215
- } else if (options.remove) {
216
- try {
217
- await agentManager.removeAgent(options.remove, options.scope);
218
- console.log('');
219
- console.log(colors.success(`Agent ${options.remove} removed successfully`));
220
- console.log('');
221
- } catch (error: any) {
222
- const { message, suggestion } = formatError(error);
223
- console.log('');
224
- console.log(colors.error(`Failed to remove agent: ${message}`));
225
- console.log(colors.textMuted(suggestion));
226
- console.log('');
227
- }
228
- } else {
229
- console.log('');
230
- console.log(colors.warning('Please specify an action: --list, --add, or --remove'));
231
- console.log('');
232
- }
233
- });
234
-
235
- program
236
- .command('mcp')
237
- .description('Add, list, or remove MCP servers')
238
- .option('-l, --list', 'List all MCP servers')
239
- .option('-a, --add <name>', 'Add a new MCP server')
240
- .option('-r, --remove <name>', 'Remove an MCP server')
241
- .option('--scope <scope>', 'Scope (global or project)', 'global')
242
- .action(async (options) => {
243
- const configManager = getConfigManager(process.cwd());
244
- const mcpManager = getMCPManager();
245
-
246
- if (options.list) {
247
- const servers = mcpManager.getAllServers();
248
-
249
- if (servers.length === 0) {
250
- console.log('');
251
- console.log(colors.warning('No MCP servers configured'));
252
- console.log(colors.textMuted('Use /mcp add in interactive mode to add servers'));
253
- console.log('');
254
- } else {
255
- const separator = icons.separator.repeat(40);
256
- console.log('');
257
- console.log(colors.primaryBright(`${icons.tool} MCP Servers`));
258
- console.log(colors.border(separator));
259
- console.log('');
260
-
261
- servers.forEach((server, index) => {
262
- const connected = server.isServerConnected() ? icons.success : icons.error;
263
- const status = server.isServerConnected() ? colors.success(connected) : colors.error(connected);
264
- const toolNames = server.getToolNames().join(', ');
265
-
266
- console.log(` ${status} ${colors.primaryBright(`Server ${index + 1}`)}`);
267
- console.log(` ${colors.textDim(` Tools: ${toolNames}`)}`);
268
- console.log('');
269
- });
270
- }
271
- } else if (options.add) {
272
- console.log('');
273
- console.log(colors.warning('MCP server addition not implemented yet'));
274
- console.log(colors.textMuted('Use /mcp add in interactive mode'));
275
- console.log('');
276
- } else if (options.remove) {
277
- try {
278
- mcpManager.disconnectServer(options.remove);
279
- const mcpServers = configManager.getMcpServers();
280
- delete mcpServers[options.remove];
281
- await configManager.save(options.scope);
282
- console.log('');
283
- console.log(colors.success(`MCP server ${options.remove} removed successfully`));
284
- console.log('');
285
- } catch (error: any) {
286
- const { message, suggestion } = formatError(error);
287
- console.log('');
288
- console.log(colors.error(`Failed to remove MCP server: ${message}`));
289
- console.log(colors.textMuted(suggestion));
290
- console.log('');
291
- }
292
- } else {
293
- console.log('');
294
- console.log(colors.warning('Please specify an action: --list, --add, or --remove'));
295
- console.log('');
296
- }
297
- });
298
-
299
- program
300
- .command('init')
301
- .description('Initialize XAGENT.md for the current project')
302
- .action(async () => {
303
- const { getMemoryManager } = await import('./memory.js');
304
- const memoryManager = getMemoryManager(process.cwd());
305
-
306
- const separator = icons.separator.repeat(40);
307
- console.log('');
308
- console.log(colors.primaryBright(`${icons.folder} Initializing Project Context`));
309
- console.log(colors.border(separator));
310
- console.log('');
311
-
312
- try {
313
- await memoryManager.initializeProject(process.cwd());
314
- console.log(colors.success('Project initialized successfully!'));
315
- console.log(colors.textMuted('You can now run "xagent start" to begin'));
316
- console.log('');
317
- } catch (error: any) {
318
- const { message, suggestion } = formatError(error);
319
- console.log(colors.error(`Initialization failed: ${message}`));
320
- console.log(colors.textMuted(suggestion));
321
- console.log('');
322
- process.exit(1);
323
- }
324
- });
325
-
326
- program
327
- .command('workflow')
328
- .description('Add, list, or remove workflows')
329
- .option('--add <workflow-id>', 'Add a workflow from the marketplace')
330
- .option('-l, --list', 'List all installed workflows')
331
- .option('-r, --remove <workflow-id>', 'Remove a workflow')
332
- .option('--scope <scope>', 'Scope (global or project)', 'project')
333
- .action(async (options) => {
334
- const { getWorkflowManager } = await import('./workflow.js');
335
- const workflowManager = getWorkflowManager(process.cwd());
336
-
337
- if (options.list) {
338
- const workflows = workflowManager.listWorkflows();
339
-
340
- if (workflows.length === 0) {
341
- console.log('');
342
- console.log(colors.warning('No workflows installed'));
343
- console.log(colors.textMuted('Use --add to install workflows from the marketplace'));
344
- console.log('');
345
- } else {
346
- const separator = icons.separator.repeat(40);
347
- console.log('');
348
- console.log(colors.primaryBright(`${icons.rocket} Installed Workflows`));
349
- console.log(colors.border(separator));
350
- console.log('');
351
-
352
- workflows.forEach((workflow, index) => {
353
- console.log(` ${colors.primaryBright(`${index + 1}. ${workflow.name}`)}`);
354
- console.log(` ${colors.textDim(` ID: ${workflow.id}`)}`);
355
- console.log(` ${colors.textDim(` ${workflow.description}`)}`);
356
- console.log('');
357
- });
358
- }
359
- } else if (options.add) {
360
- try {
361
- await workflowManager.addWorkflow(options.add, options.scope);
362
- console.log('');
363
- console.log(colors.success(`Workflow ${options.add} added successfully!`));
364
- console.log('');
365
- } catch (error: any) {
366
- const { message, suggestion } = formatError(error);
367
- console.log('');
368
- console.log(colors.error(message));
369
- console.log(colors.textMuted(suggestion));
370
- console.log('');
371
- process.exit(1);
372
- }
373
- } else if (options.remove) {
374
- try {
375
- await workflowManager.removeWorkflow(options.remove, options.scope);
376
- console.log('');
377
- console.log(colors.success(`Workflow ${options.remove} removed successfully!`));
378
- console.log('');
379
- } catch (error: any) {
380
- const { message, suggestion } = formatError(error);
381
- console.log('');
382
- console.log(colors.error(message));
383
- console.log(colors.textMuted(suggestion));
384
- console.log('');
385
- process.exit(1);
386
- }
387
- } else {
388
- console.log('');
389
- console.log(colors.warning('Please specify an action: --list, --add, or --remove'));
390
- console.log('');
391
- }
392
- });
393
-
394
- program
395
- .command('version')
396
- .description('Display version and check for updates')
397
- .action(async () => {
398
- const separator = icons.separator.repeat(40);
399
-
400
- console.log('');
401
- console.log(colors.gradient('╔════════════════════════════════════════════════════════════╗'));
402
- console.log(colors.gradient('') + ' '.repeat(56) + colors.gradient('║'));
403
- console.log(' '.repeat(20) + colors.gradient('xAgent CLI') + ' '.repeat(29) + colors.gradient('║'));
404
- console.log(colors.gradient('') + ' '.repeat(56) + colors.gradient('║'));
405
- console.log(colors.gradient('╚════════════════════════════════════════════════════════════╝'));
406
- console.log('');
407
- console.log(colors.border(separator));
408
- console.log('');
409
- console.log(` ${icons.info} ${colors.textMuted('Version:')} ${colors.primaryBright(packageJson.version)}`);
410
- console.log(` ${icons.code} ${colors.textMuted('Node.js:')} ${colors.textMuted(process.version)}`);
411
- console.log(` ${icons.bolt} ${colors.textMuted('Platform:')} ${colors.textMuted(process.platform + ' ' + process.arch)}`);
412
- console.log('');
413
- console.log(colors.border(separator));
414
- console.log('');
415
- console.log(` ${colors.primaryBright('📚 Documentation:')} ${colors.primaryBright('https://platform.xagent.cn/cli/')}`);
416
- console.log(` ${colors.primaryBright('💻 GitHub:')} ${colors.primaryBright('https://github.com/xagent-ai/xagent-cli')}`);
417
- console.log('');
418
- });
419
-
420
- program
421
- .command('gui')
422
- .description('Start GUI subagent for computer automation')
423
- .option('--headless', 'Run in headless mode (no visible window)', false)
424
- .action(async (options) => {
425
- const separator = icons.separator.repeat(40);
426
- console.log('');
427
- console.log(colors.primaryBright(`${icons.robot} GUI Subagent - Computer Automation`));
428
- console.log(colors.border(separator));
429
- console.log('');
430
-
431
- try {
432
- const configManager = getConfigManager();
433
- const authConfig = configManager.getAuthConfig();
434
-
435
- // Get GUI-specific VLM configuration
436
- const baseUrl = configManager.get('guiSubagentBaseUrl') || configManager.get('baseUrl') || '';
437
- const apiKey = configManager.get('guiSubagentApiKey') || configManager.get('apiKey') || '';
438
- const modelName = configManager.get('guiSubagentModel') || configManager.get('modelName') || '';
439
-
440
- // Determine mode: local (openai_compatible) or remote
441
- const isLocalMode = authConfig.type === 'openai_compatible';
442
-
443
- if (isLocalMode) {
444
- // Local mode: require baseUrl configuration
445
- if (!baseUrl) {
446
- console.log(colors.error('No VLM API URL configured for GUI subagent.'));
447
- console.log(colors.textMuted('Please run "xagent auth" and configure guiSubagentBaseUrl.'));
448
- console.log('');
449
- return;
450
- }
451
- console.log(colors.info(`${icons.brain} Using local VLM configuration`));
452
- console.log(colors.textMuted(` Model: ${modelName}`));
453
- console.log(colors.textMuted(` Base URL: ${baseUrl}`));
454
- console.log('');
455
- } else {
456
- // Remote mode
457
- console.log(colors.info(`${icons.brain} Using remote VLM service`));
458
- console.log(colors.textMuted(` Auth Type: ${authConfig.type}`));
459
- console.log('');
460
- }
461
-
462
- const { createGUISubAgent } = await import('./gui-subagent/index.js');
463
-
464
- // Create remoteVlmCaller for remote mode (uses full messages for consistent behavior)
465
- let remoteVlmCaller: ((messages: any[], systemPrompt: string) => Promise<string>) | undefined;
466
-
467
- if (!isLocalMode && authConfig.baseUrl) {
468
- const remoteBaseUrl = `${authConfig.baseUrl}/api/agent/vlm`;
469
- remoteVlmCaller = async (messages: any[], _systemPrompt: string): Promise<string> => {
470
- const response = await fetch(remoteBaseUrl, {
471
- method: 'POST',
472
- headers: {
473
- 'Content-Type': 'application/json',
474
- 'Authorization': `Bearer ${authConfig.apiKey || ''}`,
475
- },
476
- body: JSON.stringify({
477
- messages
478
- }),
479
- });
480
- if (!response.ok) {
481
- const errorText = await response.text();
482
- throw new Error(`Remote VLM error: ${response.status} - ${errorText}`);
483
- }
484
- const result = await response.json() as { response?: string; content?: string; message?: string };
485
- return result.response || result.content || result.message || '';
486
- };
487
- }
488
-
489
- const guiAgent = await createGUISubAgent({
490
- headless: options.headless ?? false,
491
- model: isLocalMode ? modelName : undefined,
492
- modelBaseUrl: isLocalMode ? baseUrl : undefined,
493
- modelApiKey: isLocalMode ? apiKey : undefined,
494
- remoteVlmCaller,
495
- isLocalMode,
496
- });
497
-
498
- console.log(colors.success(' GUI Subagent initialized successfully!'));
499
- console.log('');
500
- console.log(colors.textMuted('Available actions:'));
501
- console.log(colors.textDim(' - click: Click on an element'));
502
- console.log(colors.textDim(' - double_click: Double click'));
503
- console.log(colors.textDim(' - right_click: Right click'));
504
- console.log(colors.textDim(' - drag: Drag from one position to another'));
505
- console.log(colors.textDim(' - type: Type text'));
506
- console.log(colors.textDim(' - hotkey: Press keyboard shortcuts'));
507
- console.log(colors.textDim(' - scroll: Scroll up/down/left/right'));
508
- console.log(colors.textDim(' - wait: Wait for specified time'));
509
- console.log(colors.textDim(' - finished: Complete the task'));
510
- console.log('');
511
- console.log(colors.primaryBright('Use the GUI tools in the interactive session to control the computer.'));
512
- console.log('');
513
- } catch (error: any) {
514
- const { message, suggestion } = formatError(error);
515
- console.log('');
516
- console.log(colors.error(`Failed to start GUI Subagent: ${message}`));
517
- console.log(colors.textMuted(suggestion));
518
- console.log('');
519
- }
520
- });
521
-
522
- program
523
- .command('memory')
524
- .description('Manage memory files (list or clean)')
525
- .option('-l, --list', 'List all memory files')
526
- .option('--clean', 'Clean all project memories (keep global memory)')
527
- .option('--clean-project', 'Clean the current project\'s memory only')
528
- .option('--clean-all', 'Clean all memories (including global memory)')
529
- .action(async (options) => {
530
- const separator = icons.separator.repeat(40);
531
- console.log('');
532
- console.log(colors.primaryBright(`${icons.folder} Memory Management`));
533
- console.log(colors.border(separator));
534
- console.log('');
535
-
536
- const { getMemoryManager } = await import('./memory.js');
537
- const memoryManager = getMemoryManager(process.cwd());
538
- const memoriesDir = memoryManager.getMemoriesDir();
539
-
540
- // Helper to get memory info
541
- const getMemoryInfo = (fileName: string) => {
542
- if (fileName === 'global.md') {
543
- return { type: 'global', description: 'Global memory (shared across all projects)' };
544
- }
545
- const match = fileName.match(/^project_(.+)_\w{16}\.md$/);
546
- if (match) {
547
- return { type: 'project', description: `Project: ${match[1]}` };
548
- }
549
- return { type: 'unknown', description: fileName };
550
- };
551
-
552
- if (options.list) {
553
- // List all memory files
554
- console.log(colors.textMuted(`Memory directory: ${memoriesDir}`));
555
- console.log('');
556
-
557
- try {
558
- const files = await fs.readdir(memoriesDir).catch(() => []);
559
- if (files.length === 0) {
560
- console.log(colors.textMuted('No memory files found.'));
561
- console.log('');
562
- return;
563
- }
564
-
565
- const globalFile = files.find(f => f === 'global.md');
566
- const projectFiles = files.filter(f => f.startsWith('project_'));
567
-
568
- if (globalFile) {
569
- const info = getMemoryInfo(globalFile);
570
- console.log(` ${colors.success(icons.success)} ${colors.primaryBright('global.md')}`);
571
- console.log(` ${colors.textDim(` ${info.description}`)}`);
572
- console.log('');
573
- }
574
-
575
- if (projectFiles.length > 0) {
576
- console.log(colors.primaryBright(` Project Memories (${projectFiles.length})`));
577
- console.log('');
578
-
579
- for (const file of projectFiles) {
580
- const info = getMemoryInfo(file);
581
- const filePath = join(memoriesDir, file);
582
- try {
583
- const stat = await fs.stat(filePath);
584
- const size = stat.size;
585
- const sizeStr = size < 1024 ? `${size} B` : `${(size / 1024).toFixed(1)} KB`;
586
- console.log(` ${colors.success(icons.success)} ${colors.primaryBright(file)}`);
587
- console.log(` ${colors.textDim(` ${info.description} | Size: ${sizeStr}`)}`);
588
- } catch {
589
- console.log(` ${colors.success(icons.success)} ${colors.primaryBright(file)}`);
590
- console.log(` ${colors.textDim(` ${info.description}`)}`);
591
- }
592
- console.log('');
593
- }
594
- }
595
-
596
- console.log(colors.textMuted(`Total: ${files.length} memory file(s)`));
597
- console.log('');
598
- } catch (error) {
599
- console.log(colors.textMuted('No memory files found.'));
600
- console.log('');
601
- }
602
- } else if (options.clean) {
603
- // Clean all project memories (keep global.md)
604
- console.log(colors.textMuted('Cleaning all project memories...'));
605
- console.log(colors.textMuted(`Keeping: ${colors.primaryBright('global.md')}`));
606
- console.log('');
607
-
608
- try {
609
- const files = await fs.readdir(memoriesDir).catch(() => []);
610
- const projectFiles = files.filter(f => f.startsWith('project_'));
611
-
612
- if (projectFiles.length === 0) {
613
- console.log(colors.textMuted('No project memories to clean.'));
614
- console.log('');
615
- return;
616
- }
617
-
618
- let cleaned = 0;
619
- for (const file of projectFiles) {
620
- await fs.unlink(join(memoriesDir, file));
621
- cleaned++;
622
- }
623
-
624
- console.log(colors.success(`✅ Cleaned ${cleaned} project memory file(s)`));
625
- // TODO: 如果需要自动重建 project memory,取消下面注释
626
- // await memoryManager.saveMemory('# Project Context\n\nProject-specific context will be added here.', 'project');
627
- // console.log(colors.textMuted(' Recreated current project memory'));
628
- console.log(colors.textMuted(' Use /init to initialize if needed'));
629
- console.log('');
630
- } catch (error: any) {
631
- const { message, suggestion } = formatError(error);
632
- console.log(colors.error(`Failed to clean project memories: ${message}`));
633
- console.log(colors.textMuted(suggestion));
634
- console.log('');
635
- }
636
- } else if (options.cleanProject) {
637
- // Clean only the current project's memory
638
- console.log(colors.textMuted(`Cleaning current project memory...`));
639
- console.log(colors.textMuted(`Project: ${colors.primaryBright(process.cwd())}`));
640
- console.log('');
641
-
642
- try {
643
- // Find and delete the current project's memory file
644
- const memoryFiles = memoryManager.getMemoryFiles();
645
- const currentProjectMemory = memoryFiles.find(m => m.level === 'project');
646
-
647
- if (currentProjectMemory) {
648
- await fs.unlink(currentProjectMemory.path);
649
- console.log(colors.success(`✅ Cleaned current project memory`));
650
- console.log(colors.textMuted(` File: ${path.basename(currentProjectMemory.path)}`));
651
- } else {
652
- console.log(colors.textMuted('No memory found for the current project.'));
653
- }
654
- // TODO: 如果需要自动重建 project memory,取消下面注释
655
- // await memoryManager.saveMemory('# Project Context\n\nProject-specific context will be added here.', 'project');
656
- // console.log(colors.textMuted(' Recreated current project memory'));
657
- console.log(colors.textMuted(' Use /init to initialize if needed'));
658
- console.log('');
659
- } catch (error: any) {
660
- const { message, suggestion } = formatError(error);
661
- console.log(colors.error(`Failed to clean project memory: ${message}`));
662
- console.log(colors.textMuted(suggestion));
663
- console.log('');
664
- }
665
- } else if (options.cleanAll) {
666
- // Clean all memories including global
667
- console.log(colors.warning(`${icons.warning} This will delete ALL memory files including global memory.`));
668
- console.log('');
669
- console.log(colors.textMuted('Files to be deleted:'));
670
- console.log(colors.textMuted(` - global.md (global memory)`));
671
- console.log(colors.textMuted(` - all project memories`));
672
- console.log('');
673
-
674
- try {
675
- const files = await fs.readdir(memoriesDir).catch(() => []);
676
- if (files.length === 0) {
677
- console.log(colors.textMuted('No memory files to clean.'));
678
- console.log('');
679
- return;
680
- }
681
-
682
- let cleaned = 0;
683
- for (const file of files) {
684
- await fs.unlink(join(memoriesDir, file));
685
- cleaned++;
686
- }
687
-
688
- // Recreate global memory (always keep global memory available)
689
- await memoryManager.saveMemory('# Global Context\n\nGlobal preferences and settings will be added here.', 'global');
690
- // TODO: 如果需要同时重建 project memory,取消下面注释
691
- // await memoryManager.saveMemory('# Project Context\n\nProject-specific context will be added here.', 'project');
692
-
693
- console.log(colors.success(`✅ Cleaned ${cleaned} memory file(s)`));
694
- console.log(colors.textMuted(' Recreated global memory'));
695
- console.log(colors.textMuted(' Use /init to initialize project memory if needed'));
696
- console.log('');
697
- } catch (error: any) {
698
- const { message, suggestion } = formatError(error);
699
- console.log(colors.error(`Failed to clean memories: ${message}`));
700
- console.log(colors.textMuted(suggestion));
701
- console.log('');
702
- }
703
- } else {
704
- // No option specified, show help
705
- console.log(colors.textMuted('Usage:'));
706
- console.log(` ${colors.primaryBright('xagent memory -l')} ${colors.textDim('| List all memory files')}`);
707
- console.log(` ${colors.primaryBright('xagent memory --clean')} ${colors.textDim('| Clean all project memories (keep global)')}`);
708
- console.log(` ${colors.primaryBright('xagent memory --clean-project')} ${colors.textDim('| Clean current project memory only')}`);
709
- console.log(` ${colors.primaryBright('xagent memory --clean-all')} ${colors.textDim('| Clean ALL memories (including global)')}`);
710
- console.log('');
711
- }
712
- });
713
-
714
- program.parse(process.argv);
715
-
716
- if (!process.argv.slice(2).length) {
717
- program.outputHelp();
718
- }
719
-
720
- // ============================================================
721
- // Global error handling - prevent crashes from uncaught errors
722
- // ============================================================
723
-
724
- // Handle uncaught promise rejections
725
- process.on('unhandledRejection', (reason: any, promise: Promise<any>) => {
726
- console.error('\n❌ An unexpected error occurred');
727
- if (reason instanceof Error) {
728
- console.error(` ${reason.message}`);
729
- } else if (reason) {
730
- console.error(` ${String(reason)}`);
731
- }
732
- console.error('\n If this problem persists, please report this issue.');
733
- console.error('');
734
- process.exit(1);
735
- });
736
-
737
- // Handle uncaught exceptions
738
- process.on('uncaughtException', (error: Error) => {
739
- console.error('\n❌ Critical error - application will exit');
740
- console.error(` ${error.message}`);
741
- console.error('');
742
- process.exit(1);
743
- });
1
+ #!/usr/bin/env node
2
+
3
+ import { Command } from 'commander';
4
+ import chalk from 'chalk';
5
+ import { confirm } from '@clack/prompts';
6
+ import { startInteractiveSession } from './session.js';
7
+ import { getConfigManager } from './config.js';
8
+ import { AuthService, selectAuthType } from './auth.js';
9
+ import { AuthType } from './types.js';
10
+ import { fetchDefaultModels } from './ai-client/providers/remote.js';
11
+ import { getAgentManager } from './agents.js';
12
+ import { getMCPManager } from './mcp.js';
13
+ import { getLogger, setConfigProvider } from './logger.js';
14
+ import { theme, icons, colors } from './theme.js';
15
+ import { getCancellationManager } from './cancellation.js';
16
+ import { readFileSync, promises as fs, writeFileSync, existsSync } from 'fs';
17
+ import path from 'path';
18
+ import { dirname, join } from 'path';
19
+ import { fileURLToPath } from 'url';
20
+ import { glob } from 'glob';
21
+
22
+ // Get current directory
23
+ const __filename = fileURLToPath(import.meta.url);
24
+ const __dirname = dirname(__filename);
25
+
26
+ // State file for skill updates (used to notify running xAgent)
27
+ const SKILL_STATE_FILE = '.skill-state.json';
28
+
29
+ function getSkillStateFilePath(userSkillsPath: string): string {
30
+ return path.join(userSkillsPath, SKILL_STATE_FILE);
31
+ }
32
+
33
+ async function notifySkillUpdate(userSkillsPath: string): Promise<void> {
34
+ try {
35
+ const stateFilePath = getSkillStateFilePath(userSkillsPath);
36
+ const timestamp = Date.now();
37
+ const state = { lastSkillUpdate: timestamp };
38
+
39
+ await fs.writeFile(stateFilePath, JSON.stringify(state, null, 2), 'utf-8');
40
+
41
+ console.log(colors.textMuted(' ℹ️ Skills updated for running xAgent sessions'));
42
+ } catch (error) {
43
+ // Silent fail - notification is optional
44
+ }
45
+ }
46
+
47
+ // Read package.json
48
+ const packageJsonPath = join(__dirname, '../package.json');
49
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
50
+
51
+ const logger = getLogger();
52
+
53
+ // Initialize CancellationManager early to set up ESC handler
54
+ getCancellationManager();
55
+
56
+ // Set up config provider for logger to read loggerLevel
57
+ setConfigProvider(() => {
58
+ const configManager = getConfigManager();
59
+ return {
60
+ getLoggerLevel: () => configManager.getLoggerLevel()
61
+ };
62
+ });
63
+
64
+ const program = new Command();
65
+
66
+ /**
67
+ * Format error message for user-friendly display
68
+ */
69
+ function formatError(error: unknown): { message: string; suggestion: string } {
70
+ const errorMessage = error instanceof Error ? error.message : String(error);
71
+
72
+ // Network errors
73
+ if (errorMessage.includes('ENOTFOUND') || errorMessage.includes('ECONNREFUSED')) {
74
+ return {
75
+ message: 'Unable to connect to the server',
76
+ suggestion: 'Please check your network connection and try again.'
77
+ };
78
+ }
79
+ if (errorMessage.includes('ETIMEDOUT') || errorMessage.includes('ECONNRESET')) {
80
+ return {
81
+ message: 'Connection timed out',
82
+ suggestion: 'The server may be busy. Please wait a moment and try again.'
83
+ };
84
+ }
85
+ // Authentication errors
86
+ if (errorMessage.includes('401') || errorMessage.includes('Unauthorized') || errorMessage.includes('invalid token')) {
87
+ return {
88
+ message: 'Authentication failed',
89
+ suggestion: 'Please login again using: xagent auth'
90
+ };
91
+ }
92
+ // Token expired
93
+ if (errorMessage.includes('token') && errorMessage.includes('expired')) {
94
+ return {
95
+ message: 'Session expired',
96
+ suggestion: 'Please login again using: xagent auth'
97
+ };
98
+ }
99
+ // Permission errors
100
+ if (errorMessage.includes('EACCES') || errorMessage.includes('permission denied')) {
101
+ return {
102
+ message: 'Permission denied',
103
+ suggestion: 'Please check your file permissions or run with appropriate privileges.'
104
+ };
105
+ }
106
+ // File not found
107
+ if (errorMessage.includes('ENOENT') || errorMessage.includes('not found')) {
108
+ return {
109
+ message: 'File or resource not found',
110
+ suggestion: 'Please check the path and try again.'
111
+ };
112
+ }
113
+ // Invalid JSON
114
+ if (errorMessage.includes('JSON') || errorMessage.includes('parse')) {
115
+ return {
116
+ message: 'Invalid data format',
117
+ suggestion: 'The configuration file may be corrupted. Please check the file content.'
118
+ };
119
+ }
120
+
121
+ // User cancellation - no suggestion needed
122
+ if (errorMessage.includes('cancelled by user') || errorMessage.includes('Operation cancelled')) {
123
+ return {
124
+ message: 'Operation cancelled',
125
+ suggestion: ''
126
+ };
127
+ }
128
+
129
+ // Default friendly message
130
+ return {
131
+ message: 'An error occurred',
132
+ suggestion: 'Please try again. If the problem persists, check your configuration.'
133
+ };
134
+ }
135
+
136
+ /**
137
+ * Recursively copy a directory
138
+ */
139
+ async function copyDirectory(src: string, dest: string): Promise<void> {
140
+ const entries = await fs.readdir(src, { withFileTypes: true });
141
+
142
+ await fs.mkdir(dest, { recursive: true });
143
+
144
+ for (const entry of entries) {
145
+ // Skip node_modules to keep dependencies isolated
146
+ // if (entry.name === 'node_modules') continue;
147
+
148
+ const srcPath = path.join(src, entry.name);
149
+ const destPath = path.join(dest, entry.name);
150
+
151
+ if (entry.isDirectory()) {
152
+ await copyDirectory(srcPath, destPath);
153
+ } else if (entry.isFile()) {
154
+ await fs.copyFile(srcPath, destPath);
155
+ }
156
+ // Skip symbolic links for simplicity
157
+ }
158
+ }
159
+
160
+ program
161
+ .name('xagent')
162
+ .description('AI-powered command-line assistant')
163
+ .version(packageJson.version)
164
+ .option('-h, --help', 'Show help');
165
+
166
+ program
167
+ .command('start')
168
+ .description('Start the xAgent CLI interactive session')
169
+ .option('--approval-mode <mode>', 'Set approval mode (yolo, accept_edits, plan, default, smart)')
170
+ .action(async (options) => {
171
+ if (options.approvalMode) {
172
+ const { getConfigManager } = await import('./config.js');
173
+ const { ExecutionMode } = await import('./types.js');
174
+ const configManager = getConfigManager();
175
+
176
+ const validModes = Object.values(ExecutionMode) as string[];
177
+ if (!validModes.includes(options.approvalMode)) {
178
+ console.log('');
179
+ console.log(colors.error(`Invalid approval mode: ${options.approvalMode}`));
180
+ console.log(colors.textMuted(`Valid modes: ${validModes.join(', ')}`));
181
+ console.log('');
182
+ process.exit(1);
183
+ }
184
+
185
+ configManager.setApprovalMode(options.approvalMode as any);
186
+ configManager.save('global');
187
+ console.log('');
188
+ console.log(colors.success(`✅ Approval mode set to: ${options.approvalMode}`));
189
+ console.log('');
190
+ }
191
+
192
+ await startInteractiveSession();
193
+ });
194
+
195
+ program
196
+ .command('auth')
197
+ .description('Configure authentication for xAgent CLI')
198
+ .action(async () => {
199
+ const separator = icons.separator.repeat(40);
200
+ console.log('');
201
+ console.log(colors.primaryBright(`${icons.lock} Authentication Management`));
202
+ console.log(colors.border(separator));
203
+ console.log('');
204
+
205
+ const authType = await selectAuthType();
206
+ const configManager = getConfigManager();
207
+ configManager.set('selectedAuthType', authType);
208
+
209
+ // Get xagentApiBaseUrl from config (respects XAGENT_BASE_URL env var)
210
+ const config = configManager.getAuthConfig();
211
+
212
+ const authService = new AuthService({
213
+ type: authType,
214
+ apiKey: '',
215
+ baseUrl: '',
216
+ modelName: '',
217
+ xagentApiBaseUrl: config.xagentApiBaseUrl
218
+ });
219
+
220
+ const success = await authService.authenticate();
221
+
222
+ if (success) {
223
+ const authConfig = authService.getAuthConfig();
224
+
225
+ // Clear modelName for remote mode
226
+ if (authType === AuthType.OAUTH_XAGENT) {
227
+ authConfig.modelName = '';
228
+ }
229
+
230
+ configManager.setAuthConfig(authConfig);
231
+
232
+ // Set default remote model settings if not already set
233
+ if (authType === AuthType.OAUTH_XAGENT) {
234
+ const webBaseUrl = authConfig.xagentApiBaseUrl || 'https://www.xagent-colife.net';
235
+ let defaultLlmName = '';
236
+ let defaultVlmName = '';
237
+
238
+ try {
239
+ console.log(colors.textMuted(' Fetching default models from remote server...'));
240
+ const defaults = await fetchDefaultModels(authConfig.apiKey || '', webBaseUrl);
241
+
242
+ if (defaults.llm?.name) {
243
+ defaultLlmName = defaults.llm.name;
244
+ console.log(colors.textMuted(` Default LLM: ${defaults.llm.displayName || defaultLlmName}`));
245
+ }
246
+ if (defaults.vlm?.name) {
247
+ defaultVlmName = defaults.vlm.name;
248
+ console.log(colors.textMuted(` Default VLM: ${defaults.vlm.displayName || defaultVlmName}`));
249
+ }
250
+ } catch (error: any) {
251
+ console.log(colors.textMuted(` ⚠️ Failed to fetch default models: ${error.message}`));
252
+ console.log(colors.textMuted(' ⚠️ Use /model command to select models manually.'));
253
+ }
254
+
255
+ configManager.set('remote_llmModelName', defaultLlmName);
256
+ configManager.set('remote_vlmModelName', defaultVlmName);
257
+ configManager.save('global');
258
+ }
259
+
260
+ console.log('');
261
+ console.log(colors.success('Authentication configured successfully!'));
262
+ console.log(colors.textMuted('You can now run "xagent start" to begin'));
263
+ console.log('');
264
+ } else {
265
+ console.log('');
266
+ console.log(colors.error('Authentication failed. Please try again.'));
267
+ console.log(colors.textMuted('Run "xagent auth" to retry'));
268
+ console.log('');
269
+ process.exit(1);
270
+ }
271
+ });
272
+
273
+ program
274
+ .command('agent')
275
+ .description('Add, list, or remove SubAgents')
276
+ .option('-l, --list', 'List all agents')
277
+ .option('-a, --add <name>', 'Add a new agent')
278
+ .option('-r, --remove <name>', 'Remove an agent')
279
+ .option('--scope <scope>', 'Scope (global or project)', 'global')
280
+ .action(async (options) => {
281
+ const agentManager = getAgentManager(process.cwd());
282
+ await agentManager.loadAgents();
283
+
284
+ if (options.list) {
285
+ const agents = agentManager.getAllAgents();
286
+
287
+ if (agents.length === 0) {
288
+ console.log('');
289
+ console.log(colors.warning('No agents configured'));
290
+ console.log(colors.textMuted('Use /agents install in interactive mode to add agents'));
291
+ console.log('');
292
+ } else {
293
+ const separator = icons.separator.repeat(40);
294
+ console.log('');
295
+ console.log(colors.primaryBright(`${icons.robot} Available Agents`));
296
+ console.log(colors.border(separator));
297
+ console.log('');
298
+
299
+ agents.forEach((agent, index) => {
300
+ console.log(` ${colors.primaryBright(`${index + 1}. ${agent.agentType}`)}`);
301
+ console.log(` ${colors.textDim(` ${agent.whenToUse}`)}`);
302
+ console.log('');
303
+ });
304
+ }
305
+ } else if (options.add) {
306
+ console.log('');
307
+ console.log(colors.warning('Agent creation wizard not implemented yet'));
308
+ console.log(colors.textMuted('Use /agents install in interactive mode'));
309
+ console.log('');
310
+ } else if (options.remove) {
311
+ try {
312
+ await agentManager.removeAgent(options.remove, options.scope);
313
+ console.log('');
314
+ console.log(colors.success(`Agent ${options.remove} removed successfully`));
315
+ console.log('');
316
+ } catch (error: any) {
317
+ const { message, suggestion } = formatError(error);
318
+ console.log('');
319
+ console.log(colors.error(`Failed to remove agent: ${message}`));
320
+ console.log(colors.textMuted(suggestion));
321
+ console.log('');
322
+ }
323
+ } else {
324
+ console.log('');
325
+ console.log(colors.warning('Please specify an action: --list, --add, or --remove'));
326
+ console.log('');
327
+ }
328
+ });
329
+
330
+ program
331
+ .command('mcp')
332
+ .description('Add, list, or remove MCP servers')
333
+ .option('-l, --list', 'List all MCP servers')
334
+ .option('-a, --add [name]', 'Add a new MCP server (interactive if no name provided)')
335
+ .option('-r, --remove <name>', 'Remove an MCP server')
336
+ .option('--scope <scope>', 'Scope (global or project)', 'global')
337
+ .option('-t, --transport <type>', 'Transport type: stdio, http')
338
+ .option('-c, --command <cmd>', 'Command for stdio transport')
339
+ .option('--args <args>', 'Arguments for stdio transport (comma-separated)')
340
+ .option('-u, --url <url>', 'URL for HTTP transport')
341
+ .option('-k, --token <token>', 'Authentication token (Bearer)')
342
+ .option('--header <headers>', 'Custom headers (can be used multiple times)')
343
+ .option('-y, --yes', 'Skip confirmation')
344
+ .action(async (options) => {
345
+ const configManager = getConfigManager(process.cwd());
346
+ const mcpManager = getMCPManager();
347
+
348
+ if (options.list) {
349
+ const servers = mcpManager.getAllServers();
350
+
351
+ if (servers.length === 0) {
352
+ console.log('');
353
+ console.log(colors.warning('No MCP servers configured'));
354
+ console.log(colors.textMuted('Use "xagent mcp --add" to add servers'));
355
+ console.log('');
356
+ } else {
357
+ const separator = icons.separator.repeat(40);
358
+ console.log('');
359
+ console.log(colors.primaryBright(`${icons.tool} MCP Servers`));
360
+ console.log(colors.border(separator));
361
+ console.log('');
362
+
363
+ servers.forEach((server, index) => {
364
+ const connected = server.isServerConnected() ? icons.success : icons.error;
365
+ const status = server.isServerConnected() ? colors.success(connected) : colors.error(connected);
366
+ const toolNames = server.getToolNames().join(', ');
367
+
368
+ console.log(` ${status} ${colors.primaryBright(`Server ${index + 1}`)}`);
369
+ console.log(` ${colors.textDim(` Tools: ${toolNames}`)}`);
370
+ console.log('');
371
+ });
372
+ }
373
+ } else if (options.add !== undefined) {
374
+ // Check if running in non-interactive mode (transport and required params provided)
375
+ const hasTransport = options.transport;
376
+ const hasCommand = options.command;
377
+ const hasUrl = options.url;
378
+ const isNonInteractive = hasTransport && (hasCommand || hasUrl);
379
+
380
+ if (isNonInteractive) {
381
+ // Non-interactive mode: use command line arguments
382
+ const name = options.add || `mcp-${options.transport}-${Date.now().toString(36)}`;
383
+ const transport = options.transport;
384
+
385
+ const config: any = {
386
+ transport: transport,
387
+ };
388
+
389
+ if (transport === 'stdio') {
390
+ if (!options.command) {
391
+ console.log('');
392
+ console.log(colors.error('Error: --command is required for stdio transport'));
393
+ console.log('');
394
+ process.exit(1);
395
+ }
396
+ config.command = options.command;
397
+ if (options.args) {
398
+ config.args = options.args.split(',').map((a: string) => a.trim());
399
+ }
400
+ } else if (transport === 'http') {
401
+ if (!options.url) {
402
+ console.log('');
403
+ console.log(colors.error('Error: --url is required for http transport'));
404
+ console.log('');
405
+ process.exit(1);
406
+ }
407
+ config.url = options.url;
408
+ if (options.token) {
409
+ config.authToken = options.token;
410
+ }
411
+ // Handle multiple --header flags
412
+ if (options.header) {
413
+ const headers: Record<string, string> = {};
414
+ const headerArray = Array.isArray(options.header) ? options.header : [options.header];
415
+ for (const h of headerArray) {
416
+ const colonIndex = h.indexOf(':');
417
+ if (colonIndex > 0) {
418
+ const key = h.substring(0, colonIndex).trim();
419
+ const value = h.substring(colonIndex + 1).trim();
420
+ headers[key] = value;
421
+ }
422
+ }
423
+ if (Object.keys(headers).length > 0) {
424
+ config.headers = headers;
425
+ }
426
+ }
427
+ } else {
428
+ console.log('');
429
+ console.log(colors.error(`Error: Unknown transport type: ${transport}`));
430
+ console.log(colors.textMuted('Valid types: stdio, http'));
431
+ console.log('');
432
+ process.exit(1);
433
+ }
434
+
435
+ // Skip confirmation in non-interactive mode
436
+ if (!options.yes) {
437
+ console.log('');
438
+ console.log(colors.textMuted('Server configuration:'));
439
+ console.log(` ${colors.primaryBright('Name:')} ${name}`);
440
+ console.log(` ${colors.primaryBright('Transport:')} ${config.transport}`);
441
+ if (config.command) {
442
+ console.log(` ${colors.primaryBright('Command:')} ${config.command} ${(config.args || []).join(' ')}`);
443
+ }
444
+ if (config.url) {
445
+ console.log(` ${colors.primaryBright('URL:')} ${config.url}`);
446
+ if (config.authToken) {
447
+ console.log(` ${colors.primaryBright('Token:')} [hidden]`);
448
+ }
449
+ }
450
+ console.log('');
451
+ }
452
+
453
+ try {
454
+ // Save to config
455
+ configManager.addMcpServer(name, config);
456
+ configManager.save(options.scope);
457
+
458
+ // Register with MCP manager
459
+ mcpManager.registerServer(name, config);
460
+
461
+ // Try to connect
462
+ let connected = false;
463
+ try {
464
+ await mcpManager.connectServer(name);
465
+ connected = true;
466
+ } catch (error: any) {
467
+ console.log(colors.textMuted(` ⚠️ Connection failed: ${error.message}`));
468
+ console.log(colors.textMuted(' The server is saved but not connected.'));
469
+ }
470
+
471
+ if (connected) {
472
+ console.log('');
473
+ console.log(colors.success(`✅ MCP server '${name}' added and connected successfully`));
474
+ } else {
475
+ console.log('');
476
+ console.log(colors.success(`✅ MCP server '${name}' added successfully`));
477
+ }
478
+ console.log('');
479
+ } catch (error: any) {
480
+ console.log('');
481
+ console.log(colors.error(`Failed to add MCP server: ${error.message}`));
482
+ console.log('');
483
+ }
484
+ } else {
485
+ // Interactive mode
486
+ const { text, select, confirm } = await import('@clack/prompts');
487
+
488
+ const separator = icons.separator.repeat(40);
489
+ console.log('');
490
+ console.log(colors.primaryBright(`${icons.tool} Add MCP Server`));
491
+ console.log(colors.border(separator));
492
+ console.log('');
493
+
494
+ // Step 1: Enter server name
495
+ let name = options.add;
496
+ if (!name) {
497
+ name = await text({
498
+ message: 'Enter MCP server name:',
499
+ validate: (value: string | undefined) => {
500
+ if (!value || !value.trim()) {
501
+ return 'Server name is required';
502
+ }
503
+ if (!/^[a-zA-Z0-9_-]+$/.test(value)) {
504
+ return 'Server name must contain only alphanumeric characters, hyphens, and underscores';
505
+ }
506
+ return undefined;
507
+ },
508
+ }) as string;
509
+ }
510
+
511
+ // Step 2: Select transport type
512
+ const transport = await select({
513
+ message: 'Select transport type:',
514
+ options: [
515
+ { value: 'stdio', label: 'Stdio (stdin/stdout)' },
516
+ { value: 'http', label: 'HTTP (Streamable HTTP)' },
517
+ ],
518
+ }) as string | symbol;
519
+
520
+ if (typeof transport === 'symbol') {
521
+ console.log('');
522
+ console.log(colors.textMuted('Cancelled'));
523
+ console.log('');
524
+ return;
525
+ }
526
+
527
+ const config: any = {
528
+ transport: transport as 'stdio' | 'http',
529
+ };
530
+
531
+ if (transport === 'stdio') {
532
+ // Step 3: Enter command
533
+ config.command = await text({
534
+ message: 'Enter command (for stdio transport):',
535
+ validate: (value: string | undefined) =>
536
+ value && value.trim() ? undefined : 'Command is required',
537
+ }) as string;
538
+
539
+ // Step 4: Enter arguments
540
+ const argsInput = await text({
541
+ message: 'Enter arguments (comma-separated, for stdio transport):',
542
+ defaultValue: '',
543
+ }) as string;
544
+
545
+ if (argsInput.trim()) {
546
+ config.args = argsInput.split(',').map((a: string) => a.trim());
547
+ }
548
+ } else {
549
+ // Step 3: Enter URL
550
+ let url = '';
551
+ while (!url) {
552
+ url = await text({
553
+ message: 'Enter server URL (for HTTP transport):',
554
+ validate: (value: string | undefined) => {
555
+ if (!value || !value.trim()) {
556
+ return 'URL is required';
557
+ }
558
+ try {
559
+ new URL(value);
560
+ return undefined;
561
+ } catch {
562
+ return 'Invalid URL format (e.g., https://example.com)';
563
+ }
564
+ },
565
+ }) as string;
566
+ }
567
+ config.url = url;
568
+
569
+ // Step 4: Enter auth token (optional)
570
+ config.authToken = await text({
571
+ message: 'Enter Bearer token (optional):',
572
+ defaultValue: '',
573
+ }) as string;
574
+
575
+ // Step 5: Enter custom headers (optional)
576
+ const headersInput = await text({
577
+ message: 'Enter custom headers as JSON (optional):',
578
+ defaultValue: '',
579
+ }) as string;
580
+
581
+ if (headersInput.trim()) {
582
+ try {
583
+ config.headers = JSON.parse(headersInput);
584
+ } catch {
585
+ // Ignore invalid JSON
586
+ }
587
+ }
588
+ }
589
+
590
+ // Step 6: Confirm and save
591
+ console.log('');
592
+ console.log(colors.textMuted('Server configuration:'));
593
+ console.log(` ${colors.primaryBright('Name:')} ${name}`);
594
+ console.log(` ${colors.primaryBright('Transport:')} ${config.transport}`);
595
+ if (config.command) {
596
+ console.log(` ${colors.primaryBright('Command:')} ${config.command} ${(config.args || []).join(' ')}`);
597
+ }
598
+ if (config.url) {
599
+ console.log(` ${colors.primaryBright('URL:')} ${config.url}`);
600
+ }
601
+ console.log('');
602
+
603
+ const shouldSave = await confirm({
604
+ message: 'Save this MCP server configuration?',
605
+ }) as boolean | symbol;
606
+
607
+ if (typeof shouldSave === 'symbol' || !shouldSave) {
608
+ console.log('');
609
+ console.log(colors.textMuted('Cancelled'));
610
+ console.log('');
611
+ return;
612
+ }
613
+
614
+ try {
615
+ // Save to config
616
+ configManager.addMcpServer(name, config);
617
+ configManager.save(options.scope);
618
+
619
+ // Register with MCP manager
620
+ mcpManager.registerServer(name, config);
621
+
622
+ // Try to connect
623
+ let connected = false;
624
+ try {
625
+ await mcpManager.connectServer(name);
626
+ connected = true;
627
+ } catch (error: any) {
628
+ console.log(colors.textMuted(` ⚠️ Connection failed: ${error.message}`));
629
+ console.log(colors.textMuted(' The server is saved but not connected. Use "/mcp refresh" in interactive mode to retry.'));
630
+ }
631
+
632
+ if (connected) {
633
+ console.log('');
634
+ console.log(colors.success(`✅ MCP server '${name}' added and connected successfully`));
635
+ } else {
636
+ console.log('');
637
+ console.log(colors.success(`✅ MCP server '${name}' added successfully (not connected)`));
638
+ }
639
+ console.log('');
640
+ } catch (error: any) {
641
+ console.log('');
642
+ console.log(colors.error(`Failed to add MCP server: ${error.message}`));
643
+ console.log('');
644
+ }
645
+ }
646
+ } else if (options.remove) {
647
+ try {
648
+ mcpManager.disconnectServer(options.remove);
649
+ const mcpServers = configManager.getMcpServers();
650
+ delete mcpServers[options.remove];
651
+ configManager.save(options.scope);
652
+ console.log('');
653
+ console.log(colors.success(`MCP server ${options.remove} removed successfully`));
654
+ console.log('');
655
+ } catch (error: any) {
656
+ const { message, suggestion } = formatError(error);
657
+ console.log('');
658
+ console.log(colors.error(`Failed to remove MCP server: ${message}`));
659
+ console.log(colors.textMuted(suggestion));
660
+ console.log('');
661
+ }
662
+ } else {
663
+ console.log('');
664
+ console.log(colors.warning('Please specify an action: --list, --add, or --remove'));
665
+ console.log('');
666
+ console.log(colors.textMuted('Usage:'));
667
+ console.log(` ${colors.primaryBright('xagent mcp --list')} ${colors.textMuted('| List all MCP servers')}`);
668
+ console.log(` ${colors.primaryBright('xagent mcp --add')} ${colors.textMuted('| Add MCP server (interactive)')}`);
669
+ console.log('');
670
+ console.log(colors.textMuted('Non-interactive examples:'));
671
+ console.log(` ${colors.primaryBright('xagent mcp --add -t stdio -c "npx" --args "-y,@modelcontextprotocol/server-github"')}`);
672
+ console.log(` ${colors.primaryBright('xagent mcp --add -t http -u "https://example.com/mcp" -k "token"')}`);
673
+ console.log('');
674
+ console.log(colors.textMuted('Options:'));
675
+ console.log(` ${colors.primaryBright('-t, --transport')} ${colors.textMuted('Transport: stdio or http')}`);
676
+ console.log(` ${colors.primaryBright('-c, --command')} ${colors.textMuted('Command for stdio transport')}`);
677
+ console.log(` ${colors.primaryBright('--args')} ${colors.textMuted('Arguments (comma-separated)')}`);
678
+ console.log(` ${colors.primaryBright('-u, --url')} ${colors.textMuted('URL for HTTP transport')}`);
679
+ console.log(` ${colors.primaryBright('-k, --token')} ${colors.textMuted('Bearer authentication token')}`);
680
+ console.log(` ${colors.primaryBright('--header')} ${colors.textMuted('Custom header (key:value)')}`);
681
+ console.log(` ${colors.primaryBright('-y, --yes')} ${colors.textMuted('Skip confirmation')}`);
682
+ console.log('');
683
+ }
684
+ });
685
+
686
+ program
687
+ .command('init')
688
+ .description('Initialize XAGENT.md for the current project')
689
+ .action(async () => {
690
+ const { getMemoryManager } = await import('./memory.js');
691
+ const memoryManager = getMemoryManager(process.cwd());
692
+
693
+ const separator = icons.separator.repeat(40);
694
+ console.log('');
695
+ console.log(colors.primaryBright(`${icons.folder} Initializing Project Context`));
696
+ console.log(colors.border(separator));
697
+ console.log('');
698
+
699
+ try {
700
+ await memoryManager.initializeProject(process.cwd());
701
+ console.log(colors.success('Project initialized successfully!'));
702
+ console.log(colors.textMuted('You can now run "xagent start" to begin'));
703
+ console.log('');
704
+ } catch (error: any) {
705
+ const { message, suggestion } = formatError(error);
706
+ console.log(colors.error(`Initialization failed: ${message}`));
707
+ console.log(colors.textMuted(suggestion));
708
+ console.log('');
709
+ process.exit(1);
710
+ }
711
+ });
712
+
713
+ program
714
+ .command('workflow')
715
+ .description('Add, list, or remove workflows')
716
+ .option('--add <workflow-id>', 'Add a workflow from the marketplace')
717
+ .option('-l, --list', 'List all installed workflows')
718
+ .option('-r, --remove <workflow-id>', 'Remove a workflow')
719
+ .option('--scope <scope>', 'Scope (global or project)', 'project')
720
+ .action(async (options) => {
721
+ const { getWorkflowManager } = await import('./workflow.js');
722
+ const workflowManager = getWorkflowManager(process.cwd());
723
+
724
+ if (options.list) {
725
+ const workflows = workflowManager.listWorkflows();
726
+
727
+ if (workflows.length === 0) {
728
+ console.log('');
729
+ console.log(colors.warning('No workflows installed'));
730
+ console.log(colors.textMuted('Use --add to install workflows from the marketplace'));
731
+ console.log('');
732
+ } else {
733
+ const separator = icons.separator.repeat(40);
734
+ console.log('');
735
+ console.log(colors.primaryBright(`${icons.rocket} Installed Workflows`));
736
+ console.log(colors.border(separator));
737
+ console.log('');
738
+
739
+ workflows.forEach((workflow, index) => {
740
+ console.log(` ${colors.primaryBright(`${index + 1}. ${workflow.name}`)}`);
741
+ console.log(` ${colors.textDim(` ID: ${workflow.id}`)}`);
742
+ console.log(` ${colors.textDim(` ${workflow.description}`)}`);
743
+ console.log('');
744
+ });
745
+ }
746
+ } else if (options.add) {
747
+ try {
748
+ await workflowManager.addWorkflow(options.add, options.scope);
749
+ console.log('');
750
+ console.log(colors.success(`Workflow ${options.add} added successfully!`));
751
+ console.log('');
752
+ } catch (error: any) {
753
+ const { message, suggestion } = formatError(error);
754
+ console.log('');
755
+ console.log(colors.error(message));
756
+ console.log(colors.textMuted(suggestion));
757
+ console.log('');
758
+ process.exit(1);
759
+ }
760
+ } else if (options.remove) {
761
+ try {
762
+ await workflowManager.removeWorkflow(options.remove, options.scope);
763
+ console.log('');
764
+ console.log(colors.success(`Workflow ${options.remove} removed successfully!`));
765
+ console.log('');
766
+ } catch (error: any) {
767
+ const { message, suggestion } = formatError(error);
768
+ console.log('');
769
+ console.log(colors.error(message));
770
+ console.log(colors.textMuted(suggestion));
771
+ console.log('');
772
+ process.exit(1);
773
+ }
774
+ } else {
775
+ console.log('');
776
+ console.log(colors.warning('Please specify an action: --list, --add, or --remove'));
777
+ console.log('');
778
+ }
779
+ });
780
+
781
+ program
782
+ .command('skill')
783
+ .description('Manage skills')
784
+ .option('-l, --list', 'List all installed user skills')
785
+ .option('--add <source>', 'Install a skill (auto-detects local path or remote URL)')
786
+ .option('-r, --remove <skill-id>', 'Remove a user-installed skill')
787
+ .action(async (options) => {
788
+ const { getConfigManager } = await import('./config.js');
789
+ const configManager = getConfigManager();
790
+ const { promises: fs } = await import('fs');
791
+ const pathModule = await import('path');
792
+ const { exec, spawn } = await import('child_process');
793
+ const { promisify } = await import('util');
794
+ const os = await import('os');
795
+
796
+ const execAsync = promisify(exec);
797
+ const userSkillsPath = configManager.getUserSkillsPath() || pathModule.join(os.homedir(), '.xagent', 'skills');
798
+ const userNodeModulesPath = configManager.getUserNodeModulesPath() || pathModule.join(os.homedir(), '.xagent', 'node_modules');
799
+
800
+ if (options.add) {
801
+ const separator = icons.separator.repeat(40);
802
+ console.log('');
803
+ console.log(colors.primaryBright(`${icons.tool} Install Skill`));
804
+ console.log(colors.border(separator));
805
+ console.log('');
806
+
807
+ const source = options.add.trim();
808
+ const { installSkill } = await import('./skill-installer.js');
809
+ const { parseSource } = await import('./skill-installer.js');
810
+
811
+ // Auto-detect if source is local or remote
812
+ const parsed = parseSource(source);
813
+ const isLocal = parsed.type === 'local';
814
+
815
+ if (isLocal) {
816
+ // Local installation
817
+ const sourcePath = pathModule.resolve(source);
818
+ const skillName = pathModule.basename(sourcePath);
819
+ const destPath = pathModule.join(userSkillsPath, skillName);
820
+
821
+ try {
822
+ // Check if source exists
823
+ await fs.access(sourcePath);
824
+
825
+ // Check if SKILL.md exists
826
+ const skillMdPath = pathModule.join(sourcePath, 'SKILL.md');
827
+ try {
828
+ await fs.access(skillMdPath);
829
+ } catch {
830
+ console.log(colors.error(`SKILL.md not found in ${sourcePath}`));
831
+ console.log(colors.textMuted('Each skill must have a SKILL.md file'));
832
+ console.log('');
833
+ process.exit(1);
834
+ }
835
+
836
+ // Check if skill already exists in user skills path
837
+ try {
838
+ await fs.access(destPath);
839
+ console.log(colors.warning(`Skill "${skillName}" already installed`));
840
+ console.log(colors.textMuted(`Use "xagent skill -r ${skillName}" to remove it first`));
841
+ console.log('');
842
+ process.exit(1);
843
+ } catch {
844
+ // Doesn't exist, proceed
845
+ }
846
+
847
+ // Ensure user skills directory exists
848
+ await fs.mkdir(userSkillsPath, { recursive: true });
849
+
850
+ // Copy the skill
851
+ await copyDirectory(sourcePath, destPath);
852
+ console.log('');
853
+ console.log(colors.success(`✅ Skill "${skillName}" installed successfully`));
854
+ console.log(colors.textMuted(` Location: ${destPath}`));
855
+ console.log(colors.textMuted(` Type: Local`));
856
+ console.log('');
857
+
858
+ // Notify running xAgent to update system prompt
859
+ await notifySkillUpdate(userSkillsPath);
860
+ console.log('');
861
+ } catch (error: any) {
862
+ const { message, suggestion } = formatError(error);
863
+ console.log(colors.error(`Failed to install skill: ${message}`));
864
+ console.log(colors.textMuted(suggestion));
865
+ console.log('');
866
+ process.exit(1);
867
+ }
868
+ } else {
869
+ // Remote installation
870
+ console.log(colors.textMuted(` Source: ${source}`));
871
+ console.log(colors.textMuted(` Type: Remote`));
872
+ console.log('');
873
+
874
+ try {
875
+ const result = await installSkill(source);
876
+
877
+ if (result.success) {
878
+ console.log(colors.success(`✅ Skill "${result.skillName}" installed successfully`));
879
+ console.log(colors.textMuted(` Location: ${result.skillPath}`));
880
+ console.log('');
881
+
882
+ // Notify running xAgent to update system prompt
883
+ await notifySkillUpdate(userSkillsPath);
884
+ console.log(colors.textMuted('Note: Run "xagent start" to use the new skill'));
885
+ console.log('');
886
+ } else {
887
+ console.log(colors.error(`Failed to install skill: ${result.error}`));
888
+ console.log('');
889
+ process.exit(1);
890
+ }
891
+ } catch (error: any) {
892
+ const { message, suggestion } = formatError(error);
893
+ console.log(colors.error(`Failed to install skill: ${message}`));
894
+ console.log(colors.textMuted(suggestion));
895
+ console.log('');
896
+ process.exit(1);
897
+ }
898
+ }
899
+ } else if (options.list) {
900
+ const separator = icons.separator.repeat(40);
901
+ console.log('');
902
+ console.log(colors.primaryBright(`${icons.tool} Skills`));
903
+ console.log(colors.border(separator));
904
+ console.log('');
905
+
906
+ try {
907
+ const entries = await fs.readdir(userSkillsPath, { withFileTypes: true });
908
+ const skills = entries.filter(e => e.isDirectory());
909
+
910
+ if (skills.length === 0) {
911
+ console.log(colors.textMuted('No user skills installed'));
912
+ console.log('');
913
+ return;
914
+ }
915
+
916
+ for (const skill of skills) {
917
+ const skillPath = path.join(userSkillsPath, skill.name);
918
+ const skillMdPath = path.join(skillPath, 'SKILL.md');
919
+
920
+ try {
921
+ const content = await fs.readFile(skillMdPath, 'utf-8');
922
+ // Simple parsing for name and description
923
+ const nameMatch = content.match(/^name:\s*(.+)$/m);
924
+ const descMatch = content.match(/^description:\s*(.+)$/m);
925
+ const name = nameMatch ? nameMatch[1].trim() : skill.name;
926
+ const description = descMatch ? descMatch[1].trim() : 'No description';
927
+
928
+ console.log(` ${colors.primaryBright(`• ${name}`)}`);
929
+ console.log(` ${colors.textDim(` ${description}`)}`);
930
+ console.log('');
931
+ } catch {
932
+ console.log(` ${colors.primaryBright(`• ${skill.name}`)}`);
933
+ console.log(` ${colors.textDim(` (Missing SKILL.md)`)}`);
934
+ console.log('');
935
+ }
936
+ }
937
+
938
+ console.log(colors.textMuted(`Skills directory: ${userSkillsPath}`));
939
+ console.log('');
940
+ } catch (error) {
941
+ console.log(colors.textMuted('No user skills installed'));
942
+ console.log('');
943
+ }
944
+ } else if (options.remove) {
945
+ const skillPath = path.join(userSkillsPath, options.remove);
946
+
947
+ // Protect find-skills from deletion
948
+ if (options.remove === 'find-skills') {
949
+ console.log('');
950
+ console.log(colors.error(`Cannot remove protected skill: find-skills`));
951
+ console.log(colors.textMuted('find-skills is a built-in skill that helps you discover and install other skills.'));
952
+ console.log('');
953
+ process.exit(1);
954
+ }
955
+
956
+ try {
957
+ await fs.access(skillPath);
958
+ // Verify it's in user skills path (not built-in)
959
+ if (!skillPath.startsWith(userSkillsPath)) {
960
+ console.log('');
961
+ console.log(colors.error(`Cannot remove skill outside user directory: ${options.remove}`));
962
+ console.log('');
963
+ process.exit(1);
964
+ }
965
+
966
+ // Remove the skill directory
967
+ await fs.rm(skillPath, { recursive: true, force: true });
968
+ console.log('');
969
+ console.log(colors.success(`✅ Skill ${options.remove} removed successfully`));
970
+ console.log('');
971
+
972
+ // Notify running xAgent to update system prompt
973
+ await notifySkillUpdate(userSkillsPath);
974
+ console.log('');
975
+ } catch (error) {
976
+ console.log('');
977
+ console.log(colors.error(`Skill not found: ${options.remove}`));
978
+ console.log('');
979
+ process.exit(1);
980
+ }
981
+ } else {
982
+ // Show help
983
+ console.log('');
984
+ console.log(colors.textMuted('Usage:'));
985
+ console.log(` ${colors.primaryBright('xagent skill -l')} ${colors.textDim('| List all skills')}`);
986
+ console.log(` ${colors.primaryBright('xagent skill --add <source>')} ${colors.textDim('| Install skill (auto-detects local or remote)')}`);
987
+ console.log(` ${colors.primaryBright('xagent skill -r <name>')} ${colors.textDim('| Remove a skill')}`);
988
+ console.log('');
989
+ console.log(colors.textMuted('Examples:'));
990
+ console.log(` ${colors.primaryBright('xagent skill --add ./my-skill')} ${colors.textDim('| Install from local path')}`);
991
+ console.log(` ${colors.primaryBright('xagent skill --add owner/repo')} ${colors.textDim('| Install from GitHub')}`);
992
+ console.log(` ${colors.primaryBright('xagent skill --add https://github.com/owner/repo')}`);
993
+ console.log(` ${colors.primaryBright('xagent skill --add https://docs.example.com/skill.md')}`);
994
+ console.log('');
995
+ console.log(colors.textMuted('To install a new skill, use the interactive command:'));
996
+ console.log(` ${colors.primaryBright('/skill add')}`);
997
+ console.log('');
998
+ }
999
+ });
1000
+
1001
+ program
1002
+ .command('version')
1003
+ .description('Display version and check for updates')
1004
+ .action(async () => {
1005
+ const separator = icons.separator.repeat(40);
1006
+
1007
+ console.log('');
1008
+ console.log(colors.gradient('╔════════════════════════════════════════════════════════════╗'));
1009
+ console.log(colors.gradient('║') + ' '.repeat(56) + colors.gradient('║'));
1010
+ console.log(' '.repeat(20) + colors.gradient('xAgent CLI') + ' '.repeat(29) + colors.gradient('║'));
1011
+ console.log(colors.gradient('║') + ' '.repeat(56) + colors.gradient('║'));
1012
+ console.log(colors.gradient('╚════════════════════════════════════════════════════════════╝'));
1013
+ console.log('');
1014
+ console.log(colors.border(separator));
1015
+ console.log('');
1016
+ console.log(` ${icons.info} ${colors.textMuted('Version:')} ${colors.primaryBright(packageJson.version)}`);
1017
+ console.log(` ${icons.code} ${colors.textMuted('Node.js:')} ${colors.textMuted(process.version)}`);
1018
+ console.log(` ${icons.bolt} ${colors.textMuted('Platform:')} ${colors.textMuted(process.platform + ' ' + process.arch)}`);
1019
+ console.log('');
1020
+ console.log(colors.border(separator));
1021
+ console.log('');
1022
+ console.log(` ${colors.primaryBright('📚 Documentation:')} ${colors.primaryBright('https://platform.xagent.cn/cli/')}`);
1023
+ console.log(` ${colors.primaryBright('💻 GitHub:')} ${colors.primaryBright('https://github.com/xagent-ai/xagent-cli')}`);
1024
+ console.log('');
1025
+ });
1026
+
1027
+ program
1028
+ .command('gui')
1029
+ .description('Start GUI subagent for computer automation')
1030
+ .option('--headless', 'Run in headless mode (no visible window)', false)
1031
+ .action(async (options) => {
1032
+ const separator = icons.separator.repeat(40);
1033
+ console.log('');
1034
+ console.log(colors.primaryBright(`${icons.robot} GUI Subagent - Computer Automation`));
1035
+ console.log(colors.border(separator));
1036
+ console.log('');
1037
+
1038
+ try {
1039
+ const configManager = getConfigManager();
1040
+ const authConfig = configManager.getAuthConfig();
1041
+
1042
+ // Get GUI-specific VLM configuration
1043
+ const baseUrl = configManager.get('guiSubagentBaseUrl') || configManager.get('baseUrl') || '';
1044
+ const apiKey = configManager.get('guiSubagentApiKey') || configManager.get('apiKey') || '';
1045
+ const modelName = configManager.get('guiSubagentModel') || configManager.get('modelName') || '';
1046
+
1047
+ // Determine mode: local (openai_compatible) or remote
1048
+ const isLocalMode = authConfig.type === 'openai_compatible';
1049
+
1050
+ if (isLocalMode) {
1051
+ // Local mode: require baseUrl configuration
1052
+ if (!baseUrl) {
1053
+ console.log(colors.error('No VLM API URL configured for GUI subagent.'));
1054
+ console.log(colors.textMuted('Please run "xagent auth" and configure guiSubagentBaseUrl.'));
1055
+ console.log('');
1056
+ return;
1057
+ }
1058
+ console.log(colors.info(`${icons.brain} Using local VLM configuration`));
1059
+ console.log(colors.textMuted(` Model: ${modelName}`));
1060
+ console.log(colors.textMuted(` Base URL: ${baseUrl}`));
1061
+ console.log('');
1062
+ } else {
1063
+ // Remote mode
1064
+ console.log(colors.info(`${icons.brain} Using remote VLM service`));
1065
+ console.log(colors.textMuted(` Auth Type: ${authConfig.type}`));
1066
+ console.log('');
1067
+ }
1068
+
1069
+ const { createGUISubAgent } = await import('./gui-subagent/index.js');
1070
+
1071
+ // Create ref for tracking first VLM call across loop iterations
1072
+ const isFirstVlmCallRef = { current: true };
1073
+
1074
+ // Create remoteVlmCaller for remote mode (uses full messages for consistent behavior)
1075
+ let remoteVlmCaller: ((messages: any[], systemPrompt: string, taskId: string, isFirstVlmCallRef: { current: boolean }) => Promise<string>) | undefined;
1076
+
1077
+ if (!isLocalMode && authConfig.baseUrl) {
1078
+ const remoteBaseUrl = `${authConfig.baseUrl}/api/agent/vlm`;
1079
+ remoteVlmCaller = async (messages: any[], _systemPrompt: string, _taskId: string, isFirstVlmCallRef: { current: boolean }): Promise<string> => {
1080
+ const status = isFirstVlmCallRef.current ? 'begin' : 'continue';
1081
+ const response = await fetch(remoteBaseUrl, {
1082
+ method: 'POST',
1083
+ headers: {
1084
+ 'Content-Type': 'application/json',
1085
+ 'Authorization': `Bearer ${authConfig.apiKey || ''}`,
1086
+ },
1087
+ body: JSON.stringify({
1088
+ messages,
1089
+ taskId: _taskId,
1090
+ status
1091
+ }),
1092
+ });
1093
+ if (!response.ok) {
1094
+ const errorText = await response.text();
1095
+ throw new Error(`Remote VLM error: ${response.status} - ${errorText}`);
1096
+ }
1097
+ const result = await response.json() as { response?: string; content?: string; message?: string };
1098
+ // Update ref after call so subsequent calls use 'continue'
1099
+ isFirstVlmCallRef.current = false;
1100
+ return result.response || result.content || result.message || '';
1101
+ };
1102
+ }
1103
+
1104
+ const guiAgent = await createGUISubAgent({
1105
+ headless: options.headless ?? false,
1106
+ model: isLocalMode ? modelName : undefined,
1107
+ modelBaseUrl: isLocalMode ? baseUrl : undefined,
1108
+ modelApiKey: isLocalMode ? apiKey : undefined,
1109
+ isFirstVlmCallRef,
1110
+ remoteVlmCaller,
1111
+ isLocalMode,
1112
+ });
1113
+
1114
+ console.log(colors.success('✅ GUI Subagent initialized successfully!'));
1115
+ console.log('');
1116
+ console.log(colors.textMuted('Available actions:'));
1117
+ console.log(colors.textDim(' - click: Click on an element'));
1118
+ console.log(colors.textDim(' - double_click: Double click'));
1119
+ console.log(colors.textDim(' - right_click: Right click'));
1120
+ console.log(colors.textDim(' - drag: Drag from one position to another'));
1121
+ console.log(colors.textDim(' - type: Type text'));
1122
+ console.log(colors.textDim(' - hotkey: Press keyboard shortcuts'));
1123
+ console.log(colors.textDim(' - scroll: Scroll up/down/left/right'));
1124
+ console.log(colors.textDim(' - wait: Wait for specified time'));
1125
+ console.log(colors.textDim(' - finished: Complete the task'));
1126
+ console.log('');
1127
+ console.log(colors.primaryBright('Use the GUI tools in the interactive session to control the computer.'));
1128
+ console.log('');
1129
+ } catch (error: any) {
1130
+ const { message, suggestion } = formatError(error);
1131
+ console.log('');
1132
+ console.log(colors.error(`Failed to start GUI Subagent: ${message}`));
1133
+ console.log(colors.textMuted(suggestion));
1134
+ console.log('');
1135
+ }
1136
+ });
1137
+
1138
+ program
1139
+ .command('memory')
1140
+ .description('Manage memory files (list or clean)')
1141
+ .option('-l, --list', 'List all memory files')
1142
+ .option('--clean', 'Clean all project memories (keep global memory)')
1143
+ .option('--clean-project', 'Clean the current project\'s memory only')
1144
+ .option('--clean-all', 'Clean all memories (including global memory)')
1145
+ .action(async (options) => {
1146
+ const separator = icons.separator.repeat(40);
1147
+ console.log('');
1148
+ console.log(colors.primaryBright(`${icons.folder} Memory Management`));
1149
+ console.log(colors.border(separator));
1150
+ console.log('');
1151
+
1152
+ const { getMemoryManager } = await import('./memory.js');
1153
+ const memoryManager = getMemoryManager(process.cwd());
1154
+ const memoriesDir = memoryManager.getMemoriesDir();
1155
+
1156
+ // Helper to get memory info
1157
+ const getMemoryInfo = (fileName: string) => {
1158
+ if (fileName === 'global.md') {
1159
+ return { type: 'global', description: 'Global memory (shared across all projects)' };
1160
+ }
1161
+ const match = fileName.match(/^project_(.+)_\w{16}\.md$/);
1162
+ if (match) {
1163
+ return { type: 'project', description: `Project: ${match[1]}` };
1164
+ }
1165
+ return { type: 'unknown', description: fileName };
1166
+ };
1167
+
1168
+ if (options.list) {
1169
+ // List all memory files
1170
+ console.log(colors.textMuted(`Memory directory: ${memoriesDir}`));
1171
+ console.log('');
1172
+
1173
+ try {
1174
+ const files = await fs.readdir(memoriesDir).catch(() => []);
1175
+ if (files.length === 0) {
1176
+ console.log(colors.textMuted('No memory files found.'));
1177
+ console.log('');
1178
+ return;
1179
+ }
1180
+
1181
+ const globalFile = files.find(f => f === 'global.md');
1182
+ const projectFiles = files.filter(f => f.startsWith('project_'));
1183
+
1184
+ if (globalFile) {
1185
+ const info = getMemoryInfo(globalFile);
1186
+ console.log(` ${colors.success(icons.success)} ${colors.primaryBright('global.md')}`);
1187
+ console.log(` ${colors.textDim(` ${info.description}`)}`);
1188
+ console.log('');
1189
+ }
1190
+
1191
+ if (projectFiles.length > 0) {
1192
+ console.log(colors.primaryBright(` Project Memories (${projectFiles.length})`));
1193
+ console.log('');
1194
+
1195
+ for (const file of projectFiles) {
1196
+ const info = getMemoryInfo(file);
1197
+ const filePath = join(memoriesDir, file);
1198
+ try {
1199
+ const stat = await fs.stat(filePath);
1200
+ const size = stat.size;
1201
+ const sizeStr = size < 1024 ? `${size} B` : `${(size / 1024).toFixed(1)} KB`;
1202
+ console.log(` ${colors.success(icons.success)} ${colors.primaryBright(file)}`);
1203
+ console.log(` ${colors.textDim(` ${info.description} | Size: ${sizeStr}`)}`);
1204
+ } catch {
1205
+ console.log(` ${colors.success(icons.success)} ${colors.primaryBright(file)}`);
1206
+ console.log(` ${colors.textDim(` ${info.description}`)}`);
1207
+ }
1208
+ console.log('');
1209
+ }
1210
+ }
1211
+
1212
+ console.log(colors.textMuted(`Total: ${files.length} memory file(s)`));
1213
+ console.log('');
1214
+ } catch (error) {
1215
+ console.log(colors.textMuted('No memory files found.'));
1216
+ console.log('');
1217
+ }
1218
+ } else if (options.clean) {
1219
+ // Clean all project memories (keep global.md)
1220
+ console.log(colors.textMuted('Cleaning all project memories...'));
1221
+ console.log(colors.textMuted(`Keeping: ${colors.primaryBright('global.md')}`));
1222
+ console.log('');
1223
+
1224
+ try {
1225
+ const files = await fs.readdir(memoriesDir).catch(() => []);
1226
+ const projectFiles = files.filter(f => f.startsWith('project_'));
1227
+
1228
+ if (projectFiles.length === 0) {
1229
+ console.log(colors.textMuted('No project memories to clean.'));
1230
+ console.log('');
1231
+ return;
1232
+ }
1233
+
1234
+ let cleaned = 0;
1235
+ for (const file of projectFiles) {
1236
+ await fs.unlink(join(memoriesDir, file));
1237
+ cleaned++;
1238
+ }
1239
+
1240
+ console.log(colors.success(`✅ Cleaned ${cleaned} project memory file(s)`));
1241
+ // TODO: 如果需要自动重建 project memory,取消下面注释
1242
+ // await memoryManager.saveMemory('# Project Context\n\nProject-specific context will be added here.', 'project');
1243
+ // console.log(colors.textMuted(' Recreated current project memory'));
1244
+ console.log(colors.textMuted(' Use /init to initialize if needed'));
1245
+ console.log('');
1246
+ } catch (error: any) {
1247
+ const { message, suggestion } = formatError(error);
1248
+ console.log(colors.error(`Failed to clean project memories: ${message}`));
1249
+ console.log(colors.textMuted(suggestion));
1250
+ console.log('');
1251
+ }
1252
+ } else if (options.cleanProject) {
1253
+ // Clean only the current project's memory
1254
+ console.log(colors.textMuted(`Cleaning current project memory...`));
1255
+ console.log(colors.textMuted(`Project: ${colors.primaryBright(process.cwd())}`));
1256
+ console.log('');
1257
+
1258
+ try {
1259
+ // Find and delete the current project's memory file
1260
+ const memoryFiles = memoryManager.getMemoryFiles();
1261
+ const currentProjectMemory = memoryFiles.find(m => m.level === 'project');
1262
+
1263
+ if (currentProjectMemory) {
1264
+ await fs.unlink(currentProjectMemory.path);
1265
+ console.log(colors.success(`✅ Cleaned current project memory`));
1266
+ console.log(colors.textMuted(` File: ${path.basename(currentProjectMemory.path)}`));
1267
+ } else {
1268
+ console.log(colors.textMuted('No memory found for the current project.'));
1269
+ }
1270
+ // TODO: 如果需要自动重建 project memory,取消下面注释
1271
+ // await memoryManager.saveMemory('# Project Context\n\nProject-specific context will be added here.', 'project');
1272
+ // console.log(colors.textMuted(' Recreated current project memory'));
1273
+ console.log(colors.textMuted(' Use /init to initialize if needed'));
1274
+ console.log('');
1275
+ } catch (error: any) {
1276
+ const { message, suggestion } = formatError(error);
1277
+ console.log(colors.error(`Failed to clean project memory: ${message}`));
1278
+ console.log(colors.textMuted(suggestion));
1279
+ console.log('');
1280
+ }
1281
+ } else if (options.cleanAll) {
1282
+ // Clean all memories including global
1283
+ console.log(colors.warning(`${icons.warning} This will delete ALL memory files including global memory.`));
1284
+ console.log('');
1285
+ console.log(colors.textMuted('Files to be deleted:'));
1286
+ console.log(colors.textMuted(` - global.md (global memory)`));
1287
+ console.log(colors.textMuted(` - all project memories`));
1288
+ console.log('');
1289
+
1290
+ try {
1291
+ const files = await fs.readdir(memoriesDir).catch(() => []);
1292
+ if (files.length === 0) {
1293
+ console.log(colors.textMuted('No memory files to clean.'));
1294
+ console.log('');
1295
+ return;
1296
+ }
1297
+
1298
+ let cleaned = 0;
1299
+ for (const file of files) {
1300
+ await fs.unlink(join(memoriesDir, file));
1301
+ cleaned++;
1302
+ }
1303
+
1304
+ // Recreate global memory (always keep global memory available)
1305
+ await memoryManager.saveMemory('# Global Context\n\nGlobal preferences and settings will be added here.', 'global');
1306
+ // TODO: 如果需要同时重建 project memory,取消下面注释
1307
+ // await memoryManager.saveMemory('# Project Context\n\nProject-specific context will be added here.', 'project');
1308
+
1309
+ console.log(colors.success(`✅ Cleaned ${cleaned} memory file(s)`));
1310
+ console.log(colors.textMuted(' Recreated global memory'));
1311
+ console.log(colors.textMuted(' Use /init to initialize project memory if needed'));
1312
+ console.log('');
1313
+ } catch (error: any) {
1314
+ const { message, suggestion } = formatError(error);
1315
+ console.log(colors.error(`Failed to clean memories: ${message}`));
1316
+ console.log(colors.textMuted(suggestion));
1317
+ console.log('');
1318
+ }
1319
+ } else {
1320
+ // No option specified, show help
1321
+ console.log(colors.textMuted('Usage:'));
1322
+ console.log(` ${colors.primaryBright('xagent memory -l')} ${colors.textDim('| List all memory files')}`);
1323
+ console.log(` ${colors.primaryBright('xagent memory --clean')} ${colors.textDim('| Clean all project memories (keep global)')}`);
1324
+ console.log(` ${colors.primaryBright('xagent memory --clean-project')} ${colors.textDim('| Clean current project memory only')}`);
1325
+ console.log(` ${colors.primaryBright('xagent memory --clean-all')} ${colors.textDim('| Clean ALL memories (including global)')}`);
1326
+ console.log('');
1327
+ }
1328
+ });
1329
+
1330
+ program
1331
+ .command('update')
1332
+ .description('Check for updates and update xAgent CLI')
1333
+ .action(async () => {
1334
+ const separator = icons.separator.repeat(40);
1335
+ console.log('');
1336
+ console.log(colors.primaryBright(`${icons.rocket} Update Check`));
1337
+ console.log(colors.border(separator));
1338
+ console.log('');
1339
+
1340
+ try {
1341
+ const { getUpdateManager } = await import('./update.js');
1342
+ const updateManager = getUpdateManager();
1343
+ const versionInfo = await updateManager.checkForUpdates();
1344
+
1345
+ console.log(` ${icons.info} ${colors.textMuted('Current version:')} ${colors.primaryBright(versionInfo.currentVersion)}`);
1346
+ console.log(` ${icons.code} ${colors.textMuted('Latest version:')} ${colors.primaryBright(versionInfo.latestVersion)}`);
1347
+ console.log('');
1348
+
1349
+ if (versionInfo.updateAvailable) {
1350
+ console.log(colors.success(` 📦 A new version is available!`));
1351
+ console.log('');
1352
+
1353
+ if (versionInfo.releaseNotes) {
1354
+ console.log(colors.textMuted(' Release Notes:'));
1355
+ console.log(colors.textDim(` ${versionInfo.releaseNotes}`));
1356
+ console.log('');
1357
+ }
1358
+
1359
+ const shouldUpdate = await confirm({
1360
+ message: 'Do you want to update now?',
1361
+ });
1362
+
1363
+ if (shouldUpdate === true) {
1364
+ console.log('');
1365
+ await updateManager.autoUpdate();
1366
+ }
1367
+ } else {
1368
+ console.log(colors.success(` ✅ You are using the latest version`));
1369
+ console.log('');
1370
+ }
1371
+ } catch (error: any) {
1372
+ console.log(colors.error(` ❌ Failed to check for updates: ${error.message}`));
1373
+ console.log('');
1374
+ }
1375
+ });
1376
+
1377
+ program.parse(process.argv);
1378
+
1379
+ if (!process.argv.slice(2).length) {
1380
+ program.outputHelp();
1381
+ }
1382
+
1383
+ // ============================================================
1384
+ // Global error handling - prevent crashes from uncaught errors
1385
+ // ============================================================
1386
+
1387
+ // Handle uncaught promise rejections
1388
+ process.on('unhandledRejection', (reason: any, promise: Promise<any>) => {
1389
+ console.error('\n❌ An unexpected error occurred');
1390
+ if (reason instanceof Error) {
1391
+ console.error(` ${reason.message}`);
1392
+ } else if (reason) {
1393
+ console.error(` ${String(reason)}`);
1394
+ }
1395
+ console.error('\n If this problem persists, please report this issue.');
1396
+ console.error('');
1397
+ process.exit(1);
1398
+ });
1399
+
1400
+ // Handle uncaught exceptions
1401
+ process.on('uncaughtException', (error: Error) => {
1402
+ console.error('\n❌ Critical error - application will exit');
1403
+ console.error(` ${error.message}`);
1404
+ console.error('');
1405
+ process.exit(1);
1406
+ });