@xagent-ai/cli 1.2.2 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (568) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +38 -38
  2. package/.github/ISSUE_TEMPLATE/feature_request.md +20 -20
  3. package/.github/workflows/ci.yml +72 -0
  4. package/.github/workflows/release.yml +109 -0
  5. package/.gitmodules +3 -3
  6. package/README.md +326 -280
  7. package/README_CN.md +325 -279
  8. package/dist/ai-client/factory.d.ts +52 -0
  9. package/dist/ai-client/factory.d.ts.map +1 -0
  10. package/dist/ai-client/factory.js +132 -0
  11. package/dist/ai-client/factory.js.map +1 -0
  12. package/dist/ai-client/index.d.ts +20 -0
  13. package/dist/ai-client/index.d.ts.map +1 -0
  14. package/dist/ai-client/index.js +49 -0
  15. package/dist/ai-client/index.js.map +1 -0
  16. package/dist/ai-client/providers/anthropic.d.ts +57 -0
  17. package/dist/ai-client/providers/anthropic.d.ts.map +1 -0
  18. package/dist/ai-client/providers/anthropic.js +400 -0
  19. package/dist/ai-client/providers/anthropic.js.map +1 -0
  20. package/dist/ai-client/providers/openai.d.ts +57 -0
  21. package/dist/ai-client/providers/openai.d.ts.map +1 -0
  22. package/dist/ai-client/providers/openai.js +286 -0
  23. package/dist/ai-client/providers/openai.js.map +1 -0
  24. package/dist/ai-client/providers/remote.d.ts +111 -0
  25. package/dist/ai-client/providers/remote.d.ts.map +1 -0
  26. package/dist/ai-client/providers/remote.js +351 -0
  27. package/dist/ai-client/providers/remote.js.map +1 -0
  28. package/dist/ai-client/registry.d.ts +51 -0
  29. package/dist/ai-client/registry.d.ts.map +1 -0
  30. package/dist/ai-client/registry.js +81 -0
  31. package/dist/ai-client/registry.js.map +1 -0
  32. package/dist/ai-client/types.d.ts +260 -0
  33. package/dist/ai-client/types.d.ts.map +1 -0
  34. package/dist/ai-client/types.js +73 -0
  35. package/dist/ai-client/types.js.map +1 -0
  36. package/dist/ai-client-factory.d.ts +62 -0
  37. package/dist/ai-client-factory.d.ts.map +1 -0
  38. package/dist/ai-client-factory.js +157 -0
  39. package/dist/ai-client-factory.js.map +1 -0
  40. package/dist/auth.d.ts +23 -1
  41. package/dist/auth.d.ts.map +1 -1
  42. package/dist/auth.js +160 -168
  43. package/dist/auth.js.map +1 -1
  44. package/dist/cancellation.d.ts +5 -4
  45. package/dist/cancellation.d.ts.map +1 -1
  46. package/dist/cancellation.js +55 -32
  47. package/dist/cancellation.js.map +1 -1
  48. package/dist/checkpoint.d.ts +1 -1
  49. package/dist/checkpoint.d.ts.map +1 -1
  50. package/dist/checkpoint.js +2 -2
  51. package/dist/checkpoint.js.map +1 -1
  52. package/dist/cli.js +626 -13
  53. package/dist/cli.js.map +1 -1
  54. package/dist/config.d.ts +10 -4
  55. package/dist/config.d.ts.map +1 -1
  56. package/dist/config.js +62 -25
  57. package/dist/config.js.map +1 -1
  58. package/dist/context-compressor.d.ts +81 -16
  59. package/dist/context-compressor.d.ts.map +1 -1
  60. package/dist/context-compressor.js +712 -153
  61. package/dist/context-compressor.js.map +1 -1
  62. package/dist/gui-subagent/action-parser/actionParser.d.ts.map +1 -1
  63. package/dist/gui-subagent/action-parser/actionParser.js +4 -2
  64. package/dist/gui-subagent/action-parser/actionParser.js.map +1 -1
  65. package/dist/gui-subagent/agent/gui-agent.d.ts +29 -2
  66. package/dist/gui-subagent/agent/gui-agent.d.ts.map +1 -1
  67. package/dist/gui-subagent/agent/gui-agent.js +87 -45
  68. package/dist/gui-subagent/agent/gui-agent.js.map +1 -1
  69. package/dist/gui-subagent/index.d.ts +16 -1
  70. package/dist/gui-subagent/index.d.ts.map +1 -1
  71. package/dist/gui-subagent/index.js +4 -0
  72. package/dist/gui-subagent/index.js.map +1 -1
  73. package/dist/gui-subagent/operator/base-operator.d.ts.map +1 -1
  74. package/dist/gui-subagent/operator/base-operator.js +0 -1
  75. package/dist/gui-subagent/operator/base-operator.js.map +1 -1
  76. package/dist/gui-subagent/operator/computer-operator.d.ts.map +1 -1
  77. package/dist/gui-subagent/operator/computer-operator.js +29 -8
  78. package/dist/gui-subagent/operator/computer-operator.js.map +1 -1
  79. package/dist/gui-subagent/types/actions.d.ts +1 -1
  80. package/dist/gui-subagent/types/actions.d.ts.map +1 -1
  81. package/dist/gui-subagent/types/actions.js +0 -1
  82. package/dist/gui-subagent/types/actions.js.map +1 -1
  83. package/dist/gui-subagent/types/operator.d.ts +1 -1
  84. package/dist/gui-subagent/types/operator.d.ts.map +1 -1
  85. package/dist/index.d.ts +1 -2
  86. package/dist/index.d.ts.map +1 -1
  87. package/dist/index.js +1 -2
  88. package/dist/index.js.map +1 -1
  89. package/dist/input-processor.d.ts.map +1 -1
  90. package/dist/input-processor.js +6 -3
  91. package/dist/input-processor.js.map +1 -1
  92. package/dist/mcp.d.ts +5 -0
  93. package/dist/mcp.d.ts.map +1 -1
  94. package/dist/mcp.js +81 -35
  95. package/dist/mcp.js.map +1 -1
  96. package/dist/ripgrep.d.ts +29 -0
  97. package/dist/ripgrep.d.ts.map +1 -0
  98. package/dist/ripgrep.js +292 -0
  99. package/dist/ripgrep.js.map +1 -0
  100. package/dist/session.d.ts +23 -7
  101. package/dist/session.d.ts.map +1 -1
  102. package/dist/session.js +624 -243
  103. package/dist/session.js.map +1 -1
  104. package/dist/shell.d.ts +33 -0
  105. package/dist/shell.d.ts.map +1 -0
  106. package/dist/shell.js +125 -0
  107. package/dist/shell.js.map +1 -0
  108. package/dist/skill-installer.d.ts +38 -0
  109. package/dist/skill-installer.d.ts.map +1 -0
  110. package/dist/skill-installer.js +447 -0
  111. package/dist/skill-installer.js.map +1 -0
  112. package/dist/skill-invoker.d.ts +7 -1
  113. package/dist/skill-invoker.d.ts.map +1 -1
  114. package/dist/skill-invoker.js +34 -13
  115. package/dist/skill-invoker.js.map +1 -1
  116. package/dist/skill-loader.d.ts +8 -3
  117. package/dist/skill-loader.d.ts.map +1 -1
  118. package/dist/skill-loader.js +46 -44
  119. package/dist/skill-loader.js.map +1 -1
  120. package/dist/skill-manager.d.ts +85 -0
  121. package/dist/skill-manager.d.ts.map +1 -0
  122. package/dist/skill-manager.js +340 -0
  123. package/dist/skill-manager.js.map +1 -0
  124. package/dist/slash-commands.d.ts +38 -1
  125. package/dist/slash-commands.d.ts.map +1 -1
  126. package/dist/slash-commands.js +912 -296
  127. package/dist/slash-commands.js.map +1 -1
  128. package/dist/smart-approval.d.ts.map +1 -1
  129. package/dist/smart-approval.js +67 -55
  130. package/dist/smart-approval.js.map +1 -1
  131. package/dist/system-prompt-generator.d.ts +6 -0
  132. package/dist/system-prompt-generator.d.ts.map +1 -1
  133. package/dist/system-prompt-generator.js +84 -34
  134. package/dist/system-prompt-generator.js.map +1 -1
  135. package/dist/terminal.d.ts +28 -0
  136. package/dist/terminal.d.ts.map +1 -0
  137. package/dist/terminal.js +82 -0
  138. package/dist/terminal.js.map +1 -0
  139. package/dist/tools.d.ts +23 -7
  140. package/dist/tools.d.ts.map +1 -1
  141. package/dist/tools.js +797 -437
  142. package/dist/tools.js.map +1 -1
  143. package/dist/truncate.d.ts +55 -0
  144. package/dist/truncate.d.ts.map +1 -0
  145. package/dist/truncate.js +130 -0
  146. package/dist/truncate.js.map +1 -0
  147. package/dist/types.d.ts +27 -9
  148. package/dist/types.d.ts.map +1 -1
  149. package/dist/update.d.ts.map +1 -1
  150. package/dist/update.js +17 -28
  151. package/dist/update.js.map +1 -1
  152. package/dist/workflow.d.ts +5 -1
  153. package/dist/workflow.d.ts.map +1 -1
  154. package/dist/workflow.js +60 -47
  155. package/dist/workflow.js.map +1 -1
  156. package/docs/architecture/mcp-integration-guide.md +304 -194
  157. package/docs/architecture/overview.md +169 -169
  158. package/docs/architecture/tool-system-design.md +134 -134
  159. package/docs/cli/commands.md +349 -238
  160. package/docs/smart-mode.md +281 -281
  161. package/docs/third-party-models.md +439 -439
  162. package/find-skills/SKILL.md +133 -0
  163. package/package.json +89 -90
  164. package/scripts/install-ripgrep.js +241 -0
  165. package/src/ai-client/factory.ts +151 -0
  166. package/src/ai-client/index.ts +61 -0
  167. package/src/ai-client/providers/anthropic.ts +466 -0
  168. package/src/ai-client/providers/openai.ts +342 -0
  169. package/src/ai-client/providers/remote.ts +436 -0
  170. package/src/ai-client/registry.ts +97 -0
  171. package/src/ai-client/types.ts +345 -0
  172. package/src/ai-client-factory.ts +204 -0
  173. package/src/auth.ts +663 -614
  174. package/src/cancellation.ts +205 -176
  175. package/src/checkpoint.ts +219 -219
  176. package/src/cli.ts +1406 -743
  177. package/src/config.ts +341 -297
  178. package/src/context-compressor.ts +982 -290
  179. package/src/conversation.ts +288 -288
  180. package/src/gui-subagent/action-parser/actionParser.ts +318 -315
  181. package/src/gui-subagent/action-parser/constants.ts +14 -14
  182. package/src/gui-subagent/action-parser/index.ts +8 -8
  183. package/src/gui-subagent/action-parser/types.ts +31 -31
  184. package/src/gui-subagent/agent/gui-agent.ts +1151 -1089
  185. package/src/gui-subagent/agent/index.ts +5 -5
  186. package/src/gui-subagent/index.ts +177 -163
  187. package/src/gui-subagent/operator/base-operator.ts +244 -245
  188. package/src/gui-subagent/operator/computer-operator.ts +540 -520
  189. package/src/gui-subagent/operator/index.ts +6 -6
  190. package/src/gui-subagent/types/actions.ts +260 -262
  191. package/src/gui-subagent/types/index.ts +6 -6
  192. package/src/gui-subagent/types/operator.ts +106 -106
  193. package/src/gui-subagent/utils.ts +51 -51
  194. package/src/index.ts +17 -18
  195. package/src/input-processor.ts +6 -3
  196. package/src/logger.ts +438 -438
  197. package/src/mcp.ts +730 -682
  198. package/src/memory.ts +344 -344
  199. package/src/ripgrep.ts +368 -0
  200. package/src/session-manager.ts +308 -308
  201. package/src/session.ts +948 -386
  202. package/src/shell.ts +133 -0
  203. package/src/skill-installer.ts +518 -0
  204. package/src/skill-invoker.ts +960 -935
  205. package/src/skill-loader.ts +501 -496
  206. package/src/skill-manager.ts +384 -0
  207. package/src/slash-commands.ts +2181 -1389
  208. package/src/smart-approval.ts +117 -73
  209. package/src/system-prompt-generator.ts +89 -34
  210. package/src/terminal.ts +96 -0
  211. package/src/theme.ts +738 -738
  212. package/src/tools.ts +1336 -773
  213. package/src/truncate.ts +173 -0
  214. package/src/types.ts +219 -198
  215. package/src/update.ts +22 -32
  216. package/src/workflow.ts +523 -508
  217. package/tsconfig.json +22 -22
  218. package/vitest.config.ts +19 -19
  219. package/dist/ai-client.d.ts +0 -86
  220. package/dist/ai-client.d.ts.map +0 -1
  221. package/dist/ai-client.js +0 -1372
  222. package/dist/ai-client.js.map +0 -1
  223. package/dist/gui-subagent/operator/browser-operator.d.ts +0 -36
  224. package/dist/gui-subagent/operator/browser-operator.d.ts.map +0 -1
  225. package/dist/gui-subagent/operator/browser-operator.js +0 -306
  226. package/dist/gui-subagent/operator/browser-operator.js.map +0 -1
  227. package/dist/gui-subagent/operator/desktop-operator.d.ts +0 -55
  228. package/dist/gui-subagent/operator/desktop-operator.d.ts.map +0 -1
  229. package/dist/gui-subagent/operator/desktop-operator.js +0 -527
  230. package/dist/gui-subagent/operator/desktop-operator.js.map +0 -1
  231. package/dist/hook.d.ts +0 -73
  232. package/dist/hook.d.ts.map +0 -1
  233. package/dist/hook.js +0 -156
  234. package/dist/hook.js.map +0 -1
  235. package/dist/input-history.d.ts +0 -24
  236. package/dist/input-history.d.ts.map +0 -1
  237. package/dist/input-history.js +0 -94
  238. package/dist/input-history.js.map +0 -1
  239. package/dist/keyboard-manager.d.ts +0 -151
  240. package/dist/keyboard-manager.d.ts.map +0 -1
  241. package/dist/keyboard-manager.js +0 -396
  242. package/dist/keyboard-manager.js.map +0 -1
  243. package/dist/print-system-prompt.d.ts +0 -2
  244. package/dist/print-system-prompt.d.ts.map +0 -1
  245. package/dist/print-system-prompt.js +0 -40
  246. package/dist/print-system-prompt.js.map +0 -1
  247. package/dist/remote-ai-client.d.ts +0 -104
  248. package/dist/remote-ai-client.d.ts.map +0 -1
  249. package/dist/remote-ai-client.js +0 -552
  250. package/dist/remote-ai-client.js.map +0 -1
  251. package/dist/sdk-output-adapter.d.ts +0 -232
  252. package/dist/sdk-output-adapter.d.ts.map +0 -1
  253. package/dist/sdk-output-adapter.js +0 -636
  254. package/dist/sdk-output-adapter.js.map +0 -1
  255. package/dist/sdk-session-v2.d.ts +0 -13
  256. package/dist/sdk-session-v2.d.ts.map +0 -1
  257. package/dist/sdk-session-v2.js +0 -46
  258. package/dist/sdk-session-v2.js.map +0 -1
  259. package/dist/sdk-session.d.ts +0 -13
  260. package/dist/sdk-session.d.ts.map +0 -1
  261. package/dist/sdk-session.js +0 -48
  262. package/dist/sdk-session.js.map +0 -1
  263. package/dist/test-boundary-conditions.d.ts.map +0 -1
  264. package/dist/test-boundary-conditions.js.map +0 -1
  265. package/dist/test-cancellation-fix.d.ts.map +0 -1
  266. package/dist/test-cancellation-fix.js.map +0 -1
  267. package/dist/test-input-history.d.ts.map +0 -1
  268. package/dist/test-input-history.js.map +0 -1
  269. package/dist/test-interaction-flow.d.ts.map +0 -1
  270. package/dist/test-interaction-flow.js.map +0 -1
  271. package/dist/test-quick.d.ts.map +0 -1
  272. package/dist/test-quick.js.map +0 -1
  273. package/dist/test-user-interaction.d.ts.map +0 -1
  274. package/dist/test-user-interaction.js.map +0 -1
  275. package/dist/tools/edit-diff.d.ts +0 -32
  276. package/dist/tools/edit-diff.d.ts.map +0 -1
  277. package/dist/tools/edit-diff.js +0 -185
  278. package/dist/tools/edit-diff.js.map +0 -1
  279. package/dist/tools/edit.d.ts +0 -11
  280. package/dist/tools/edit.d.ts.map +0 -1
  281. package/dist/tools/edit.js +0 -129
  282. package/dist/tools/edit.js.map +0 -1
  283. package/dist/unified-session.d.ts +0 -42
  284. package/dist/unified-session.d.ts.map +0 -1
  285. package/dist/unified-session.js +0 -271
  286. package/dist/unified-session.js.map +0 -1
  287. package/skills/.claude-plugin/marketplace.json +0 -45
  288. package/skills/README.md +0 -94
  289. package/skills/THIRD_PARTY_NOTICES.md +0 -405
  290. package/skills/skills/algorithmic-art/LICENSE.txt +0 -202
  291. package/skills/skills/algorithmic-art/SKILL.md +0 -405
  292. package/skills/skills/algorithmic-art/templates/generator_template.js +0 -223
  293. package/skills/skills/algorithmic-art/templates/viewer.html +0 -599
  294. package/skills/skills/brand-guidelines/LICENSE.txt +0 -202
  295. package/skills/skills/brand-guidelines/SKILL.md +0 -73
  296. package/skills/skills/canvas-design/LICENSE.txt +0 -202
  297. package/skills/skills/canvas-design/SKILL.md +0 -130
  298. package/skills/skills/canvas-design/canvas-fonts/ArsenalSC-OFL.txt +0 -93
  299. package/skills/skills/canvas-design/canvas-fonts/ArsenalSC-Regular.ttf +0 -0
  300. package/skills/skills/canvas-design/canvas-fonts/BigShoulders-Bold.ttf +0 -0
  301. package/skills/skills/canvas-design/canvas-fonts/BigShoulders-OFL.txt +0 -93
  302. package/skills/skills/canvas-design/canvas-fonts/BigShoulders-Regular.ttf +0 -0
  303. package/skills/skills/canvas-design/canvas-fonts/Boldonse-OFL.txt +0 -93
  304. package/skills/skills/canvas-design/canvas-fonts/Boldonse-Regular.ttf +0 -0
  305. package/skills/skills/canvas-design/canvas-fonts/BricolageGrotesque-Bold.ttf +0 -0
  306. package/skills/skills/canvas-design/canvas-fonts/BricolageGrotesque-OFL.txt +0 -93
  307. package/skills/skills/canvas-design/canvas-fonts/BricolageGrotesque-Regular.ttf +0 -0
  308. package/skills/skills/canvas-design/canvas-fonts/CrimsonPro-Bold.ttf +0 -0
  309. package/skills/skills/canvas-design/canvas-fonts/CrimsonPro-Italic.ttf +0 -0
  310. package/skills/skills/canvas-design/canvas-fonts/CrimsonPro-OFL.txt +0 -93
  311. package/skills/skills/canvas-design/canvas-fonts/CrimsonPro-Regular.ttf +0 -0
  312. package/skills/skills/canvas-design/canvas-fonts/DMMono-OFL.txt +0 -93
  313. package/skills/skills/canvas-design/canvas-fonts/DMMono-Regular.ttf +0 -0
  314. package/skills/skills/canvas-design/canvas-fonts/EricaOne-OFL.txt +0 -94
  315. package/skills/skills/canvas-design/canvas-fonts/EricaOne-Regular.ttf +0 -0
  316. package/skills/skills/canvas-design/canvas-fonts/GeistMono-Bold.ttf +0 -0
  317. package/skills/skills/canvas-design/canvas-fonts/GeistMono-OFL.txt +0 -93
  318. package/skills/skills/canvas-design/canvas-fonts/GeistMono-Regular.ttf +0 -0
  319. package/skills/skills/canvas-design/canvas-fonts/Gloock-OFL.txt +0 -93
  320. package/skills/skills/canvas-design/canvas-fonts/Gloock-Regular.ttf +0 -0
  321. package/skills/skills/canvas-design/canvas-fonts/IBMPlexMono-Bold.ttf +0 -0
  322. package/skills/skills/canvas-design/canvas-fonts/IBMPlexMono-OFL.txt +0 -93
  323. package/skills/skills/canvas-design/canvas-fonts/IBMPlexMono-Regular.ttf +0 -0
  324. package/skills/skills/canvas-design/canvas-fonts/IBMPlexSerif-Bold.ttf +0 -0
  325. package/skills/skills/canvas-design/canvas-fonts/IBMPlexSerif-BoldItalic.ttf +0 -0
  326. package/skills/skills/canvas-design/canvas-fonts/IBMPlexSerif-Italic.ttf +0 -0
  327. package/skills/skills/canvas-design/canvas-fonts/IBMPlexSerif-Regular.ttf +0 -0
  328. package/skills/skills/canvas-design/canvas-fonts/InstrumentSans-Bold.ttf +0 -0
  329. package/skills/skills/canvas-design/canvas-fonts/InstrumentSans-BoldItalic.ttf +0 -0
  330. package/skills/skills/canvas-design/canvas-fonts/InstrumentSans-Italic.ttf +0 -0
  331. package/skills/skills/canvas-design/canvas-fonts/InstrumentSans-OFL.txt +0 -93
  332. package/skills/skills/canvas-design/canvas-fonts/InstrumentSans-Regular.ttf +0 -0
  333. package/skills/skills/canvas-design/canvas-fonts/InstrumentSerif-Italic.ttf +0 -0
  334. package/skills/skills/canvas-design/canvas-fonts/InstrumentSerif-Regular.ttf +0 -0
  335. package/skills/skills/canvas-design/canvas-fonts/Italiana-OFL.txt +0 -93
  336. package/skills/skills/canvas-design/canvas-fonts/Italiana-Regular.ttf +0 -0
  337. package/skills/skills/canvas-design/canvas-fonts/JetBrainsMono-Bold.ttf +0 -0
  338. package/skills/skills/canvas-design/canvas-fonts/JetBrainsMono-OFL.txt +0 -93
  339. package/skills/skills/canvas-design/canvas-fonts/JetBrainsMono-Regular.ttf +0 -0
  340. package/skills/skills/canvas-design/canvas-fonts/Jura-Light.ttf +0 -0
  341. package/skills/skills/canvas-design/canvas-fonts/Jura-Medium.ttf +0 -0
  342. package/skills/skills/canvas-design/canvas-fonts/Jura-OFL.txt +0 -93
  343. package/skills/skills/canvas-design/canvas-fonts/LibreBaskerville-OFL.txt +0 -93
  344. package/skills/skills/canvas-design/canvas-fonts/LibreBaskerville-Regular.ttf +0 -0
  345. package/skills/skills/canvas-design/canvas-fonts/Lora-Bold.ttf +0 -0
  346. package/skills/skills/canvas-design/canvas-fonts/Lora-BoldItalic.ttf +0 -0
  347. package/skills/skills/canvas-design/canvas-fonts/Lora-Italic.ttf +0 -0
  348. package/skills/skills/canvas-design/canvas-fonts/Lora-OFL.txt +0 -93
  349. package/skills/skills/canvas-design/canvas-fonts/Lora-Regular.ttf +0 -0
  350. package/skills/skills/canvas-design/canvas-fonts/NationalPark-Bold.ttf +0 -0
  351. package/skills/skills/canvas-design/canvas-fonts/NationalPark-OFL.txt +0 -93
  352. package/skills/skills/canvas-design/canvas-fonts/NationalPark-Regular.ttf +0 -0
  353. package/skills/skills/canvas-design/canvas-fonts/NothingYouCouldDo-OFL.txt +0 -93
  354. package/skills/skills/canvas-design/canvas-fonts/NothingYouCouldDo-Regular.ttf +0 -0
  355. package/skills/skills/canvas-design/canvas-fonts/Outfit-Bold.ttf +0 -0
  356. package/skills/skills/canvas-design/canvas-fonts/Outfit-OFL.txt +0 -93
  357. package/skills/skills/canvas-design/canvas-fonts/Outfit-Regular.ttf +0 -0
  358. package/skills/skills/canvas-design/canvas-fonts/PixelifySans-Medium.ttf +0 -0
  359. package/skills/skills/canvas-design/canvas-fonts/PixelifySans-OFL.txt +0 -93
  360. package/skills/skills/canvas-design/canvas-fonts/PoiretOne-OFL.txt +0 -93
  361. package/skills/skills/canvas-design/canvas-fonts/PoiretOne-Regular.ttf +0 -0
  362. package/skills/skills/canvas-design/canvas-fonts/RedHatMono-Bold.ttf +0 -0
  363. package/skills/skills/canvas-design/canvas-fonts/RedHatMono-OFL.txt +0 -93
  364. package/skills/skills/canvas-design/canvas-fonts/RedHatMono-Regular.ttf +0 -0
  365. package/skills/skills/canvas-design/canvas-fonts/Silkscreen-OFL.txt +0 -93
  366. package/skills/skills/canvas-design/canvas-fonts/Silkscreen-Regular.ttf +0 -0
  367. package/skills/skills/canvas-design/canvas-fonts/SmoochSans-Medium.ttf +0 -0
  368. package/skills/skills/canvas-design/canvas-fonts/SmoochSans-OFL.txt +0 -93
  369. package/skills/skills/canvas-design/canvas-fonts/Tektur-Medium.ttf +0 -0
  370. package/skills/skills/canvas-design/canvas-fonts/Tektur-OFL.txt +0 -93
  371. package/skills/skills/canvas-design/canvas-fonts/Tektur-Regular.ttf +0 -0
  372. package/skills/skills/canvas-design/canvas-fonts/WorkSans-Bold.ttf +0 -0
  373. package/skills/skills/canvas-design/canvas-fonts/WorkSans-BoldItalic.ttf +0 -0
  374. package/skills/skills/canvas-design/canvas-fonts/WorkSans-Italic.ttf +0 -0
  375. package/skills/skills/canvas-design/canvas-fonts/WorkSans-OFL.txt +0 -93
  376. package/skills/skills/canvas-design/canvas-fonts/WorkSans-Regular.ttf +0 -0
  377. package/skills/skills/canvas-design/canvas-fonts/YoungSerif-OFL.txt +0 -93
  378. package/skills/skills/canvas-design/canvas-fonts/YoungSerif-Regular.ttf +0 -0
  379. package/skills/skills/doc-coauthoring/SKILL.md +0 -375
  380. package/skills/skills/docx/LICENSE.txt +0 -30
  381. package/skills/skills/docx/SKILL.md +0 -197
  382. package/skills/skills/docx/docx-js.md +0 -350
  383. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -1499
  384. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -146
  385. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -1085
  386. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -11
  387. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -3081
  388. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -23
  389. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -185
  390. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -287
  391. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -1676
  392. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -28
  393. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -144
  394. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -174
  395. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -25
  396. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -18
  397. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -59
  398. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -56
  399. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -195
  400. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -582
  401. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -25
  402. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -4439
  403. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -570
  404. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -509
  405. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -12
  406. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -108
  407. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -96
  408. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -3646
  409. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -116
  410. package/skills/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -42
  411. package/skills/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -50
  412. package/skills/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -49
  413. package/skills/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -33
  414. package/skills/skills/docx/ooxml/schemas/mce/mc.xsd +0 -75
  415. package/skills/skills/docx/ooxml/schemas/microsoft/wml-2010.xsd +0 -560
  416. package/skills/skills/docx/ooxml/schemas/microsoft/wml-2012.xsd +0 -67
  417. package/skills/skills/docx/ooxml/schemas/microsoft/wml-2018.xsd +0 -14
  418. package/skills/skills/docx/ooxml/schemas/microsoft/wml-cex-2018.xsd +0 -20
  419. package/skills/skills/docx/ooxml/schemas/microsoft/wml-cid-2016.xsd +0 -13
  420. package/skills/skills/docx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -4
  421. package/skills/skills/docx/ooxml/schemas/microsoft/wml-symex-2015.xsd +0 -8
  422. package/skills/skills/docx/ooxml/scripts/pack.py +0 -159
  423. package/skills/skills/docx/ooxml/scripts/unpack.py +0 -29
  424. package/skills/skills/docx/ooxml/scripts/validate.py +0 -69
  425. package/skills/skills/docx/ooxml/scripts/validation/__init__.py +0 -15
  426. package/skills/skills/docx/ooxml/scripts/validation/base.py +0 -951
  427. package/skills/skills/docx/ooxml/scripts/validation/docx.py +0 -274
  428. package/skills/skills/docx/ooxml/scripts/validation/pptx.py +0 -315
  429. package/skills/skills/docx/ooxml/scripts/validation/redlining.py +0 -279
  430. package/skills/skills/docx/ooxml.md +0 -610
  431. package/skills/skills/docx/scripts/__init__.py +0 -1
  432. package/skills/skills/docx/scripts/document.py +0 -1276
  433. package/skills/skills/docx/scripts/templates/comments.xml +0 -3
  434. package/skills/skills/docx/scripts/templates/commentsExtended.xml +0 -3
  435. package/skills/skills/docx/scripts/templates/commentsExtensible.xml +0 -3
  436. package/skills/skills/docx/scripts/templates/commentsIds.xml +0 -3
  437. package/skills/skills/docx/scripts/templates/people.xml +0 -3
  438. package/skills/skills/docx/scripts/utilities.py +0 -374
  439. package/skills/skills/frontend-design/LICENSE.txt +0 -177
  440. package/skills/skills/frontend-design/SKILL.md +0 -42
  441. package/skills/skills/internal-comms/LICENSE.txt +0 -202
  442. package/skills/skills/internal-comms/SKILL.md +0 -32
  443. package/skills/skills/internal-comms/examples/3p-updates.md +0 -47
  444. package/skills/skills/internal-comms/examples/company-newsletter.md +0 -65
  445. package/skills/skills/internal-comms/examples/faq-answers.md +0 -30
  446. package/skills/skills/internal-comms/examples/general-comms.md +0 -16
  447. package/skills/skills/mcp-builder/LICENSE.txt +0 -202
  448. package/skills/skills/mcp-builder/SKILL.md +0 -236
  449. package/skills/skills/mcp-builder/reference/evaluation.md +0 -602
  450. package/skills/skills/mcp-builder/reference/mcp_best_practices.md +0 -249
  451. package/skills/skills/mcp-builder/reference/node_mcp_server.md +0 -970
  452. package/skills/skills/mcp-builder/reference/python_mcp_server.md +0 -719
  453. package/skills/skills/mcp-builder/scripts/connections.py +0 -151
  454. package/skills/skills/mcp-builder/scripts/evaluation.py +0 -373
  455. package/skills/skills/mcp-builder/scripts/example_evaluation.xml +0 -22
  456. package/skills/skills/mcp-builder/scripts/requirements.txt +0 -2
  457. package/skills/skills/pdf/LICENSE.txt +0 -30
  458. package/skills/skills/pdf/SKILL.md +0 -294
  459. package/skills/skills/pdf/forms.md +0 -205
  460. package/skills/skills/pdf/reference.md +0 -612
  461. package/skills/skills/pdf/scripts/check_bounding_boxes.py +0 -70
  462. package/skills/skills/pdf/scripts/check_bounding_boxes_test.py +0 -226
  463. package/skills/skills/pdf/scripts/check_fillable_fields.py +0 -12
  464. package/skills/skills/pdf/scripts/convert_pdf_to_images.py +0 -35
  465. package/skills/skills/pdf/scripts/create_validation_image.py +0 -41
  466. package/skills/skills/pdf/scripts/extract_form_field_info.py +0 -152
  467. package/skills/skills/pdf/scripts/fill_fillable_fields.py +0 -114
  468. package/skills/skills/pdf/scripts/fill_pdf_form_with_annotations.py +0 -108
  469. package/skills/skills/pptx/LICENSE.txt +0 -30
  470. package/skills/skills/pptx/SKILL.md +0 -484
  471. package/skills/skills/pptx/html2pptx.md +0 -625
  472. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -1499
  473. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -146
  474. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -1085
  475. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -11
  476. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -3081
  477. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -23
  478. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -185
  479. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -287
  480. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -1676
  481. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -28
  482. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -144
  483. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -174
  484. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -25
  485. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -18
  486. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -59
  487. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -56
  488. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -195
  489. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -582
  490. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -25
  491. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -4439
  492. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -570
  493. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -509
  494. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -12
  495. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -108
  496. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -96
  497. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -3646
  498. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -116
  499. package/skills/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -42
  500. package/skills/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -50
  501. package/skills/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -49
  502. package/skills/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -33
  503. package/skills/skills/pptx/ooxml/schemas/mce/mc.xsd +0 -75
  504. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-2010.xsd +0 -560
  505. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-2012.xsd +0 -67
  506. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-2018.xsd +0 -14
  507. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-cex-2018.xsd +0 -20
  508. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-cid-2016.xsd +0 -13
  509. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -4
  510. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-symex-2015.xsd +0 -8
  511. package/skills/skills/pptx/ooxml/scripts/pack.py +0 -159
  512. package/skills/skills/pptx/ooxml/scripts/unpack.py +0 -29
  513. package/skills/skills/pptx/ooxml/scripts/validate.py +0 -69
  514. package/skills/skills/pptx/ooxml/scripts/validation/__init__.py +0 -15
  515. package/skills/skills/pptx/ooxml/scripts/validation/base.py +0 -951
  516. package/skills/skills/pptx/ooxml/scripts/validation/docx.py +0 -274
  517. package/skills/skills/pptx/ooxml/scripts/validation/pptx.py +0 -315
  518. package/skills/skills/pptx/ooxml/scripts/validation/redlining.py +0 -279
  519. package/skills/skills/pptx/ooxml.md +0 -427
  520. package/skills/skills/pptx/scripts/html2pptx.js +0 -979
  521. package/skills/skills/pptx/scripts/inventory.py +0 -1020
  522. package/skills/skills/pptx/scripts/rearrange.py +0 -231
  523. package/skills/skills/pptx/scripts/replace.py +0 -385
  524. package/skills/skills/pptx/scripts/thumbnail.py +0 -450
  525. package/skills/skills/skill-creator/LICENSE.txt +0 -202
  526. package/skills/skills/skill-creator/SKILL.md +0 -356
  527. package/skills/skills/skill-creator/references/output-patterns.md +0 -82
  528. package/skills/skills/skill-creator/references/workflows.md +0 -28
  529. package/skills/skills/skill-creator/scripts/init_skill.py +0 -303
  530. package/skills/skills/skill-creator/scripts/package_skill.py +0 -110
  531. package/skills/skills/skill-creator/scripts/quick_validate.py +0 -95
  532. package/skills/skills/slack-gif-creator/LICENSE.txt +0 -202
  533. package/skills/skills/slack-gif-creator/SKILL.md +0 -254
  534. package/skills/skills/slack-gif-creator/core/easing.py +0 -234
  535. package/skills/skills/slack-gif-creator/core/frame_composer.py +0 -176
  536. package/skills/skills/slack-gif-creator/core/gif_builder.py +0 -269
  537. package/skills/skills/slack-gif-creator/core/validators.py +0 -136
  538. package/skills/skills/slack-gif-creator/requirements.txt +0 -4
  539. package/skills/skills/theme-factory/LICENSE.txt +0 -202
  540. package/skills/skills/theme-factory/SKILL.md +0 -59
  541. package/skills/skills/theme-factory/theme-showcase.pdf +0 -0
  542. package/skills/skills/theme-factory/themes/arctic-frost.md +0 -19
  543. package/skills/skills/theme-factory/themes/botanical-garden.md +0 -19
  544. package/skills/skills/theme-factory/themes/desert-rose.md +0 -19
  545. package/skills/skills/theme-factory/themes/forest-canopy.md +0 -19
  546. package/skills/skills/theme-factory/themes/golden-hour.md +0 -19
  547. package/skills/skills/theme-factory/themes/midnight-galaxy.md +0 -19
  548. package/skills/skills/theme-factory/themes/modern-minimalist.md +0 -19
  549. package/skills/skills/theme-factory/themes/ocean-depths.md +0 -19
  550. package/skills/skills/theme-factory/themes/sunset-boulevard.md +0 -19
  551. package/skills/skills/theme-factory/themes/tech-innovation.md +0 -19
  552. package/skills/skills/web-artifacts-builder/LICENSE.txt +0 -202
  553. package/skills/skills/web-artifacts-builder/SKILL.md +0 -74
  554. package/skills/skills/web-artifacts-builder/scripts/bundle-artifact.sh +0 -54
  555. package/skills/skills/web-artifacts-builder/scripts/init-artifact.sh +0 -322
  556. package/skills/skills/webapp-testing/LICENSE.txt +0 -202
  557. package/skills/skills/webapp-testing/SKILL.md +0 -96
  558. package/skills/skills/webapp-testing/examples/console_logging.py +0 -35
  559. package/skills/skills/webapp-testing/examples/element_discovery.py +0 -40
  560. package/skills/skills/webapp-testing/examples/static_html_automation.py +0 -33
  561. package/skills/skills/webapp-testing/scripts/with_server.py +0 -106
  562. package/skills/skills/xlsx/LICENSE.txt +0 -30
  563. package/skills/skills/xlsx/SKILL.md +0 -289
  564. package/skills/skills/xlsx/recalc.py +0 -178
  565. package/skills/spec/agent-skills-spec.md +0 -3
  566. package/skills/template/SKILL.md +0 -6
  567. package/src/ai-client.ts +0 -1560
  568. package/src/remote-ai-client.ts +0 -664
