agent-messenger 2.10.1 → 2.11.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 (536) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/.env.template +4 -1
  3. package/README.md +77 -27
  4. package/bun.lock +26 -0
  5. package/dist/package.json +14 -1
  6. package/dist/src/platforms/channeltalk/commands/auth.d.ts +2 -1
  7. package/dist/src/platforms/channeltalk/commands/auth.d.ts.map +1 -1
  8. package/dist/src/platforms/channeltalk/commands/auth.js +5 -3
  9. package/dist/src/platforms/channeltalk/commands/auth.js.map +1 -1
  10. package/dist/src/platforms/channeltalk/token-extractor.d.ts +2 -1
  11. package/dist/src/platforms/channeltalk/token-extractor.d.ts.map +1 -1
  12. package/dist/src/platforms/channeltalk/token-extractor.js +22 -6
  13. package/dist/src/platforms/channeltalk/token-extractor.js.map +1 -1
  14. package/dist/src/platforms/channeltalkbot/cli.d.ts.map +1 -1
  15. package/dist/src/platforms/channeltalkbot/cli.js +11 -1
  16. package/dist/src/platforms/channeltalkbot/cli.js.map +1 -1
  17. package/dist/src/platforms/channeltalkbot/commands/auth.d.ts.map +1 -1
  18. package/dist/src/platforms/channeltalkbot/commands/auth.js +1 -5
  19. package/dist/src/platforms/channeltalkbot/commands/auth.js.map +1 -1
  20. package/dist/src/platforms/channeltalkbot/commands/bot.d.ts.map +1 -1
  21. package/dist/src/platforms/channeltalkbot/commands/bot.js +1 -6
  22. package/dist/src/platforms/channeltalkbot/commands/bot.js.map +1 -1
  23. package/dist/src/platforms/channeltalkbot/commands/chat.d.ts.map +1 -1
  24. package/dist/src/platforms/channeltalkbot/commands/chat.js +1 -6
  25. package/dist/src/platforms/channeltalkbot/commands/chat.js.map +1 -1
  26. package/dist/src/platforms/channeltalkbot/commands/group.d.ts.map +1 -1
  27. package/dist/src/platforms/channeltalkbot/commands/group.js +1 -6
  28. package/dist/src/platforms/channeltalkbot/commands/group.js.map +1 -1
  29. package/dist/src/platforms/channeltalkbot/commands/manager.d.ts.map +1 -1
  30. package/dist/src/platforms/channeltalkbot/commands/manager.js +1 -6
  31. package/dist/src/platforms/channeltalkbot/commands/manager.js.map +1 -1
  32. package/dist/src/platforms/channeltalkbot/commands/message.d.ts.map +1 -1
  33. package/dist/src/platforms/channeltalkbot/commands/message.js +1 -6
  34. package/dist/src/platforms/channeltalkbot/commands/message.js.map +1 -1
  35. package/dist/src/platforms/channeltalkbot/commands/whoami.d.ts.map +1 -1
  36. package/dist/src/platforms/channeltalkbot/commands/whoami.js +1 -6
  37. package/dist/src/platforms/channeltalkbot/commands/whoami.js.map +1 -1
  38. package/dist/src/platforms/channeltalkbot/credential-manager.d.ts +5 -0
  39. package/dist/src/platforms/channeltalkbot/credential-manager.d.ts.map +1 -1
  40. package/dist/src/platforms/channeltalkbot/credential-manager.js +34 -4
  41. package/dist/src/platforms/channeltalkbot/credential-manager.js.map +1 -1
  42. package/dist/src/platforms/discord/commands/auth.d.ts +1 -0
  43. package/dist/src/platforms/discord/commands/auth.d.ts.map +1 -1
  44. package/dist/src/platforms/discord/commands/auth.js +3 -1
  45. package/dist/src/platforms/discord/commands/auth.js.map +1 -1
  46. package/dist/src/platforms/discord/listener.d.ts +2 -0
  47. package/dist/src/platforms/discord/listener.d.ts.map +1 -1
  48. package/dist/src/platforms/discord/listener.js +51 -21
  49. package/dist/src/platforms/discord/listener.js.map +1 -1
  50. package/dist/src/platforms/discord/token-extractor.d.ts +2 -1
  51. package/dist/src/platforms/discord/token-extractor.d.ts.map +1 -1
  52. package/dist/src/platforms/discord/token-extractor.js +21 -6
  53. package/dist/src/platforms/discord/token-extractor.js.map +1 -1
  54. package/dist/src/platforms/discordbot/cli.d.ts.map +1 -1
  55. package/dist/src/platforms/discordbot/cli.js +12 -1
  56. package/dist/src/platforms/discordbot/cli.js.map +1 -1
  57. package/dist/src/platforms/discordbot/client.d.ts +3 -0
  58. package/dist/src/platforms/discordbot/client.d.ts.map +1 -1
  59. package/dist/src/platforms/discordbot/client.js +3 -0
  60. package/dist/src/platforms/discordbot/client.js.map +1 -1
  61. package/dist/src/platforms/discordbot/commands/auth.d.ts.map +1 -1
  62. package/dist/src/platforms/discordbot/commands/auth.js +1 -5
  63. package/dist/src/platforms/discordbot/commands/auth.js.map +1 -1
  64. package/dist/src/platforms/discordbot/commands/message.d.ts.map +1 -1
  65. package/dist/src/platforms/discordbot/commands/message.js +1 -6
  66. package/dist/src/platforms/discordbot/commands/message.js.map +1 -1
  67. package/dist/src/platforms/discordbot/commands/server.d.ts.map +1 -1
  68. package/dist/src/platforms/discordbot/commands/server.js +1 -4
  69. package/dist/src/platforms/discordbot/commands/server.js.map +1 -1
  70. package/dist/src/platforms/discordbot/commands/whoami.d.ts.map +1 -1
  71. package/dist/src/platforms/discordbot/commands/whoami.js +1 -6
  72. package/dist/src/platforms/discordbot/commands/whoami.js.map +1 -1
  73. package/dist/src/platforms/discordbot/index.d.ts +3 -1
  74. package/dist/src/platforms/discordbot/index.d.ts.map +1 -1
  75. package/dist/src/platforms/discordbot/index.js +2 -1
  76. package/dist/src/platforms/discordbot/index.js.map +1 -1
  77. package/dist/src/platforms/discordbot/listener.d.ts +43 -0
  78. package/dist/src/platforms/discordbot/listener.d.ts.map +1 -0
  79. package/dist/src/platforms/discordbot/listener.js +292 -0
  80. package/dist/src/platforms/discordbot/listener.js.map +1 -0
  81. package/dist/src/platforms/discordbot/types.d.ts +161 -0
  82. package/dist/src/platforms/discordbot/types.d.ts.map +1 -1
  83. package/dist/src/platforms/discordbot/types.js +34 -0
  84. package/dist/src/platforms/discordbot/types.js.map +1 -1
  85. package/dist/src/platforms/instagram/commands/auth.d.ts.map +1 -1
  86. package/dist/src/platforms/instagram/commands/auth.js +3 -1
  87. package/dist/src/platforms/instagram/commands/auth.js.map +1 -1
  88. package/dist/src/platforms/instagram/token-extractor.d.ts +2 -1
  89. package/dist/src/platforms/instagram/token-extractor.d.ts.map +1 -1
  90. package/dist/src/platforms/instagram/token-extractor.js +11 -2
  91. package/dist/src/platforms/instagram/token-extractor.js.map +1 -1
  92. package/dist/src/platforms/slack/commands/auth.d.ts.map +1 -1
  93. package/dist/src/platforms/slack/commands/auth.js +4 -2
  94. package/dist/src/platforms/slack/commands/auth.js.map +1 -1
  95. package/dist/src/platforms/slack/token-extractor.d.ts +4 -1
  96. package/dist/src/platforms/slack/token-extractor.d.ts.map +1 -1
  97. package/dist/src/platforms/slack/token-extractor.js +64 -15
  98. package/dist/src/platforms/slack/token-extractor.js.map +1 -1
  99. package/dist/src/platforms/slackbot/cli.d.ts.map +1 -1
  100. package/dist/src/platforms/slackbot/cli.js +15 -3
  101. package/dist/src/platforms/slackbot/cli.js.map +1 -1
  102. package/dist/src/platforms/slackbot/client.d.ts +22 -1
  103. package/dist/src/platforms/slackbot/client.d.ts.map +1 -1
  104. package/dist/src/platforms/slackbot/client.js +104 -1
  105. package/dist/src/platforms/slackbot/client.js.map +1 -1
  106. package/dist/src/platforms/slackbot/commands/auth.d.ts.map +1 -1
  107. package/dist/src/platforms/slackbot/commands/auth.js +1 -5
  108. package/dist/src/platforms/slackbot/commands/auth.js.map +1 -1
  109. package/dist/src/platforms/slackbot/commands/file.d.ts +3 -0
  110. package/dist/src/platforms/slackbot/commands/file.d.ts.map +1 -0
  111. package/dist/src/platforms/slackbot/commands/file.js +164 -0
  112. package/dist/src/platforms/slackbot/commands/file.js.map +1 -0
  113. package/dist/src/platforms/slackbot/commands/index.d.ts +1 -0
  114. package/dist/src/platforms/slackbot/commands/index.d.ts.map +1 -1
  115. package/dist/src/platforms/slackbot/commands/index.js +1 -0
  116. package/dist/src/platforms/slackbot/commands/index.js.map +1 -1
  117. package/dist/src/platforms/slackbot/commands/message.d.ts.map +1 -1
  118. package/dist/src/platforms/slackbot/commands/message.js +19 -0
  119. package/dist/src/platforms/slackbot/commands/message.js.map +1 -1
  120. package/dist/src/platforms/slackbot/commands/whoami.d.ts.map +1 -1
  121. package/dist/src/platforms/slackbot/commands/whoami.js +1 -6
  122. package/dist/src/platforms/slackbot/commands/whoami.js.map +1 -1
  123. package/dist/src/platforms/slackbot/credential-manager.d.ts +1 -0
  124. package/dist/src/platforms/slackbot/credential-manager.d.ts.map +1 -1
  125. package/dist/src/platforms/slackbot/credential-manager.js +30 -2
  126. package/dist/src/platforms/slackbot/credential-manager.js.map +1 -1
  127. package/dist/src/platforms/slackbot/index.d.ts +4 -1
  128. package/dist/src/platforms/slackbot/index.d.ts.map +1 -1
  129. package/dist/src/platforms/slackbot/index.js +1 -0
  130. package/dist/src/platforms/slackbot/index.js.map +1 -1
  131. package/dist/src/platforms/slackbot/listener.d.ts +44 -0
  132. package/dist/src/platforms/slackbot/listener.d.ts.map +1 -0
  133. package/dist/src/platforms/slackbot/listener.js +313 -0
  134. package/dist/src/platforms/slackbot/listener.js.map +1 -0
  135. package/dist/src/platforms/slackbot/types.d.ts +196 -1
  136. package/dist/src/platforms/slackbot/types.d.ts.map +1 -1
  137. package/dist/src/platforms/slackbot/types.js +4 -1
  138. package/dist/src/platforms/slackbot/types.js.map +1 -1
  139. package/dist/src/platforms/teams/commands/auth.d.ts +1 -0
  140. package/dist/src/platforms/teams/commands/auth.d.ts.map +1 -1
  141. package/dist/src/platforms/teams/commands/auth.js +37 -6
  142. package/dist/src/platforms/teams/commands/auth.js.map +1 -1
  143. package/dist/src/platforms/teams/ensure-auth.js +31 -9
  144. package/dist/src/platforms/teams/ensure-auth.js.map +1 -1
  145. package/dist/src/platforms/teams/token-extractor.d.ts +4 -1
  146. package/dist/src/platforms/teams/token-extractor.d.ts.map +1 -1
  147. package/dist/src/platforms/teams/token-extractor.js +80 -31
  148. package/dist/src/platforms/teams/token-extractor.js.map +1 -1
  149. package/dist/src/platforms/webex/commands/auth.d.ts +1 -0
  150. package/dist/src/platforms/webex/commands/auth.d.ts.map +1 -1
  151. package/dist/src/platforms/webex/commands/auth.js +3 -1
  152. package/dist/src/platforms/webex/commands/auth.js.map +1 -1
  153. package/dist/src/platforms/webex/token-extractor.d.ts +3 -1
  154. package/dist/src/platforms/webex/token-extractor.d.ts.map +1 -1
  155. package/dist/src/platforms/webex/token-extractor.js +16 -2
  156. package/dist/src/platforms/webex/token-extractor.js.map +1 -1
  157. package/dist/src/platforms/wechatbot/cli.d.ts.map +1 -1
  158. package/dist/src/platforms/wechatbot/cli.js +11 -1
  159. package/dist/src/platforms/wechatbot/cli.js.map +1 -1
  160. package/dist/src/platforms/wechatbot/commands/auth.d.ts.map +1 -1
  161. package/dist/src/platforms/wechatbot/commands/auth.js +1 -5
  162. package/dist/src/platforms/wechatbot/commands/auth.js.map +1 -1
  163. package/dist/src/platforms/wechatbot/commands/message.d.ts.map +1 -1
  164. package/dist/src/platforms/wechatbot/commands/message.js +1 -6
  165. package/dist/src/platforms/wechatbot/commands/message.js.map +1 -1
  166. package/dist/src/platforms/wechatbot/commands/template.d.ts.map +1 -1
  167. package/dist/src/platforms/wechatbot/commands/template.js +1 -6
  168. package/dist/src/platforms/wechatbot/commands/template.js.map +1 -1
  169. package/dist/src/platforms/wechatbot/commands/user.d.ts.map +1 -1
  170. package/dist/src/platforms/wechatbot/commands/user.js +1 -6
  171. package/dist/src/platforms/wechatbot/commands/user.js.map +1 -1
  172. package/dist/src/platforms/wechatbot/commands/whoami.d.ts.map +1 -1
  173. package/dist/src/platforms/wechatbot/commands/whoami.js +1 -6
  174. package/dist/src/platforms/wechatbot/commands/whoami.js.map +1 -1
  175. package/dist/src/platforms/whatsappbot/cli.d.ts.map +1 -1
  176. package/dist/src/platforms/whatsappbot/cli.js +11 -1
  177. package/dist/src/platforms/whatsappbot/cli.js.map +1 -1
  178. package/dist/src/platforms/whatsappbot/commands/auth.d.ts.map +1 -1
  179. package/dist/src/platforms/whatsappbot/commands/auth.js +1 -5
  180. package/dist/src/platforms/whatsappbot/commands/auth.js.map +1 -1
  181. package/dist/src/platforms/whatsappbot/commands/message.d.ts.map +1 -1
  182. package/dist/src/platforms/whatsappbot/commands/message.js +1 -6
  183. package/dist/src/platforms/whatsappbot/commands/message.js.map +1 -1
  184. package/dist/src/platforms/whatsappbot/commands/template.d.ts.map +1 -1
  185. package/dist/src/platforms/whatsappbot/commands/template.js +1 -6
  186. package/dist/src/platforms/whatsappbot/commands/template.js.map +1 -1
  187. package/dist/src/platforms/whatsappbot/commands/whoami.d.ts.map +1 -1
  188. package/dist/src/platforms/whatsappbot/commands/whoami.js +1 -6
  189. package/dist/src/platforms/whatsappbot/commands/whoami.js.map +1 -1
  190. package/dist/src/shared/chromium/browsers.d.ts +8 -0
  191. package/dist/src/shared/chromium/browsers.d.ts.map +1 -1
  192. package/dist/src/shared/chromium/browsers.js +58 -3
  193. package/dist/src/shared/chromium/browsers.js.map +1 -1
  194. package/dist/src/shared/chromium/cli-options.d.ts +5 -0
  195. package/dist/src/shared/chromium/cli-options.d.ts.map +1 -0
  196. package/dist/src/shared/chromium/cli-options.js +8 -0
  197. package/dist/src/shared/chromium/cli-options.js.map +1 -0
  198. package/dist/src/shared/chromium/decryptor.d.ts +6 -0
  199. package/dist/src/shared/chromium/decryptor.d.ts.map +1 -1
  200. package/dist/src/shared/chromium/decryptor.js +26 -6
  201. package/dist/src/shared/chromium/decryptor.js.map +1 -1
  202. package/dist/src/shared/chromium/index.d.ts +3 -1
  203. package/dist/src/shared/chromium/index.d.ts.map +1 -1
  204. package/dist/src/shared/chromium/index.js +2 -1
  205. package/dist/src/shared/chromium/index.js.map +1 -1
  206. package/dist/src/shared/utils/cli-output.d.ts +7 -0
  207. package/dist/src/shared/utils/cli-output.d.ts.map +1 -0
  208. package/dist/src/shared/utils/cli-output.js +7 -0
  209. package/dist/src/shared/utils/cli-output.js.map +1 -0
  210. package/dist/src/tui/app.d.ts.map +1 -1
  211. package/dist/src/tui/app.js +73 -20
  212. package/dist/src/tui/app.js.map +1 -1
  213. package/docs/content/docs/cli/channeltalk.mdx +4 -0
  214. package/docs/content/docs/cli/discord.mdx +5 -0
  215. package/docs/content/docs/cli/instagram.mdx +3 -0
  216. package/docs/content/docs/cli/slack.mdx +5 -0
  217. package/docs/content/docs/cli/slackbot.mdx +60 -22
  218. package/docs/content/docs/cli/teams.mdx +5 -0
  219. package/docs/content/docs/cli/webex.mdx +3 -0
  220. package/docs/content/docs/sdk/channeltalkbot.mdx +38 -1
  221. package/docs/content/docs/sdk/discordbot.mdx +501 -0
  222. package/docs/content/docs/sdk/meta.json +2 -0
  223. package/docs/content/docs/sdk/slackbot.mdx +576 -0
  224. package/e2e/README.md +1 -1
  225. package/e2e/channeltalk.e2e.test.ts +13 -13
  226. package/e2e/channeltalkbot.e2e.test.ts +13 -13
  227. package/e2e/config.ts +9 -4
  228. package/e2e/discord.e2e.test.ts +24 -24
  229. package/e2e/discordbot.e2e.test.ts +16 -16
  230. package/e2e/instagram.e2e.test.ts +10 -10
  231. package/e2e/kakaotalk.e2e.test.ts +7 -7
  232. package/e2e/line.e2e.test.ts +8 -8
  233. package/e2e/slack.e2e.test.ts +34 -34
  234. package/e2e/slackbot.e2e.test.ts +14 -14
  235. package/e2e/teams.e2e.test.ts +23 -23
  236. package/e2e/telegram.e2e.test.ts +8 -8
  237. package/e2e/webex.e2e.test.ts +14 -14
  238. package/e2e/whatsapp.e2e.test.ts +8 -8
  239. package/e2e/whatsappbot.e2e.test.ts +6 -6
  240. package/examples/discordbot-listen.ts +65 -0
  241. package/examples/slackbot-listen.ts +65 -0
  242. package/package.json +14 -1
  243. package/skills/agent-channeltalk/SKILL.md +5 -1
  244. package/skills/agent-channeltalk/references/authentication.md +5 -1
  245. package/skills/agent-channeltalkbot/SKILL.md +17 -3
  246. package/skills/agent-channeltalkbot/references/authentication.md +7 -5
  247. package/skills/agent-discord/SKILL.md +5 -1
  248. package/skills/agent-discord/references/authentication.md +7 -1
  249. package/skills/agent-discordbot/SKILL.md +13 -2
  250. package/skills/agent-discordbot/references/common-patterns.md +1 -1
  251. package/skills/agent-instagram/SKILL.md +7 -1
  252. package/skills/agent-instagram/references/authentication.md +6 -0
  253. package/skills/agent-kakaotalk/SKILL.md +1 -1
  254. package/skills/agent-line/SKILL.md +1 -1
  255. package/skills/agent-slack/SKILL.md +5 -1
  256. package/skills/agent-slack/references/authentication.md +7 -1
  257. package/skills/agent-slackbot/SKILL.md +56 -4
  258. package/skills/agent-slackbot/references/authentication.md +4 -0
  259. package/skills/agent-teams/SKILL.md +5 -1
  260. package/skills/agent-teams/references/authentication.md +7 -1
  261. package/skills/agent-telegram/SKILL.md +1 -1
  262. package/skills/agent-webex/SKILL.md +7 -1
  263. package/skills/agent-webex/references/authentication.md +6 -0
  264. package/skills/agent-wechatbot/SKILL.md +16 -1
  265. package/skills/agent-wechatbot/references/authentication.md +219 -0
  266. package/skills/agent-wechatbot/references/common-patterns.md +358 -0
  267. package/skills/agent-wechatbot/templates/account-summary.sh +122 -0
  268. package/skills/agent-wechatbot/templates/post-message.sh +122 -0
  269. package/skills/agent-wechatbot/templates/send-template.sh +152 -0
  270. package/skills/agent-whatsapp/SKILL.md +1 -1
  271. package/skills/agent-whatsappbot/SKILL.md +30 -1
  272. package/src/platforms/channeltalk/client.test.ts +26 -26
  273. package/src/platforms/channeltalk/commands/auth.test.ts +31 -19
  274. package/src/platforms/channeltalk/commands/auth.ts +15 -5
  275. package/src/platforms/channeltalk/commands/bot.test.ts +2 -2
  276. package/src/platforms/channeltalk/commands/chat.test.ts +3 -3
  277. package/src/platforms/channeltalk/commands/group.test.ts +4 -4
  278. package/src/platforms/channeltalk/commands/manager.test.ts +2 -2
  279. package/src/platforms/channeltalk/commands/message.test.ts +17 -17
  280. package/src/platforms/channeltalk/commands/snapshot.test.ts +7 -7
  281. package/src/platforms/channeltalk/commands/whoami.test.ts +3 -3
  282. package/src/platforms/channeltalk/credential-manager.test.ts +18 -18
  283. package/src/platforms/channeltalk/ensure-auth.test.ts +5 -5
  284. package/src/platforms/channeltalk/index.test.ts +23 -23
  285. package/src/platforms/channeltalk/token-extractor.test.ts +21 -21
  286. package/src/platforms/channeltalk/token-extractor.ts +24 -5
  287. package/src/platforms/channeltalk/types.test.ts +12 -12
  288. package/src/platforms/channeltalkbot/cli.ts +9 -0
  289. package/src/platforms/channeltalkbot/client.test.ts +14 -14
  290. package/src/platforms/channeltalkbot/commands/auth.test.ts +16 -16
  291. package/src/platforms/channeltalkbot/commands/auth.ts +1 -5
  292. package/src/platforms/channeltalkbot/commands/bot.test.ts +6 -6
  293. package/src/platforms/channeltalkbot/commands/bot.ts +1 -6
  294. package/src/platforms/channeltalkbot/commands/chat.test.ts +9 -9
  295. package/src/platforms/channeltalkbot/commands/chat.ts +1 -6
  296. package/src/platforms/channeltalkbot/commands/group.test.ts +6 -6
  297. package/src/platforms/channeltalkbot/commands/group.ts +1 -6
  298. package/src/platforms/channeltalkbot/commands/manager.test.ts +3 -3
  299. package/src/platforms/channeltalkbot/commands/manager.ts +1 -6
  300. package/src/platforms/channeltalkbot/commands/message.test.ts +10 -10
  301. package/src/platforms/channeltalkbot/commands/message.ts +1 -6
  302. package/src/platforms/channeltalkbot/commands/snapshot.test.ts +7 -7
  303. package/src/platforms/channeltalkbot/commands/whoami.test.ts +6 -4
  304. package/src/platforms/channeltalkbot/commands/whoami.ts +1 -6
  305. package/src/platforms/channeltalkbot/credential-manager.test.ts +123 -29
  306. package/src/platforms/channeltalkbot/credential-manager.ts +37 -4
  307. package/src/platforms/channeltalkbot/index.test.ts +15 -15
  308. package/src/platforms/discord/client.test.ts +28 -28
  309. package/src/platforms/discord/commands/auth.test.ts +7 -7
  310. package/src/platforms/discord/commands/auth.ts +13 -2
  311. package/src/platforms/discord/commands/channel.test.ts +7 -7
  312. package/src/platforms/discord/commands/dm.test.ts +4 -4
  313. package/src/platforms/discord/commands/file.test.ts +4 -4
  314. package/src/platforms/discord/commands/friend.test.ts +6 -6
  315. package/src/platforms/discord/commands/member.test.ts +5 -5
  316. package/src/platforms/discord/commands/mention.test.ts +5 -5
  317. package/src/platforms/discord/commands/message.test.ts +9 -9
  318. package/src/platforms/discord/commands/note.test.ts +6 -6
  319. package/src/platforms/discord/commands/profile.test.ts +4 -4
  320. package/src/platforms/discord/commands/reaction.test.ts +5 -5
  321. package/src/platforms/discord/commands/server.test.ts +7 -7
  322. package/src/platforms/discord/commands/snapshot.test.ts +6 -6
  323. package/src/platforms/discord/commands/thread.test.ts +6 -6
  324. package/src/platforms/discord/commands/user.test.ts +5 -5
  325. package/src/platforms/discord/commands/whoami.test.ts +6 -6
  326. package/src/platforms/discord/credential-manager.test.ts +16 -16
  327. package/src/platforms/discord/ensure-auth.test.ts +8 -8
  328. package/src/platforms/discord/index.test.ts +17 -17
  329. package/src/platforms/discord/listener.test.ts +92 -34
  330. package/src/platforms/discord/listener.ts +43 -19
  331. package/src/platforms/discord/token-extractor.test.ts +53 -53
  332. package/src/platforms/discord/token-extractor.ts +30 -6
  333. package/src/platforms/discord/types.test.ts +26 -26
  334. package/src/platforms/discordbot/cli.ts +10 -0
  335. package/src/platforms/discordbot/client.test.ts +31 -31
  336. package/src/platforms/discordbot/client.ts +4 -0
  337. package/src/platforms/discordbot/commands/auth.test.ts +18 -18
  338. package/src/platforms/discordbot/commands/auth.ts +1 -5
  339. package/src/platforms/discordbot/commands/channel.test.ts +11 -11
  340. package/src/platforms/discordbot/commands/file.test.ts +7 -7
  341. package/src/platforms/discordbot/commands/message.test.ts +25 -25
  342. package/src/platforms/discordbot/commands/message.ts +1 -6
  343. package/src/platforms/discordbot/commands/reaction.test.ts +6 -6
  344. package/src/platforms/discordbot/commands/server.test.ts +12 -12
  345. package/src/platforms/discordbot/commands/server.ts +1 -5
  346. package/src/platforms/discordbot/commands/snapshot.test.ts +13 -13
  347. package/src/platforms/discordbot/commands/thread.test.ts +10 -10
  348. package/src/platforms/discordbot/commands/user.test.ts +9 -9
  349. package/src/platforms/discordbot/commands/whoami.test.ts +4 -4
  350. package/src/platforms/discordbot/commands/whoami.ts +1 -6
  351. package/src/platforms/discordbot/credential-manager.test.ts +28 -28
  352. package/src/platforms/discordbot/index.test.ts +82 -0
  353. package/src/platforms/discordbot/index.ts +27 -9
  354. package/src/platforms/discordbot/listener.test.ts +1002 -0
  355. package/src/platforms/discordbot/listener.ts +321 -0
  356. package/src/platforms/discordbot/types.ts +163 -0
  357. package/src/platforms/instagram/client.test.ts +18 -18
  358. package/src/platforms/instagram/commands/auth.test.ts +11 -11
  359. package/src/platforms/instagram/commands/auth.ts +9 -1
  360. package/src/platforms/instagram/commands/chat.test.ts +6 -6
  361. package/src/platforms/instagram/commands/message.test.ts +11 -11
  362. package/src/platforms/instagram/commands/shared.test.ts +12 -12
  363. package/src/platforms/instagram/commands/whoami.test.ts +3 -3
  364. package/src/platforms/instagram/credential-manager.test.ts +21 -21
  365. package/src/platforms/instagram/ensure-auth.test.ts +4 -4
  366. package/src/platforms/instagram/index.test.ts +9 -9
  367. package/src/platforms/instagram/listener.test.ts +8 -8
  368. package/src/platforms/instagram/token-extractor.test.ts +35 -35
  369. package/src/platforms/instagram/token-extractor.ts +13 -1
  370. package/src/platforms/kakaotalk/client.test.ts +33 -33
  371. package/src/platforms/kakaotalk/commands/auth.test.ts +11 -11
  372. package/src/platforms/kakaotalk/commands/chat.test.ts +6 -6
  373. package/src/platforms/kakaotalk/commands/message.test.ts +7 -7
  374. package/src/platforms/kakaotalk/commands/whoami.test.ts +5 -5
  375. package/src/platforms/kakaotalk/credential-manager.test.ts +15 -15
  376. package/src/platforms/kakaotalk/index.test.ts +15 -15
  377. package/src/platforms/kakaotalk/listener.test.ts +17 -17
  378. package/src/platforms/line/client.test.ts +17 -17
  379. package/src/platforms/line/commands/auth.test.ts +8 -8
  380. package/src/platforms/line/commands/chat.test.ts +7 -7
  381. package/src/platforms/line/commands/friend.test.ts +6 -6
  382. package/src/platforms/line/commands/message.test.ts +7 -7
  383. package/src/platforms/line/commands/whoami.test.ts +6 -6
  384. package/src/platforms/line/credential-manager.test.ts +17 -17
  385. package/src/platforms/line/index.test.ts +10 -10
  386. package/src/platforms/line/listener.test.ts +15 -15
  387. package/src/platforms/line/types.test.ts +14 -14
  388. package/src/platforms/slack/cli.test.ts +8 -8
  389. package/src/platforms/slack/client.test.ts +151 -151
  390. package/src/platforms/slack/commands/activity.test.ts +13 -13
  391. package/src/platforms/slack/commands/auth.test.ts +34 -34
  392. package/src/platforms/slack/commands/auth.ts +11 -2
  393. package/src/platforms/slack/commands/bookmark.test.ts +9 -9
  394. package/src/platforms/slack/commands/channel.test.ts +17 -17
  395. package/src/platforms/slack/commands/drafts.test.ts +7 -7
  396. package/src/platforms/slack/commands/emoji.test.ts +3 -3
  397. package/src/platforms/slack/commands/file.test.ts +12 -12
  398. package/src/platforms/slack/commands/message.test.ts +19 -19
  399. package/src/platforms/slack/commands/pin.test.ts +7 -7
  400. package/src/platforms/slack/commands/reaction.test.ts +10 -10
  401. package/src/platforms/slack/commands/reminder.test.ts +9 -9
  402. package/src/platforms/slack/commands/saved.test.ts +7 -7
  403. package/src/platforms/slack/commands/sections.test.ts +5 -5
  404. package/src/platforms/slack/commands/snapshot.test.ts +13 -13
  405. package/src/platforms/slack/commands/unread.test.ts +6 -6
  406. package/src/platforms/slack/commands/user.test.ts +10 -10
  407. package/src/platforms/slack/commands/usergroup.test.ts +15 -15
  408. package/src/platforms/slack/commands/whoami.test.ts +6 -6
  409. package/src/platforms/slack/commands/workspace.test.ts +26 -26
  410. package/src/platforms/slack/credential-manager.test.ts +14 -14
  411. package/src/platforms/slack/ensure-auth.test.ts +21 -21
  412. package/src/platforms/slack/index.test.ts +12 -12
  413. package/src/platforms/slack/listener.test.ts +17 -17
  414. package/src/platforms/slack/token-extractor-node.test.ts +2 -2
  415. package/src/platforms/slack/token-extractor.test.ts +133 -37
  416. package/src/platforms/slack/token-extractor.ts +76 -13
  417. package/src/platforms/slack/types.test.ts +21 -21
  418. package/src/platforms/slackbot/cli.ts +13 -1
  419. package/src/platforms/slackbot/client.test.ts +296 -22
  420. package/src/platforms/slackbot/client.ts +130 -2
  421. package/src/platforms/slackbot/commands/auth.test.ts +14 -14
  422. package/src/platforms/slackbot/commands/auth.ts +1 -5
  423. package/src/platforms/slackbot/commands/channel.test.ts +7 -7
  424. package/src/platforms/slackbot/commands/file.test.ts +201 -0
  425. package/src/platforms/slackbot/commands/file.ts +212 -0
  426. package/src/platforms/slackbot/commands/index.ts +1 -0
  427. package/src/platforms/slackbot/commands/message.test.ts +13 -13
  428. package/src/platforms/slackbot/commands/message.ts +22 -0
  429. package/src/platforms/slackbot/commands/reaction.test.ts +6 -6
  430. package/src/platforms/slackbot/commands/user.test.ts +7 -7
  431. package/src/platforms/slackbot/commands/whoami.test.ts +4 -4
  432. package/src/platforms/slackbot/commands/whoami.ts +1 -6
  433. package/src/platforms/slackbot/credential-manager.test.ts +83 -23
  434. package/src/platforms/slackbot/credential-manager.ts +32 -2
  435. package/src/platforms/slackbot/index.test.ts +59 -0
  436. package/src/platforms/slackbot/index.ts +31 -7
  437. package/src/platforms/slackbot/listener.test.ts +1012 -0
  438. package/src/platforms/slackbot/listener.ts +362 -0
  439. package/src/platforms/slackbot/types.test.ts +7 -7
  440. package/src/platforms/slackbot/types.ts +224 -1
  441. package/src/platforms/teams/client.test.ts +30 -30
  442. package/src/platforms/teams/commands/auth.test.ts +9 -9
  443. package/src/platforms/teams/commands/auth.ts +66 -7
  444. package/src/platforms/teams/commands/channel.test.ts +7 -7
  445. package/src/platforms/teams/commands/file.test.ts +4 -4
  446. package/src/platforms/teams/commands/message.test.ts +5 -5
  447. package/src/platforms/teams/commands/reaction.test.ts +4 -4
  448. package/src/platforms/teams/commands/snapshot.test.ts +7 -7
  449. package/src/platforms/teams/commands/team.test.ts +8 -8
  450. package/src/platforms/teams/commands/user.test.ts +4 -4
  451. package/src/platforms/teams/commands/whoami.test.ts +6 -6
  452. package/src/platforms/teams/credential-manager.test.ts +17 -17
  453. package/src/platforms/teams/ensure-auth.test.ts +69 -18
  454. package/src/platforms/teams/ensure-auth.ts +39 -11
  455. package/src/platforms/teams/index.test.ts +15 -15
  456. package/src/platforms/teams/token-extractor.test.ts +251 -69
  457. package/src/platforms/teams/token-extractor.ts +94 -31
  458. package/src/platforms/teams/types.test.ts +26 -26
  459. package/src/platforms/telegram/app-config.test.ts +4 -4
  460. package/src/platforms/telegram/chat-utils.test.ts +12 -12
  461. package/src/platforms/telegram/client.test.ts +4 -4
  462. package/src/platforms/telegram/commands/auth.test.ts +16 -16
  463. package/src/platforms/telegram/commands/chat.test.ts +9 -9
  464. package/src/platforms/telegram/commands/message.test.ts +6 -6
  465. package/src/platforms/telegram/commands/shared.test.ts +3 -3
  466. package/src/platforms/telegram/commands/whoami.test.ts +3 -3
  467. package/src/platforms/telegram/credential-manager.test.ts +10 -10
  468. package/src/platforms/telegram/types.test.ts +6 -6
  469. package/src/platforms/webex/app-config.test.ts +8 -8
  470. package/src/platforms/webex/cli.test.ts +5 -5
  471. package/src/platforms/webex/client.test.ts +65 -65
  472. package/src/platforms/webex/commands/auth.test.ts +18 -18
  473. package/src/platforms/webex/commands/auth.ts +13 -2
  474. package/src/platforms/webex/commands/member.test.ts +5 -5
  475. package/src/platforms/webex/commands/message.test.ts +12 -12
  476. package/src/platforms/webex/commands/snapshot.test.ts +5 -5
  477. package/src/platforms/webex/commands/space.test.ts +10 -10
  478. package/src/platforms/webex/commands/whoami.test.ts +6 -6
  479. package/src/platforms/webex/credential-manager.test.ts +22 -22
  480. package/src/platforms/webex/encryption.test.ts +4 -4
  481. package/src/platforms/webex/ensure-auth.test.ts +5 -5
  482. package/src/platforms/webex/index.test.ts +5 -5
  483. package/src/platforms/webex/markdown-to-html.test.ts +33 -33
  484. package/src/platforms/webex/token-extractor.test.ts +23 -23
  485. package/src/platforms/webex/token-extractor.ts +25 -3
  486. package/src/platforms/webex/types.test.ts +27 -27
  487. package/src/platforms/wechatbot/cli.ts +9 -0
  488. package/src/platforms/wechatbot/client.test.ts +27 -27
  489. package/src/platforms/wechatbot/commands/auth.test.ts +15 -15
  490. package/src/platforms/wechatbot/commands/auth.ts +1 -5
  491. package/src/platforms/wechatbot/commands/message.test.ts +8 -8
  492. package/src/platforms/wechatbot/commands/message.ts +1 -6
  493. package/src/platforms/wechatbot/commands/template.test.ts +9 -9
  494. package/src/platforms/wechatbot/commands/template.ts +1 -6
  495. package/src/platforms/wechatbot/commands/user.test.ts +7 -7
  496. package/src/platforms/wechatbot/commands/user.ts +1 -6
  497. package/src/platforms/wechatbot/commands/whoami.test.ts +5 -5
  498. package/src/platforms/wechatbot/commands/whoami.ts +1 -6
  499. package/src/platforms/wechatbot/credential-manager.test.ts +18 -18
  500. package/src/platforms/wechatbot/index.test.ts +10 -10
  501. package/src/platforms/wechatbot/types.test.ts +25 -25
  502. package/src/platforms/whatsapp/commands/auth.test.ts +13 -13
  503. package/src/platforms/whatsapp/commands/chat.test.ts +8 -8
  504. package/src/platforms/whatsapp/commands/message.test.ts +10 -10
  505. package/src/platforms/whatsapp/commands/whoami.test.ts +3 -3
  506. package/src/platforms/whatsapp/credential-manager.test.ts +23 -23
  507. package/src/platforms/whatsapp/ensure-auth.test.ts +4 -4
  508. package/src/platforms/whatsapp/index.test.ts +8 -8
  509. package/src/platforms/whatsapp/types.test.ts +42 -42
  510. package/src/platforms/whatsappbot/cli.ts +9 -0
  511. package/src/platforms/whatsappbot/client.test.ts +27 -27
  512. package/src/platforms/whatsappbot/commands/auth.test.ts +14 -14
  513. package/src/platforms/whatsappbot/commands/auth.ts +1 -5
  514. package/src/platforms/whatsappbot/commands/message.test.ts +16 -16
  515. package/src/platforms/whatsappbot/commands/message.ts +1 -6
  516. package/src/platforms/whatsappbot/commands/template.test.ts +9 -9
  517. package/src/platforms/whatsappbot/commands/template.ts +1 -6
  518. package/src/platforms/whatsappbot/commands/whoami.test.ts +5 -5
  519. package/src/platforms/whatsappbot/commands/whoami.ts +1 -6
  520. package/src/platforms/whatsappbot/credential-manager.test.ts +18 -18
  521. package/src/platforms/whatsappbot/index.test.ts +7 -7
  522. package/src/platforms/whatsappbot/types.test.ts +18 -18
  523. package/src/shared/chromium/browsers.test.ts +102 -22
  524. package/src/shared/chromium/browsers.ts +72 -3
  525. package/src/shared/chromium/cli-options.test.ts +22 -0
  526. package/src/shared/chromium/cli-options.ts +12 -0
  527. package/src/shared/chromium/cookie-reader.test.ts +13 -13
  528. package/src/shared/chromium/decryptor.test.ts +97 -32
  529. package/src/shared/chromium/decryptor.ts +27 -6
  530. package/src/shared/chromium/index.ts +3 -0
  531. package/src/shared/utils/cli-output.test.ts +57 -0
  532. package/src/shared/utils/cli-output.ts +8 -0
  533. package/src/shared/utils/concurrency.test.ts +6 -6
  534. package/src/shared/utils/derived-key-cache.test.ts +11 -11
  535. package/src/tui/app.ts +129 -20
  536. package/src/tui/utils.test.ts +31 -31
