agent-messenger 1.0.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 (394) hide show
  1. package/.claude/commands/release.md +92 -0
  2. package/.claude-plugin/README.md +144 -0
  3. package/.claude-plugin/marketplace.json +37 -0
  4. package/.claude-plugin/plugin.json +17 -0
  5. package/.github/workflows/ci.yml +30 -0
  6. package/CLAUDE.md +106 -0
  7. package/CONTRIBUTING.md +131 -0
  8. package/README.md +140 -0
  9. package/biome.json +34 -0
  10. package/bun.lock +252 -0
  11. package/dist/cli.d.ts +5 -0
  12. package/dist/cli.d.ts.map +1 -0
  13. package/dist/cli.js +21 -0
  14. package/dist/cli.js.map +1 -0
  15. package/dist/commands/auth.d.ts +3 -0
  16. package/dist/commands/auth.d.ts.map +1 -0
  17. package/dist/commands/auth.js +140 -0
  18. package/dist/commands/auth.js.map +1 -0
  19. package/dist/commands/channel.d.ts +3 -0
  20. package/dist/commands/channel.d.ts.map +1 -0
  21. package/dist/commands/channel.js +118 -0
  22. package/dist/commands/channel.js.map +1 -0
  23. package/dist/commands/file.d.ts +3 -0
  24. package/dist/commands/file.d.ts.map +1 -0
  25. package/dist/commands/file.js +113 -0
  26. package/dist/commands/file.js.map +1 -0
  27. package/dist/commands/index.d.ts +9 -0
  28. package/dist/commands/index.d.ts.map +1 -0
  29. package/dist/commands/index.js +9 -0
  30. package/dist/commands/index.js.map +1 -0
  31. package/dist/commands/message.d.ts +3 -0
  32. package/dist/commands/message.d.ts.map +1 -0
  33. package/dist/commands/message.js +214 -0
  34. package/dist/commands/message.js.map +1 -0
  35. package/dist/commands/reaction.d.ts +3 -0
  36. package/dist/commands/reaction.d.ts.map +1 -0
  37. package/dist/commands/reaction.js +100 -0
  38. package/dist/commands/reaction.js.map +1 -0
  39. package/dist/commands/snapshot.d.ts +3 -0
  40. package/dist/commands/snapshot.d.ts.map +1 -0
  41. package/dist/commands/snapshot.js +88 -0
  42. package/dist/commands/snapshot.js.map +1 -0
  43. package/dist/commands/user.d.ts +3 -0
  44. package/dist/commands/user.d.ts.map +1 -0
  45. package/dist/commands/user.js +96 -0
  46. package/dist/commands/user.js.map +1 -0
  47. package/dist/commands/workspace.d.ts +3 -0
  48. package/dist/commands/workspace.d.ts.map +1 -0
  49. package/dist/commands/workspace.js +89 -0
  50. package/dist/commands/workspace.js.map +1 -0
  51. package/dist/lib/credential-manager.d.ts +13 -0
  52. package/dist/lib/credential-manager.d.ts.map +1 -0
  53. package/dist/lib/credential-manager.js +58 -0
  54. package/dist/lib/credential-manager.js.map +1 -0
  55. package/dist/lib/index.d.ts +3 -0
  56. package/dist/lib/index.d.ts.map +1 -0
  57. package/dist/lib/index.js +3 -0
  58. package/dist/lib/index.js.map +1 -0
  59. package/dist/lib/ref-manager.d.ts +26 -0
  60. package/dist/lib/ref-manager.d.ts.map +1 -0
  61. package/dist/lib/ref-manager.js +92 -0
  62. package/dist/lib/ref-manager.js.map +1 -0
  63. package/dist/lib/slack-client.d.ts +37 -0
  64. package/dist/lib/slack-client.d.ts.map +1 -0
  65. package/dist/lib/slack-client.js +379 -0
  66. package/dist/lib/slack-client.js.map +1 -0
  67. package/dist/lib/token-extractor.d.ts +28 -0
  68. package/dist/lib/token-extractor.d.ts.map +1 -0
  69. package/dist/lib/token-extractor.js +401 -0
  70. package/dist/lib/token-extractor.js.map +1 -0
  71. package/dist/package.json +37 -0
  72. package/dist/src/cli.d.ts +5 -0
  73. package/dist/src/cli.d.ts.map +1 -0
  74. package/dist/src/cli.js +22 -0
  75. package/dist/src/cli.js.map +1 -0
  76. package/dist/src/platforms/discord/cli.d.ts +5 -0
  77. package/dist/src/platforms/discord/cli.d.ts.map +1 -0
  78. package/dist/src/platforms/discord/cli.js +22 -0
  79. package/dist/src/platforms/discord/cli.js.map +1 -0
  80. package/dist/src/platforms/discord/client.d.ts +34 -0
  81. package/dist/src/platforms/discord/client.d.ts.map +1 -0
  82. package/dist/src/platforms/discord/client.js +187 -0
  83. package/dist/src/platforms/discord/client.js.map +1 -0
  84. package/dist/src/platforms/discord/client.test.d.ts +2 -0
  85. package/dist/src/platforms/discord/client.test.d.ts.map +1 -0
  86. package/dist/src/platforms/discord/client.test.js +367 -0
  87. package/dist/src/platforms/discord/client.test.js.map +1 -0
  88. package/dist/src/platforms/discord/commands/auth.d.ts +13 -0
  89. package/dist/src/platforms/discord/commands/auth.d.ts.map +1 -0
  90. package/dist/src/platforms/discord/commands/auth.js +155 -0
  91. package/dist/src/platforms/discord/commands/auth.js.map +1 -0
  92. package/dist/src/platforms/discord/commands/auth.test.d.ts +2 -0
  93. package/dist/src/platforms/discord/commands/auth.test.d.ts.map +1 -0
  94. package/dist/src/platforms/discord/commands/auth.test.js +65 -0
  95. package/dist/src/platforms/discord/commands/auth.test.js.map +1 -0
  96. package/dist/src/platforms/discord/commands/channel.d.ts +13 -0
  97. package/dist/src/platforms/discord/commands/channel.d.ts.map +1 -0
  98. package/dist/src/platforms/discord/commands/channel.js +99 -0
  99. package/dist/src/platforms/discord/commands/channel.js.map +1 -0
  100. package/dist/src/platforms/discord/commands/channel.test.d.ts +2 -0
  101. package/dist/src/platforms/discord/commands/channel.test.d.ts.map +1 -0
  102. package/dist/src/platforms/discord/commands/channel.test.js +136 -0
  103. package/dist/src/platforms/discord/commands/channel.test.js.map +1 -0
  104. package/dist/src/platforms/discord/commands/file.d.ts +13 -0
  105. package/dist/src/platforms/discord/commands/file.d.ts.map +1 -0
  106. package/dist/src/platforms/discord/commands/file.js +99 -0
  107. package/dist/src/platforms/discord/commands/file.js.map +1 -0
  108. package/dist/src/platforms/discord/commands/file.test.d.ts +2 -0
  109. package/dist/src/platforms/discord/commands/file.test.d.ts.map +1 -0
  110. package/dist/src/platforms/discord/commands/file.test.js +83 -0
  111. package/dist/src/platforms/discord/commands/file.test.js.map +1 -0
  112. package/dist/src/platforms/discord/commands/guild.d.ts +15 -0
  113. package/dist/src/platforms/discord/commands/guild.d.ts.map +1 -0
  114. package/dist/src/platforms/discord/commands/guild.js +102 -0
  115. package/dist/src/platforms/discord/commands/guild.js.map +1 -0
  116. package/dist/src/platforms/discord/commands/guild.test.d.ts +2 -0
  117. package/dist/src/platforms/discord/commands/guild.test.d.ts.map +1 -0
  118. package/dist/src/platforms/discord/commands/guild.test.js +100 -0
  119. package/dist/src/platforms/discord/commands/guild.test.js.map +1 -0
  120. package/dist/src/platforms/discord/commands/index.d.ts +9 -0
  121. package/dist/src/platforms/discord/commands/index.d.ts.map +1 -0
  122. package/dist/src/platforms/discord/commands/index.js +9 -0
  123. package/dist/src/platforms/discord/commands/index.js.map +1 -0
  124. package/dist/src/platforms/discord/commands/message.d.ts +17 -0
  125. package/dist/src/platforms/discord/commands/message.d.ts.map +1 -0
  126. package/dist/src/platforms/discord/commands/message.js +131 -0
  127. package/dist/src/platforms/discord/commands/message.js.map +1 -0
  128. package/dist/src/platforms/discord/commands/message.test.d.ts +2 -0
  129. package/dist/src/platforms/discord/commands/message.test.d.ts.map +1 -0
  130. package/dist/src/platforms/discord/commands/message.test.js +91 -0
  131. package/dist/src/platforms/discord/commands/message.test.js.map +1 -0
  132. package/dist/src/platforms/discord/commands/reaction.d.ts +12 -0
  133. package/dist/src/platforms/discord/commands/reaction.d.ts.map +1 -0
  134. package/dist/src/platforms/discord/commands/reaction.js +99 -0
  135. package/dist/src/platforms/discord/commands/reaction.js.map +1 -0
  136. package/dist/src/platforms/discord/commands/reaction.test.d.ts +2 -0
  137. package/dist/src/platforms/discord/commands/reaction.test.d.ts.map +1 -0
  138. package/dist/src/platforms/discord/commands/reaction.test.js +115 -0
  139. package/dist/src/platforms/discord/commands/reaction.test.js.map +1 -0
  140. package/dist/src/platforms/discord/commands/snapshot.d.ts +9 -0
  141. package/dist/src/platforms/discord/commands/snapshot.d.ts.map +1 -0
  142. package/dist/src/platforms/discord/commands/snapshot.js +80 -0
  143. package/dist/src/platforms/discord/commands/snapshot.js.map +1 -0
  144. package/dist/src/platforms/discord/commands/snapshot.test.d.ts +2 -0
  145. package/dist/src/platforms/discord/commands/snapshot.test.d.ts.map +1 -0
  146. package/dist/src/platforms/discord/commands/snapshot.test.js +25 -0
  147. package/dist/src/platforms/discord/commands/snapshot.test.js.map +1 -0
  148. package/dist/src/platforms/discord/commands/user.d.ts +3 -0
  149. package/dist/src/platforms/discord/commands/user.d.ts.map +1 -0
  150. package/dist/src/platforms/discord/commands/user.js +94 -0
  151. package/dist/src/platforms/discord/commands/user.js.map +1 -0
  152. package/dist/src/platforms/discord/commands/user.test.d.ts +2 -0
  153. package/dist/src/platforms/discord/commands/user.test.d.ts.map +1 -0
  154. package/dist/src/platforms/discord/commands/user.test.js +103 -0
  155. package/dist/src/platforms/discord/commands/user.test.js.map +1 -0
  156. package/dist/src/platforms/discord/credential-manager.d.ts +33 -0
  157. package/dist/src/platforms/discord/credential-manager.d.ts.map +1 -0
  158. package/dist/src/platforms/discord/credential-manager.js +73 -0
  159. package/dist/src/platforms/discord/credential-manager.js.map +1 -0
  160. package/dist/src/platforms/discord/credential-manager.test.d.ts +2 -0
  161. package/dist/src/platforms/discord/credential-manager.test.d.ts.map +1 -0
  162. package/dist/src/platforms/discord/credential-manager.test.js +136 -0
  163. package/dist/src/platforms/discord/credential-manager.test.js.map +1 -0
  164. package/dist/src/platforms/discord/token-extractor.d.ts +55 -0
  165. package/dist/src/platforms/discord/token-extractor.d.ts.map +1 -0
  166. package/dist/src/platforms/discord/token-extractor.js +462 -0
  167. package/dist/src/platforms/discord/token-extractor.js.map +1 -0
  168. package/dist/src/platforms/discord/token-extractor.test.d.ts +2 -0
  169. package/dist/src/platforms/discord/token-extractor.test.d.ts.map +1 -0
  170. package/dist/src/platforms/discord/token-extractor.test.js +789 -0
  171. package/dist/src/platforms/discord/token-extractor.test.js.map +1 -0
  172. package/dist/src/platforms/discord/types.d.ts +251 -0
  173. package/dist/src/platforms/discord/types.d.ts.map +1 -0
  174. package/dist/src/platforms/discord/types.js +74 -0
  175. package/dist/src/platforms/discord/types.js.map +1 -0
  176. package/dist/src/platforms/discord/types.test.d.ts +2 -0
  177. package/dist/src/platforms/discord/types.test.d.ts.map +1 -0
  178. package/dist/src/platforms/discord/types.test.js +211 -0
  179. package/dist/src/platforms/discord/types.test.js.map +1 -0
  180. package/dist/src/platforms/slack/cli.d.ts +5 -0
  181. package/dist/src/platforms/slack/cli.d.ts.map +1 -0
  182. package/dist/src/platforms/slack/cli.js +22 -0
  183. package/dist/src/platforms/slack/cli.js.map +1 -0
  184. package/dist/src/platforms/slack/client.d.ts +47 -0
  185. package/dist/src/platforms/slack/client.d.ts.map +1 -0
  186. package/dist/src/platforms/slack/client.js +412 -0
  187. package/dist/src/platforms/slack/client.js.map +1 -0
  188. package/dist/src/platforms/slack/commands/auth.d.ts +3 -0
  189. package/dist/src/platforms/slack/commands/auth.d.ts.map +1 -0
  190. package/dist/src/platforms/slack/commands/auth.js +156 -0
  191. package/dist/src/platforms/slack/commands/auth.js.map +1 -0
  192. package/dist/src/platforms/slack/commands/channel.d.ts +3 -0
  193. package/dist/src/platforms/slack/commands/channel.d.ts.map +1 -0
  194. package/dist/src/platforms/slack/commands/channel.js +118 -0
  195. package/dist/src/platforms/slack/commands/channel.js.map +1 -0
  196. package/dist/src/platforms/slack/commands/file.d.ts +3 -0
  197. package/dist/src/platforms/slack/commands/file.d.ts.map +1 -0
  198. package/dist/src/platforms/slack/commands/file.js +113 -0
  199. package/dist/src/platforms/slack/commands/file.js.map +1 -0
  200. package/dist/src/platforms/slack/commands/index.d.ts +9 -0
  201. package/dist/src/platforms/slack/commands/index.d.ts.map +1 -0
  202. package/dist/src/platforms/slack/commands/index.js +9 -0
  203. package/dist/src/platforms/slack/commands/index.js.map +1 -0
  204. package/dist/src/platforms/slack/commands/message.d.ts +3 -0
  205. package/dist/src/platforms/slack/commands/message.d.ts.map +1 -0
  206. package/dist/src/platforms/slack/commands/message.js +263 -0
  207. package/dist/src/platforms/slack/commands/message.js.map +1 -0
  208. package/dist/src/platforms/slack/commands/reaction.d.ts +3 -0
  209. package/dist/src/platforms/slack/commands/reaction.d.ts.map +1 -0
  210. package/dist/src/platforms/slack/commands/reaction.js +100 -0
  211. package/dist/src/platforms/slack/commands/reaction.js.map +1 -0
  212. package/dist/src/platforms/slack/commands/snapshot.d.ts +3 -0
  213. package/dist/src/platforms/slack/commands/snapshot.d.ts.map +1 -0
  214. package/dist/src/platforms/slack/commands/snapshot.js +87 -0
  215. package/dist/src/platforms/slack/commands/snapshot.js.map +1 -0
  216. package/dist/src/platforms/slack/commands/user.d.ts +3 -0
  217. package/dist/src/platforms/slack/commands/user.d.ts.map +1 -0
  218. package/dist/src/platforms/slack/commands/user.js +96 -0
  219. package/dist/src/platforms/slack/commands/user.js.map +1 -0
  220. package/dist/src/platforms/slack/commands/workspace.d.ts +3 -0
  221. package/dist/src/platforms/slack/commands/workspace.d.ts.map +1 -0
  222. package/dist/src/platforms/slack/commands/workspace.js +89 -0
  223. package/dist/src/platforms/slack/commands/workspace.js.map +1 -0
  224. package/dist/src/platforms/slack/credential-manager.d.ts +13 -0
  225. package/dist/src/platforms/slack/credential-manager.d.ts.map +1 -0
  226. package/dist/src/platforms/slack/credential-manager.js +58 -0
  227. package/dist/src/platforms/slack/credential-manager.js.map +1 -0
  228. package/dist/src/platforms/slack/index.d.ts +3 -0
  229. package/dist/src/platforms/slack/index.d.ts.map +1 -0
  230. package/dist/src/platforms/slack/index.js +3 -0
  231. package/dist/src/platforms/slack/index.js.map +1 -0
  232. package/dist/src/platforms/slack/token-extractor.d.ts +28 -0
  233. package/dist/src/platforms/slack/token-extractor.d.ts.map +1 -0
  234. package/dist/src/platforms/slack/token-extractor.js +401 -0
  235. package/dist/src/platforms/slack/token-extractor.js.map +1 -0
  236. package/dist/src/platforms/slack/types.d.ts +369 -0
  237. package/dist/src/platforms/slack/types.d.ts.map +1 -0
  238. package/dist/src/platforms/slack/types.js +92 -0
  239. package/dist/src/platforms/slack/types.js.map +1 -0
  240. package/dist/src/shared/utils/concurrency.d.ts +2 -0
  241. package/dist/src/shared/utils/concurrency.d.ts.map +1 -0
  242. package/dist/src/shared/utils/concurrency.js +14 -0
  243. package/dist/src/shared/utils/concurrency.js.map +1 -0
  244. package/dist/src/shared/utils/concurrency.test.d.ts +2 -0
  245. package/dist/src/shared/utils/concurrency.test.d.ts.map +1 -0
  246. package/dist/src/shared/utils/concurrency.test.js +39 -0
  247. package/dist/src/shared/utils/concurrency.test.js.map +1 -0
  248. package/dist/src/shared/utils/error-handler.d.ts +2 -0
  249. package/dist/src/shared/utils/error-handler.d.ts.map +1 -0
  250. package/dist/src/shared/utils/error-handler.js +5 -0
  251. package/dist/src/shared/utils/error-handler.js.map +1 -0
  252. package/dist/src/shared/utils/output.d.ts +2 -0
  253. package/dist/src/shared/utils/output.d.ts.map +1 -0
  254. package/dist/src/shared/utils/output.js +4 -0
  255. package/dist/src/shared/utils/output.js.map +1 -0
  256. package/dist/tests/cli.test.d.ts +2 -0
  257. package/dist/tests/cli.test.d.ts.map +1 -0
  258. package/dist/tests/cli.test.js +83 -0
  259. package/dist/tests/cli.test.js.map +1 -0
  260. package/dist/tests/commands/.test-slack-data/Local Storage/leveldb/CURRENT +1 -0
  261. package/dist/tests/commands/.test-slack-data/Local Storage/leveldb/LOCK +0 -0
  262. package/dist/tests/commands/.test-slack-data/Local Storage/leveldb/LOG +3 -0
  263. package/dist/tests/commands/.test-slack-data/Local Storage/leveldb/LOG.old +1 -0
  264. package/dist/tests/commands/.test-slack-data/Local Storage/leveldb/MANIFEST-000004 +0 -0
  265. package/dist/tests/commands/auth.test.d.ts +2 -0
  266. package/dist/tests/commands/auth.test.d.ts.map +1 -0
  267. package/dist/tests/commands/auth.test.js +304 -0
  268. package/dist/tests/commands/auth.test.js.map +1 -0
  269. package/dist/tests/commands/channel.test.d.ts +2 -0
  270. package/dist/tests/commands/channel.test.d.ts.map +1 -0
  271. package/dist/tests/commands/channel.test.js +166 -0
  272. package/dist/tests/commands/channel.test.js.map +1 -0
  273. package/dist/tests/commands/file.test.d.ts +2 -0
  274. package/dist/tests/commands/file.test.d.ts.map +1 -0
  275. package/dist/tests/commands/file.test.js +175 -0
  276. package/dist/tests/commands/file.test.js.map +1 -0
  277. package/dist/tests/commands/message.test.d.ts +2 -0
  278. package/dist/tests/commands/message.test.d.ts.map +1 -0
  279. package/dist/tests/commands/message.test.js +293 -0
  280. package/dist/tests/commands/message.test.js.map +1 -0
  281. package/dist/tests/commands/reaction.test.d.ts +2 -0
  282. package/dist/tests/commands/reaction.test.d.ts.map +1 -0
  283. package/dist/tests/commands/reaction.test.js +84 -0
  284. package/dist/tests/commands/reaction.test.js.map +1 -0
  285. package/dist/tests/commands/snapshot.test.d.ts +2 -0
  286. package/dist/tests/commands/snapshot.test.d.ts.map +1 -0
  287. package/dist/tests/commands/snapshot.test.js +280 -0
  288. package/dist/tests/commands/snapshot.test.js.map +1 -0
  289. package/dist/tests/commands/user.test.d.ts +2 -0
  290. package/dist/tests/commands/user.test.d.ts.map +1 -0
  291. package/dist/tests/commands/user.test.js +117 -0
  292. package/dist/tests/commands/user.test.js.map +1 -0
  293. package/dist/tests/commands/workspace.test.d.ts +2 -0
  294. package/dist/tests/commands/workspace.test.d.ts.map +1 -0
  295. package/dist/tests/commands/workspace.test.js +453 -0
  296. package/dist/tests/commands/workspace.test.js.map +1 -0
  297. package/dist/tests/credential-manager.test.d.ts +2 -0
  298. package/dist/tests/credential-manager.test.d.ts.map +1 -0
  299. package/dist/tests/credential-manager.test.js +199 -0
  300. package/dist/tests/credential-manager.test.js.map +1 -0
  301. package/dist/tests/slack-client.test.d.ts +2 -0
  302. package/dist/tests/slack-client.test.d.ts.map +1 -0
  303. package/dist/tests/slack-client.test.js +741 -0
  304. package/dist/tests/slack-client.test.js.map +1 -0
  305. package/dist/tests/types.test.d.ts +2 -0
  306. package/dist/tests/types.test.d.ts.map +1 -0
  307. package/dist/tests/types.test.js +215 -0
  308. package/dist/tests/types.test.js.map +1 -0
  309. package/dist/types/index.d.ts +369 -0
  310. package/dist/types/index.d.ts.map +1 -0
  311. package/dist/types/index.js +92 -0
  312. package/dist/types/index.js.map +1 -0
  313. package/dist/utils/error-handler.d.ts +2 -0
  314. package/dist/utils/error-handler.d.ts.map +1 -0
  315. package/dist/utils/error-handler.js +5 -0
  316. package/dist/utils/error-handler.js.map +1 -0
  317. package/dist/utils/output.d.ts +2 -0
  318. package/dist/utils/output.d.ts.map +1 -0
  319. package/dist/utils/output.js +4 -0
  320. package/dist/utils/output.js.map +1 -0
  321. package/docs/discord.md +182 -0
  322. package/docs/slack.md +160 -0
  323. package/package.json +37 -0
  324. package/skills/agent-discord/SKILL.md +273 -0
  325. package/skills/agent-discord/references/authentication.md +294 -0
  326. package/skills/agent-discord/references/common-patterns.md +455 -0
  327. package/skills/agent-discord/templates/guild-summary.sh +167 -0
  328. package/skills/agent-discord/templates/monitor-channel.sh +180 -0
  329. package/skills/agent-discord/templates/post-message.sh +173 -0
  330. package/skills/agent-slack/SKILL.md +268 -0
  331. package/skills/agent-slack/references/authentication.md +332 -0
  332. package/skills/agent-slack/references/common-patterns.md +527 -0
  333. package/skills/agent-slack/templates/monitor-channel.sh +186 -0
  334. package/skills/agent-slack/templates/post-message.sh +130 -0
  335. package/skills/agent-slack/templates/workspace-summary.sh +149 -0
  336. package/src/cli.ts +29 -0
  337. package/src/platforms/discord/cli.ts +36 -0
  338. package/src/platforms/discord/client.test.ts +456 -0
  339. package/src/platforms/discord/client.ts +281 -0
  340. package/src/platforms/discord/commands/auth.test.ts +72 -0
  341. package/src/platforms/discord/commands/auth.ts +206 -0
  342. package/src/platforms/discord/commands/channel.test.ts +153 -0
  343. package/src/platforms/discord/commands/channel.ts +127 -0
  344. package/src/platforms/discord/commands/file.test.ts +98 -0
  345. package/src/platforms/discord/commands/file.ts +134 -0
  346. package/src/platforms/discord/commands/guild.test.ts +117 -0
  347. package/src/platforms/discord/commands/guild.ts +129 -0
  348. package/src/platforms/discord/commands/index.ts +8 -0
  349. package/src/platforms/discord/commands/message.test.ts +107 -0
  350. package/src/platforms/discord/commands/message.ts +182 -0
  351. package/src/platforms/discord/commands/reaction.test.ts +123 -0
  352. package/src/platforms/discord/commands/reaction.ts +156 -0
  353. package/src/platforms/discord/commands/snapshot.test.ts +29 -0
  354. package/src/platforms/discord/commands/snapshot.ts +104 -0
  355. package/src/platforms/discord/commands/user.test.ts +115 -0
  356. package/src/platforms/discord/commands/user.ts +124 -0
  357. package/src/platforms/discord/credential-manager.test.ts +173 -0
  358. package/src/platforms/discord/credential-manager.ts +95 -0
  359. package/src/platforms/discord/token-extractor.test.ts +918 -0
  360. package/src/platforms/discord/token-extractor.ts +549 -0
  361. package/src/platforms/discord/types.test.ts +245 -0
  362. package/src/platforms/discord/types.ts +158 -0
  363. package/src/platforms/slack/cli.ts +36 -0
  364. package/src/platforms/slack/client.ts +466 -0
  365. package/src/platforms/slack/commands/auth.ts +211 -0
  366. package/src/platforms/slack/commands/channel.ts +158 -0
  367. package/src/platforms/slack/commands/file.ts +153 -0
  368. package/src/platforms/slack/commands/index.ts +8 -0
  369. package/src/platforms/slack/commands/message.ts +369 -0
  370. package/src/platforms/slack/commands/reaction.ts +166 -0
  371. package/src/platforms/slack/commands/snapshot.ts +114 -0
  372. package/src/platforms/slack/commands/user.ts +110 -0
  373. package/src/platforms/slack/commands/workspace.ts +111 -0
  374. package/src/platforms/slack/credential-manager.ts +74 -0
  375. package/src/platforms/slack/index.ts +2 -0
  376. package/src/platforms/slack/token-extractor.ts +496 -0
  377. package/src/platforms/slack/types.ts +193 -0
  378. package/src/shared/utils/concurrency.test.ts +53 -0
  379. package/src/shared/utils/concurrency.ts +20 -0
  380. package/src/shared/utils/error-handler.ts +4 -0
  381. package/src/shared/utils/output.ts +3 -0
  382. package/tests/cli.test.ts +94 -0
  383. package/tests/commands/auth.test.ts +383 -0
  384. package/tests/commands/channel.test.ts +185 -0
  385. package/tests/commands/file.test.ts +204 -0
  386. package/tests/commands/message.test.ts +344 -0
  387. package/tests/commands/reaction.test.ts +101 -0
  388. package/tests/commands/snapshot.test.ts +308 -0
  389. package/tests/commands/user.test.ts +138 -0
  390. package/tests/commands/workspace.test.ts +528 -0
  391. package/tests/credential-manager.test.ts +241 -0
  392. package/tests/slack-client.test.ts +916 -0
  393. package/tests/types.test.ts +241 -0
  394. package/tsconfig.json +36 -0