@@ -1,9 +1,10 @@
1
- import inquirer from 'inquirer';
1
+ import { select, confirm, text } from '@clack/prompts';
2
2
  import chalk from 'chalk';
3
3
  import ora from 'ora';
4
4
  import fs from 'fs/promises';
5
5
  import path from 'path';
6
6
  import { ExecutionMode, AuthType } from './types.js';
7
+ import { fetchDefaultModels } from './ai-client/providers/remote.js';
7
8
  import { getToolRegistry } from './tools.js';
8
9
  import { getAgentManager } from './agents.js';
9
10
  import { getMemoryManager } from './memory.js';
@@ -11,10 +12,11 @@ import { getMCPManager } from './mcp.js';
11
12
  import { getCheckpointManager } from './checkpoint.js';
12
13
  import { getConfigManager } from './config.js';
13
14
  import { getLogger } from './logger.js';
14
- import { getContextCompressor } from './context-compressor.js';
15
+ import { getContextCompressor, } from './context-compressor.js';
15
16
  import { getConversationManager } from './conversation.js';
16
17
  import { icons, colors } from './theme.js';
17
- import { AuthService } from './auth.js';
18
+ import { ensureTtySane } from './terminal.js';
19
+ import { AuthService, selectAuthType, THIRD_PARTY_PROVIDERS, VLM_PROVIDERS } from './auth.js';
18
20
  const logger = getLogger();
