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,53 @@
1
+ import { describe, expect, test } from 'bun:test'
2
+ import { parallelMap } from './concurrency'
3
+
4
+ describe('parallelMap', () => {
5
+ test('processes items in parallel', async () => {
6
+ const items = [1, 2, 3, 4, 5]
7
+ const results = await parallelMap(items, async (n) => n * 2)
8
+ expect(results).toEqual([2, 4, 6, 8, 10])
9
+ })
10
+
11
+ test('maintains order of results', async () => {
12
+ const items = [100, 50, 10]
13
+ const results = await parallelMap(
14
+ items,
15
+ async (delay) => {
16
+ await new Promise((r) => setTimeout(r, delay))
17
+ return delay
18
+ },
19
+ 3
20
+ )
21
+ expect(results).toEqual([100, 50, 10])
22
+ })
23
+
24
+ test('respects concurrency limit', async () => {
25
+ let concurrent = 0
26
+ let maxConcurrent = 0
27
+ const items = [1, 2, 3, 4, 5, 6]
28
+
29
+ await parallelMap(
30
+ items,
31
+ async () => {
32
+ concurrent++
33
+ maxConcurrent = Math.max(maxConcurrent, concurrent)
34
+ await new Promise((r) => setTimeout(r, 10))
35
+ concurrent--
36
+ },
37
+ 2
38
+ )
39
+
40
+ expect(maxConcurrent).toBe(2)
41
+ })
42
+
43
+ test('handles empty array', async () => {
44
+ const results = await parallelMap([], async (n: number) => n * 2)
45
+ expect(results).toEqual([])
46
+ })
47
+
48
+ test('passes index to function', async () => {
49
+ const items = ['a', 'b', 'c']
50
+ const results = await parallelMap(items, async (item, index) => `${item}${index}`)
51
+ expect(results).toEqual(['a0', 'b1', 'c2'])
52
+ })
53
+ })
@@ -0,0 +1,20 @@
1
+ export async function parallelMap<T, R>(
2
+ items: T[],
3
+ fn: (item: T, index: number) => Promise<R>,
4
+ concurrency = 5
5
+ ): Promise<R[]> {
6
+ const results: R[] = new Array(items.length)
7
+ let currentIndex = 0
8
+
9
+ async function worker(): Promise<void> {
10
+ while (currentIndex < items.length) {
11
+ const index = currentIndex++
12
+ results[index] = await fn(items[index], index)
13
+ }
14
+ }
15
+
16
+ const workers = Array.from({ length: Math.min(concurrency, items.length) }, () => worker())
17
+ await Promise.all(workers)
18
+
19
+ return results
20
+ }
@@ -0,0 +1,4 @@
1
+ export function handleError(error: Error): void {
2
+ console.error(JSON.stringify({ error: error.message }))
3
+ process.exit(1)
4
+ }
@@ -0,0 +1,3 @@
1
+ export function formatOutput(data: unknown, pretty?: boolean): string {
2
+ return pretty ? JSON.stringify(data, null, 2) : JSON.stringify(data)
3
+ }
@@ -0,0 +1,94 @@
1
+ import { describe, expect, test } from 'bun:test'
2
+ import { spawn } from 'bun'
3
+ import pkg from '../package.json'
4
+ import { handleError } from '../src/shared/utils/error-handler'
5
+ import { formatOutput } from '../src/shared/utils/output'
6
+
7
+ describe('CLI Framework', () => {
8
+ describe('formatOutput utility', () => {
9
+ test('formats JSON without pretty flag', () => {
10
+ const data = { message: 'hello', count: 42 }
11
+ const result = formatOutput(data, false)
12
+ expect(result).toBe('{"message":"hello","count":42}')
13
+ })
14
+
15
+ test('formats JSON with pretty flag', () => {
16
+ const data = { message: 'hello', count: 42 }
17
+ const result = formatOutput(data, true)
18
+ const expected = JSON.stringify(data, null, 2)
19
+ expect(result).toBe(expected)
20
+ })
21
+
22
+ test('handles arrays', () => {
23
+ const data = [1, 2, 3]
24
+ const result = formatOutput(data, false)
25
+ expect(result).toBe('[1,2,3]')
26
+ })
27
+
28
+ test('handles nested objects with pretty flag', () => {
29
+ const data = { user: { name: 'Alice', id: 1 } }
30
+ const result = formatOutput(data, true)
31
+ expect(result).toContain('"user"')
32
+ expect(result).toContain('"name"')
33
+ })
34
+ })
35
+
36
+ describe('handleError utility', () => {
37
+ test('logs error as JSON and exits', () => {
38
+ const originalExit = process.exit
39
+ const originalError = console.error
40
+ let capturedOutput = ''
41
+
42
+ console.error = (msg: string) => {
43
+ capturedOutput = msg
44
+ }
45
+ process.exit = (() => {
46
+ throw new Error('EXIT_CALLED')
47
+ }) as never
48
+
49
+ try {
50
+ handleError(new Error('Test error'))
51
+ } catch (e) {
52
+ if (e instanceof Error && e.message === 'EXIT_CALLED') {
53
+ expect(capturedOutput).toContain('Test error')
54
+ expect(capturedOutput).toContain('error')
55
+ }
56
+ }
57
+
58
+ console.error = originalError
59
+ process.exit = originalExit
60
+ })
61
+ })
62
+
63
+ describe('Slack CLI program structure', () => {
64
+ test('--help shows all commands and global options', async () => {
65
+ const proc = spawn(['bun', 'run', './src/platforms/slack/cli.ts', '--help'], {
66
+ cwd: process.cwd(),
67
+ stdio: ['pipe', 'pipe', 'pipe'],
68
+ })
69
+
70
+ const output = await new Response(proc.stdout).text()
71
+
72
+ expect(output).toContain('auth')
73
+ expect(output).toContain('workspace')
74
+ expect(output).toContain('message')
75
+ expect(output).toContain('channel')
76
+ expect(output).toContain('user')
77
+ expect(output).toContain('reaction')
78
+ expect(output).toContain('file')
79
+ expect(output).toContain('snapshot')
80
+ expect(output).toContain('--pretty')
81
+ expect(output).toContain('--workspace')
82
+ })
83
+
84
+ test('--version shows package version', async () => {
85
+ const proc = spawn(['bun', 'run', './src/platforms/slack/cli.ts', '--version'], {
86
+ cwd: process.cwd(),
87
+ stdio: ['pipe', 'pipe', 'pipe'],
88
+ })
89
+
90
+ const output = await new Response(proc.stdout).text()
91
+ expect(output.trim()).toBe(pkg.version)
92
+ })
93
+ })
94
+ })
@@ -0,0 +1,383 @@
1
+ import { afterAll, beforeEach, describe, expect, mock, test } from 'bun:test'
2
+ import { mkdirSync, rmSync } from 'node:fs'
3
+ import { homedir } from 'node:os'
4
+ import { join } from 'node:path'
5
+ import { CredentialManager } from '../../src/platforms/slack/credential-manager'
6
+ import { type ExtractedWorkspace, TokenExtractor } from '../../src/platforms/slack/token-extractor'
7
+
8
+ const testConfigDir = join(import.meta.dir, '.test-auth-config')
9
+ const testSlackDir = join(import.meta.dir, '.test-slack-data')
10
+
11
+ describe('TokenExtractor', () => {
12
+ let extractor: TokenExtractor
13
+
14
+ beforeEach(() => {
15
+ rmSync(testSlackDir, { recursive: true, force: true })
16
+ mkdirSync(testSlackDir, { recursive: true })
17
+ })
18
+
19
+ afterAll(() => {
20
+ rmSync(testSlackDir, { recursive: true, force: true })
21
+ })
22
+
23
+ describe('getSlackDir', () => {
24
+ test('returns correct path for darwin', () => {
25
+ // Given: Platform is darwin
26
+ extractor = new TokenExtractor('darwin')
27
+
28
+ // When: getSlackDir is called
29
+ const dir = extractor.getSlackDir()
30
+
31
+ // Then: Should return macOS path (direct or sandboxed depending on what exists)
32
+ const directPath = join(homedir(), 'Library', 'Application Support', 'Slack')
33
+ const sandboxedPath = join(
34
+ homedir(),
35
+ 'Library',
36
+ 'Containers',
37
+ 'com.tinyspeck.slackmacgap',
38
+ 'Data',
39
+ 'Library',
40
+ 'Application Support',
41
+ 'Slack'
42
+ )
43
+ expect([directPath, sandboxedPath]).toContain(dir)
44
+ })
45
+
46
+ test('returns correct path for linux', () => {
47
+ // Given: Platform is linux
48
+ extractor = new TokenExtractor('linux')
49
+
50
+ // When: getSlackDir is called
51
+ const dir = extractor.getSlackDir()
52
+
53
+ // Then: Should return Linux path
54
+ expect(dir).toBe(join(homedir(), '.config', 'Slack'))
55
+ })
56
+
57
+ test('returns correct path for win32', () => {
58
+ // Given: Platform is win32
59
+ extractor = new TokenExtractor('win32')
60
+
61
+ // When: getSlackDir is called
62
+ const dir = extractor.getSlackDir()
63
+
64
+ // Then: Should return Windows path
65
+ expect(dir).toContain('Slack')
66
+ })
67
+
68
+ test('throws error for unsupported platform', () => {
69
+ // Given: Platform is unsupported
70
+ // When/Then: Constructor should throw
71
+ expect(() => new TokenExtractor('freebsd' as NodeJS.Platform)).toThrow('Unsupported platform')
72
+ })
73
+ })
74
+
75
+ describe('extract', () => {
76
+ test('throws error when Slack directory does not exist', async () => {
77
+ // Given: Slack directory does not exist
78
+ extractor = new TokenExtractor('darwin', '/nonexistent/path')
79
+
80
+ // When/Then: extract should throw
81
+ await expect(extractor.extract()).rejects.toThrow('Slack directory not found')
82
+ })
83
+
84
+ test('returns empty array when no tokens found', async () => {
85
+ // Given: Slack directory exists but has no tokens
86
+ mkdirSync(join(testSlackDir, 'storage'), { recursive: true })
87
+ extractor = new TokenExtractor('darwin', testSlackDir)
88
+
89
+ // When: extract is called
90
+ const result = await extractor.extract()
91
+
92
+ // Then: Should return empty array
93
+ expect(result).toEqual([])
94
+ })
95
+ })
96
+
97
+ describe('extractTokensFromLevelDB', () => {
98
+ test('extracts xoxc tokens from LevelDB', async () => {
99
+ // Given: LevelDB with xoxc token data
100
+ // This test requires mocking LevelDB - we'll test the integration
101
+ extractor = new TokenExtractor('darwin', testSlackDir)
102
+
103
+ // When: extractTokensFromLevelDB is called
104
+ // Then: Should extract tokens (mocked in integration test)
105
+ expect(extractor).toBeDefined()
106
+ })
107
+ })
108
+
109
+ describe('extractCookieFromSQLite', () => {
110
+ test('extracts xoxd cookie from SQLite', async () => {
111
+ // Given: SQLite Cookies database with d cookie
112
+ // This test requires mocking SQLite - we'll test the integration
113
+ extractor = new TokenExtractor('darwin', testSlackDir)
114
+
115
+ // When: extractCookieFromSQLite is called
116
+ // Then: Should extract cookie (mocked in integration test)
117
+ expect(extractor).toBeDefined()
118
+ })
119
+ })
120
+ })
121
+
122
+ describe('Auth Commands Integration', () => {
123
+ let credManager: CredentialManager
124
+
125
+ beforeEach(() => {
126
+ rmSync(testConfigDir, { recursive: true, force: true })
127
+ credManager = new CredentialManager(testConfigDir)
128
+ })
129
+
130
+ afterAll(() => {
131
+ rmSync(testConfigDir, { recursive: true, force: true })
132
+ })
133
+
134
+ describe('auth extract', () => {
135
+ test('stores extracted workspaces in credential manager', async () => {
136
+ // Given: Extracted workspaces
137
+ const workspaces: ExtractedWorkspace[] = [
138
+ {
139
+ workspace_id: 'T123',
140
+ workspace_name: 'acme-corp',
141
+ token: 'xoxc-123-456',
142
+ cookie: 'xoxd-abc',
143
+ },
144
+ {
145
+ workspace_id: 'T456',
146
+ workspace_name: 'side-project',
147
+ token: 'xoxc-789-012',
148
+ cookie: 'xoxd-def',
149
+ },
150
+ ]
151
+
152
+ // When: Workspaces are stored
153
+ for (const ws of workspaces) {
154
+ await credManager.setWorkspace(ws)
155
+ }
156
+ await credManager.setCurrentWorkspace('T123')
157
+
158
+ // Then: All workspaces should be retrievable
159
+ const config = await credManager.load()
160
+ expect(Object.keys(config.workspaces)).toHaveLength(2)
161
+ expect(config.current_workspace).toBe('T123')
162
+ expect(config.workspaces.T123.token).toBe('xoxc-123-456')
163
+ expect(config.workspaces.T456.token).toBe('xoxc-789-012')
164
+ })
165
+
166
+ test('sets first workspace as current if none exists', async () => {
167
+ // Given: No current workspace
168
+ const workspace: ExtractedWorkspace = {
169
+ workspace_id: 'T789',
170
+ workspace_name: 'new-workspace',
171
+ token: 'xoxc-new',
172
+ cookie: 'xoxd-new',
173
+ }
174
+
175
+ // When: First workspace is stored
176
+ await credManager.setWorkspace(workspace)
177
+ const config = await credManager.load()
178
+
179
+ // Then: If no current, should set first as current
180
+ if (!config.current_workspace) {
181
+ await credManager.setCurrentWorkspace('T789')
182
+ }
183
+
184
+ const updated = await credManager.load()
185
+ expect(updated.current_workspace).toBe('T789')
186
+ })
187
+ })
188
+
189
+ describe('auth logout', () => {
190
+ test('removes workspace by id', async () => {
191
+ // Given: A workspace exists
192
+ await credManager.setWorkspace({
193
+ workspace_id: 'T-logout',
194
+ workspace_name: 'to-logout',
195
+ token: 'xoxc-logout',
196
+ cookie: 'xoxd-logout',
197
+ })
198
+
199
+ // When: Workspace is removed
200
+ await credManager.removeWorkspace('T-logout')
201
+
202
+ // Then: Workspace should not exist
203
+ const ws = await credManager.getWorkspace('T-logout')
204
+ expect(ws).toBeNull()
205
+ })
206
+
207
+ test('removes current workspace and clears current', async () => {
208
+ // Given: Current workspace is set
209
+ await credManager.setWorkspace({
210
+ workspace_id: 'T-current',
211
+ workspace_name: 'current',
212
+ token: 'xoxc-current',
213
+ cookie: 'xoxd-current',
214
+ })
215
+ await credManager.setCurrentWorkspace('T-current')
216
+
217
+ // When: Current workspace is removed
218
+ await credManager.removeWorkspace('T-current')
219
+
220
+ // Then: Current should be null
221
+ const config = await credManager.load()
222
+ expect(config.current_workspace).toBeNull()
223
+ })
224
+
225
+ test('throws error when workspace not found', async () => {
226
+ // Given: Workspace does not exist
227
+ // When: Trying to get non-existent workspace
228
+ const ws = await credManager.getWorkspace('nonexistent')
229
+
230
+ // Then: Should return null (command should handle this)
231
+ expect(ws).toBeNull()
232
+ })
233
+ })
234
+
235
+ describe('auth status', () => {
236
+ test('returns current workspace info', async () => {
237
+ // Given: A current workspace is set
238
+ await credManager.setWorkspace({
239
+ workspace_id: 'T-status',
240
+ workspace_name: 'status-test',
241
+ token: 'xoxc-status',
242
+ cookie: 'xoxd-status',
243
+ })
244
+ await credManager.setCurrentWorkspace('T-status')
245
+
246
+ // When: Getting current workspace
247
+ const ws = await credManager.getWorkspace()
248
+
249
+ // Then: Should return workspace info
250
+ expect(ws).not.toBeNull()
251
+ expect(ws?.workspace_id).toBe('T-status')
252
+ expect(ws?.workspace_name).toBe('status-test')
253
+ })
254
+
255
+ test('returns null when no workspace configured', async () => {
256
+ // Given: No workspace configured
257
+ // When: Getting current workspace
258
+ const ws = await credManager.getWorkspace()
259
+
260
+ // Then: Should return null
261
+ expect(ws).toBeNull()
262
+ })
263
+
264
+ test('validates token with Slack API', async () => {
265
+ // Given: A workspace with valid credentials
266
+ // This would require mocking SlackClient.testAuth()
267
+ // We test the integration pattern here
268
+
269
+ const mockTestAuth = mock(() =>
270
+ Promise.resolve({
271
+ user_id: 'U123',
272
+ team_id: 'T123',
273
+ user: 'testuser',
274
+ team: 'Test Team',
275
+ })
276
+ )
277
+
278
+ // When: testAuth is called
279
+ const result = await mockTestAuth()
280
+
281
+ // Then: Should return auth info
282
+ expect(result.user_id).toBe('U123')
283
+ expect(result.team_id).toBe('T123')
284
+ expect(result.user).toBe('testuser')
285
+ expect(result.team).toBe('Test Team')
286
+ })
287
+ })
288
+ })
289
+
290
+ describe('Platform Detection', () => {
291
+ test('auto-detects current platform', () => {
292
+ // Given: Running on current platform
293
+ const platform = process.platform
294
+
295
+ // When: TokenExtractor is created without explicit platform
296
+ const _extractor = new TokenExtractor()
297
+
298
+ // Then: Should use current platform
299
+ expect(['darwin', 'linux', 'win32']).toContain(platform)
300
+ })
301
+ })
302
+
303
+ describe('Output Formatting', () => {
304
+ test('formats extract output correctly', () => {
305
+ // Given: Extracted workspaces
306
+ const output = {
307
+ workspaces: ['T123/acme-corp', 'T456/side-project'],
308
+ current: 'T123',
309
+ }
310
+
311
+ // When: Formatted as JSON
312
+ const json = JSON.stringify(output)
313
+ const pretty = JSON.stringify(output, null, 2)
314
+
315
+ // Then: Should be valid JSON
316
+ expect(JSON.parse(json)).toEqual(output)
317
+ expect(pretty).toContain('\n')
318
+ })
319
+
320
+ test('formats status output correctly', () => {
321
+ // Given: Status info
322
+ const output = {
323
+ workspace_id: 'T123',
324
+ workspace_name: 'acme-corp',
325
+ user: 'testuser',
326
+ team: 'Acme Corp',
327
+ valid: true,
328
+ }
329
+
330
+ // When: Formatted as JSON
331
+ const json = JSON.stringify(output)
332
+
333
+ // Then: Should be valid JSON
334
+ expect(JSON.parse(json)).toEqual(output)
335
+ })
336
+
337
+ test('formats logout output correctly', () => {
338
+ // Given: Logout result
339
+ const output = {
340
+ removed: 'T123',
341
+ success: true,
342
+ }
343
+
344
+ // When: Formatted as JSON
345
+ const json = JSON.stringify(output)
346
+
347
+ // Then: Should be valid JSON
348
+ expect(JSON.parse(json)).toEqual(output)
349
+ })
350
+ })
351
+
352
+ describe('Error Handling', () => {
353
+ test('handles missing Slack installation gracefully', async () => {
354
+ // Given: Slack is not installed
355
+ const extractor = new TokenExtractor('darwin', '/nonexistent/slack')
356
+
357
+ // When/Then: Should throw descriptive error
358
+ await expect(extractor.extract()).rejects.toThrow('Slack directory not found')
359
+ })
360
+
361
+ test('handles corrupted LevelDB gracefully', async () => {
362
+ // Given: Corrupted LevelDB
363
+ // This would require creating a corrupted LevelDB file
364
+ // We test that the extractor handles errors gracefully
365
+ const extractor = new TokenExtractor('darwin', testSlackDir)
366
+
367
+ // When: Trying to extract from non-existent storage
368
+ // Then: Should handle gracefully (return empty or throw)
369
+ await expect(extractor.extract()).rejects.toThrow()
370
+ })
371
+
372
+ test('handles missing Cookies database gracefully', async () => {
373
+ // Given: No Cookies database
374
+ mkdirSync(join(testSlackDir, 'storage'), { recursive: true })
375
+ const extractor = new TokenExtractor('darwin', testSlackDir)
376
+
377
+ // When: Trying to extract
378
+ const result = await extractor.extract()
379
+
380
+ // Then: Should return empty array (no tokens found)
381
+ expect(result).toEqual([])
382
+ })
383
+ })