@@ -0,0 +1,57 @@
1
+ import { afterEach, beforeEach, describe, expect, it, mock } from 'bun:test'
2
+
3
+ import { cliOutput } from './cli-output'
4
+
5
+ describe('cliOutput', () => {
6
+ let logSpy: ReturnType<typeof mock>
7
+ let exitSpy: ReturnType<typeof mock>
8
+ let originalLog: typeof console.log
9
+ let originalExit: typeof process.exit
10
+
11
+ beforeEach(() => {
12
+ originalLog = console.log
13
+ originalExit = process.exit
14
+ logSpy = mock(() => {})
15
+ exitSpy = mock(((_code?: number) => undefined) as never)
16
+ console.log = logSpy as unknown as typeof console.log
17
+ process.exit = exitSpy as unknown as typeof process.exit
18
+ })
19
+
20
+ afterEach(() => {
21
+ console.log = originalLog
22
+ process.exit = originalExit
23
+ })
24
+
25
+ it('prints compact JSON for success results', () => {
26
+ cliOutput({ ok: true, value: 42 })
27
+
28
+ expect(logSpy).toHaveBeenCalledWith('{"ok":true,"value":42}')
29
+ expect(exitSpy).not.toHaveBeenCalled()
30
+ })
31
+
32
+ it('prints pretty JSON when pretty=true', () => {
33
+ cliOutput({ ok: true }, true)
34
+
35
+ expect(logSpy).toHaveBeenCalledWith('{\n "ok": true\n}')
36
+ })
37
+
38
+ it('exits 1 when result.error is set', () => {
39
+ cliOutput({ error: 'Something went wrong' })
40
+
41
+ expect(logSpy).toHaveBeenCalledWith('{"error":"Something went wrong"}')
42
+ expect(exitSpy).toHaveBeenCalledWith(1)
43
+ })
44
+
45
+ it('does not exit when exitOnError=false even with error set', () => {
46
+ cliOutput({ error: 'Soft fail' }, false, false)
47
+
48
+ expect(logSpy).toHaveBeenCalledWith('{"error":"Soft fail"}')
49
+ expect(exitSpy).not.toHaveBeenCalled()
50
+ })
51
+
52
+ it('does not exit when error is undefined', () => {
53
+ cliOutput({ error: undefined, success: true })
54
+
55
+ expect(exitSpy).not.toHaveBeenCalled()
56
+ })
57
+ })
@@ -0,0 +1,8 @@
1
+ import { formatOutput } from './output'
2
+
3
+ export type CliResult = { error?: string } & Record<string, unknown>
4
+
5
+ export function cliOutput<T extends { error?: string }>(result: T, pretty?: boolean, exitOnError = true): void {
6
+ console.log(formatOutput(result, pretty))
7
+ if (result.error && exitOnError) process.exit(1)
8
+ }
@@ -1,15 +1,15 @@
1
- import { describe, expect, test } from 'bun:test'
1
+ import { describe, expect, it } from 'bun:test'
2
2
 