19
21
  export class SlashCommandHandler {
20
22
  configManager;
@@ -27,6 +29,8 @@ export class SlashCommandHandler {
27
29
  conversationHistory = [];
28
30
  onClearCallback = null;
29
31
  onSystemPromptUpdate = null;
32
+ onConfigUpdate = null;
33
+ remoteAIClient = null; // Reference to InteractiveSession's remoteAIClient
30
34
  constructor() {
31
35
  this.configManager = getConfigManager(process.cwd());
32
36
  this.agentManager = getAgentManager(process.cwd());
@@ -36,6 +40,12 @@ export class SlashCommandHandler {
36
40
  this.contextCompressor = getContextCompressor();
37
41
  this.conversationManager = getConversationManager();
38
42
  }
43
+ /**
44
+ * Set remote AI client reference (called from InteractiveSession)
45
+ */
46
+ setRemoteAIClient(client) {
47
+ this.remoteAIClient = client;
48
+ }
39
49
  /**
40
50
  * Set callback for clearing conversation
41
51
  */
@@ -48,6 +58,12 @@ export class SlashCommandHandler {
48
58
  setSystemPromptUpdateCallback(callback) {
49
59
  this.onSystemPromptUpdate = callback;
50
60
  }
61
+ /**
62
+ * Set callback for config update (called after /auth changes config)
63
+ */
64
+ setConfigUpdateCallback(callback) {
65
+ this.onConfigUpdate = callback;
66
+ }
51
67
  /**
52
68
  * Set current conversation history (includes all user/assistant/tool messages)
53
69
  */
@@ -91,8 +107,11 @@ export class SlashCommandHandler {
91
107
  case 'mcp':
92
108
  await this.handleMcp(args);
93
109
  break;
94
- case 'vlm':
95
- await this.handleVlm();
110
+ case 'skill':
111
+ await this.handleSkill(args);
112
+ break;
113
+ case 'model':
114
+ await this.handleModel();
96
115
  break;
97
116
  case 'memory':
98
117
  await this.handleMemory(args);
@@ -118,9 +137,14 @@ export class SlashCommandHandler {
118
137
  case 'compress':
119
138
  await this.handleCompress(args);
120
139
  break;
140
+ case 'update':
141
+ await this.handleUpdate();
142
+ break;
121
143
  default:
122
144
  logger.warn(`Unknown command: /${command}`, 'Type /help for available commands');
123
145
  }
146
+ // Ensure stdin is in raw mode for proper input handling after @clack/prompts usage
147
+ ensureTtySane();
124
148
  return true;
125
149
  }
126
150
  async showHelp() {
@@ -128,7 +152,10 @@ export class SlashCommandHandler {
128
152
  console.log('');
129
153
  console.log(colors.primaryBright('╔════════════════════════════════════════════════════════════╗'));
130
154
  console.log(colors.primaryBright('║') + ' '.repeat(56) + colors.primaryBright('║'));
131
- console.log(' '.repeat(14) + colors.gradient('📚 XAGENT CLI Help') + ' '.repeat(31) + colors.primaryBright('║'));
155
+ console.log(' '.repeat(14) +
156
+ colors.gradient('📚 XAGENT CLI Help') +
157
+ ' '.repeat(31) +
158
+ colors.primaryBright('║'));
132
159
  console.log(colors.primaryBright('║') + ' '.repeat(56) + colors.primaryBright('║'));
133
160
  console.log(colors.primaryBright('╚════════════════════════════════════════════════════════════╝'));
134
161
  console.log('');
@@ -146,20 +173,20 @@ export class SlashCommandHandler {
146
173
  cmd: '/help [command]',
147
174
  desc: 'Show help information',
148
175
  detail: 'View all available commands or detailed description of specific command',
149
- example: '/help\n/help mode'
176
+ example: '/help\n/help mode',
150
177
  },
151
178
  {
152
179
  cmd: '/clear',
153
180
  desc: 'Clear conversation history',
154
181
  detail: 'Clear all conversation records of current session, start new conversation',
155
- example: '/clear'
182
+ example: '/clear',
156
183
  },
157
184
  {
158
185
  cmd: '/exit',
159
186
  desc: 'Exit program',
160
187
  detail: 'Safely exit XAGENT CLI',
161
- example: '/exit'
162
- }
188
+ example: '/exit',
189
+ },
163
190
  ]);
164
191
  // Project Management
165
192
  this.showHelpCategory('Project Management', [
@@ -167,14 +194,14 @@ export class SlashCommandHandler {
167
194
  cmd: '/init',
168
195
  desc: 'Initialize project context',
169
196
  detail: 'Create XAGENT.md file in current directory, used to store project context information',
170
- example: '/init'
197
+ example: '/init',
171
198
  },
172
199
  {
173
200
  cmd: '/memory [show|clear]',
174
201
  desc: 'Manage project memory',
175
202
  detail: 'View or clear memory (global, current, all, or filename)',
176
- example: '/memory show\n/memory clear\n/memory clear global\n/memory clear all'
177
- }
203
+ example: '/memory show\n/memory clear\n/memory clear global\n/memory clear all',
204
+ },
178
205
  ]);
179
206
  // Authentication & Configuration
180
207
  this.showHelpCategory('Authentication & Configuration', [
@@ -182,7 +209,7 @@ export class SlashCommandHandler {
182
209
  cmd: '/auth',
183
210
  desc: 'Configure authentication information',
184
211
  detail: 'Change or view current authentication configuration',
185
- example: '/auth'
212
+ example: '/auth',
186
213
  },
187
214
  {
188
215
  cmd: '/mode [mode]',
@@ -194,14 +221,14 @@ export class SlashCommandHandler {
194
221
  'accept_edits - Automatically accept edit operations',
195
222
  'plan - Plan before executing',
196
223
  'default - Safe execution, requires confirmation',
197
- 'smart - Smart approval (recommended)'
198
- ]
224
+ 'smart - Smart approval (recommended)',
225
+ ],
199
226
  },
200
227
  {
201
228
  cmd: '/think [on|off|display]',
202
229
  desc: 'Control thinking mode',
203
230
  detail: 'Enable/disable AI thinking process display',
204
- example: '/think on\n/think off\n/think display compact'
231
+ example: '/think on\n/think off\n/think display compact',
205
232
  },
206
233
  // {
207
234
  // cmd: '/language [zh|en]',
@@ -213,8 +240,8 @@ export class SlashCommandHandler {
213
240
  cmd: '/theme',
214
241
  desc: 'Switch theme',
215
242
  detail: 'Change UI theme style',
216
- example: '/theme'
217
- }
243
+ example: '/theme',
244
+ },
218
245
  ]);
