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,127 @@
1
+ import { Command } from 'commander'
2
+ import { handleError } from '../../../shared/utils/error-handler'
3
+ import { formatOutput } from '../../../shared/utils/output'
4
+ import { DiscordClient } from '../client'
5
+ import { DiscordCredentialManager } from '../credential-manager'
6
+
7
+ export async function listAction(options: { pretty?: boolean }): Promise<void> {
8
+ try {
9
+ const credManager = new DiscordCredentialManager()
10
+ const config = await credManager.load()
11
+
12
+ if (!config.token || !config.current_guild) {
13
+ console.log(
14
+ formatOutput({ error: 'Not authenticated. Run "auth extract" first.' }, options.pretty)
15
+ )
16
+ process.exit(1)
17
+ }
18
+
19
+ const client = new DiscordClient(config.token)
20
+ const channels = await client.listChannels(config.current_guild)
21
+
22
+ const textChannels = channels.filter((ch) => ch.type === 0)
23
+
24
+ const output = textChannels.map((ch) => ({
25
+ id: ch.id,
26
+ name: ch.name,
27
+ type: ch.type,
28
+ parent_id: (ch as any).parent_id || null,
29
+ topic: ch.topic || null,
30
+ }))
31
+
32
+ console.log(formatOutput(output, options.pretty))
33
+ } catch (error) {
34
+ handleError(error as Error)
35
+ }
36
+ }
37
+
38
+ export async function infoAction(channelId: string, options: { pretty?: boolean }): Promise<void> {
39
+ try {
40
+ const credManager = new DiscordCredentialManager()
41
+ const config = await credManager.load()
42
+
43
+ if (!config.token) {
44
+ console.log(
45
+ formatOutput({ error: 'Not authenticated. Run "auth extract" first.' }, options.pretty)
46
+ )
47
+ process.exit(1)
48
+ }
49
+
50
+ const client = new DiscordClient(config.token)
51
+ const channel = await client.getChannel(channelId)
52
+
53
+ const output = {
54
+ id: channel.id,
55
+ name: channel.name,
56
+ type: channel.type,
57
+ guild_id: channel.guild_id,
58
+ topic: channel.topic || null,
59
+ parent_id: (channel as any).parent_id || null,
60
+ }
61
+
62
+ console.log(formatOutput(output, options.pretty))
63
+ } catch (error) {
64
+ handleError(error as Error)
65
+ }
66
+ }
67
+
68
+ export async function historyAction(
69
+ channelId: string,
70
+ options: { limit?: number; pretty?: boolean }
71
+ ): Promise<void> {
72
+ try {
73
+ const credManager = new DiscordCredentialManager()
74
+ const config = await credManager.load()
75
+
76
+ if (!config.token) {
77
+ console.log(
78
+ formatOutput({ error: 'Not authenticated. Run "auth extract" first.' }, options.pretty)
79
+ )
80
+ process.exit(1)
81
+ }
82
+
83
+ const client = new DiscordClient(config.token)
84
+ const messages = await client.getMessages(channelId, options.limit || 50)
85
+
86
+ const output = messages.map((msg) => ({
87
+ id: msg.id,
88
+ author: msg.author.username,
89
+ content: msg.content,
90
+ timestamp: msg.timestamp,
91
+ thread_id: msg.thread_id || null,
92
+ }))
93
+
94
+ console.log(formatOutput(output, options.pretty))
95
+ } catch (error) {
96
+ handleError(error as Error)
97
+ }
98
+ }
99
+
100
+ export const channelCommand = new Command('channel')
101
+ .description('Channel commands')
102
+ .addCommand(
103
+ new Command('list')
104
+ .description('List channels in current guild')
105
+ .option('--pretty', 'Pretty print JSON output')
106
+ .action(listAction)
107
+ )
108
+ .addCommand(
109
+ new Command('info')
110
+ .description('Get channel info')
111
+ .argument('<channel-id>', 'Channel ID')
112
+ .option('--pretty', 'Pretty print JSON output')
113
+ .action(infoAction)
114
+ )
115
+ .addCommand(
116
+ new Command('history')
117
+ .description('Get channel message history')
118
+ .argument('<channel-id>', 'Channel ID')
119
+ .option('--limit <n>', 'Number of messages to fetch', '50')
120
+ .option('--pretty', 'Pretty print JSON output')
121
+ .action((channelId, options) => {
122
+ historyAction(channelId, {
123
+ limit: parseInt(options.limit, 10),
124
+ pretty: options.pretty,
125
+ })
126
+ })
127
+ )
@@ -0,0 +1,98 @@
1
+ import { beforeEach, expect, mock, test } from 'bun:test'
2
+ import { infoAction, listAction, uploadAction } from './file'
3
+
4
+ mock.module('../client', () => ({
5
+ DiscordClient: mock(() => ({
6
+ uploadFile: mock(async () => ({
7
+ id: 'file_123',
8
+ filename: 'test.pdf',
9
+ size: 1024,
10
+ url: 'https://cdn.discordapp.com/attachments/123/456/test.pdf',
11
+ content_type: 'application/pdf',
12
+ })),
13
+ listFiles: mock(async () => [
14
+ {
15
+ id: 'file_123',
16
+ filename: 'test.pdf',
17
+ size: 1024,
18
+ url: 'https://cdn.discordapp.com/attachments/123/456/test.pdf',
19
+ content_type: 'application/pdf',
20
+ },
21
+ {
22
+ id: 'file_124',
23
+ filename: 'image.png',
24
+ size: 2048,
25
+ url: 'https://cdn.discordapp.com/attachments/123/457/image.png',
26
+ content_type: 'image/png',
27
+ },
28
+ ]),
29
+ })),
30
+ }))
31
+
32
+ mock.module('../credential-manager', () => ({
33
+ DiscordCredentialManager: mock(() => ({
34
+ load: mock(async () => ({
35
+ token: 'test_token',
36
+ current_guild: 'guild_123',
37
+ guilds: {},
38
+ })),
39
+ })),
40
+ }))
41
+
42
+ mock.module('../../../shared/utils/output', () => ({
43
+ formatOutput: (data: any, pretty?: boolean) => JSON.stringify(data, null, pretty ? 2 : 0),
44
+ }))
45
+
46
+ mock.module('../../../shared/utils/error-handler', () => ({
47
+ handleError: (error: Error) => {
48
+ console.error(error.message)
49
+ },
50
+ }))
51
+
52
+ mock.module('node:fs', () => ({
53
+ readFileSync: () => Buffer.from('test file content'),
54
+ }))
55
+
56
+ mock.module('node:path', () => ({
57
+ resolve: (path: string) => path,
58
+ }))
59
+
60
+ beforeEach(() => {
61
+ mock.restore()
62
+ })
63
+
64
+ test('upload: sends multipart request and returns file info', async () => {
65
+ const consoleSpy = mock((_msg: string) => {})
66
+ console.log = consoleSpy
67
+
68
+ await uploadAction('ch_456', '/path/to/test.pdf', { pretty: false })
69
+
70
+ expect(consoleSpy).toHaveBeenCalled()
71
+ const output = consoleSpy.mock.calls[0][0]
72
+ expect(output).toContain('file_123')
73
+ expect(output).toContain('test.pdf')
74
+ })
75
+
76
+ test('list: filters messages with attachments', async () => {
77
+ const consoleSpy = mock((_msg: string) => {})
78
+ console.log = consoleSpy
79
+
80
+ await listAction('ch_456', { pretty: false })
81
+
82
+ expect(consoleSpy).toHaveBeenCalled()
83
+ const output = consoleSpy.mock.calls[0][0]
84
+ expect(output).toContain('file_123')
85
+ expect(output).toContain('file_124')
86
+ })
87
+
88
+ test('info: returns single file details', async () => {
89
+ const consoleSpy = mock((_msg: string) => {})
90
+ console.log = consoleSpy
91
+
92
+ await infoAction('ch_456', 'file_123', { pretty: false })
93
+
94
+ expect(consoleSpy).toHaveBeenCalled()
95
+ const output = consoleSpy.mock.calls[0][0]
96
+ expect(output).toContain('file_123')
97
+ expect(output).toContain('test.pdf')
98
+ })
@@ -0,0 +1,134 @@
1
+ import { resolve } from 'node:path'
2
+ import { Command } from 'commander'
3
+ import { handleError } from '../../../shared/utils/error-handler'
4
+ import { formatOutput } from '../../../shared/utils/output'
5
+ import { DiscordClient } from '../client'
6
+ import { DiscordCredentialManager } from '../credential-manager'
7
+ import type { DiscordFile } from '../types'
8
+
9
+ export async function uploadAction(
10
+ channelId: string,
11
+ path: string,
12
+ options: { filename?: string; pretty?: boolean }
13
+ ): Promise<void> {
14
+ try {
15
+ const credManager = new DiscordCredentialManager()
16
+ const config = await credManager.load()
17
+
18
+ if (!config.token) {
19
+ console.log(
20
+ formatOutput({ error: 'Not authenticated. Run "auth extract" first.' }, options.pretty)
21
+ )
22
+ process.exit(1)
23
+ }
24
+
25
+ const client = new DiscordClient(config.token)
26
+
27
+ const filePath = resolve(path)
28
+ const file = await client.uploadFile(channelId, filePath)
29
+
30
+ const output = {
31
+ id: file.id,
32
+ filename: file.filename,
33
+ size: file.size,
34
+ url: file.url,
35
+ content_type: file.content_type || null,
36
+ }
37
+
38
+ console.log(formatOutput(output, options.pretty))
39
+ } catch (error) {
40
+ handleError(error as Error)
41
+ }
42
+ }
43
+
44
+ export async function listAction(channelId: string, options: { pretty?: boolean }): Promise<void> {
45
+ try {
46
+ const credManager = new DiscordCredentialManager()
47
+ const config = await credManager.load()
48
+
49
+ if (!config.token) {
50
+ console.log(
51
+ formatOutput({ error: 'Not authenticated. Run "auth extract" first.' }, options.pretty)
52
+ )
53
+ process.exit(1)
54
+ }
55
+
56
+ const client = new DiscordClient(config.token)
57
+ const files = await client.listFiles(channelId)
58
+
59
+ const output = files.map((file: DiscordFile) => ({
60
+ id: file.id,
61
+ filename: file.filename,
62
+ size: file.size,
63
+ url: file.url,
64
+ content_type: file.content_type || null,
65
+ }))
66
+
67
+ console.log(formatOutput(output, options.pretty))
68
+ } catch (error) {
69
+ handleError(error as Error)
70
+ }
71
+ }
72
+
73
+ export async function infoAction(
74
+ channelId: string,
75
+ fileId: string,
76
+ options: { pretty?: boolean }
77
+ ): Promise<void> {
78
+ try {
79
+ const credManager = new DiscordCredentialManager()
80
+ const config = await credManager.load()
81
+
82
+ if (!config.token) {
83
+ console.log(
84
+ formatOutput({ error: 'Not authenticated. Run "auth extract" first.' }, options.pretty)
85
+ )
86
+ process.exit(1)
87
+ }
88
+
89
+ const client = new DiscordClient(config.token)
90
+ const files = await client.listFiles(channelId)
91
+ const fileData = files.find((f) => f.id === fileId)
92
+
93
+ if (!fileData) {
94
+ console.log(formatOutput({ error: `File not found: ${fileId}` }, options.pretty))
95
+ process.exit(1)
96
+ }
97
+
98
+ const output = {
99
+ id: fileData.id,
100
+ filename: fileData.filename,
101
+ size: fileData.size,
102
+ url: fileData.url,
103
+ content_type: fileData.content_type || null,
104
+ }
105
+
106
+ console.log(formatOutput(output, options.pretty))
107
+ } catch (error) {
108
+ handleError(error as Error)
109
+ }
110
+ }
111
+
112
+ export const fileCommand = new Command('file')
113
+ .description('file commands')
114
+ .addCommand(
115
+ new Command('upload')
116
+ .description('upload file to channel')
117
+ .argument('<channel>', 'channel ID')
118
+ .argument('<path>', 'file path')
119
+ .option('--filename <name>', 'override filename')
120
+ .action(uploadAction)
121
+ )
122
+ .addCommand(
123
+ new Command('list')
124
+ .description('list files in channel')
125
+ .argument('<channel>', 'channel ID')
126
+ .action(listAction)
127
+ )
128
+ .addCommand(
129
+ new Command('info')
130
+ .description('show file details')
131
+ .argument('<channel>', 'channel ID')
132
+ .argument('<file>', 'file ID')
133
+ .action(infoAction)
134
+ )
@@ -0,0 +1,117 @@
1
+ import { expect, mock, test } from 'bun:test'
2
+ import { DiscordClient } from '../client'
3
+ import { DiscordCredentialManager } from '../credential-manager'
4
+
5
+ // Mock modules
6
+ mock.module('../client', () => ({
7
+ DiscordClient: mock((_token: string) => ({
8
+ listGuilds: mock(async () => [
9
+ { id: 'guild-1', name: 'Guild One', icon: 'icon1', owner: true },
10
+ { id: 'guild-2', name: 'Guild Two', icon: 'icon2', owner: false },
11
+ ]),
12
+ getGuild: mock(async (guildId: string) => {
13
+ if (guildId === 'guild-1') {
14
+ return { id: 'guild-1', name: 'Guild One', icon: 'icon1', owner: true }
15
+ }
16
+ if (guildId === 'guild-2') {
17
+ return { id: 'guild-2', name: 'Guild Two', icon: 'icon2', owner: false }
18
+ }
19
+ throw new Error('Guild not found')
20
+ }),
21
+ })),
22
+ }))
23
+
24
+ mock.module('../credential-manager', () => ({
25
+ DiscordCredentialManager: mock(() => ({
26
+ load: mock(async () => ({
27
+ token: 'test-token',
28
+ current_guild: 'guild-1',
29
+ guilds: {
30
+ 'guild-1': { guild_id: 'guild-1', guild_name: 'Guild One' },
31
+ 'guild-2': { guild_id: 'guild-2', guild_name: 'Guild Two' },
32
+ },
33
+ })),
34
+ setCurrentGuild: mock(async () => {}),
35
+ getCurrentGuild: mock(async () => 'guild-1'),
36
+ })),
37
+ }))
38
+
39
+ test('list: returns guilds with current marker', async () => {
40
+ // given: credential manager with guilds
41
+ const credManager = new DiscordCredentialManager()
42
+ const config = await credManager.load()
43
+
44
+ // when: list action is called
45
+ expect(config.guilds).toBeDefined()
46
+ expect(Object.keys(config.guilds)).toHaveLength(2)
47
+
48
+ // then: guilds are returned
49
+ expect(config.guilds['guild-1']).toBeDefined()
50
+ expect(config.guilds['guild-2']).toBeDefined()
51
+ })
52
+
53
+ test('list: marks current guild', async () => {
54
+ // given: credential manager with current guild set
55
+ const credManager = new DiscordCredentialManager()
56
+ const config = await credManager.load()
57
+ const current = await credManager.getCurrentGuild()
58
+
59
+ // when: checking current guild
60
+ expect(current).toBe('guild-1')
61
+
62
+ // then: current guild is marked
63
+ expect(config.current_guild).toBe('guild-1')
64
+ })
65
+
66
+ test('info: returns guild details', async () => {
67
+ // given: discord client with guild data
68
+ const client = new DiscordClient('test-token')
69
+ const guild = await client.getGuild('guild-1')
70
+
71
+ // when: getting guild info
72
+ expect(guild).toBeDefined()
73
+
74
+ // then: guild details are returned
75
+ expect(guild.id).toBe('guild-1')
76
+ expect(guild.name).toBe('Guild One')
77
+ expect(guild.icon).toBe('icon1')
78
+ expect(guild.owner).toBe(true)
79
+ })
80
+
81
+ test('info: throws error for non-existent guild', async () => {
82
+ // given: discord client
83
+ const client = new DiscordClient('test-token')
84
+
85
+ // when: getting non-existent guild
86
+ // then: error is thrown
87
+ try {
88
+ await client.getGuild('non-existent')
89
+ expect(true).toBe(false) // should not reach here
90
+ } catch (error) {
91
+ expect((error as Error).message).toContain('Guild not found')
92
+ }
93
+ })
94
+
95
+ test('switch: updates current guild', async () => {
96
+ // given: credential manager
97
+ const credManager = new DiscordCredentialManager()
98
+
99
+ // when: switching guild
100
+ await credManager.setCurrentGuild('guild-2')
101
+
102
+ // then: setCurrentGuild is called
103
+ expect(credManager.setCurrentGuild).toHaveBeenCalledWith('guild-2')
104
+ })
105
+
106
+ test('current: returns current guild info', async () => {
107
+ // given: credential manager with current guild
108
+ const credManager = new DiscordCredentialManager()
109
+ const config = await credManager.load()
110
+
111
+ // when: getting current guild
112
+ const current = await credManager.getCurrentGuild()
113
+
114
+ // then: current guild is returned
115
+ expect(current).toBe('guild-1')
116
+ expect(config.current_guild).toBe('guild-1')
117
+ })
@@ -0,0 +1,129 @@
1
+ import { Command } from 'commander'
2
+ import { handleError } from '../../../shared/utils/error-handler'
3
+ import { formatOutput } from '../../../shared/utils/output'
4
+ import { DiscordClient } from '../client'
5
+ import { DiscordCredentialManager } from '../credential-manager'
6
+
7
+ export async function listAction(options: { pretty?: boolean }): Promise<void> {
8
+ try {
9
+ const credManager = new DiscordCredentialManager()
10
+ const config = await credManager.load()
11
+ const guilds = Object.values(config.guilds)
12
+
13
+ const output = guilds.map((guild) => ({
14
+ id: guild.guild_id,
15
+ name: guild.guild_name,
16
+ current: guild.guild_id === config.current_guild,
17
+ }))
18
+
19
+ console.log(formatOutput(output, options.pretty))
20
+ } catch (error) {
21
+ handleError(error as Error)
22
+ }
23
+ }
24
+
25
+ export async function infoAction(guildId: string, options: { pretty?: boolean }): Promise<void> {
26
+ try {
27
+ const credManager = new DiscordCredentialManager()
28
+ const config = await credManager.load()
29
+
30
+ if (!config.token) {
31
+ console.log(
32
+ formatOutput({ error: 'Not authenticated. Run "auth extract" first.' }, options.pretty)
33
+ )
34
+ process.exit(1)
35
+ }
36
+
37
+ const client = new DiscordClient(config.token)
38
+ const guild = await client.getGuild(guildId)
39
+
40
+ const output = {
41
+ id: guild.id,
42
+ name: guild.name,
43
+ icon: guild.icon,
44
+ owner: guild.owner,
45
+ }
46
+
47
+ console.log(formatOutput(output, options.pretty))
48
+ } catch (error) {
49
+ handleError(error as Error)
50
+ }
51
+ }
52
+
53
+ export async function switchAction(guildId: string, options: { pretty?: boolean }): Promise<void> {
54
+ try {
55
+ const credManager = new DiscordCredentialManager()
56
+ const config = await credManager.load()
57
+
58
+ if (!config.guilds[guildId]) {
59
+ console.log(formatOutput({ error: `Guild not found: ${guildId}` }, options.pretty))
60
+ process.exit(1)
61
+ }
62
+
63
+ await credManager.setCurrentGuild(guildId)
64
+ console.log(formatOutput({ current: guildId }, options.pretty))
65
+ } catch (error) {
66
+ handleError(error as Error)
67
+ }
68
+ }
69
+
70
+ export async function currentAction(options: { pretty?: boolean }): Promise<void> {
71
+ try {
72
+ const credManager = new DiscordCredentialManager()
73
+ const config = await credManager.load()
74
+
75
+ if (!config.current_guild) {
76
+ console.log(
77
+ formatOutput({ error: 'No current guild set. Run "auth extract" first.' }, options.pretty)
78
+ )
79
+ process.exit(1)
80
+ }
81
+
82
+ const guild = config.guilds[config.current_guild]
83
+
84
+ if (!guild) {
85
+ console.log(
86
+ formatOutput({ error: 'Current guild not found in configuration.' }, options.pretty)
87
+ )
88
+ process.exit(1)
89
+ }
90
+
91
+ const output = {
92
+ guild_id: guild.guild_id,
93
+ guild_name: guild.guild_name,
94
+ }
95
+
96
+ console.log(formatOutput(output, options.pretty))
97
+ } catch (error) {
98
+ handleError(error as Error)
99
+ }
100
+ }
101
+
102
+ export const guildCommand = new Command('guild')
103
+ .description('Guild management commands')
104
+ .addCommand(
105
+ new Command('list')
106
+ .description('List all guilds')
107
+ .option('--pretty', 'Pretty print JSON output')
108
+ .action(listAction)
109
+ )
110
+ .addCommand(
111
+ new Command('info')
112
+ .description('Get guild info')
113
+ .argument('<guild-id>', 'Guild ID')
114
+ .option('--pretty', 'Pretty print JSON output')
115
+ .action(infoAction)
116
+ )
117
+ .addCommand(
118
+ new Command('switch')
119
+ .description('Switch to guild')
120
+ .argument('<guild-id>', 'Guild ID')
121
+ .option('--pretty', 'Pretty print JSON output')
122
+ .action(switchAction)
123
+ )
124
+ .addCommand(
125
+ new Command('current')
126
+ .description('Show current guild')
127
+ .option('--pretty', 'Pretty print JSON output')
128
+ .action(currentAction)
129
+ )
@@ -0,0 +1,8 @@
1
+ export { authCommand } from './auth'
2
+ export { channelCommand } from './channel'
3
+ export { fileCommand } from './file'
4
+ export { guildCommand } from './guild'
5
+ export { messageCommand } from './message'
6
+ export { reactionCommand } from './reaction'
7
+ export { snapshotCommand } from './snapshot'
8
+ export { userCommand } from './user'