3
3
  import { parallelMap } from './concurrency'
4
4
 
5
5
  describe('parallelMap', () => {
6
- test('processes items in parallel', async () => {
6
+ it('processes items in parallel', async () => {
7
7
  const items = [1, 2, 3, 4, 5]
8
8
  const results = await parallelMap(items, async (n) => n * 2)
9
9
  expect(results).toEqual([2, 4, 6, 8, 10])
10
10
  })
11
11
 
12
- test('maintains order of results', async () => {
12
+ it('maintains order of results', async () => {
13
13
  const items = [100, 50, 10]
14
14
  const results = await parallelMap(
15
15
  items,
@@ -22,7 +22,7 @@ describe('parallelMap', () => {
22
22
  expect(results).toEqual([100, 50, 10])
23
23
  })
24
24
 
25
- test('respects concurrency limit', async () => {
25
+ it('respects concurrency limit', async () => {
26
26
  let concurrent = 0
27
27
  let maxConcurrent = 0
28
28
  const items = [1, 2, 3, 4, 5, 6]
@@ -41,12 +41,12 @@ describe('parallelMap', () => {
41
41
  expect(maxConcurrent).toBe(2)
42
42
  })
43
43
 
44
- test('handles empty array', async () => {
44
+ it('handles empty array', async () => {
45
45
  const results = await parallelMap([], async (n: number) => n * 2)
46
46
  expect(results).toEqual([])
47
47
  })
48
48
 
49
- test('passes index to function', async () => {
49
+ it('passes index to function', async () => {
50
50
  const items = ['a', 'b', 'c']
51
51
  const results = await parallelMap(items, async (item, index) => `${item}${index}`)
52
52
  expect(results).toEqual(['a0', 'b1', 'c2'])
@@ -1,4 +1,4 @@
1
- import { afterEach, beforeEach, describe, expect, test } from 'bun:test'
1
+ import { afterEach, beforeEach, describe, expect, it } from 'bun:test'
2
2
  import { existsSync, mkdirSync, rmSync } from 'node:fs'
3
3
  import { tmpdir } from 'node:os'
4
4
  import { join } from 'node:path'
@@ -22,12 +22,12 @@ describe('DerivedKeyCache', () => {
22
22
  })
23
23
 
24
24
  describe('get', () => {
25
- test('returns null when no cached key exists', async () => {
25
+ it('returns null when no cached key exists', async () => {
26
26
  const result = await cache.get('slack')
27
27
  expect(result).toBeNull()
28
28
  })
29
29
 
30
- test('returns cached key when it exists', async () => {
30
+ it('returns cached key when it exists', async () => {
31
31
  // given
32
32
  const key = Buffer.from('test-key-16bytes')
33
33
  await cache.set('slack', key)
@@ -39,7 +39,7 @@ describe('DerivedKeyCache', () => {
39
39
  expect(result).toEqual(key)
40
40
  })
41
41
 
42
- test('returns different keys for different platforms', async () => {
42
+ it('returns different keys for different platforms', async () => {
43
43
  // given
44
44
  const slackKey = Buffer.from('slack-key-16byte')
45
45
  const discordKey = Buffer.from('discord-key-16by')
@@ -53,7 +53,7 @@ describe('DerivedKeyCache', () => {
53
53
  })
54
54
 
55
55
  describe('set', () => {
56
- test('creates cache directory if it does not exist', async () => {
56
+ it('creates cache directory if it does not exist', async () => {
57
57
  // given
58
58
  const nestedDir = join(testDir, 'nested', 'cache')
59
59
  const nestedCache = new DerivedKeyCache(nestedDir)
@@ -65,7 +65,7 @@ describe('DerivedKeyCache', () => {
65
65
  expect(existsSync(nestedDir)).toBe(true)
66
66
  })
67
67
 
68
- test('overwrites existing cached key', async () => {
68
+ it('overwrites existing cached key', async () => {
69
69
  // given
70
70
  const oldKey = Buffer.from('old-key-16bytes!')
71
71
  const newKey = Buffer.from('new-key-16bytes!')
@@ -80,7 +80,7 @@ describe('DerivedKeyCache', () => {
80
80
  })
81
81
 
82
82
  describe('clear', () => {
83
- test('removes cached key for platform', async () => {
83
+ it('removes cached key for platform', async () => {
84
84
  // given
85
85
  await cache.set('slack', Buffer.from('test-key'))
86
86
 
@@ -91,7 +91,7 @@ describe('DerivedKeyCache', () => {
91
91
  expect(await cache.get('slack')).toBeNull()
92
92
  })
93
93
 
94
- test('does not affect other platforms', async () => {
94
+ it('does not affect other platforms', async () => {
95
95
  // given
96
96
  const discordKey = Buffer.from('discord-key')
97
97
  await cache.set('slack', Buffer.from('slack-key'))
@@ -105,13 +105,13 @@ describe('DerivedKeyCache', () => {
105
105
  expect(await cache.get('discord')).toEqual(discordKey)
106
106
  })
107
107
 
108
- test('does not throw when key does not exist', async () => {
108
+ it('does not throw when key does not exist', async () => {
109
109
  await expect(cache.clear('slack')).resolves.toBeUndefined()
110
110
  })
111
111
  })
112
112
 
113
113
  describe('clearAll', () => {
114
- test('removes all cached keys', async () => {
114
+ it('removes all cached keys', async () => {
115
115
  // given
116
116
  await cache.set('slack', Buffer.from('slack-key'))
117
117
  await cache.set('discord', Buffer.from('discord-key'))
@@ -126,7 +126,7 @@ describe('DerivedKeyCache', () => {
126
126
  expect(await cache.get('teams')).toBeNull()
127
127
  })
128
128
 
129
- test('does not throw when cache directory does not exist', async () => {
129
+ it('does not throw when cache directory does not exist', async () => {
130
130
  // given
131
131
  const emptyCache = new DerivedKeyCache(join(testDir, 'nonexistent'))
132
132
 
package/src/tui/app.ts CHANGED
@@ -1,20 +1,89 @@
1
1
  import blessed from 'blessed'
2
2
 
3
- import { ChannelTalkAdapter } from './adapters/channeltalk-adapter'
4
- import { DiscordAdapter } from './adapters/discord-adapter'
5
- import { InstagramAdapter } from './adapters/instagram-adapter'
6
- import { KakaoTalkAdapter } from './adapters/kakaotalk-adapter'
7
- import { LineAdapter } from './adapters/line-adapter'
8
- import { SlackAdapter } from './adapters/slack-adapter'
9
- import { TeamsAdapter } from './adapters/teams-adapter'
10
- import { TelegramAdapter } from './adapters/telegram-adapter'
11
3
  import type { AuthIO, PlatformAdapter, UnifiedChannel, UnifiedMessage, Workspace } from './adapters/types'
12
- import { WebexAdapter } from './adapters/webex-adapter'
13
- import { WhatsAppAdapter } from './adapters/whatsapp-adapter'
14
4
  import { formatTimestamp } from './utils'
15
5
  import { ChannelPicker } from './views/channel-picker'
16
6
  import { WorkspacePicker } from './views/workspace-picker'
17
7
 
8
+ type PlatformAdapterFactory = () => Promise<PlatformAdapter>
9
+
10
+ class LazyPlatformAdapter implements PlatformAdapter {
11
+ readonly name: string
12
+ private adapter: PlatformAdapter | null = null
13
+ private loadPromise: Promise<PlatformAdapter> | null = null
14
+
15
+ constructor(
16
+ name: string,
17
+ private readonly fallbackAuthHint: string,
18
+ private readonly factory: PlatformAdapterFactory,
19
+ ) {
20
+ this.name = name
21
+ }
22
+
23
+ private async load(): Promise<PlatformAdapter> {
24
+ if (this.adapter) return this.adapter
25
+ this.loadPromise ??= this.factory()
26
+ .then((adapter) => {
27
+ this.adapter = adapter
28
+ return adapter
29
+ })
30
+ .catch((error: unknown) => {
31
+ this.loadPromise = null
32
+ throw error
33
+ })
34
+ return this.loadPromise
35
+ }
36
+
37
+ async login(): Promise<void> {
38
+ await (await this.load()).login()
39
+ }
40
+
41
+ async getChannels(): Promise<UnifiedChannel[]> {
42
+ return (await this.load()).getChannels()
43
+ }
44
+
45
+ async getMessages(channelId: string, limit?: number): Promise<UnifiedMessage[]> {
46
+ return (await this.load()).getMessages(channelId, limit)
47
+ }
48
+
49
+ async sendMessage(channelId: string, text: string): Promise<void> {
50
+ await (await this.load()).sendMessage(channelId, text)
51
+ }
52
+
53
+ async startListening(onMessage: (msg: UnifiedMessage) => void): Promise<void> {
54
+ const adapter = await this.load()
55
+ await adapter.startListening?.(onMessage)
56
+ }
57
+
58
+ stopListening(): void {
59
+ this.adapter?.stopListening?.()
60
+ }
61
+
62
+ async getWorkspaces(): Promise<Workspace[]> {
63
+ return (await this.load()).getWorkspaces?.() ?? []
64
+ }
65
+
66
+ async switchWorkspace(workspaceId: string): Promise<void> {
67
+ await (await this.load()).switchWorkspace?.(workspaceId)
68
+ }
69
+
70
+ getCurrentWorkspace(): Workspace | null {
71
+ return this.adapter?.getCurrentWorkspace?.() ?? null
72
+ }
73
+
74
+ getAuthHint() {
75
+ return this.adapter?.getAuthHint() ?? { command: this.fallbackAuthHint, description: `Authenticate ${this.name}` }
76
+ }
77
+
78
+ async authenticate(io: AuthIO): Promise<void> {
79
+ await (await this.load()).authenticate(io)
80
+ }
81
+ }
82
+
83
+ function lazyAdapter(name: string, fallbackAuthHint: string, factory: PlatformAdapterFactory): PlatformAdapter {
84
+ return new LazyPlatformAdapter(name, fallbackAuthHint, factory)
85
+ }
86
+
18
87
  type AppMode = 'selection' | 'read' | 'write' | 'auth'
19
88
  type NavLevel = 'platform' | 'workspace' | 'channel'
20
89
 
@@ -36,7 +105,11 @@ export async function createApp(): Promise<void> {
36
105
 
37
106
  const platformStates: PlatformState[] = [
38
107
  {
39
- adapter: new SlackAdapter(),
108
+ adapter: lazyAdapter(
109
+ 'Slack',
110
+ 'agent-slack auth extract',
111
+ async () => new (await import('./adapters/slack-adapter')).SlackAdapter(),
112
+ ),
40
113
  label: 'Slack',
41
114
  enabled: false,
42
115
  channels: null,
@@ -45,7 +118,11 @@ export async function createApp(): Promise<void> {
45
118
  lastChannelId: null,
46
119
  },
47
120
  {
48
- adapter: new DiscordAdapter(),
121
+ adapter: lazyAdapter(
122
+ 'Discord',
123
+ 'agent-discord auth extract',
124
+ async () => new (await import('./adapters/discord-adapter')).DiscordAdapter(),
125
+ ),
49
126
  label: 'Discord',
50
127
  enabled: false,
51
128
  channels: null,
@@ -54,7 +131,11 @@ export async function createApp(): Promise<void> {
54
131
  lastChannelId: null,
55
132
  },
56
133
  {
57
- adapter: new TeamsAdapter(),
134
+ adapter: lazyAdapter(
135
+ 'Teams',
136
+ 'agent-teams auth extract',
137
+ async () => new (await import('./adapters/teams-adapter')).TeamsAdapter(),
138
+ ),
58
139
  label: 'Teams',
59
140
  enabled: false,
60
141
  channels: null,
@@ -63,7 +144,11 @@ export async function createApp(): Promise<void> {
63
144
  lastChannelId: null,
64
145
  },
65
146
  {
66
- adapter: new WebexAdapter(),
147
+ adapter: lazyAdapter(
148
+ 'Webex',
149
+ 'agent-webex auth extract',
150
+ async () => new (await import('./adapters/webex-adapter')).WebexAdapter(),
151
+ ),
67
152
  label: 'Webex',
68
153
  enabled: false,
69
154
  channels: null,
@@ -72,7 +157,11 @@ export async function createApp(): Promise<void> {
72
157
  lastChannelId: null,
73
158
  },
74
159
  {
75
- adapter: new TelegramAdapter(),
160
+ adapter: lazyAdapter(
161
+ 'Telegram',
162
+ 'agent-telegram auth login',
163
+ async () => new (await import('./adapters/telegram-adapter')).TelegramAdapter(),
164
+ ),
76
165
  label: 'Telegram',
77
166
  enabled: false,
78
167
  channels: null,
@@ -81,7 +170,11 @@ export async function createApp(): Promise<void> {
81
170
  lastChannelId: null,
82
171
  },
83
172
  {
84
- adapter: new WhatsAppAdapter(),
173
+ adapter: lazyAdapter(
174
+ 'WhatsApp',
175
+ 'agent-whatsapp auth login',
176
+ async () => new (await import('./adapters/whatsapp-adapter')).WhatsAppAdapter(),
177
+ ),
85
178
  label: 'WhatsApp',
86
179
  enabled: false,
87
180
  channels: null,
@@ -90,7 +183,11 @@ export async function createApp(): Promise<void> {
90
183
  lastChannelId: null,
91
184
  },
92
185
  {
93
- adapter: new LineAdapter(),
186
+ adapter: lazyAdapter(
187
+ 'LINE',
188
+ 'agent-line auth login',
189
+ async () => new (await import('./adapters/line-adapter')).LineAdapter(),
190
+ ),
94
191
  label: 'LINE',
95
192
  enabled: false,
96
193
  channels: null,
@@ -99,7 +196,11 @@ export async function createApp(): Promise<void> {
99
196
  lastChannelId: null,
100
197
  },
101
198
  {
102
- adapter: new InstagramAdapter(),
199
+ adapter: lazyAdapter(
200
+ 'Instagram',
201
+ 'agent-instagram auth login',
202
+ async () => new (await import('./adapters/instagram-adapter')).InstagramAdapter(),
203
+ ),
103
204
  label: 'Instagram',
104
205
  enabled: false,
105
206
  channels: null,
@@ -108,7 +209,11 @@ export async function createApp(): Promise<void> {
108
209
  lastChannelId: null,
109
210
  },
110
211
  {
111
- adapter: new KakaoTalkAdapter(),
212
+ adapter: lazyAdapter(
213
+ 'KakaoTalk',
214
+ 'agent-kakaotalk auth extract',
215
+ async () => new (await import('./adapters/kakaotalk-adapter')).KakaoTalkAdapter(),
216
+ ),
112
217
  label: 'KakaoTalk',
113
218
  enabled: false,
114
219
  channels: null,
@@ -117,7 +222,11 @@ export async function createApp(): Promise<void> {
117
222
  lastChannelId: null,
118
223
  },
119
224
  {
120
- adapter: new ChannelTalkAdapter(),
225
+ adapter: lazyAdapter(
226
+ 'Channel Talk',
227
+ 'agent-channeltalk auth extract',
228
+ async () => new (await import('./adapters/channeltalk-adapter')).ChannelTalkAdapter(),
229
+ ),
121
230
  label: 'Channel Talk',
122
231
  enabled: false,
123
232
  channels: null,
@@ -1,16 +1,16 @@
1
- import { describe, test, expect } from 'bun:test'
1
+ import { describe, it, expect } from 'bun:test'
2
2
 
3
3
  import { formatTimestamp, truncate, fuzzyMatch, stripHtml } from './utils'
4
4
 
5
5
  describe('formatTimestamp', () => {
6
- test("today's date returns HH:MM", () => {
6
+ it("returns HH:MM for today's date", () => {
7
7
  const now = new Date()
8
8
  const epochSeconds = (now.getTime() / 1000).toFixed(6)
9
9
  const result = formatTimestamp(epochSeconds)
10
10
  expect(result).toMatch(/^\d{2}:\d{2}$/)
11
11
  })
12
12
 
13
- test("yesterday's date returns MM/DD HH:MM", () => {
13
+ it("returns MM/DD HH:MM for yesterday's date", () => {
14
14
  const yesterday = new Date()
15
15
  yesterday.setDate(yesterday.getDate() - 1)
16
16
  const epochSeconds = (yesterday.getTime() / 1000).toFixed(6)
@@ -18,24 +18,24 @@ describe('formatTimestamp', () => {
18
18
  expect(result).toMatch(/^\d{2}\/\d{2} \d{2}:\d{2}$/)
19
19
  })
20
20
 
21
- test('ISO 8601 string for today returns HH:MM', () => {
21
+ it('ISO 8601 string for today returns HH:MM', () => {
22
22
  const now = new Date()
23
23
  const iso = now.toISOString()
24
24
  const result = formatTimestamp(iso)
25
25
  expect(result).toMatch(/^\d{2}:\d{2}$/)
26
26
  })
27
27
 
28
- test('ISO 8601 string for past date returns MM/DD HH:MM', () => {
28
+ it('ISO 8601 string for past date returns MM/DD HH:MM', () => {
29
29
  const result = formatTimestamp('2024-03-15T10:30:00Z')
30
30
  expect(result).toMatch(/^\d{2}\/\d{2} \d{2}:\d{2}$/)
31
31
  })
32
32
 
33
- test('invalid string returns original', () => {
33
+ it('invalid string returns original', () => {
34
34
  expect(formatTimestamp('not-a-date')).toBe('not-a-date')
35
35
  expect(formatTimestamp('abc123')).toBe('abc123')
36
36
  })
37
37
 
38
- test('Slack-style epoch with microseconds', () => {
38
+ it('formats Slack-style epoch with microseconds as HH:MM', () => {
39
39
  const now = new Date()
40
40
  const slackTs = `${Math.floor(now.getTime() / 1000)}.123456`
41
41
  const result = formatTimestamp(slackTs)
@@ -44,105 +44,105 @@ describe('formatTimestamp', () => {
44
44
  })
45
45
 
46
46
  describe('truncate', () => {
47
- test('short string returned unchanged', () => {
47
+ it('returns short string unchanged', () => {
48
48
  expect(truncate('hello', 10)).toBe('hello')
49
49
  })
50
50
 
51
- test('exact length returned unchanged', () => {
51
+ it('returns string unchanged when length equals maxLen', () => {
52
52
  expect(truncate('hello', 5)).toBe('hello')
53
53
  })
54
54
 
55
- test('long string gets truncated with ellipsis', () => {
55
+ it('long string gets truncated with ellipsis', () => {
56
56
  expect(truncate('hello world', 8)).toBe('hello...')
57
57
  })
58
58
 
59
- test('maxLen of 3 truncates without ellipsis', () => {
59
+ it('truncates without ellipsis when maxLen is 3', () => {
60
60
  expect(truncate('hello', 3)).toBe('hel')
61
61
  })
62
62
 
63
- test('maxLen of 1 truncates without ellipsis', () => {
63
+ it('truncates without ellipsis when maxLen is 1', () => {
64
64
  expect(truncate('hello', 1)).toBe('h')
65
65
  })
66
66
 
67
- test('maxLen of 0 returns empty string', () => {
67
+ it('returns empty string when maxLen is 0', () => {
68
68
  expect(truncate('hello', 0)).toBe('')
69
69
  })
70
70
 
71
- test('maxLen of 4 adds ellipsis', () => {
71
+ it('adds ellipsis when maxLen is 4', () => {
72
72
  expect(truncate('hello', 4)).toBe('h...')
73
73
  })
74
74
  })
75
75
 
76
76
  describe('fuzzyMatch', () => {
77
- test('exact match returns true', () => {
77
+ it('exact match returns true', () => {
78
78
  expect(fuzzyMatch('general', 'general')).toBe(true)
79
79
  })
80
80
 
81
- test('partial match in order returns true', () => {
81
+ it('partial match in order returns true', () => {
82
82
  expect(fuzzyMatch('gnrl', 'general')).toBe(true)
83
83
  })
84
84
 
85
- test('case insensitive match', () => {
85
+ it('matches case-insensitively', () => {
86
86
  expect(fuzzyMatch('GNRL', 'general')).toBe(true)
87
87
  expect(fuzzyMatch('gnrl', 'GENERAL')).toBe(true)
88
88
  })
89
89
 
90
- test('empty query returns true', () => {
90
+ it('empty query returns true', () => {
91
91
  expect(fuzzyMatch('', 'anything')).toBe(true)
92
92
  expect(fuzzyMatch('', '')).toBe(true)
93
93
  })
94
94
 
95
- test('no match returns false', () => {
95
+ it('no match returns false', () => {
96
96
  expect(fuzzyMatch('xyz', 'general')).toBe(false)
97
97
  })
98
98
 
99
- test('characters out of order returns false', () => {
99
+ it('characters out of order returns false', () => {
100
100
  expect(fuzzyMatch('lrng', 'general')).toBe(false)
101
101
  })
102
102
 
103
- test('query longer than text returns false', () => {
103
+ it('query longer than text returns false', () => {
104
104
  expect(fuzzyMatch('generalgeneral', 'general')).toBe(false)
105
105
  })
106
106
  })
107
107
 
108
108
  describe('stripHtml', () => {
109
- test('removes simple tags', () => {
109
+ it('removes simple tags', () => {
110
110
  expect(stripHtml('<p>hello</p>')).toBe('hello')
111
111
  })
112
112
 
113
- test('removes nested tags', () => {
113
+ it('removes nested tags', () => {
114
114
  expect(stripHtml('<div><p><strong>hello</strong></p></div>')).toBe('hello')
115
115
  })
116
116
 
117
- test('decodes &amp;', () => {
117
+ it('decodes &amp;', () => {
118
118
  expect(stripHtml('a &amp; b')).toBe('a & b')
119
119
  })
120
120
 
121
- test('decodes &lt; and &gt;', () => {
121
+ it('decodes &lt; and &gt;', () => {
122
122
  expect(stripHtml('&lt;tag&gt;')).toBe('<tag>')
123
123
  })
124
124
 
125
- test('decodes &quot;', () => {
125
+ it('decodes &quot;', () => {
126
126
  expect(stripHtml('say &quot;hello&quot;')).toBe('say "hello"')
127
127
  })
128
128
 
129
- test('decodes &#39;', () => {
129
+ it('decodes &#39;', () => {
130
130
  expect(stripHtml('it&#39;s')).toBe("it's")
131
131
  })
132
132
 
133
- test('collapses multiple whitespace', () => {
133
+ it('collapses multiple whitespace', () => {
134
134
  expect(stripHtml('hello world')).toBe('hello world')
135
135
  })
136
136
 
137
- test('trims leading and trailing whitespace', () => {
137
+ it('trims leading and trailing whitespace', () => {
138
138
  expect(stripHtml(' hello ')).toBe('hello')
139
139
  })
140
140
 
141
- test('handles multiple entities and tags together', () => {
141
+ it('handles multiple entities and tags together', () => {
142
142
  expect(stripHtml('<p>Hello &amp; <strong>World</strong></p>')).toBe('Hello & World')
143
143
  })
144
144
 
145
- test('whitespace from tag removal is collapsed', () => {
145
+ it('collapses whitespace left by tag removal', () => {
146
146
  expect(stripHtml('<p>hello</p> <p>world</p>')).toBe('hello world')
147
147
  })
148
148
  })