219
246
  // Feature Extensions
220
247
  this.showHelpCategory('Feature Extensions', [
@@ -222,13 +249,19 @@ export class SlashCommandHandler {
222
249
  cmd: '/agents [list|online|install|remove]',
223
250
  desc: 'Manage sub-agents',
224
251
  detail: 'View, install or remove specialized AI sub-agents',
225
- example: '/agents list\n/agents online\n/agents install explore-agent'
252
+ example: '/agents list\n/agents online\n/agents install explore-agent',
226
253
  },
227
254
  {
228
255
  cmd: '/mcp [list|add|remove|refresh]',
229
256
  desc: 'Manage MCP servers',
230
257
  detail: 'Manage Model Context Protocol servers',
231
- example: '/mcp list\n/mcp add server-name'
258
+ example: '/mcp list\n/mcp add server-name',
259
+ },
260
+ {
261
+ cmd: '/skill [list|add|remove]',
262
+ desc: 'Manage skills',
263
+ detail: 'Install, list, or remove skills from ~/.xagent/skills',
264
+ example: '/skill list\n/skill add ./my-skill\n/skill add owner/repo\n/skill remove my-skill'
232
265
  },
233
266
  {
234
267
  cmd: '/vlm',
@@ -236,12 +269,18 @@ export class SlashCommandHandler {
236
269
  detail: 'Configure Vision-Language Model for browser/desktop automation',
237
270
  example: '/vlm'
238
271
  },
272
+ {
273
+ cmd: '/model',
274
+ desc: 'Configure LLM/VLM models',
275
+ detail: 'Configure or switch LLM and VLM models for remote mode',
276
+ example: '/model',
277
+ },
239
278
  {
240
279
  cmd: '/tools [verbose|simple]',
241
280
  desc: 'Manage tool display',
242
281
  detail: 'View available tools or switch tool call display mode',
243
- example: '/tools\n/tools verbose\n/tools simple'
244
- }
282
+ example: '/tools\n/tools verbose\n/tools simple',
283
+ },
245
284
  ]);
246
285
  // Advanced Features
247
286
  this.showHelpCategory('Advanced Features', [
@@ -249,26 +288,32 @@ export class SlashCommandHandler {
249
288
  cmd: '/restore',
250
289
  desc: 'Restore from checkpoint',
251
290
  detail: 'Restore conversation state from historical checkpoints',
252
- example: '/restore'
291
+ example: '/restore',
253
292
  },
254
293
  {
255
294
  cmd: '/compress [on|off|max_message|max_token|exec]',
256
295
  desc: 'Manage context compression',
257
296
  detail: 'Configure compression settings or execute compression manually',
258
- example: '/compress\n/compress exec\n/compress on\n/compress max_message 50\n/compress max_token 1500000'
297
+ example: '/compress\n/compress exec\n/compress on\n/compress max_message 50\n/compress max_token 1500000',
259
298
  },
260
299
  {
261
300
  cmd: '/stats',
262
301
  desc: 'Show session statistics',
263
302
  detail: 'View statistics information of current session',
264
- example: '/stats'
303
+ example: '/stats',
265
304
  },
266
305
  {
267
306
  cmd: '/about',
268
307
  desc: 'Show version information',
269
308
  detail: 'View version and related information of XAGENT CLI',
270
- example: '/about'
271
- }
309
+ example: '/about',
310
+ },
311
+ {
312
+ cmd: '/update',
313
+ desc: 'Check for updates',
314
+ detail: 'Check for new versions and update xAgent CLI',
315
+ example: '/update',
316
+ },
272
317
  ]);
273
318
  // Keyboard Shortcuts
274
319
  console.log('');
