@xagent-ai/cli 1.2.2 → 1.3.1

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