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,496 @@
1
+ import { Database } from 'bun:sqlite'
2
+ import { execSync } from 'node:child_process'
3
+ import { createDecipheriv, pbkdf2Sync } from 'node:crypto'
4
+ import { existsSync, readdirSync, readFileSync } from 'node:fs'
5
+ import { homedir } from 'node:os'
6
+ import { join } from 'node:path'
7
+ import { ClassicLevel } from 'classic-level'
8
+
9
+ export interface ExtractedWorkspace {
10
+ workspace_id: string
11
+ workspace_name: string
12
+ token: string
13
+ cookie: string
14
+ }
15
+
16
+ interface TokenInfo {
17
+ token: string
18
+ teamId: string
19
+ teamName: string
20
+ }
21
+
22
+ export class TokenExtractor {
23
+ private platform: NodeJS.Platform
24
+ private slackDir: string
25
+
26
+ constructor(platform?: NodeJS.Platform, slackDir?: string) {
27
+ this.platform = platform ?? process.platform
28
+
29
+ if (!['darwin', 'linux', 'win32'].includes(this.platform)) {
30
+ throw new Error(`Unsupported platform: ${this.platform}`)
31
+ }
32
+
33
+ this.slackDir = slackDir ?? this.getSlackDir()
34
+ }
35
+
36
+ getSlackDir(): string {
37
+ switch (this.platform) {
38
+ case 'darwin': {
39
+ // Check direct download version first
40
+ const directPath = join(homedir(), 'Library', 'Application Support', 'Slack')
41
+ if (existsSync(directPath)) {
42
+ return directPath
43
+ }
44
+ // Check App Store (sandboxed) version
45
+ const sandboxedPath = join(
46
+ homedir(),
47
+ 'Library',
48
+ 'Containers',
49
+ 'com.tinyspeck.slackmacgap',
50
+ 'Data',
51
+ 'Library',
52
+ 'Application Support',
53
+ 'Slack'
54
+ )
55
+ if (existsSync(sandboxedPath)) {
56
+ return sandboxedPath
57
+ }
58
+ // Default to direct path for error message
59
+ return directPath
60
+ }
61
+ case 'linux':
62
+ return join(homedir(), '.config', 'Slack')
63
+ case 'win32':
64
+ return join(process.env.APPDATA || join(homedir(), 'AppData', 'Roaming'), 'Slack')
65
+ default:
66
+ throw new Error(`Unsupported platform: ${this.platform}`)
67
+ }
68
+ }
69
+
70
+ async extract(): Promise<ExtractedWorkspace[]> {
71
+ if (!existsSync(this.slackDir)) {
72
+ throw new Error(`Slack directory not found: ${this.slackDir}`)
73
+ }
74
+
75
+ const tokens = await this.extractTokensFromLevelDB()
76
+ if (tokens.length === 0) {
77
+ return []
78
+ }
79
+
80
+ const cookie = await this.extractCookieFromSQLite()
81
+
82
+ return tokens.map((t) => ({
83
+ workspace_id: t.teamId,
84
+ workspace_name: t.teamName,
85
+ token: t.token,
86
+ cookie: cookie,
87
+ }))
88
+ }
89
+
90
+ private async extractTokensFromLevelDB(): Promise<TokenInfo[]> {
91
+ const possibleDirs = [
92
+ join(this.slackDir, 'storage'),
93
+ join(this.slackDir, 'Local Storage', 'leveldb'),
94
+ join(this.slackDir, 'IndexedDB'),
95
+ ]
96
+
97
+ const tokens: TokenInfo[] = []
98
+
99
+ for (const baseDir of possibleDirs) {
100
+ if (!existsSync(baseDir)) {
101
+ continue
102
+ }
103
+
104
+ const levelDbDirs = this.findLevelDBDirs(baseDir)
105
+ if (baseDir.endsWith('leveldb') && this.isLevelDBDir(baseDir)) {
106
+ levelDbDirs.push(baseDir)
107
+ }
108
+
109
+ for (const dbDir of levelDbDirs) {
110
+ try {
111
+ const extracted = await this.extractFromLevelDB(dbDir)
112
+ tokens.push(...extracted)
113
+ } catch {}
114
+ }
115
+ }
116
+
117
+ return this.deduplicateTokens(tokens)
118
+ }
119
+
120
+ private deduplicateTokens(tokens: TokenInfo[]): TokenInfo[] {
121
+ const seen = new Map<string, TokenInfo>()
122
+ for (const token of tokens) {
123
+ if (!seen.has(token.teamId) || token.teamName !== 'unknown') {
124
+ seen.set(token.teamId, token)
125
+ }
126
+ }
127
+ return Array.from(seen.values())
128
+ }
129
+
130
+ private findLevelDBDirs(baseDir: string): string[] {
131
+ const dirs: string[] = []
132
+
133
+ try {
134
+ const entries = readdirSync(baseDir, { withFileTypes: true })
135
+ for (const entry of entries) {
136
+ if (entry.isDirectory()) {
137
+ const fullPath = join(baseDir, entry.name)
138
+ if (this.isLevelDBDir(fullPath)) {
139
+ dirs.push(fullPath)
140
+ }
141
+ dirs.push(...this.findLevelDBDirs(fullPath))
142
+ }
143
+ }
144
+ } catch {
145
+ return dirs
146
+ }
147
+
148
+ return dirs
149
+ }
150
+
151
+ private isLevelDBDir(dir: string): boolean {
152
+ try {
153
+ const files = readdirSync(dir)
154
+ return files.some((f) => f.endsWith('.ldb') || f.endsWith('.log') || f === 'CURRENT')
155
+ } catch {
156
+ return false
157
+ }
158
+ }
159
+
160
+ private async extractFromLevelDB(dbPath: string): Promise<TokenInfo[]> {
161
+ const tokens: TokenInfo[] = []
162
+
163
+ // First try reading LDB files directly (more reliable for sandboxed apps)
164
+ const directTokens = this.extractTokensFromLDBFiles(dbPath)
165
+ if (directTokens.length > 0) {
166
+ return directTokens
167
+ }
168
+
169
+ // Fallback to ClassicLevel for standard installations
170
+ let db: ClassicLevel<string, string> | null = null
171
+ try {
172
+ db = new ClassicLevel(dbPath, { valueEncoding: 'utf8' })
173
+
174
+ for await (const [key, value] of db.iterator()) {
175
+ if (typeof value === 'string' && value.includes('xoxc-')) {
176
+ const extracted = this.parseTokenData(key, value)
177
+ if (extracted) {
178
+ tokens.push(extracted)
179
+ }
180
+ }
181
+ }
182
+ } catch {
183
+ } finally {
184
+ if (db) {
185
+ try {
186
+ await db.close()
187
+ } catch {}
188
+ }
189
+ }
190
+
191
+ return tokens
192
+ }
193
+
194
+ private extractTokensFromLDBFiles(dbPath: string): TokenInfo[] {
195
+ const tokens: TokenInfo[] = []
196
+ try {
197
+ // Prioritize .log files (not compacted, have clean data)
198
+ // Then fall back to .ldb files
199
+ const logFiles = readdirSync(dbPath).filter((f) => f.endsWith('.log'))
200
+ const ldbFiles = readdirSync(dbPath).filter((f) => f.endsWith('.ldb'))
201
+ const files = [...logFiles, ...ldbFiles]
202
+
203
+ for (const file of files) {
204
+ const filePath = join(dbPath, file)
205
+ const content = readFileSync(filePath)
206
+ const isLogFile = file.endsWith('.log')
207
+
208
+ const xoxcMarker = Buffer.from('xoxc-')
209
+ let idx = content.indexOf(xoxcMarker, 0)
210
+ while (idx !== -1) {
211
+ const tokenData = isLogFile
212
+ ? this.extractTokenFromLogFile(content, idx)
213
+ : this.extractTokenFromBuffer(content, idx)
214
+ if (tokenData) {
215
+ tokens.push(tokenData)
216
+ }
217
+ idx = content.indexOf(xoxcMarker, idx + 5)
218
+ }
219
+ }
220
+ } catch {}
221
+ return tokens
222
+ }
223
+
224
+ private extractTokenFromLogFile(buffer: Buffer, startIdx: number): TokenInfo | null {
225
+ // LOG files have clean (non-fragmented) JSON data
226
+ const chunk = buffer.subarray(startIdx, startIdx + 300)
227
+ const str = chunk.toString('utf8')
228
+
229
+ // Token ends at quote
230
+ const endQuote = str.indexOf('"')
231
+ if (endQuote === -1) return null
232
+
233
+ const token = str.substring(0, endQuote)
234
+
235
+ // Validate token format
236
+ if (!/^xoxc-\d+-\d+-\d+-[0-9a-f]{64}$/i.test(token)) {
237
+ return null
238
+ }
239
+
240
+ let teamId = 'unknown'
241
+ let teamName = 'unknown'
242
+
243
+ const surroundingChunk = buffer.subarray(Math.max(0, startIdx - 500), startIdx + 500)
244
+ const surroundingStr = surroundingChunk.toString('utf8')
245
+
246
+ const teamIdMatch = surroundingStr.match(/T[A-Z0-9]{8,11}/)
247
+ if (teamIdMatch) {
248
+ teamId = teamIdMatch[0]
249
+ }
250
+
251
+ const teamNameMatch = surroundingStr.match(/"name"\s*:\s*"([^"]+)"/)
252
+ if (teamNameMatch) {
253
+ teamName = teamNameMatch[1]
254
+ }
255
+
256
+ return { token, teamId, teamName }
257
+ }
258
+
259
+ private extractTokenFromBuffer(buffer: Buffer, startIdx: number): TokenInfo | null {
260
+ const chunk = buffer.subarray(startIdx, startIdx + 200)
261
+
262
+ // LevelDB fragmentation pattern observed:
263
+ // Token bytes: xoxc-455709840052 [19 0d f0 5e] 228-6209589301201-9f47...
264
+ // The 4 garbage bytes (0x19 0x0d 0xf0 0xNN) replace a hyphen between numeric segments
265
+ //
266
+ // Strategy: scan for valid token chars, when we hit a non-valid sequence,
267
+ // check if it's a 4-byte fragmentation marker and insert a hyphen
268
+
269
+ const result: number[] = []
270
+ const validChars = new Set('0123456789abcdefABCDEF-xoc'.split('').map((c) => c.charCodeAt(0)))
271
+ const terminators = new Set([0x22, 0x00, 0x7d, 0x2c]) // " null } ,
272
+
273
+ let i = 0
274
+ while (i < chunk.length) {
275
+ const byte = chunk[i]
276
+
277
+ if (terminators.has(byte)) {
278
+ break
279
+ }
280
+
281
+ if (validChars.has(byte)) {
282
+ result.push(byte)
283
+ i++
284
+ } else {
285
+ // Check for 4-byte fragmentation marker pattern
286
+ // Pattern: 0x19 0x0d 0xf0 0xNN (where NN varies)
287
+ if (
288
+ i + 3 < chunk.length &&
289
+ chunk[i] === 0x19 &&
290
+ chunk[i + 1] === 0x0d &&
291
+ chunk[i + 2] === 0xf0
292
+ ) {
293
+ // Skip the 4 garbage bytes and insert a hyphen
294
+ result.push(0x2d) // hyphen
295
+ i += 4
296
+ } else {
297
+ // Unknown garbage - insert hyphen and skip this byte
298
+ if (result.length > 0 && result[result.length - 1] !== 0x2d) {
299
+ result.push(0x2d) // hyphen
300
+ }
301
+ i++
302
+ }
303
+ }
304
+ }
305
+
306
+ const reconstructed = Buffer.from(result).toString('utf8')
307
+
308
+ // Clean up any double hyphens
309
+ const cleaned = reconstructed.replace(/--+/g, '-').replace(/-$/, '')
310
+
311
+ // xoxc tokens: xoxc-NUM-NUM-NUM-64HEX (4 parts after xoxc)
312
+ const tokenPatterns = [/xoxc-\d+-\d+-\d+-[0-9a-f]{64}/i, /xoxc-\d+-\d+-[0-9a-f]{64}/i]
313
+
314
+ let token: string | null = null
315
+ for (const pattern of tokenPatterns) {
316
+ const match = cleaned.match(pattern)
317
+ if (match) {
318
+ token = match[0]
319
+ break
320
+ }
321
+ }
322
+
323
+ if (!token) {
324
+ return null
325
+ }
326
+
327
+ const parts = token.split('-')
328
+ if (parts.length < 4) {
329
+ return null
330
+ }
331
+
332
+ const lastPart = parts[parts.length - 1]
333
+ if (!/^[0-9a-f]{64}$/i.test(lastPart)) {
334
+ return null
335
+ }
336
+
337
+ let teamId = 'unknown'
338
+ let teamName = 'unknown'
339
+
340
+ const surroundingChunk = buffer.subarray(Math.max(0, startIdx - 500), startIdx + 500)
341
+ const surroundingStr = surroundingChunk.toString('utf8')
342
+
343
+ const teamIdMatch = surroundingStr.match(/T[A-Z0-9]{8,11}/)
344
+ if (teamIdMatch) {
345
+ teamId = teamIdMatch[0]
346
+ }
347
+
348
+ const teamNameMatch = surroundingStr.match(/"team_name"\s*:\s*"([^"]+)"/)
349
+ if (teamNameMatch) {
350
+ teamName = teamNameMatch[1]
351
+ }
352
+
353
+ return { token, teamId, teamName }
354
+ }
355
+
356
+ private parseTokenData(_key: string, value: string): TokenInfo | null {
357
+ const tokenMatch = value.match(/xoxc-[a-zA-Z0-9-]+/)
358
+ if (!tokenMatch) {
359
+ return null
360
+ }
361
+
362
+ const token = tokenMatch[0]
363
+
364
+ let teamId = 'unknown'
365
+ let teamName = 'unknown'
366
+
367
+ const teamIdMatch = value.match(/"team_id"\s*:\s*"(T[A-Z0-9]+)"/)
368
+ if (teamIdMatch) {
369
+ teamId = teamIdMatch[1]
370
+ }
371
+
372
+ const teamNameMatch = value.match(/"team_name"\s*:\s*"([^"]+)"/)
373
+ if (teamNameMatch) {
374
+ teamName = teamNameMatch[1]
375
+ } else {
376
+ const domainMatch = value.match(/"domain"\s*:\s*"([^"]+)"/)
377
+ if (domainMatch) {
378
+ teamName = domainMatch[1]
379
+ }
380
+ }
381
+
382
+ return { token, teamId, teamName }
383
+ }
384
+
385
+ private async extractCookieFromSQLite(): Promise<string> {
386
+ const cookiesPath = join(this.slackDir, 'Cookies')
387
+ if (!existsSync(cookiesPath)) {
388
+ const networkCookiesPath = join(this.slackDir, 'Network', 'Cookies')
389
+ if (!existsSync(networkCookiesPath)) {
390
+ return ''
391
+ }
392
+ return this.readCookieFromDB(networkCookiesPath)
393
+ }
394
+ return this.readCookieFromDB(cookiesPath)
395
+ }
396
+
397
+ private readCookieFromDB(dbPath: string): string {
398
+ try {
399
+ const db = new Database(dbPath, { readonly: true })
400
+
401
+ const row = db
402
+ .query(
403
+ `SELECT value, encrypted_value
404
+ FROM cookies
405
+ WHERE name = 'd' AND host_key LIKE '%slack.com%'
406
+ ORDER BY last_access_utc DESC
407
+ LIMIT 1`
408
+ )
409
+ .get() as { value?: string; encrypted_value?: Uint8Array } | null
410
+
411
+ db.close()
412
+
413
+ if (!row) {
414
+ return ''
415
+ }
416
+
417
+ if (row.value?.startsWith('xoxd-')) {
418
+ return row.value
419
+ }
420
+
421
+ if (row.encrypted_value && row.encrypted_value.length > 0) {
422
+ const decrypted = this.tryDecryptCookie(Buffer.from(row.encrypted_value))
423
+ if (decrypted) {
424
+ return decrypted
425
+ }
426
+ }
427
+
428
+ return ''
429
+ } catch {
430
+ return ''
431
+ }
432
+ }
433
+
434
+ private tryDecryptCookie(encrypted: Buffer): string | null {
435
+ const str = encrypted.toString('utf8')
436
+ if (str.startsWith('xoxd-')) {
437
+ return str
438
+ }
439
+
440
+ // Check for v10 encryption (macOS Keychain)
441
+ if (encrypted.length > 3 && encrypted.subarray(0, 3).toString() === 'v10') {
442
+ return this.decryptV10Cookie(encrypted)
443
+ }
444
+
445
+ return null
446
+ }
447
+
448
+ private decryptV10Cookie(encrypted: Buffer): string | null {
449
+ try {
450
+ const key = this.getDerivedKey()
451
+ if (!key) {
452
+ return null
453
+ }
454
+
455
+ // v10 uses AES-128-CBC with 16-space IV (Chrome/Electron pattern)
456
+ const iv = Buffer.alloc(16, ' ')
457
+ const ciphertext = encrypted.subarray(3)
458
+
459
+ const decipher = createDecipheriv('aes-128-cbc', key, iv)
460
+ const decrypted = Buffer.concat([decipher.update(ciphertext), decipher.final()])
461
+ const result = decrypted.toString('utf8')
462
+
463
+ // Extract xoxd- token from decrypted data (may have padding/garbage before it)
464
+ const match = result.match(/xoxd-[A-Za-z0-9%]+/)
465
+ return match ? match[0] : null
466
+ } catch {
467
+ return null
468
+ }
469
+ }
470
+
471
+ private getDerivedKey(): Buffer | null {
472
+ if (this.platform !== 'darwin') {
473
+ return null
474
+ }
475
+
476
+ try {
477
+ let password: string
478
+ try {
479
+ password = execSync(
480
+ 'security find-generic-password -ga "Slack App Store Key" -s "Slack Safe Storage" -w 2>/dev/null',
481
+ { encoding: 'utf8' }
482
+ ).trim()
483
+ } catch {
484
+ password = execSync(
485
+ 'security find-generic-password -ga "Slack Key" -s "Slack Safe Storage" -w 2>/dev/null',
486
+ { encoding: 'utf8' }
487
+ ).trim()
488
+ }
489
+
490
+ // Chrome/Electron uses PBKDF2 with these parameters
491
+ return pbkdf2Sync(password, 'saltysalt', 1003, 16, 'sha1')
492
+ } catch {
493
+ return null
494
+ }
495
+ }
496
+ }
@@ -0,0 +1,193 @@
1
+ /**
2
+ * Core type definitions for agent-slack
3
+ */
4
+
5
+ import { z } from 'zod'
6
+
7
+ export interface SlackChannel {
8
+ id: string
9
+ name: string
10
+ is_private: boolean
11
+ is_archived: boolean
12
+ created: number
13
+ creator: string
14
+ topic?: {
15
+ value: string
16
+ creator: string
17
+ last_set: number
18
+ }
19
+ purpose?: {
20
+ value: string
21
+ creator: string
22
+ last_set: number
23
+ }
24
+ }
25
+
26
+ export interface SlackMessage {
27
+ ts: string
28
+ text: string
29
+ user?: string
30
+ username?: string
31
+ type: string
32
+ thread_ts?: string
33
+ reply_count?: number
34
+ replies?: Array<{ user: string; ts: string }>
35
+ edited?: {
36
+ user: string
37
+ ts: string
38
+ }
39
+ }
40
+
41
+ export interface SlackUser {
42
+ id: string
43
+ name: string
44
+ real_name: string
45
+ is_admin: boolean
46
+ is_owner: boolean
47
+ is_bot: boolean
48
+ is_app_user: boolean
49
+ profile?: {
50
+ email?: string
51
+ phone?: string
52
+ title?: string
53
+ status_text?: string
54
+ }
55
+ }
56
+
57
+ export interface SlackReaction {
58
+ name: string
59
+ count: number
60
+ users: string[]
61
+ }
62
+
63
+ export interface SlackFile {
64
+ id: string
65
+ name: string
66
+ title: string
67
+ mimetype: string
68
+ size: number
69
+ url_private: string
70
+ created: number
71
+ user: string
72
+ channels?: string[]
73
+ }
74
+
75
+ export interface SlackSearchResult {
76
+ ts: string
77
+ text: string
78
+ user?: string
79
+ username?: string
80
+ channel: {
81
+ id: string
82
+ name: string
83
+ }
84
+ permalink: string
85
+ }
86
+
87
+ export interface WorkspaceCredentials {
88
+ workspace_id: string
89
+ workspace_name: string
90
+ token: string
91
+ cookie: string
92
+ }
93
+
94
+ export interface Config {
95
+ current_workspace: string | null
96
+ workspaces: Record<string, WorkspaceCredentials>
97
+ }
98
+
99
+ // Zod validation schemas
100
+ export const SlackChannelSchema = z.object({
101
+ id: z.string(),
102
+ name: z.string(),
103
+ is_private: z.boolean(),
104
+ is_archived: z.boolean(),
105
+ created: z.number(),
106
+ creator: z.string(),
107
+ topic: z
108
+ .object({
109
+ value: z.string(),
110
+ creator: z.string(),
111
+ last_set: z.number(),
112
+ })
113
+ .optional(),
114
+ purpose: z
115
+ .object({
116
+ value: z.string(),
117
+ creator: z.string(),
118
+ last_set: z.number(),
119
+ })
120
+ .optional(),
121
+ })
122
+
123
+ export const SlackMessageSchema = z.object({
124
+ ts: z.string(),
125
+ text: z.string(),
126
+ user: z.string().optional(),
127
+ username: z.string().optional(),
128
+ type: z.string(),
129
+ thread_ts: z.string().optional(),
130
+ reply_count: z.number().optional(),
131
+ replies: z
132
+ .array(
133
+ z.object({
134
+ user: z.string(),
135
+ ts: z.string(),
136
+ })
137
+ )
138
+ .optional(),
139
+ edited: z
140
+ .object({
141
+ user: z.string(),
142
+ ts: z.string(),
143
+ })
144
+ .optional(),
145
+ })
146
+
147
+ export const SlackUserSchema = z.object({
148
+ id: z.string(),
149
+ name: z.string(),
150
+ real_name: z.string(),
151
+ is_admin: z.boolean(),
152
+ is_owner: z.boolean(),
153
+ is_bot: z.boolean(),
154
+ is_app_user: z.boolean(),
155
+ profile: z
156
+ .object({
157
+ email: z.string().optional(),
158
+ phone: z.string().optional(),
159
+ title: z.string().optional(),
160
+ status_text: z.string().optional(),
161
+ })
162
+ .optional(),
163
+ })
164
+
165
+ export const SlackReactionSchema = z.object({
166
+ name: z.string(),
167
+ count: z.number(),
168
+ users: z.array(z.string()),
169
+ })
170
+
171
+ export const SlackFileSchema = z.object({
172
+ id: z.string(),
173
+ name: z.string(),
174
+ title: z.string(),
175
+ mimetype: z.string(),
176
+ size: z.number(),
177
+ url_private: z.string(),
178
+ created: z.number(),
179
+ user: z.string(),
180
+ channels: z.array(z.string()).optional(),
181
+ })
182
+
183
+ export const WorkspaceCredentialsSchema = z.object({
184
+ workspace_id: z.string(),
185
+ workspace_name: z.string(),
186
+ token: z.string(),
187
+ cookie: z.string(),
188
+ })
189
+
190
+ export const ConfigSchema = z.object({
191
+ current_workspace: z.string().nullable(),
192
+ workspaces: z.record(z.string(), WorkspaceCredentialsSchema),
193
+ })