@@ -287,18 +332,18 @@ export class SlashCommandHandler {
287
332
  console.log(colors.primaryBright(title));
288
333
  console.log(colors.border(separator));
289
334
  console.log('');
290
- commands.forEach(cmd => {
335
+ commands.forEach((cmd) => {
291
336
  console.log(colors.primaryBright(` ${cmd.cmd}`));
292
337
  console.log(colors.textDim(` ${cmd.desc}`));
293
338
  console.log(colors.textMuted(` ${cmd.detail}`));
294
339
  if (cmd.modes) {
295
340
  console.log(colors.textDim(` Available modes:`));
296
- cmd.modes.forEach(mode => {
341
+ cmd.modes.forEach((mode) => {
297
342
  console.log(colors.textDim(` • ${mode}`));
298
343
  });
299
344
  }
300
345
  console.log(colors.accent(` Examples:`));
301
- cmd.example.split('\n').forEach(ex => {
346
+ cmd.example.split('\n').forEach((ex) => {
302
347
  console.log(colors.codeText(` ${ex}`));
303
348
  });
304
349
  console.log('');
@@ -317,9 +362,9 @@ export class SlashCommandHandler {
317
362
  async handleClear() {
318
363
  // Clear local conversation history
319
364
  this.conversationHistory = [];
320
- // Clear ConversationManager 中的当前对话
365
+ // Clear current conversation in ConversationManager
321
366
  await this.conversationManager.clearCurrentConversation();
322
- // Call callback to notify InteractiveSession 清空对话
367
+ // Call callback to notify InteractiveSession to clear conversation
323
368
  if (this.onClearCallback) {
324
369
  this.onClearCallback();
325
370
  }
@@ -331,37 +376,131 @@ export class SlashCommandHandler {
331
376
  }
332
377
  async handleAuth() {
333
378
  logger.section('Authentication Management');
334
- const { action } = await inquirer.prompt([
335
- {
336
- type: 'list',
337
- name: 'action',
338
- message: 'Select action:',
339
- choices: [
340
- { name: 'Change authentication method', value: 'change' },
341
- { name: 'Show current auth config', value: 'show' },
342
- { name: 'Back', value: 'back' }
343
- ]
344
- }
345
- ]);
379
+ // Show current authentication configuration
380
+ const authConfig = this.configManager.getAuthConfig();
381
+ const isRemote = authConfig.type === AuthType.OAUTH_XAGENT;
382
+ const currentType = isRemote ? 'xAgent (Remote)' : 'Third-party API (Local)';
383
+ console.log(chalk.cyan('\n📋 Current Authentication Configuration:\n'));
384
+ console.log(` ${chalk.yellow('Mode:')} ${currentType}`);
385
+ if (isRemote) {
386
+ // Remote mode: show remote_llmModelName and remote_vlmModelName
387
+ const llmModel = authConfig.remote_llmModelName || 'Not set';
388
+ const vlmModel = authConfig.remote_vlmModelName || 'Not set';
389
+ console.log(` ${chalk.yellow('LLM Model:')} ${llmModel}`);
390
+ console.log(` ${chalk.yellow('VLM Model:')} ${vlmModel}`);
391
+ }
392
+ else {
393
+ // Local mode: show modelName (LLM) and guiSubagentModel (VLM)
394
+ const llmModel = authConfig.modelName || 'Not set';
395
+ const vlmModel = this.configManager.get('guiSubagentModel') || 'Not set';
396
+ console.log(` ${chalk.yellow('LLM Model:')} ${llmModel}`);
397
+ console.log(` ${chalk.yellow('VLM Model:')} ${vlmModel}`);
398
+ }
399
+ console.log('');
400
+ const action = await select({
401
+ message: 'Select action:',
402
+ options: [
403
+ { value: 'switch', label: 'Switch authentication method' },
404
+ { value: 'back', label: 'Back' },
405
+ ],
406
+ });
346
407
  if (action === 'back') {
347
408
  return;
348
409
  }
349
- if (action === 'show') {
350
- const authConfig = this.configManager.getAuthConfig();
351
- logger.subsection('Current Authentication Configuration');
352
- console.log(JSON.stringify(authConfig, null, 2));
353
- }
354
- else if (action === 'change') {
355
- const { selectAuthType } = await inquirer.prompt([
356
- {
357
- type: 'confirm',
358
- name: 'selectAuthType',
359
- message: 'Do you want to change authentication type?',
360
- default: false
410
+ if (action === 'switch') {
411
+ // Use the same selection UI as initial setup
412
+ const confirmSwitch = await confirm({
413
+ message: `Switch from "${currentType}" to another authentication method?`,
414
+ });
415
+ if (confirmSwitch === false || confirmSwitch === undefined) {
416
+ return;
417
+ }
418
+ // Select authentication type (same as initial setup)
419
+ const authType = await selectAuthType();
420
+ if (authType === AuthType.OAUTH_XAGENT) {
421
+ // Switch to xAgent (Remote mode)
422
+ const authService = new AuthService({
423
+ type: AuthType.OAUTH_XAGENT,
424
+ apiKey: '',
425
+ baseUrl: '',
426
+ xagentApiBaseUrl: authConfig.xagentApiBaseUrl,
427
+ });
428
+ const success = await authService.authenticate();
429
+ if (success) {
430
+ const newAuthConfig = authService.getAuthConfig();
431
+ this.configManager.setAuthConfig({
432
+ selectedAuthType: newAuthConfig.type,
433
+ apiKey: newAuthConfig.apiKey,
434
+ refreshToken: newAuthConfig.refreshToken,
435
+ baseUrl: newAuthConfig.baseUrl,
436
+ modelName: '',
437
+ xagentApiBaseUrl: newAuthConfig.xagentApiBaseUrl,
438
+ guiSubagentModel: '',
439
+ guiSubagentBaseUrl: 'https://www.xagent-colife.net/v3',
440
+ guiSubagentApiKey: '',
441
+ });
442
+ // Set default remote model settings if not already set
443
+ // Fetch default models from /models/default endpoint
444
+ const webBaseUrl = newAuthConfig.xagentApiBaseUrl || 'https://www.xagent-colife.net';
445
+ let defaultLlmName = '';
446
+ let defaultVlmName = '';
447
+ try {
448
+ console.log(chalk.cyan('\n📊 Fetching default models from remote server...'));
449
+ const defaults = await fetchDefaultModels(newAuthConfig.apiKey || '', webBaseUrl);
450
+ if (defaults.llm?.name) {
451
+ defaultLlmName = defaults.llm.name;
452
+ console.log(chalk.cyan(` LLM Model: ${defaults.llm.name}`));
453
+ }
454
+ if (defaults.vlm?.name) {
455
+ defaultVlmName = defaults.vlm.name;
456
+ console.log(chalk.cyan(` VLM Model: ${defaults.vlm.name}`));
457
+ }
458
+ }
459
+ catch (error) {
460
+ console.log(chalk.yellow(` ⚠️ Failed to fetch default models: ${error.message}`));
461
+ console.log(chalk.yellow(' ⚠️ Use /model command to select models manually.'));
462
+ }
463
+ console.log('');
464
+ this.configManager.set('remote_llmModelName', defaultLlmName);
465
+ this.configManager.set('remote_vlmModelName', defaultVlmName);
466
+ this.configManager.save('global');
467
+ // Notify InteractiveSession to update aiClient config
468
+ if (this.onConfigUpdate) {
469
+ this.onConfigUpdate();
470
+ }
471
+ console.log(chalk.green('\n✅ Authentication switched to xAgent (Remote mode)!'));
472
+ // Removed: logging partial token for security
473
+ }
474
+ }
475
+ else {
476
+ // Switch to Third-party API (Local mode)
477
+ const authService = new AuthService({
478
+ type: AuthType.OPENAI_COMPATIBLE,
479
+ apiKey: '',
480
+ baseUrl: '',
481
+ modelName: '',
482
+ });
483
+ const success = await authService.authenticate();
484
+ if (success) {
485
+ const newAuthConfig = authService.getAuthConfig();
486
+ this.configManager.setAuthConfig({
487
+ selectedAuthType: newAuthConfig.type,
488
+ apiKey: newAuthConfig.apiKey,
489
+ baseUrl: newAuthConfig.baseUrl,
490
+ modelName: newAuthConfig.modelName,
491
+ xagentApiBaseUrl: '',
492
+ refreshToken: '',
493
+ guiSubagentModel: '',
494
+ guiSubagentBaseUrl: '',
495
+ guiSubagentApiKey: '',
496
+ });
497
+ this.configManager.save('global');
498
+ // Notify InteractiveSession to update aiClient config
499
+ if (this.onConfigUpdate) {
500
+ this.onConfigUpdate();
501
+ }
502
+ console.log(chalk.green('\n✅ Authentication switched to Third-party API (Local mode)!'));
361
503
  }
362
- ]);
363
- if (selectAuthType) {
364
- logger.warn('Please restart xAgent CLI and run /auth again', 'Authentication changes require restart');
365
504
  }
366
505
  }
367
506
  }
@@ -371,35 +510,33 @@ export class SlashCommandHandler {
371
510
  const currentAuthType = authConfig.type;
372
511
  if (currentAuthType !== AuthType.OAUTH_XAGENT) {
373
512
  console.log(chalk.yellow('\n⚠️ Current authentication type is not OAuth xAgent.'));
374
- const { proceed } = await inquirer.prompt([
375
- {
376
- type: 'confirm',
377
- name: 'proceed',
378
- message: 'Do you want to switch to OAuth xAgent authentication?',
379
- default: false
380
- }
381
- ]);
382
- if (!proceed) {
513
+ const proceed = await confirm({
514
+ message: 'Do you want to switch to OAuth xAgent authentication?',
515
+ });
516
+ if (proceed === false || proceed === undefined) {
383
517
  return;
384
518
  }
385
519
  // Switch to OAuth xAgent
386
- await this.configManager.setAuthConfig({
520
+ this.configManager.setAuthConfig({
387
521
  selectedAuthType: AuthType.OAUTH_XAGENT,
388
522
  apiKey: '',
389
523
  refreshToken: '',
390
- baseUrl: ''
524
+ baseUrl: '',
391
525
  });
392
- await this.configManager.save('global');
526
+ this.configManager.save('global');
393
527
  console.log(chalk.green('✅ Switched to OAuth xAgent authentication.'));
394
528
  }
395
529
  console.log(chalk.cyan('\n🔐 Starting OAuth xAgent login...'));
396
530
  console.log(chalk.gray(' A browser will open for you to complete authentication.\n'));
397
531
  try {
532
+ // Get xagentApiBaseUrl from config (respects XAGENT_BASE_URL env var)
533
+ const config = this.configManager.getAuthConfig();
398
534
  const authService = new AuthService({
399
535
  type: AuthType.OAUTH_XAGENT,
400
536
  apiKey: '',
401
537
  baseUrl: '',
402
- refreshToken: ''
538
+ refreshToken: '',
539
+ xagentApiBaseUrl: config.xagentApiBaseUrl,
403
540
  });
404
541
  const success = await authService.authenticate();
405
542
  if (success) {
@@ -416,75 +553,320 @@ export class SlashCommandHandler {
416
553
  console.log(chalk.red(`\n❌ Login error: ${error.message || 'Unknown error'}`));
417
554
  }
418
555
  }
419
- async handleVlm() {
420
- logger.section('VLM Configuration for GUI Agent');
421
- // Show current VLM config
422
- const currentVlmConfig = {
423
- model: this.configManager.get('guiSubagentModel'),
424
- baseUrl: this.configManager.get('guiSubagentBaseUrl'),
425
- apiKey: this.configManager.get('guiSubagentApiKey') ? '***' : ''
426
- };
427
- console.log(chalk.cyan('\n📊 Current VLM Configuration:\n'));
428
- console.log(` Model: ${chalk.yellow(currentVlmConfig.model || 'Not configured')}`);
429
- console.log(` Base URL: ${chalk.yellow(currentVlmConfig.baseUrl || 'Not configured')}`);
430
- console.log(` API Key: ${chalk.yellow(currentVlmConfig.apiKey || 'Not configured')}`);
431
- console.log();
432
- const { action } = await inquirer.prompt([
433
- {
434
- type: 'list',
435
- name: 'action',
436
- message: 'Select action:',
437
- choices: [
438
- { name: 'Configure VLM', value: 'configure' },
439
- { name: 'Remove VLM configuration', value: 'remove' },
440
- { name: 'Back', value: 'back' }
441
- ]
442
- }
443
- ]);
444
- if (action === 'back') {
445
- return;
556
+ /**
557
+ * Handle /model command - Configure LLM/VLM models
558
+ * Supports both remote mode (xAgent) and local mode (third-party API)
559
+ */
560
+ async handleModel() {
561
+ const authConfig = this.configManager.getAuthConfig();
562
+ // Determine mode and show appropriate UI
563
+ if (authConfig.type === AuthType.OAUTH_XAGENT) {
564
+ // Remote mode - use backend models
565
+ await this.handleRemoteModel();
566
+ }
567
+ else {
568
+ // Local mode - configure third-party API directly
569
+ await this.handleLocalModel();
446
570
  }
447
- if (action === 'remove') {
448
- const { confirm } = await inquirer.prompt([
449
- {
450
- type: 'confirm',
451
- name: 'confirm',
452
- message: 'Are you sure you want to remove VLM configuration?',
453
- default: false
571
+ }
572
+ /**
573
+ * Handle /model command for remote mode - Configure models from backend
574
+ */
575
+ async handleRemoteModel() {
576
+ const authConfig = this.configManager.getAuthConfig();
577
+ // Auto-fetch default models if not set
578
+ let currentLlm = authConfig.remote_llmModelName;
579
+ let currentVlm = authConfig.remote_vlmModelName;
580
+ if (!currentLlm || !currentVlm) {
581
+ console.log(chalk.cyan('\n📊 Fetching default models from remote server...'));
582
+ // Try to use RemoteAIClient first, otherwise fetch directly
583
+ let defaults = null;
584
+ if (this.remoteAIClient) {
585
+ try {
586
+ defaults = await this.remoteAIClient.getDefaultModels();
587
+ }
588
+ catch (error) {
589
+ console.log(chalk.yellow(` ⚠️ Failed to get defaults from RemoteAIClient: ${error.message}`));
590
+ }
591
+ }
592
+ // If RemoteAIClient failed or not available, fetch directly
593
+ if (!defaults) {
594
+ try {
595
+ const webBaseUrl = authConfig.xagentApiBaseUrl || 'https://www.xagent-colife.net';
596
+ defaults = await fetchDefaultModels(authConfig.apiKey || '', webBaseUrl);
597
+ }
598
+ catch (error) {
599
+ console.log(chalk.yellow(` ⚠️ Failed to fetch default models: ${error.message}`));
600
+ }
601
+ }
602
+ if (defaults) {
603
+ if (!currentLlm && defaults.llm?.name) {
604
+ currentLlm = defaults.llm.name;
605
+ this.configManager.set('remote_llmModelName', currentLlm);
606
+ console.log(chalk.cyan(` Default LLM: ${defaults.llm.displayName || currentLlm}`));
607
+ }
608
+ if (!currentVlm && defaults.vlm?.name) {
609
+ currentVlm = defaults.vlm.name;
610
+ this.configManager.set('remote_vlmModelName', currentVlm);
611
+ console.log(chalk.cyan(` Default VLM: ${defaults.vlm.displayName || currentVlm}`));
454
612
  }
455
- ]);
456
- if (confirm) {
457
- await this.configManager.set('guiSubagentModel', '');
458
- await this.configManager.set('guiSubagentBaseUrl', '');
459
- await this.configManager.set('guiSubagentApiKey', '');
460
- await this.configManager.save('global');
461
- console.log(chalk.green('✅ VLM configuration removed successfully!'));
613
+ this.configManager.save('global');
614
+ }
615
+ else {
616
+ console.log(chalk.yellow(' ⚠️ Use /auth to configure remote mode first.'));
617
+ return;
462
618
  }
619
+ }
620
+ // Get RemoteAIClient instance (from InteractiveSession) for model selection
621
+ const remoteClient = this.remoteAIClient;
622
+ // Display current configuration
623
+ console.log(chalk.cyan('\n📊 Current Model Configuration:\n'));
624
+ console.log(` ${chalk.yellow('LLM Model:')} ${currentLlm || 'Not set'}`);
625
+ console.log(` ${chalk.yellow('VLM Model:')} ${currentVlm || 'Not set'}`);
626
+ console.log('');
627
+ // Main menu
628
+ const action = await select({
629
+ message: 'Select action:',
630
+ options: [
631
+ { value: 'llm', label: 'Change LLM model' },
632
+ { value: 'vlm', label: 'Change VLM model' },
633
+ { value: 'back', label: 'Back' },
634
+ ],
635
+ });
636
+ if (action === 'back' || typeof action === 'symbol') {
463
637
  return;
464
638
  }
465
- if (action === 'configure') {
466
- // Use AuthService to configure VLM
467
- const authService = new AuthService({
468
- type: 'openai_compatible',
469
- apiKey: '',
470
- baseUrl: '',
471
- modelName: ''
639
+ // Restore stdin raw mode after @clack/prompts interaction
640
+ ensureTtySane();
641
+ // Get and display provider list
642
+ try {
643
+ const models = await remoteClient.getRemoteModels();
644
+ const modelList = action === 'llm' ? models.llm : models.vlm;
645
+ if (modelList.length === 0) {
646
+ console.log(chalk.yellow('\n⚠️ No models available.'));
647
+ return;
648
+ }
649
+ // Build choice list
650
+ const choices = modelList.map((m) => ({
651
+ name: `${m.displayName} (${m.name})`,
652
+ value: m.name
653
+ }));
654
+ const selectedModel = await select({
655
+ message: action === 'llm' ? 'Select LLM Model:' : 'Select VLM Model:',
656
+ options: choices
472
657
  });
473
- const vlmConfig = await authService.configureAndValidateVLM();
474
- if (vlmConfig) {
475
- // Save VLM configuration
476
- await this.configManager.set('guiSubagentModel', vlmConfig.model);
477
- await this.configManager.set('guiSubagentBaseUrl', vlmConfig.baseUrl);
478
- await this.configManager.set('guiSubagentApiKey', vlmConfig.apiKey);
479
- await this.configManager.save('global');
480
- console.log(chalk.green('✅ VLM configuration saved successfully!'));
481
- console.log(chalk.cyan(` Model: ${vlmConfig.model}`));
482
- console.log(chalk.cyan(` Base URL: ${vlmConfig.baseUrl}`));
658
+ if (typeof selectedModel !== 'string') {
659
+ return;
660
+ }
661
+ const configKey = action === 'llm' ? 'remote_llmModelName' : 'remote_vlmModelName';
662
+ this.configManager.set(configKey, selectedModel);
663
+ this.configManager.save('global');
664
+ // Clear conversation history to avoid tool call ID conflicts between providers
665
+ if (this.onClearCallback) {
666
+ this.onClearCallback();
667
+ console.log(chalk.cyan(' Conversation cleared to avoid tool call ID conflicts between models.'));
668
+ }
669
+ // Notify InteractiveSession to update aiClient config
670
+ if (this.onConfigUpdate) {
671
+ this.onConfigUpdate();
672
+ }
673
+ console.log(chalk.green('\n✅ Model updated successfully!'));
674
+ console.log(` ${action === 'llm' ? 'LLM' : 'VLM'}: ${selectedModel}`);
675
+ }
676
+ catch (error) {
677
+ console.log(chalk.red(`\n❌ Failed to get models: ${error.message}`));
678
+ }
679
+ }
680
+ /**
681
+ * Handle /model command for local mode - Configure third-party API directly
682
+ * Reuses code from initial setup flow (authenticateWithOpenAICompatible and configureAndValidateVLM)
683
+ */
684
+ async handleLocalModel() {
685
+ // Display current configuration
686
+ const currentLlmModel = this.configManager.get('modelName') || this.configManager.getAuthConfig().modelName;
687
+ const currentVlmModel = this.configManager.get('guiSubagentModel');
688
+ console.log(chalk.cyan('\n📊 Current Local Model Configuration:\n'));
689
+ console.log(` ${chalk.yellow('LLM Model:')} ${currentLlmModel || 'Not set'}`);
690
+ console.log(` ${chalk.yellow('VLM Model:')} ${currentVlmModel || 'Not set'}`);
691
+ console.log('');
692
+ // Main menu - choose to configure LLM or VLM
693
+ const action = await select({
694
+ message: 'Select action:',
695
+ options: [
696
+ { value: 'llm', label: 'Change LLM (select provider and API)' },
697
+ { value: 'vlm', label: 'Change VLM (for GUI automation)' },
698
+ { value: 'back', label: 'Back' },
699
+ ],
700
+ });
701
+ if (action === 'back' || typeof action === 'symbol') {
702
+ return;
703
+ }
704
+ if (action === 'llm') {
705
+ await this.configureLocalLLM();
706
+ }
707
+ else if (action === 'vlm') {
708
+ await this.configureLocalVLM();
709
+ }
710
+ }
711
+ /**
712
+ * Configure LLM for local mode - Reuses authenticateWithOpenAICompatible logic
713
+ */
714
+ async configureLocalLLM() {
715
+ // THIRD_PARTY_PROVIDERS already imported at top level
716
+ const provider = await select({
717
+ message: 'Select third-party model provider:',
718
+ options: THIRD_PARTY_PROVIDERS.map((p) => ({
719
+ value: p,
720
+ label: `${p.name} - ${p.description}`,
721
+ })),
722
+ });
723
+ if (typeof provider === 'symbol') {
724
+ return;
725
+ }
726
+ const selectedProvider = provider;
727
+ let baseUrl = selectedProvider.baseUrl;
728
+ let modelName = selectedProvider.defaultModel;
729
+ if (selectedProvider.name === 'Custom') {
730
+ baseUrl = (await import('@clack/prompts').then(m => m.text({
731
+ message: 'Enter API Base URL:',
732
+ defaultValue: 'https://api.openai.com/v1',
733
+ validate: (value) => {
734
+ if (!value || value.trim().length === 0) {
735
+ return 'Base URL cannot be empty';
736
+ }
737
+ return undefined;
738
+ },
739
+ })));
740
+ modelName = (await import('@clack/prompts').then(m => m.text({
741
+ message: 'Enter model name:',
742
+ defaultValue: 'gpt-4',
743
+ validate: (value) => {
744
+ if (!value || value.trim().length === 0) {
745
+ return 'Model name cannot be empty';
746
+ }
747
+ return undefined;
748
+ },
749
+ })));
750
+ baseUrl = baseUrl.trim();
751
+ modelName = modelName.trim();
752
+ }
753
+ else {
754
+ console.log(chalk.cyan(`\nSelected: ${selectedProvider.name}`));
755
+ console.log(chalk.cyan(`API URL: ${baseUrl}`));
756
+ if (selectedProvider.models && selectedProvider.models.length > 0) {
757
+ console.log(chalk.cyan(`Available models: ${selectedProvider.models.join(', ')}`));
758
+ const selectedModel = await select({
759
+ message: 'Select model:',
760
+ options: selectedProvider.models.map((model) => ({
761
+ value: model,
762
+ label: model === selectedProvider.defaultModel ? `${model} (default)` : model,
763
+ })),
764
+ });
765
+ if (typeof selectedModel === 'symbol') {
766
+ return;
767
+ }
768
+ modelName = selectedModel;
483
769
  }
484
770
  else {
485
- console.log(chalk.red('❌ VLM configuration failed or cancelled'));
771
+ console.log(chalk.cyan(`Default model: ${modelName}`));
772
+ const confirmModel = (await import('@clack/prompts').then(m => m.text({
773
+ message: `Enter model name (press Enter to use default value ${modelName}):`,
774
+ defaultValue: modelName,
775
+ validate: (value) => {
776
+ if (!value || value.trim().length === 0) {
777
+ return 'Model name cannot be empty';
778
+ }
779
+ return undefined;
780
+ },
781
+ })));
782
+ modelName = confirmModel.trim();
486
783
  }
487
784
  }
785
+ const apiKey = (await import('@clack/prompts').then(m => m.password({
786
+ message: `Enter ${selectedProvider.name} API Key:`,
787
+ validate: (value) => {
788
+ if (!value || value.trim().length === 0) {
789
+ return 'API Key cannot be empty';
790
+ }
791
+ return undefined;
792
+ },
793
+ })));
794
+ // Update config
795
+ this.configManager.set('baseUrl', baseUrl);
796
+ this.configManager.set('apiKey', apiKey.trim());
797
+ this.configManager.set('modelName', modelName);
798
+ this.configManager.save('global');
799
+ console.log(chalk.green('\n✅ LLM configuration updated successfully!'));
800
+ console.log(chalk.cyan(` Provider: ${selectedProvider.name}`));
801
+ console.log(chalk.cyan(` Model: ${modelName}`));
802
+ console.log(chalk.cyan(` API URL: ${baseUrl}`));
803
+ // Clear conversation and notify config update
804
+ if (this.onClearCallback) {
805
+ this.onClearCallback();
806
+ }
807
+ if (this.onConfigUpdate) {
808
+ this.onConfigUpdate();
809
+ }
810
+ }
811
+ /**
812
+ * Configure VLM for local mode - Select provider and modelName (baseUrl from VLM_PROVIDERS)
813
+ */
814
+ async configureLocalVLM() {
815
+ // Get current VLM config
816
+ const currentModel = this.configManager.get('guiSubagentModel');
817
+ const currentBaseUrl = this.configManager.get('guiSubagentBaseUrl');
818
+ console.log(chalk.cyan('\n📊 Current VLM Configuration:\n'));
819
+ console.log(` ${chalk.yellow('Model:')} ${currentModel || 'Not set'}`);
820
+ console.log(` ${chalk.yellow('Base URL:')} ${currentBaseUrl || 'Not set'}`);
821
+ console.log('');
822
+ // Step 1: Select VLM provider
823
+ const provider = await select({
824
+ message: 'Select VLM provider:',
825
+ options: VLM_PROVIDERS.map((p) => ({
826
+ value: p,
827
+ label: `${p.name} - ${p.defaultModel}`,
828
+ })),
829
+ });
830
+ // User cancelled
831
+ if (typeof provider === 'symbol') {
832
+ return;
833
+ }
834
+ const selectedProvider = provider;
835
+ // Step 2: Select model from provider's models list
836
+ const model = await select({
837
+ message: 'Select VLM Model:',
838
+ options: selectedProvider.models.map((m) => ({
839
+ value: m,
840
+ label: m,
841
+ })),
842
+ });
843
+ // User cancelled
844
+ if (typeof model === 'symbol') {
845
+ return;
846
+ }
847
+ // Step 3: Get API Key
848
+ const apiKey = (await text({
849
+ message: `Enter ${selectedProvider.name} API Key:`,
850
+ validate: (value) => {
851
+ if (!value || value.trim().length === 0) {
852
+ return 'API Key cannot be empty';
853
+ }
854
+ return undefined;
855
+ },
856
+ }));
857
+ // Save configuration
858
+ this.configManager.set('guiSubagentModel', model);
859
+ this.configManager.set('guiSubagentBaseUrl', selectedProvider.baseUrl);
860
+ this.configManager.set('guiSubagentApiKey', apiKey);
861
+ this.configManager.save('global');
862
+ console.log(chalk.green('\n✅ VLM configuration updated successfully!'));
863
+ console.log(chalk.cyan(` Provider: ${selectedProvider.name}`));
864
+ console.log(chalk.cyan(` Model: ${model}`));
865
+ console.log(chalk.cyan(` Base URL: ${selectedProvider.baseUrl}`));
866
+ // Notify config update
867
+ if (this.onConfigUpdate) {
868
+ this.onConfigUpdate();
869
+ }
488
870
  }
489
871
  async handleMode(args) {
490
872
  const modes = Object.values(ExecutionMode);
@@ -493,7 +875,7 @@ export class SlashCommandHandler {
493
875
  const newMode = args[0].toLowerCase();
494
876
  if (modes.includes(newMode)) {
495
877
  this.configManager.setApprovalMode(newMode);
496
- await this.configManager.save('global');
878
+ this.configManager.save('global');
497
879
  console.log(chalk.green(`✅ Approval mode changed to: ${newMode}`));
498
880
  }
499
881
  else {
@@ -509,7 +891,7 @@ export class SlashCommandHandler {
509
891
  { mode: 'accept_edits', desc: 'Accept all edits automatically' },
510
892
  { mode: 'plan', desc: 'Plan before executing' },
511
893
  { mode: 'default', desc: 'Safe execution with confirmations' },
512
- { mode: 'smart', desc: 'Smart approval with intelligent security checks' }
894
+ { mode: 'smart', desc: 'Smart approval with intelligent security checks' },
513
895
  ];
514
896
  descriptions.forEach(({ mode, desc }) => {
515
897
  const current = mode === currentMode ? chalk.green(' [current]') : '';
@@ -526,13 +908,13 @@ export class SlashCommandHandler {
526
908
  if (action === 'on' || action === 'true' || action === '1') {
527
909
  thinkingConfig.enabled = true;
528
910
  this.configManager.setThinkingConfig(thinkingConfig);
529
- await this.configManager.save('global');
911
+ this.configManager.save('global');
530
912
  console.log(chalk.green('✅ Thinking mode enabled'));
531
913
  }
532
914
  else if (action === 'off' || action === 'false' || action === '0') {
533
915
  thinkingConfig.enabled = false;
534
916
  this.configManager.setThinkingConfig(thinkingConfig);
535
- await this.configManager.save('global');
917
+ this.configManager.save('global');
536
918
  console.log(chalk.green('✅ Thinking mode disabled'));
537
919
  }
538
920
  else if (action === 'display' && args[1]) {
@@ -540,9 +922,9 @@ export class SlashCommandHandler {
540
922
  const validModes = ['full', 'compact', 'indicator'];
541
923
  if (validModes.includes(displayMode)) {
542
924
  thinkingConfig.displayMode = displayMode;
543
- thinkingConfig.enabled = true; // Auto-enable when setting display mode
925
+ thinkingConfig.enabled = true;
544
926
  this.configManager.setThinkingConfig(thinkingConfig);
545
- await this.configManager.save('global');
927
+ this.configManager.save('global');
546
928
  console.log(chalk.green(`✅ Thinking display mode set to: ${displayMode}`));
547
929
  }
548
930
  else {
@@ -650,7 +1032,9 @@ export class SlashCommandHandler {
650
1032
  const status = isConnected ? chalk.green('✓ Connected') : chalk.red('✗ Disconnected');
651
1033
  const tools = server?.getToolNames() || [];
652
1034
  const transport = serverConfig?.transport || serverConfig?.type || 'unknown';
653
- const command = serverConfig?.command ? `${serverConfig.command} ${(serverConfig.args || []).join(' ')}` : serverConfig?.url || 'N/A';
1035
+ const command = serverConfig?.command
1036
+ ? `${serverConfig.command} ${(serverConfig.args || []).join(' ')}`
1037
+ : serverConfig?.url || 'N/A';
654
1038
  console.log('');
655
1039
  console.log(` ${chalk.cyan(serverName)} ${status}`);
656
1040
  console.log(` Transport: ${transport}`);
@@ -661,80 +1045,87 @@ export class SlashCommandHandler {
661
1045
  logger.info(`Total: ${serverConfigs.length} server(s)`);
662
1046
  }
663
1047
  async addMcpServerInteractive(serverName) {
664
- const { name, command, args: serverArgs, transport, url, authToken, headers } = await inquirer.prompt([
665
- {
666
- type: 'input',
667
- name: 'name',
668
- message: 'Enter MCP server name:',
669
- default: serverName,
670
- validate: (input) => {
671
- if (!input.trim()) {
672
- return 'Server name is required';
673
- }
674
- const servers = this.mcpManager.getAllServers();
675
- if (servers.some((s) => s.config?.name === input)) {
676
- return 'Server with this name already exists';
677
- }
678
- return true;
1048
+ let name = (await text({
1049
+ message: 'Enter MCP server name:',
1050
+ defaultValue: serverName,
1051
+ validate: (value) => {
1052
+ if (!value || !value.trim()) {
1053
+ return 'Server name is required';
679
1054
  }
1055
+ if (!/^[a-zA-Z0-9_-]+$/.test(value)) {
1056
+ return 'Server name must contain only alphanumeric characters, hyphens, and underscores';
1057
+ }
1058
+ const servers = this.mcpManager.getAllServers();
1059
+ if (servers.some((s) => s.config?.name === value)) {
1060
+ return 'Server with this name already exists';
1061
+ }
1062
+ return undefined;
680
1063
  },
681
- {
682
- type: 'list',
683
- name: 'transport',
684
- message: 'Select transport type:',
685
- choices: [
686
- { name: 'Stdio (stdin/stdout)', value: 'stdio' },
687
- { name: 'HTTP/SSE', value: 'sse' },
688
- { name: 'HTTP (POST)', value: 'http' }
689
- ],
690
- default: 'stdio'
691
- },
692
- {
693
- type: 'input',
694
- name: 'command',
1064
+ }));
1065
+ const transport = await select({
1066
+ message: 'Select transport type:',
1067
+ options: [
1068
+ { value: 'stdio', label: 'Stdio (stdin/stdout)' },
1069
+ { value: 'sse', label: 'HTTP/SSE' },
1070
+ { value: 'http', label: 'HTTP (POST)' },
1071
+ ],
1072
+ });
1073
+ if (typeof transport === 'symbol') {
1074
+ return;
1075
+ }
1076
+ let command = '';
1077
+ let serverArgs = [];
1078
+ let url = '';
1079
+ let authToken = '';
1080
+ let headers;
1081
+ if (transport === 'stdio') {
1082
+ command = (await text({
695
1083
  message: 'Enter command (for stdio transport):',
696
- when: (answers) => answers.transport === 'stdio',
697
- validate: (input) => input.trim() ? true : 'Command is required'
698
- },
699
- {
700
- type: 'input',
701
- name: 'args',
1084
+ validate: (value) => value && value.trim() ? undefined : 'Command is required',
1085
+ }));
1086
+ const argsInput = (await text({
702
1087
  message: 'Enter arguments (comma-separated, for stdio transport):',
703
- when: (answers) => answers.transport === 'stdio',
704
- filter: (input) => input ? input.split(',').map((a) => a.trim()) : []
705
- },
706
- {
707
- type: 'input',
708
- name: 'url',
1088
+ defaultValue: '',
1089
+ }));
1090
+ if (argsInput.trim()) {
1091
+ serverArgs = argsInput.split(',').map((a) => a.trim());
1092
+ }
1093
+ }
1094
+ else {
1095
+ url = (await text({
709
1096
  message: 'Enter server URL (for HTTP/SSE/HTTP transport):',
710
- when: (answers) => answers.transport === 'sse' || answers.transport === 'http',
711
- validate: (input) => input.trim() ? true : 'URL is required'
712
- },
713
- {
714
- type: 'password',
715
- name: 'authToken',
716
- message: 'Enter authentication token (optional):',
717
- when: (answers) => answers.transport === 'sse' || answers.transport === 'http'
718
- },
719
- {
720
- type: 'input',
721
- name: 'headers',
722
- message: 'Enter custom headers as JSON (optional, e.g., {"Authorization": "Bearer token"}):',
723
- when: (answers) => answers.transport === 'sse' || answers.transport === 'http',
724
- filter: (input) => {
725
- if (!input.trim())
726
- return undefined;
1097
+ validate: (value) => {
1098
+ if (!value || !value.trim()) {
1099
+ return 'URL is required';
1100
+ }
727
1101
  try {
728
- return JSON.parse(input);
1102
+ new URL(value);
1103
+ return undefined;
729
1104
  }
730
1105
  catch {
731
- return undefined;
1106
+ return 'Invalid URL format (e.g., https://example.com)';
732
1107
  }
1108
+ },
1109
+ }));
1110
+ authToken = (await text({
1111
+ message: 'Enter authentication token (optional):',
1112
+ defaultValue: '',
1113
+ }));
1114
+ const headersInput = (await text({
1115
+ message: 'Enter custom headers as JSON (optional, e.g., {"Authorization": "Bearer token"}):',
1116
+ defaultValue: '',
1117
+ }));
1118
+ if (headersInput.trim()) {
1119
+ try {
1120
+ headers = JSON.parse(headersInput);
1121
+ }
1122
+ catch {
1123
+ headers = undefined;
733
1124
  }
734
1125
  }
735
- ]);
1126
+ }
736
1127
  const config = {
737
- transport: transport
1128
+ transport: transport,
738
1129
  };
739
1130
  if (transport === 'stdio') {
740
1131
  config.command = command;
@@ -744,30 +1135,39 @@ export class SlashCommandHandler {
744
1135
  }
745
1136
  else {
746
1137
  config.url = url;
747
- if (authToken) {
748
- config.authToken = authToken;
1138
+ // Handle user input that mistakenly puts Bearer token in headers field
1139
+ // Detect pattern: headers looks like "Bearer xxx.yyy.zzz" (JWT token)
1140
+ let resolvedAuthToken = authToken;
1141
+ let resolvedHeaders = headers;
1142
+ if (headers && typeof headers === 'string' && !authToken) {
1143
+ const trimmedHeaders = headers.trim();
1144
+ if (trimmedHeaders.startsWith('Bearer ') && trimmedHeaders.split('.').length === 3) {
1145
+ // User mistakenly put token in headers field - extract it
1146
+ resolvedAuthToken = trimmedHeaders;
1147
+ resolvedHeaders = undefined;
1148
+ console.log('[MCP] Note: Detected Bearer token in headers field, moved to authToken');
1149
+ }
1150
+ }
1151
+ if (resolvedAuthToken) {
1152
+ config.authToken = resolvedAuthToken;
749
1153
  }
750
- if (headers) {
751
- config.headers = headers;
1154
+ if (resolvedHeaders) {
1155
+ config.headers = resolvedHeaders;
752
1156
  }
753
1157
  }
754
1158
  try {
755
- // Save to config file
756
1159
  this.configManager.addMcpServer(name, config);
757
- await this.configManager.save('global');
758
- // Register to MCP Manager
1160
+ this.configManager.save('global');
759
1161
  this.mcpManager.registerServer(name, config);
760
- // Connect to server (with error handling)
761
1162
  let connected = false;
762
1163
  try {
763
1164
  await this.mcpManager.connectServer(name);
764
1165
  connected = true;
765
1166
  }
766
1167
  catch (error) {
767
- // Connection failed - cleanup
768
1168
  this.mcpManager.disconnectServer(name);
769
1169
  this.configManager.removeMcpServer(name);
770
- await this.configManager.save('global');
1170
+ this.configManager.save('global');
771
1171
  throw new Error(`Connection failed: ${error.message}`);
772
1172
  }
773
1173
  // Register MCP tools with simple names
@@ -790,22 +1190,21 @@ export class SlashCommandHandler {
790
1190
  logger.warn('No MCP servers configured', 'Use /mcp add to add servers');
791
1191
  return;
792
1192
  }
793
- const serverNames = servers.map((s) => {
1193
+ const serverOptions = servers.map((s) => {
794
1194
  const tools = s.getToolNames();
795
1195
  const status = s.isServerConnected() ? '✓' : '✗';
796
1196
  return {
797
- name: `${status} ${s.config?.name || 'unknown'} (${tools.length} tools)`,
798
- value: s.config?.name
1197
+ value: s.config?.name,
1198
+ label: `${status} ${s.config?.name || 'unknown'} (${tools.length} tools)`,
799
1199
  };
800
1200
  });
801
- const { serverName } = await inquirer.prompt([
802
- {
803
- type: 'list',
804
- name: 'serverName',
805
- message: 'Select MCP server to remove:',
806
- choices: serverNames
807
- }
808
- ]);
1201
+ const serverName = (await select({
1202
+ message: 'Select MCP server to remove:',
1203
+ options: serverOptions,
1204
+ }));
1205
+ if (typeof serverName === 'symbol') {
1206
+ return;
1207
+ }
809
1208
  await this.removeMcpServer(serverName);
810
1209
  }
811
1210
  async removeMcpServer(serverName) {
@@ -821,7 +1220,7 @@ export class SlashCommandHandler {
821
1220
  toolRegistry.unregisterMCPTools(serverName);
822
1221
  // Remove from config
823
1222
  this.configManager.removeMcpServer(serverName);
824
- await this.configManager.save('global');
1223
+ this.configManager.save('global');
825
1224
  // Update system prompt to reflect removed MCP tools
826
1225
  if (this.onSystemPromptUpdate) {
827
1226
  await this.onSystemPromptUpdate();
@@ -914,8 +1313,7 @@ export class SlashCommandHandler {
914
1313
  return;
915
1314
  }
916
1315
  // Clear specific file by filename or path
917
- const targetMemory = memoryFiles.find((m) => path.basename(m.path) === target ||
918
- m.path === target);
1316
+ const targetMemory = memoryFiles.find((m) => path.basename(m.path) === target || m.path === target);
919
1317
  if (targetMemory) {
920
1318
  try {
921
1319
  await fs.unlink(targetMemory.path);
@@ -949,22 +1347,20 @@ export class SlashCommandHandler {
949
1347
  logger.info(`Directory: ${memoriesDir}`);
950
1348
  console.log('');
951
1349
  memoryFiles.forEach((file) => {
952
- const level = file.level === 'global' ? chalk.blue('[global]') :
953
- file.level === 'project' ? chalk.green('[project]') :
954
- chalk.yellow('[subdirectory]');
1350
+ const level = file.level === 'global'
1351
+ ? chalk.blue('[global]')
1352
+ : file.level === 'project'
1353
+ ? chalk.green('[project]')
1354
+ : chalk.yellow('[subdirectory]');
955
1355
  logger.info(` ${level} ${path.basename(file.path)}`);
956
1356
  });
957
1357
  console.log('');
958
1358
  // logger.info('Usage: /memory clear [global|current|all|<filename>]');
959
1359
  }
960
1360
  async addMemory() {
961
- const { entry } = await inquirer.prompt([
962
- {
963
- type: 'editor',
964
- name: 'entry',
965
- message: 'Enter memory entry (opens editor):'
966
- }
967
- ]);
1361
+ const entry = (await text({
1362
+ message: 'Enter memory entry (opens editor):',
1363
+ }));
968
1364
  if (entry && entry.trim()) {
969
1365
  await this.memoryManager.addMemoryEntry(entry.trim());
970
1366
  console.log(chalk.green('✅ Memory entry added'));
@@ -1001,18 +1397,17 @@ export class SlashCommandHandler {
1001
1397
  }
1002
1398
  }
1003
1399
  else {
1004
- const choices = checkpoints.map((cp) => ({
1005
- name: `${new Date(cp.timestamp).toLocaleString()} - ${cp.description}`,
1006
- value: cp.id
1400
+ const checkpointOptions = checkpoints.map((cp) => ({
1401
+ value: cp.id,
1402
+ label: `${new Date(cp.timestamp).toLocaleString()} - ${cp.description}`,
1007
1403
  }));
1008
- const { checkpointId } = await inquirer.prompt([
1009
- {
1010
- type: 'list',
1011
- name: 'checkpointId',
1012
- message: 'Select checkpoint to restore:',
1013
- choices
1014
- }
1015
- ]);
1404
+ const checkpointId = await select({
1405
+ message: 'Select checkpoint to restore:',
1406
+ options: checkpointOptions,
1407
+ });
1408
+ if (typeof checkpointId === 'symbol') {
1409
+ return;
1410
+ }
1016
1411
  try {
1017
1412
  await this.checkpointManager.restoreCheckpoint(checkpointId);
1018
1413
  logger.success(`Checkpoint ${checkpointId} restored successfully!`);
@@ -1026,7 +1421,7 @@ export class SlashCommandHandler {
1026
1421
  const toolRegistry = getToolRegistry();
1027
1422
  const tools = toolRegistry.getAll();
1028
1423
  logger.section('Available Tools');
1029
- tools.forEach(tool => {
1424
+ tools.forEach((tool) => {
1030
1425
  logger.info(` ${tool.name}`);
1031
1426
  logger.info(` ${tool.description}`);
1032
1427
  });
@@ -1045,12 +1440,12 @@ export class SlashCommandHandler {
1045
1440
  const mode = args[0].toLowerCase();
1046
1441
  if (mode === 'verbose' || mode === 'detail' || mode === 'true' || mode === 'on') {
1047
1442
  this.configManager.set('showToolDetails', true);
1048
- await this.configManager.save('global');
1443
+ this.configManager.save('global');
1049
1444
  logger.success('Tool display mode switched to verbose mode', 'Will show complete tool call information');
1050
1445
  }
1051
1446
  else if (mode === 'simple' || mode === 'concise' || mode === 'false' || mode === 'off') {
1052
1447
  this.configManager.set('showToolDetails', false);
1053
- await this.configManager.save('global');
1448
+ this.configManager.save('global');
1054
1449
  logger.success('Tool display mode switched to simple mode', 'Only show tool execution status');
1055
1450
  }
1056
1451
  else {
@@ -1059,6 +1454,8 @@ export class SlashCommandHandler {
1059
1454
  }
1060
1455
  async handleStats() {
1061
1456
  logger.section('Session Statistics');
1457
+ const authConfig = this.configManager.getAuthConfig();
1458
+ logger.info(` Base URL: ${authConfig.baseUrl}`);
1062
1459
  logger.info(` Execution Mode: ${this.configManager.getExecutionMode()}`);
1063
1460
  logger.info(` Language: ${this.configManager.getLanguage()}`);
1064
1461
  logger.info(` Checkpointing: ${this.checkpointManager.isEnabled() ? 'Enabled' : 'Disabled'}`);
@@ -1069,17 +1466,16 @@ export class SlashCommandHandler {
1069
1466
  logger.warn('Theme switching not implemented yet', 'Check back later for updates');
1070
1467
  }
1071
1468
  async handleLanguage() {
1072
- const { language } = await inquirer.prompt([
1073
- {
1074
- type: 'list',
1075
- name: 'language',
1076
- message: 'Select language:',
1077
- choices: [
1078
- { name: 'Chinese', value: 'zh' },
1079
- { name: 'English', value: 'en' }
1080
- ]
1081
- }
1082
- ]);
1469
+ const language = (await select({
1470
+ message: 'Select language:',
1471
+ options: [
1472
+ { value: 'zh', label: 'Chinese' },
1473
+ { value: 'en', label: 'English' },
1474
+ ],
1475
+ }));
1476
+ if (typeof language === 'symbol') {
1477
+ return;
1478
+ }
1083
1479
  this.configManager.setLanguage(language);
1084
1480
  logger.success(`Language changed to: ${language === 'zh' ? 'Chinese' : 'English'}`, 'Restart CLI to apply changes');
1085
1481
  }
@@ -1091,6 +1487,45 @@ export class SlashCommandHandler {
1091
1487
  logger.link('Documentation', 'https://platform.xagent.cn/');
1092
1488
  logger.link('GitHub', 'https://github.com/xagent-ai/xagent-cli');
1093
1489
  }
1490
+ async handleUpdate() {
1491
+ const separator = icons.separator.repeat(Math.min(40, process.stdout.columns || 80));
1492
+ console.log('');
1493
+ console.log(colors.primaryBright(`${icons.rocket} Update Check`));
1494
+ console.log(colors.border(separator));
1495
+ console.log('');
1496
+ try {
1497
+ const { getUpdateManager } = await import('./update.js');
1498
+ const updateManager = getUpdateManager();
1499
+ const versionInfo = await updateManager.checkForUpdates();
1500
+ console.log(` ${icons.info} ${colors.textMuted('Current version:')} ${colors.primaryBright(versionInfo.currentVersion)}`);
1501
+ console.log(` ${icons.code} ${colors.textMuted('Latest version:')} ${colors.primaryBright(versionInfo.latestVersion)}`);
1502
+ console.log('');
1503
+ if (versionInfo.updateAvailable) {
1504
+ console.log(colors.success(` 📦 A new version is available!`));
1505
+ console.log('');
1506
+ if (versionInfo.releaseNotes) {
1507
+ console.log(colors.textMuted(' Release Notes:'));
1508
+ console.log(colors.textDim(` ${versionInfo.releaseNotes}`));
1509
+ console.log('');
1510
+ }
1511
+ const shouldUpdate = await confirm({
1512
+ message: 'Do you want to update now?',
1513
+ });
1514
+ if (shouldUpdate === true) {
1515
+ console.log('');
1516
+ await updateManager.autoUpdate();
1517
+ }
1518
+ }
1519
+ else {
1520
+ console.log(colors.success(` ✅ You are using the latest version`));
1521
+ console.log('');
1522
+ }
1523
+ }
1524
+ catch (error) {
1525
+ console.log(colors.error(` ❌ Failed to check for updates: ${error.message}`));
1526
+ console.log('');
1527
+ }
1528
+ }
1094
1529
  async handleCompress(args) {
1095
1530
  const config = this.configManager.getContextCompressionConfig();
1096
1531
  // If there are arguments, process config or execute
@@ -1106,15 +1541,11 @@ export class SlashCommandHandler {
1106
1541
  // Display current configuration
1107
1542
  console.log(chalk.cyan('\n📦 Context Compression:\n'));
1108
1543
  console.log(` Status: ${config.enabled ? chalk.green('Enabled') : chalk.red('Disabled')}`);
1109
- console.log(` Max Messages: ${chalk.yellow(config.maxMessages.toString())}`);
1110
- console.log(` Max Tokens: ${chalk.yellow(config.maxContextSize.toString())}`);
1111
1544
  console.log('');
1112
1545
  console.log(chalk.gray('Usage:'));
1113
1546
  console.log(chalk.gray(' /compress - Show current configuration'));
1114
1547
  console.log(chalk.gray(' /compress exec - Execute compression now'));
1115
1548
  console.log(chalk.gray(' /compress on|off - Enable/disable compression'));
1116
- console.log(chalk.gray(' /compress max_message <n> - Set max messages before compression'));
1117
- console.log(chalk.gray(' /compress max_token <n> - Set max tokens before compression'));
1118
1549
  console.log('');
1119
1550
  }
1120
1551
  async executeCompression(config) {
@@ -1133,7 +1564,7 @@ export class SlashCommandHandler {
1133
1564
  const spinner = ora({
1134
1565
  text: 'Compressing context...',
1135
1566
  spinner: 'dots',
1136
- color: 'cyan'
1567
+ color: 'cyan',
1137
1568
  }).start();
1138
1569
  try {
1139
1570
  const result = await this.contextCompressor.compressContext(messages, 'You are a helpful AI assistant.', config);
@@ -1159,50 +1590,235 @@ export class SlashCommandHandler {
1159
1590
  case 'on':
1160
1591
  config.enabled = true;
1161
1592
  this.configManager.setContextCompressionConfig(config);
1162
- await this.configManager.save('global');
1593
+ this.configManager.save('global');
1163
1594
  console.log(chalk.green('✅ Context compression enabled'));
1164
1595
  break;
1165
1596
  case 'off':
1166
1597
  config.enabled = false;
1167
1598
  this.configManager.setContextCompressionConfig(config);
1168
- await this.configManager.save('global');
1599
+ this.configManager.save('global');
1169
1600
  console.log(chalk.green('✅ Context compression disabled'));
1170
1601
  break;
1171
- case 'max_message':
1172
- if (args[1]) {
1173
- const maxMessages = parseInt(args[1], 10);
1174
- if (isNaN(maxMessages) || maxMessages < 1) {
1175
- console.log(chalk.red('❌ Invalid value for max_message. Must be a positive number.'));
1176
- return;
1177
- }
1178
- config.maxMessages = maxMessages;
1179
- this.configManager.setContextCompressionConfig(config);
1180
- await this.configManager.save('global');
1181
- console.log(chalk.green(`✅ Max messages set to: ${maxMessages}`));
1602
+ default:
1603
+ console.log(chalk.red(`❌ Unknown action: ${action}`));
1604
+ console.log(chalk.gray('Available actions: on, off, exec'));
1605
+ }
1606
+ }
1607
+ async handleSkill(args) {
1608
+ const os = await import('os');
1609
+ const path = await import('path');
1610
+ const { fileURLToPath } = await import('url');
1611
+ const { promises: fs } = await import('fs');
1612
+ const action = args[0] || 'list';
1613
+ const userSkillsPath = this.configManager.getUserSkillsPath() || path.join(os.homedir(), '.xagent', 'skills');
1614
+ switch (action) {
1615
+ case 'list':
1616
+ await this.listUserSkills(userSkillsPath, fs, path);
1617
+ break;
1618
+ case 'add':
1619
+ await this.addSkill(args[1], userSkillsPath, fs, path);
1620
+ break;
1621
+ case 'remove':
1622
+ await this.removeSkill(args[1], userSkillsPath, fs, path);
1623
+ break;
1624
+ default:
1625
+ console.log(chalk.cyan('\n🔧 Skills:\n'));
1626
+ console.log(` Skills directory: ${chalk.yellow(userSkillsPath)}\n`);
1627
+ console.log(chalk.gray('Available commands:'));
1628
+ console.log(chalk.gray(' /skill list - List installed skills'));
1629
+ console.log(chalk.gray(' /skill add <source> - Add a skill (local path or remote URL)'));
1630
+ console.log(chalk.gray(' /skill remove <name> - Remove a user-installed skill'));
1631
+ console.log();
1632
+ console.log(chalk.gray('Examples:'));
1633
+ console.log(chalk.gray(' /skill add ./my-skill - Local path'));
1634
+ console.log(chalk.gray(' /skill add owner/repo - GitHub shorthand'));
1635
+ console.log(chalk.gray(' /skill add https://github.com/owner/repo - GitHub URL'));
1636
+ console.log();
1637
+ }
1638
+ }
1639
+ async listUserSkills(userSkillsPath, fs, path) {
1640
+ console.log(chalk.cyan('\n🔧 Skills:\n'));
1641
+ try {
1642
+ const entries = await fs.readdir(userSkillsPath, { withFileTypes: true });
1643
+ const skills = entries.filter((e) => e.isDirectory());
1644
+ if (skills.length === 0) {
1645
+ console.log(chalk.gray(' No skills installed'));
1646
+ console.log(chalk.cyan('\n To add a skill, use:'));
1647
+ console.log(chalk.cyan(' /skill add <path-to-skill>\n'));
1648
+ return;
1649
+ }
1650
+ for (const skill of skills) {
1651
+ const skillPath = path.join(userSkillsPath, skill.name);
1652
+ const skillMdPath = path.join(skillPath, 'SKILL.md');
1653
+ try {
1654
+ const content = await fs.readFile(skillMdPath, 'utf-8');
1655
+ const nameMatch = content.match(/^name:\s*(.+)$/m);
1656
+ const descMatch = content.match(/^description:\s*(.+)$/m);
1657
+ const name = nameMatch ? nameMatch[1].trim() : skill.name;
1658
+ const description = descMatch ? descMatch[1].trim() : 'No description';
1659
+ console.log(` ${chalk.cyan('•')} ${chalk.yellow(name)}`);
1660
+ console.log(` ${chalk.gray(description)}`);
1661
+ console.log();
1662
+ }
1663
+ catch {
1664
+ console.log(` ${chalk.cyan('•')} ${chalk.yellow(skill.name)}`);
1665
+ console.log(` ${chalk.gray('(Missing SKILL.md)')}`);
1666
+ console.log();
1667
+ }
1668
+ }
1669
+ console.log(chalk.gray(` Skills directory: ${userSkillsPath}`));
1670
+ console.log();
1671
+ }
1672
+ catch (error) {
1673
+ if (error.code === 'ENOENT') {
1674
+ console.log(chalk.gray(' No skills installed'));
1675
+ console.log(chalk.cyan('\n To add a skill, use:'));
1676
+ console.log(chalk.cyan(' /skill add <path-to-skill>\n'));
1677
+ }
1678
+ else {
1679
+ console.log(chalk.red(` Error: ${error.message}`));
1680
+ }
1681
+ }
1682
+ }
1683
+ async addSkill(source, userSkillsPath, fs, path) {
1684
+ if (!source) {
1685
+ console.log(chalk.yellow('\n⚠️ Please specify a skill source'));
1686
+ console.log(chalk.cyan(' Usage: /skill add <source>\n'));
1687
+ console.log(chalk.gray(' Examples:'));
1688
+ console.log(chalk.gray(' /skill add ./my-skill - Local path'));
1689
+ console.log(chalk.gray(' /skill add owner/repo - GitHub shorthand'));
1690
+ console.log(chalk.gray(' /skill add https://github.com/owner/repo'));
1691
+ console.log();
1692
+ return;
1693
+ }
1694
+ const { parseSource, installSkill } = await import('./skill-installer.js');
1695
+ const parsed = parseSource(source.trim());
1696
+ const isLocal = parsed.type === 'local';
1697
+ if (isLocal) {
1698
+ // Local installation
1699
+ const resolvedPath = path.resolve(source);
1700
+ const skillName = path.basename(resolvedPath);
1701
+ const destPath = path.join(userSkillsPath, skillName);
1702
+ try {
1703
+ // Check if source exists
1704
+ await fs.access(resolvedPath);
1705
+ // Check if SKILL.md exists
1706
+ const skillMdPath = path.join(resolvedPath, 'SKILL.md');
1707
+ try {
1708
+ await fs.access(skillMdPath);
1709
+ }
1710
+ catch {
1711
+ console.log(chalk.red(`\n❌ SKILL.md not found in ${resolvedPath}`));
1712
+ console.log(chalk.gray(' Each skill must have a SKILL.md file\n'));
1713
+ return;
1714
+ }
1715
+ // Check if skill already exists
1716
+ try {
1717
+ await fs.access(destPath);
1718
+ console.log(chalk.yellow(`\n⚠️ Skill "${skillName}" already installed`));
1719
+ console.log(chalk.cyan(` Use: /skill remove ${skillName} to remove it first\n`));
1720
+ return;
1721
+ }
1722
+ catch {
1723
+ // Doesn't exist, proceed
1724
+ }
1725
+ // Ensure skills directory exists
1726
+ await fs.mkdir(userSkillsPath, { recursive: true });
1727
+ // Copy the skill
1728
+ await this.copyDirectory(resolvedPath, destPath);
1729
+ console.log(chalk.green('\n✅ Skill installed successfully'));
1730
+ console.log(chalk.gray(` Name: ${skillName}`));
1731
+ console.log(chalk.gray(` Location: ${destPath}`));
1732
+ console.log(chalk.gray(` Type: Local`));
1733
+ console.log();
1734
+ // Trigger system prompt update
1735
+ this.onSystemPromptUpdate?.();
1736
+ }
1737
+ catch (error) {
1738
+ if (error.code === 'ENOENT') {
1739
+ console.log(chalk.red(`\n❌ Skill not found: ${source}\n`));
1182
1740
  }
1183
1741
  else {
1184
- console.log(chalk.gray('Usage: /compress max_message <number>'));
1742
+ console.log(chalk.red(`\n❌ Error installing skill: ${error.message}\n`));
1185
1743
  }
1186
- break;
1187
- case 'max_token':
1188
- if (args[1]) {
1189
- const maxContextSize = parseInt(args[1], 10);
1190
- if (isNaN(maxContextSize) || maxContextSize < 1000) {
1191
- console.log(chalk.red('❌ Invalid value for max_token. Must be at least 1000.'));
1192
- return;
1193
- }
1194
- config.maxContextSize = maxContextSize;
1195
- this.configManager.setContextCompressionConfig(config);
1196
- await this.configManager.save('global');
1197
- console.log(chalk.green(`✅ Max tokens set to: ${maxContextSize}`));
1744
+ }
1745
+ }
1746
+ else {
1747
+ // Remote installation
1748
+ console.log(chalk.cyan('\n📦 Installing skill from remote source...\n'));
1749
+ console.log(chalk.gray(` Source: ${source}`));
1750
+ console.log(chalk.gray(` Type: Remote`));
1751
+ console.log();
1752
+ try {
1753
+ const result = await installSkill(source);
1754
+ if (result.success) {
1755
+ console.log(chalk.green('✅ Skill installed successfully'));
1756
+ console.log(chalk.gray(` Name: ${result.skillName}`));
1757
+ console.log(chalk.gray(` Location: ${result.skillPath}`));
1758
+ console.log(chalk.gray(' Type: Remote'));
1759
+ console.log();
1760
+ // Trigger system prompt update - skill is immediately available
1761
+ this.onSystemPromptUpdate?.();
1198
1762
  }
1199
1763
  else {
1200
- console.log(chalk.gray('Usage: /compress max_token <number>'));
1764
+ console.log(chalk.red(`\n❌ Failed to install skill: ${result.error}\n`));
1201
1765
  }
1202
- break;
1203
- default:
1204
- console.log(chalk.red(`❌ Unknown action: ${action}`));
1205
- console.log(chalk.gray('Available actions: on, off, max_message, max_token, exec'));
1766
+ }
1767
+ catch (error) {
1768
+ console.log(chalk.red(`\n❌ Error installing skill: ${error.message}\n`));
1769
+ }
1770
+ }
1771
+ }
1772
+ async removeSkill(skillName, userSkillsPath, fs, path) {
1773
+ if (!skillName) {
1774
+ console.log(chalk.yellow('\n⚠️ Please specify a skill name'));
1775
+ console.log(chalk.cyan(' Usage: /skill remove <skill-name>\n'));
1776
+ return;
1777
+ }
1778
+ // Protect find-skills from deletion
1779
+ if (skillName === 'find-skills') {
1780
+ console.log(chalk.red('\n❌ Cannot remove protected skill: find-skills'));
1781
+ console.log(chalk.gray(' find-skills is a built-in skill that helps you discover and install other skills.\n'));
1782
+ return;
1783
+ }
1784
+ const skillPath = path.join(userSkillsPath, skillName);
1785
+ try {
1786
+ await fs.access(skillPath);
1787
+ // Verify it's in skills path
1788
+ if (!skillPath.startsWith(userSkillsPath)) {
1789
+ console.log(chalk.red(`\n❌ Cannot remove skill outside user directory\n`));
1790
+ return;
1791
+ }
1792
+ // Remove the skill directory
1793
+ await fs.rm(skillPath, { recursive: true, force: true });
1794
+ console.log(chalk.green('\n✅ Skill removed successfully'));
1795
+ console.log();
1796
+ // Trigger system prompt update
1797
+ this.onSystemPromptUpdate?.();
1798
+ }
1799
+ catch (error) {
1800
+ if (error.code === 'ENOENT' || error.code === 'ENOENT') {
1801
+ console.log(chalk.yellow(`\n⚠️ Skill not found: ${skillName}\n`));
1802
+ }
1803
+ else {
1804
+ console.log(chalk.red(`\n❌ Error removing skill: ${error.message}\n`));
1805
+ }
1806
+ }
1807
+ }
1808
+ async copyDirectory(src, dest) {
1809
+ const entries = await fs.readdir(src, { withFileTypes: true });
1810
+ await fs.mkdir(dest, { recursive: true });
1811
+ for (const entry of entries) {
1812
+ // Skip node_modules to keep dependencies isolated
1813
+ // if (entry.name === 'node_modules') continue;
1814
+ const srcPath = path.join(src, entry.name);
1815
+ const destPath = path.join(dest, entry.name);
1816
+ if (entry.isDirectory()) {
1817
+ await this.copyDirectory(srcPath, destPath);
1818
+ }
1819
+ else if (entry.isFile()) {
1820
+ await fs.copyFile(srcPath, destPath);
1821
+ }
1206
1822
  }
1207
1823
  }
1208
1824
  }