@@ -0,0 +1,466 @@
1
+ import { WebClient } from '@slack/web-api'
2
+ import type { SlackChannel, SlackFile, SlackMessage, SlackSearchResult, SlackUser } from './types'
3
+
4
+ export class SlackError extends Error {
5
+ code: string
6
+
7
+ constructor(message: string, code: string) {
8
+ super(message)
9
+ this.name = 'SlackError'
10
+ this.code = code
11
+ }
12
+ }
13
+
14
+ const MAX_RETRIES = 3
15
+ const RATE_LIMIT_ERROR_CODE = 'slack_webapi_rate_limited_error'
16
+
17
+ export class SlackClient {
18
+ private client: WebClient
19
+
20
+ constructor(token: string, cookie: string) {
21
+ if (!token) {
22
+ throw new SlackError('Token is required', 'missing_token')
23
+ }
24
+ if (!cookie) {
25
+ throw new SlackError('Cookie is required', 'missing_cookie')
26
+ }
27
+
28
+ this.client = new WebClient(token, {
29
+ headers: { Cookie: `d=${cookie}` },
30
+ })
31
+ }
32
+
33
+ private async withRetry<T>(operation: () => Promise<T>): Promise<T> {
34
+ let lastError: Error | undefined
35
+ for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
36
+ try {
37
+ return await operation()
38
+ } catch (error: any) {
39
+ lastError = error
40
+ if (error.code === RATE_LIMIT_ERROR_CODE && attempt < MAX_RETRIES) {
41
+ const retryAfter = error.retryAfter || 1
42
+ await this.sleep(retryAfter * 1000 * (attempt + 1))
43
+ continue
44
+ }
45
+ break
46
+ }
47
+ }
48
+ throw new SlackError(
49
+ lastError?.message || 'Unknown error',
50
+ (lastError as any)?.code || 'unknown_error'
51
+ )
52
+ }
53
+
54
+ private sleep(ms: number): Promise<void> {
55
+ return new Promise((resolve) => setTimeout(resolve, ms))
56
+ }
57
+
58
+ private checkResponse(response: { ok?: boolean; error?: string }): void {
59
+ if (!response.ok) {
60
+ throw new SlackError(response.error || 'API call failed', response.error || 'api_error')
61
+ }
62
+ }
63
+
64
+ async testAuth(): Promise<{ user_id: string; team_id: string; user?: string; team?: string }> {
65
+ return this.withRetry(async () => {
66
+ const response = await this.client.auth.test()
67
+ this.checkResponse(response)
68
+ return {
69
+ user_id: response.user_id!,
70
+ team_id: response.team_id!,
71
+ user: response.user,
72
+ team: response.team,
73
+ }
74
+ })
75
+ }
76
+
77
+ async listChannels(): Promise<SlackChannel[]> {
78
+ return this.withRetry(async () => {
79
+ const channels: SlackChannel[] = []
80
+ let cursor: string | undefined
81
+
82
+ do {
83
+ const response = await this.client.conversations.list({
84
+ cursor,
85
+ limit: 200,
86
+ types: 'public_channel,private_channel',
87
+ })
88
+ this.checkResponse(response)
89
+
90
+ if (response.channels) {
91
+ for (const ch of response.channels) {
92
+ channels.push({
93
+ id: ch.id!,
94
+ name: ch.name!,
95
+ is_private: ch.is_private || false,
96
+ is_archived: ch.is_archived || false,
97
+ created: ch.created || 0,
98
+ creator: ch.creator || '',
99
+ topic: ch.topic
100
+ ? {
101
+ value: ch.topic.value || '',
102
+ creator: ch.topic.creator || '',
103
+ last_set: ch.topic.last_set || 0,
104
+ }
105
+ : undefined,
106
+ purpose: ch.purpose
107
+ ? {
108
+ value: ch.purpose.value || '',
109
+ creator: ch.purpose.creator || '',
110
+ last_set: ch.purpose.last_set || 0,
111
+ }
112
+ : undefined,
113
+ })
114
+ }
115
+ }
116
+
117
+ cursor = response.response_metadata?.next_cursor
118
+ } while (cursor)
119
+
120
+ return channels
121
+ })
122
+ }
123
+
124
+ async getChannel(id: string): Promise<SlackChannel> {
125
+ return this.withRetry(async () => {
126
+ const response = await this.client.conversations.info({ channel: id })
127
+ this.checkResponse(response)
128
+
129
+ const ch = response.channel!
130
+ return {
131
+ id: ch.id!,
132
+ name: ch.name!,
133
+ is_private: ch.is_private || false,
134
+ is_archived: ch.is_archived || false,
135
+ created: ch.created || 0,
136
+ creator: ch.creator || '',
137
+ topic: ch.topic
138
+ ? {
139
+ value: ch.topic.value || '',
140
+ creator: ch.topic.creator || '',
141
+ last_set: ch.topic.last_set || 0,
142
+ }
143
+ : undefined,
144
+ purpose: ch.purpose
145
+ ? {
146
+ value: ch.purpose.value || '',
147
+ creator: ch.purpose.creator || '',
148
+ last_set: ch.purpose.last_set || 0,
149
+ }
150
+ : undefined,
151
+ }
152
+ })
153
+ }
154
+
155
+ async sendMessage(channel: string, text: string, threadTs?: string): Promise<SlackMessage> {
156
+ return this.withRetry(async () => {
157
+ const response = await this.client.chat.postMessage({
158
+ channel,
159
+ text,
160
+ thread_ts: threadTs,
161
+ })
162
+ this.checkResponse(response)
163
+
164
+ const msg = response.message!
165
+ return {
166
+ ts: response.ts!,
167
+ text: msg.text || text,
168
+ type: msg.type || 'message',
169
+ user: msg.user,
170
+ thread_ts: msg.thread_ts,
171
+ }
172
+ })
173
+ }
174
+
175
+ async getMessages(channel: string, limit = 20): Promise<SlackMessage[]> {
176
+ return this.withRetry(async () => {
177
+ const response = await this.client.conversations.history({
178
+ channel,
179
+ limit,
180
+ })
181
+ this.checkResponse(response)
182
+
183
+ return (response.messages || []).map((msg) => ({
184
+ ts: msg.ts!,
185
+ text: msg.text || '',
186
+ type: msg.type || 'message',
187
+ user: msg.user,
188
+ username: msg.username,
189
+ thread_ts: msg.thread_ts,
190
+ reply_count: msg.reply_count,
191
+ replies: (msg as any).replies,
192
+ edited: msg.edited
193
+ ? {
194
+ user: msg.edited.user || '',
195
+ ts: msg.edited.ts || '',
196
+ }
197
+ : undefined,
198
+ }))
199
+ })
200
+ }
201
+
202
+ async getMessage(channel: string, ts: string): Promise<SlackMessage | null> {
203
+ return this.withRetry(async () => {
204
+ const response = await this.client.conversations.history({
205
+ channel,
206
+ oldest: ts,
207
+ inclusive: true,
208
+ limit: 1,
209
+ })
210
+ this.checkResponse(response)
211
+
212
+ const msg = response.messages?.[0]
213
+ if (!msg || msg.ts !== ts) {
214
+ return null
215
+ }
216
+
217
+ return {
218
+ ts: msg.ts!,
219
+ text: msg.text || '',
220
+ type: msg.type || 'message',
221
+ user: msg.user,
222
+ username: msg.username,
223
+ thread_ts: msg.thread_ts,
224
+ reply_count: msg.reply_count,
225
+ replies: (msg as any).replies,
226
+ edited: msg.edited
227
+ ? {
228
+ user: msg.edited.user || '',
229
+ ts: msg.edited.ts || '',
230
+ }
231
+ : undefined,
232
+ }
233
+ })
234
+ }
235
+
236
+ async updateMessage(channel: string, ts: string, text: string): Promise<SlackMessage> {
237
+ return this.withRetry(async () => {
238
+ const response = await this.client.chat.update({
239
+ channel,
240
+ ts,
241
+ text,
242
+ })
243
+ this.checkResponse(response)
244
+
245
+ const msg = response.message!
246
+ return {
247
+ ts: response.ts!,
248
+ text: msg.text || text,
249
+ type: 'message',
250
+ user: msg.user,
251
+ }
252
+ })
253
+ }
254
+
255
+ async deleteMessage(channel: string, ts: string): Promise<void> {
256
+ return this.withRetry(async () => {
257
+ const response = await this.client.chat.delete({
258
+ channel,
259
+ ts,
260
+ })
261
+ this.checkResponse(response)
262
+ })
263
+ }
264
+
265
+ async addReaction(channel: string, ts: string, emoji: string): Promise<void> {
266
+ return this.withRetry(async () => {
267
+ const response = await this.client.reactions.add({
268
+ channel,
269
+ timestamp: ts,
270
+ name: emoji,
271
+ })
272
+ this.checkResponse(response)
273
+ })
274
+ }
275
+
276
+ async removeReaction(channel: string, ts: string, emoji: string): Promise<void> {
277
+ return this.withRetry(async () => {
278
+ const response = await this.client.reactions.remove({
279
+ channel,
280
+ timestamp: ts,
281
+ name: emoji,
282
+ })
283
+ this.checkResponse(response)
284
+ })
285
+ }
286
+
287
+ async listUsers(): Promise<SlackUser[]> {
288
+ return this.withRetry(async () => {
289
+ const users: SlackUser[] = []
290
+ let cursor: string | undefined
291
+
292
+ do {
293
+ const response = await this.client.users.list({
294
+ cursor,
295
+ limit: 200,
296
+ })
297
+ this.checkResponse(response)
298
+
299
+ if (response.members) {
300
+ for (const member of response.members) {
301
+ users.push({
302
+ id: member.id!,
303
+ name: member.name!,
304
+ real_name: member.real_name || member.name || '',
305
+ is_admin: member.is_admin || false,
306
+ is_owner: member.is_owner || false,
307
+ is_bot: member.is_bot || false,
308
+ is_app_user: member.is_app_user || false,
309
+ profile: member.profile
310
+ ? {
311
+ email: member.profile.email,
312
+ phone: member.profile.phone,
313
+ title: member.profile.title,
314
+ status_text: member.profile.status_text,
315
+ }
316
+ : undefined,
317
+ })
318
+ }
319
+ }
320
+
321
+ cursor = response.response_metadata?.next_cursor
322
+ } while (cursor)
323
+
324
+ return users
325
+ })
326
+ }
327
+
328
+ async getUser(id: string): Promise<SlackUser> {
329
+ return this.withRetry(async () => {
330
+ const response = await this.client.users.info({ user: id })
331
+ this.checkResponse(response)
332
+
333
+ const member = response.user!
334
+ return {
335
+ id: member.id!,
336
+ name: member.name!,
337
+ real_name: member.real_name || member.name || '',
338
+ is_admin: member.is_admin || false,
339
+ is_owner: member.is_owner || false,
340
+ is_bot: member.is_bot || false,
341
+ is_app_user: member.is_app_user || false,
342
+ profile: member.profile
343
+ ? {
344
+ email: member.profile.email,
345
+ phone: member.profile.phone,
346
+ title: member.profile.title,
347
+ status_text: member.profile.status_text,
348
+ }
349
+ : undefined,
350
+ }
351
+ })
352
+ }
353
+
354
+ async uploadFile(channels: string[], file: Buffer, filename: string): Promise<SlackFile> {
355
+ return this.withRetry(async () => {
356
+ const response = await this.client.files.uploadV2({
357
+ channel_id: channels[0],
358
+ file,
359
+ filename,
360
+ })
361
+ this.checkResponse(response)
362
+
363
+ const f = response.file as any
364
+ return {
365
+ id: f.id!,
366
+ name: f.name!,
367
+ title: f.title || f.name || '',
368
+ mimetype: f.mimetype || 'application/octet-stream',
369
+ size: f.size || 0,
370
+ url_private: f.url_private || '',
371
+ created: f.created || 0,
372
+ user: f.user || '',
373
+ channels: f.channels,
374
+ }
375
+ })
376
+ }
377
+
378
+ async listFiles(channel?: string): Promise<SlackFile[]> {
379
+ return this.withRetry(async () => {
380
+ const response = await this.client.files.list({
381
+ channel,
382
+ })
383
+ this.checkResponse(response)
384
+
385
+ return (response.files || []).map((f) => ({
386
+ id: f.id!,
387
+ name: f.name!,
388
+ title: f.title || f.name || '',
389
+ mimetype: f.mimetype || 'application/octet-stream',
390
+ size: f.size || 0,
391
+ url_private: f.url_private || '',
392
+ created: f.created || 0,
393
+ user: f.user || '',
394
+ channels: f.channels,
395
+ }))
396
+ })
397
+ }
398
+
399
+ async searchMessages(
400
+ query: string,
401
+ options: { sort?: 'score' | 'timestamp'; sortDir?: 'asc' | 'desc'; count?: number } = {}
402
+ ): Promise<SlackSearchResult[]> {
403
+ return this.withRetry(async () => {
404
+ const response = await this.client.search.messages({
405
+ query,
406
+ sort: options.sort || 'timestamp',
407
+ sort_dir: options.sortDir || 'desc',
408
+ count: options.count || 20,
409
+ })
410
+ this.checkResponse(response)
411
+
412
+ const matches = (response.messages as any)?.matches || []
413
+ return matches.map((match: any) => ({
414
+ ts: match.ts,
415
+ text: match.text || '',
416
+ user: match.user,
417
+ username: match.username,
418
+ channel: {
419
+ id: match.channel?.id || '',
420
+ name: match.channel?.name || '',
421
+ },
422
+ permalink: match.permalink || '',
423
+ }))
424
+ })
425
+ }
426
+
427
+ async getThreadReplies(
428
+ channel: string,
429
+ threadTs: string,
430
+ options: { limit?: number; oldest?: string; latest?: string; cursor?: string } = {}
431
+ ): Promise<{ messages: SlackMessage[]; has_more: boolean; next_cursor?: string }> {
432
+ return this.withRetry(async () => {
433
+ const response = await this.client.conversations.replies({
434
+ channel,
435
+ ts: threadTs,
436
+ limit: options.limit || 100,
437
+ oldest: options.oldest,
438
+ latest: options.latest,
439
+ cursor: options.cursor,
440
+ })
441
+ this.checkResponse(response)
442
+
443
+ const messages = (response.messages || []).map((msg: any) => ({
444
+ ts: msg.ts!,
445
+ text: msg.text || '',
446
+ type: msg.type || 'message',
447
+ user: msg.user,
448
+ username: msg.username,
449
+ thread_ts: msg.thread_ts,
450
+ reply_count: msg.reply_count,
451
+ edited: msg.edited
452
+ ? {
453
+ user: msg.edited.user || '',
454
+ ts: msg.edited.ts || '',
455
+ }
456
+ : undefined,
457
+ }))
458
+
459
+ return {
460
+ messages,
461
+ has_more: response.has_more || false,
462
+ next_cursor: response.response_metadata?.next_cursor,
463
+ }
464
+ })
465
+ }
466
+ }
@@ -0,0 +1,211 @@
1
+ import { Command } from 'commander'
2
+ import { handleError } from '../../../shared/utils/error-handler'
3
+ import { formatOutput } from '../../../shared/utils/output'
4
+ import { SlackClient } from '../client'
5
+ import { CredentialManager } from '../credential-manager'
6
+ import { TokenExtractor } from '../token-extractor'
7
+
8
+ async function extractAction(options: { pretty?: boolean; debug?: boolean }): Promise<void> {
9
+ try {
10
+ const extractor = new TokenExtractor()
11
+
12
+ if (process.platform === 'darwin') {
13
+ console.log('')
14
+ console.log(' Extracting your Slack credentials...')
15
+ console.log('')
16
+ console.log(' Your Mac may ask for your password to access Keychain.')
17
+ console.log(' This is required because Slack encrypts your login cookies')
18
+ console.log(' using macOS Keychain for security.')
19
+ console.log('')
20
+ console.log(' What happens:')
21
+ console.log(" 1. We read the encrypted cookie from Slack's local storage")
22
+ console.log(' 2. macOS Keychain decrypts it (requires your password)')
23
+ console.log(' 3. The credentials are stored locally in ~/.config/agent-messenger/')
24
+ console.log('')
25
+ console.log(' Your password is never stored or transmitted anywhere.')
26
+ console.log('')
27
+ }
28
+
29
+ if (options.debug) {
30
+ console.error(`[debug] Slack directory: ${extractor.getSlackDir()}`)
31
+ }
32
+
33
+ const workspaces = await extractor.extract()
34
+
35
+ if (options.debug) {
36
+ console.error(`[debug] Found ${workspaces.length} workspace(s)`)
37
+ for (const ws of workspaces) {
38
+ console.error(
39
+ `[debug] - ${ws.workspace_id}: token=${ws.token.substring(0, 20)}..., cookie=${ws.cookie ? 'present' : 'missing'}`
40
+ )
41
+ }
42
+ }
43
+
44
+ if (workspaces.length === 0) {
45
+ console.log(
46
+ formatOutput(
47
+ {
48
+ error: 'No workspaces found. Make sure Slack desktop app is installed and logged in.',
49
+ hint: options.debug ? undefined : 'Run with --debug for more info.',
50
+ },
51
+ options.pretty
52
+ )
53
+ )
54
+ process.exit(1)
55
+ }
56
+
57
+ const credManager = new CredentialManager()
58
+ const config = await credManager.load()
59
+
60
+ const validWorkspaces = []
61
+ for (const ws of workspaces) {
62
+ if (options.debug) {
63
+ console.error(`[debug] Testing credentials for ${ws.workspace_id}...`)
64
+ }
65
+
66
+ try {
67
+ const client = new SlackClient(ws.token, ws.cookie)
68
+ const authInfo = await client.testAuth()
69
+ ws.workspace_name = authInfo.team || ws.workspace_name
70
+ validWorkspaces.push(ws)
71
+ await credManager.setWorkspace(ws)
72
+
73
+ if (options.debug) {
74
+ console.error(`[debug] ✓ Valid: ${authInfo.team} (${authInfo.user})`)
75
+ }
76
+ } catch (error) {
77
+ if (options.debug) {
78
+ console.error(`[debug] ✗ Invalid: ${(error as Error).message}`)
79
+ }
80
+ }
81
+ }
82
+
83
+ if (validWorkspaces.length === 0) {
84
+ console.log(
85
+ formatOutput(
86
+ {
87
+ error:
88
+ 'Extracted tokens are invalid. Make sure you are logged into the Slack desktop app.',
89
+ extracted_count: workspaces.length,
90
+ },
91
+ options.pretty
92
+ )
93
+ )
94
+ process.exit(1)
95
+ }
96
+
97
+ if (!config.current_workspace && validWorkspaces.length > 0) {
98
+ await credManager.setCurrentWorkspace(validWorkspaces[0].workspace_id)
99
+ }
100
+
101
+ const output = {
102
+ workspaces: validWorkspaces.map((ws) => `${ws.workspace_id}/${ws.workspace_name}`),
103
+ current: config.current_workspace || validWorkspaces[0].workspace_id,
104
+ }
105
+
106
+ console.log(formatOutput(output, options.pretty))
107
+ } catch (error) {
108
+ handleError(error as Error)
109
+ }
110
+ }
111
+
112
+ async function logoutAction(
113
+ workspace: string | undefined,
114
+ options: { pretty?: boolean }
115
+ ): Promise<void> {
116
+ try {
117
+ const credManager = new CredentialManager()
118
+ const config = await credManager.load()
119
+
120
+ let targetWorkspace = workspace
121
+
122
+ if (!targetWorkspace) {
123
+ if (!config.current_workspace) {
124
+ console.log(
125
+ formatOutput(
126
+ { error: 'No current workspace set. Specify a workspace ID.' },
127
+ options.pretty
128
+ )
129
+ )
130
+ process.exit(1)
131
+ }
132
+ targetWorkspace = config.current_workspace
133
+ }
134
+
135
+ if (!config.workspaces[targetWorkspace]) {
136
+ console.log(
137
+ formatOutput({ error: `Workspace not found: ${targetWorkspace}` }, options.pretty)
138
+ )
139
+ process.exit(1)
140
+ }
141
+
142
+ await credManager.removeWorkspace(targetWorkspace)
143
+
144
+ console.log(formatOutput({ removed: targetWorkspace, success: true }, options.pretty))
145
+ } catch (error) {
146
+ handleError(error as Error)
147
+ }
148
+ }
149
+
150
+ async function statusAction(options: { pretty?: boolean }): Promise<void> {
151
+ try {
152
+ const credManager = new CredentialManager()
153
+ const ws = await credManager.getWorkspace()
154
+
155
+ if (!ws) {
156
+ console.log(
157
+ formatOutput(
158
+ { error: 'No workspace configured. Run "auth extract" first.' },
159
+ options.pretty
160
+ )
161
+ )
162
+ process.exit(1)
163
+ }
164
+
165
+ let authInfo: { user_id: string; team_id: string; user?: string; team?: string } | null = null
166
+ let valid = false
167
+
168
+ try {
169
+ const client = new SlackClient(ws.token, ws.cookie)
170
+ authInfo = await client.testAuth()
171
+ valid = true
172
+ } catch {
173
+ valid = false
174
+ }
175
+
176
+ const output = {
177
+ workspace_id: ws.workspace_id,
178
+ workspace_name: ws.workspace_name,
179
+ user: authInfo?.user,
180
+ team: authInfo?.team,
181
+ valid,
182
+ }
183
+
184
+ console.log(formatOutput(output, options.pretty))
185
+ } catch (error) {
186
+ handleError(error as Error)
187
+ }
188
+ }
189
+
190
+ export const authCommand = new Command('auth')
191
+ .description('Authentication commands')
192
+ .addCommand(
193
+ new Command('extract')
194
+ .description('Extract tokens from Slack desktop app')
195
+ .option('--pretty', 'Pretty print JSON output')
196
+ .option('--debug', 'Show debug output for troubleshooting')
197
+ .action(extractAction)
198
+ )
199
+ .addCommand(
200
+ new Command('logout')
201
+ .description('Logout from workspace')
202
+ .argument('[workspace]', 'Workspace ID')
203
+ .option('--pretty', 'Pretty print JSON output')
204
+ .action(logoutAction)
205
+ )
206
+ .addCommand(
207
+ new Command('status')
208
+ .description('Show authentication status')
209
+ .option('--pretty', 'Pretty print JSON output')
210
+ .action(statusAction)
211
+ )