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
@@ -1,4 +1,4 @@
1
- import { afterEach, beforeEach, expect, spyOn, test } from 'bun:test'
1
+ import { afterEach, beforeEach, expect, spyOn, it } from 'bun:test'
2
2
 
3
3
  import { TeamsClient } from '../client'
4
4
  import { TeamsCredentialManager } from '../credential-manager'
@@ -60,7 +60,7 @@ afterEach(() => {
60
60
  credManagerSaveConfigSpy?.mockRestore()
61
61
  })
62
62
 
63
- test('list: returns teams with current marker', async () => {
63
+ it('list: returns teams with current marker', async () => {
64
64
  // given: credential manager with teams
65
65
  const credManager = new TeamsCredentialManager()
66
66
  const config = await credManager.loadConfig()
@@ -75,7 +75,7 @@ test('list: returns teams with current marker', async () => {
75
75
  expect(account.teams['team-2']).toBeDefined()
76
76
  })
77
77
 
78
- test('list: marks current team', async () => {
78
+ it('list: marks current team', async () => {
79
79
  // given: credential manager with current team set
80
80
  const credManager = new TeamsCredentialManager()
81
81
  const config = await credManager.loadConfig()
@@ -88,7 +88,7 @@ test('list: marks current team', async () => {
88
88
  expect(config!.accounts.work.current_team).toBe('team-1')
89
89
  })
90
90
 
91
- test('info: returns team details', async () => {
91
+ it('info: returns team details', async () => {
92
92
  // given: teams client with team data
93
93
  const client = await new TeamsClient().login({ token: 'test-token', region: 'emea' })
94
94
  const team = await client.getTeam('team-1')
@@ -102,7 +102,7 @@ test('info: returns team details', async () => {
102
102
  expect(team.description).toBe('First team')
103
103
  })
104
104
 
105
- test('info: throws error for non-existent team', async () => {
105
+ it('info: throws error for non-existent team', async () => {
106
106
  // given: teams client
107
107
  const client = await new TeamsClient().login({ token: 'test-token', region: 'emea' })
108
108
 
@@ -116,7 +116,7 @@ test('info: throws error for non-existent team', async () => {
116
116
  }
117
117
  })
118
118
 
119
- test('switch: updates current team', async () => {
119
+ it('switch: updates current team', async () => {
120
120
  // given: credential manager
121
121
  const credManager = new TeamsCredentialManager()
122
122
 
@@ -127,7 +127,7 @@ test('switch: updates current team', async () => {
127
127
  expect(credManager.setCurrentTeam).toHaveBeenCalledWith('team-2', 'Team Two')
128
128
  })
129
129
 
130
- test('current: returns current team info', async () => {
130
+ it('current: returns current team info', async () => {
131
131
  // given: credential manager with current team
132
132
  const credManager = new TeamsCredentialManager()
133
133
  const config = await credManager.loadConfig()
@@ -140,7 +140,7 @@ test('current: returns current team info', async () => {
140
140
  expect(config!.accounts.work.current_team).toBe('team-1')
141
141
  })
142
142
 
143
- test('remove: removes team from config', async () => {
143
+ it('remove: removes team from config', async () => {
144
144
  // given: credential manager with teams
145
145
  const credManager = new TeamsCredentialManager()
146
146
  const config = await credManager.loadConfig()
@@ -1,4 +1,4 @@
1
- import { expect, mock, test } from 'bun:test'
1
+ import { expect, mock, it } from 'bun:test'
2
2
 
3
3
  // Mock TeamsClient
4
4
  const mockClient = {
@@ -28,7 +28,7 @@ const mockClient = {
28
28
  ]),
29
29
  }
30
30
 
31
- test('me returns current user info', async () => {
31
+ it('me returns current user info', async () => {
32
32
  // given: authenticated user
33
33
  const user = await mockClient.testAuth()
34
34
 
@@ -46,7 +46,7 @@ test('me returns current user info', async () => {
46
46
  expect(result.email).toBe('test@example.com')
47
47
  })
48
48
 
49
- test('info returns user details by id', async () => {
49
+ it('info returns user details by id', async () => {
50
50
  // given: user id
51
51
  const userId = 'user123'
52
52
 
@@ -64,7 +64,7 @@ test('info returns user details by id', async () => {
64
64
  expect(result.displayName).toBe('Test User')
65
65
  })
66
66
 
67
- test('list returns team members', async () => {
67
+ it('list returns team members', async () => {
68
68
  // given: team id
69
69
  const teamId = 'team123'
70
70
 
@@ -1,4 +1,4 @@
1
- import { afterEach, beforeEach, expect, spyOn, test } from 'bun:test'
1
+ import { afterEach, beforeEach, expect, spyOn, it } from 'bun:test'
2
2
 
3
3
  import { TeamsClient } from '@/platforms/teams/client'
4
4
  import { whoamiAction, whoamiCommand } from '@/platforms/teams/commands/whoami'
@@ -33,19 +33,19 @@ afterEach(() => {
33
33
  processExitSpy?.mockRestore()
34
34
  })
35
35
 
36
- test('whoami command is defined with correct name and description', () => {
36
+ it('whoami command is defined with correct name and description', () => {
37
37
  expect(whoamiCommand).toBeDefined()
38
38
  expect(whoamiCommand.name()).toBe('whoami')
39
39
  expect(whoamiCommand.description()).toBe('Show current authenticated user')
40
40
  })
41
41
 
42
- test('whoami command has --pretty option', () => {
42
+ it('whoami command has --pretty option', () => {
43
43
  const options = whoamiCommand.options
44
44
  const hasPretty = options.some((opt: { long?: string }) => opt.long === '--pretty')
45
45
  expect(hasPretty).toBe(true)
46
46
  })
47
47
 
48
- test('whoami outputs id and displayName', async () => {
48
+ it('whoami outputs id and displayName', async () => {
49
49
  await whoamiAction({})
50
50
 
51
51
  expect(consoleLogSpy).toHaveBeenCalledWith(
@@ -56,7 +56,7 @@ test('whoami outputs id and displayName', async () => {
56
56
  )
57
57
  })
58
58
 
59
- test('whoami outputs pretty-printed JSON when pretty is true', async () => {
59
+ it('whoami outputs pretty-printed JSON when pretty is true', async () => {
60
60
  await whoamiAction({ pretty: true })
61
61
 
62
62
  expect(consoleLogSpy).toHaveBeenCalledWith(
@@ -71,7 +71,7 @@ test('whoami outputs pretty-printed JSON when pretty is true', async () => {
71
71
  )
72
72
  })
73
73
 
74
- test('whoami exits with error when not authenticated', async () => {
74
+ it('whoami exits with error when not authenticated', async () => {
75
75
  credManagerSpy.mockResolvedValue(null)
76
76
 
77
77
  await whoamiAction({})
@@ -1,4 +1,4 @@
1
- import { afterAll, describe, expect, test } from 'bun:test'
1
+ import { afterAll, describe, expect, it } from 'bun:test'
2
2
  import { existsSync, rmSync } from 'node:fs'
3
3
  import { join } from 'node:path'
4
4
 
@@ -19,14 +19,14 @@ afterAll(() => {
19
19
  })
20
20
 
21
21
  describe('TeamsCredentialManager', () => {
22
- test('loadConfig returns null when file does not exist', async () => {
22
+ it('loadConfig returns null when file does not exist', async () => {
23
23
  const manager = setup()
24
24
  const config = await manager.loadConfig()
25
25
 
26
26
  expect(config).toBeNull()
27
27
  })
28
28
 
29
- test('saveConfig creates config file with correct permissions', async () => {
29
+ it('saveConfig creates config file with correct permissions', async () => {
30
30
  const testConfigDir = join(
31
31
  import.meta.dir,
32
32
  `.test-teams-config-${Date.now()}-${Math.random().toString(36).slice(2)}`,
@@ -58,13 +58,13 @@ describe('TeamsCredentialManager', () => {
58
58
  expect(loaded).toEqual(config)
59
59
  })
60
60
 
61
- test('getToken returns null when not authenticated', async () => {
61
+ it('getToken returns null when not authenticated', async () => {
62
62
  const manager = setup()
63
63
  const token = await manager.getToken()
64
64
  expect(token).toBeNull()
65
65
  })
66
66
 
67
- test('setToken saves token to config', async () => {
67
+ it('setToken saves token to config', async () => {
68
68
  const manager = setup()
69
69
  await manager.setToken('test-token-123', 'work')
70
70
 
@@ -72,7 +72,7 @@ describe('TeamsCredentialManager', () => {
72
72
  expect(token).toBe('test-token-123')
73
73
  })
74
74
 
75
- test('setToken saves token with expiry', async () => {
75
+ it('setToken saves token with expiry', async () => {
76
76
  const manager = setup()
77
77
  const expiresAt = '2025-12-31T23:59:59Z'
78
78
  await manager.setToken('test-token-123', 'work', expiresAt)
@@ -82,13 +82,13 @@ describe('TeamsCredentialManager', () => {
82
82
  expect(config?.accounts?.work?.token_expires_at).toBe(expiresAt)
83
83
  })
84
84
 
85
- test('getCurrentTeam returns null when not set', async () => {
85
+ it('getCurrentTeam returns null when not set', async () => {
86
86
  const manager = setup()
87
87
  const team = await manager.getCurrentTeam()
88
88
  expect(team).toBeNull()
89
89
  })
90
90
 
91
- test('getTokenWithExpiry includes region', async () => {
91
+ it('getTokenWithExpiry includes region', async () => {
92
92
  const manager = setup()
93
93
  await manager.saveConfig({
94
94
  current_account: 'work',
@@ -113,7 +113,7 @@ describe('TeamsCredentialManager', () => {
113
113
  })
114
114
  })
115
115
 
116
- test('getCurrentTeam returns null when current_team is set but team not in teams record', async () => {
116
+ it('getCurrentTeam returns null when current_team is set but team not in teams record', async () => {
117
117
  const manager = setup()
118
118
  await manager.setToken('test-token', 'work')
119
119
  const config = await manager.loadConfig()
@@ -126,7 +126,7 @@ describe('TeamsCredentialManager', () => {
126
126
  expect(team).toBeNull()
127
127
  })
128
128
 
129
- test('setCurrentTeam saves team info', async () => {
129
+ it('setCurrentTeam saves team info', async () => {
130
130
  const manager = setup()
131
131
  await manager.setToken('test-token', 'work')
132
132
  await manager.setCurrentTeam('team-456', 'My Team')
@@ -135,7 +135,7 @@ describe('TeamsCredentialManager', () => {
135
135
  expect(team).toEqual({ team_id: 'team-456', team_name: 'My Team' })
136
136
  })
137
137
 
138
- test('setCurrentTeam updates existing team', async () => {
138
+ it('setCurrentTeam updates existing team', async () => {
139
139
  const manager = setup()
140
140
  await manager.setToken('test-token', 'work')
141
141
  await manager.setCurrentTeam('team-1', 'Team One')
@@ -149,7 +149,7 @@ describe('TeamsCredentialManager', () => {
149
149
  expect(config?.accounts?.work?.teams['team-2']).toEqual({ team_id: 'team-2', team_name: 'Team Two' })
150
150
  })
151
151
 
152
- test('clearCredentials removes all credentials', async () => {
152
+ it('clearCredentials removes all credentials', async () => {
153
153
  const manager = setup()
154
154
  await manager.setToken('test-token', 'work', '2025-12-31T23:59:59Z')
155
155
  await manager.setCurrentTeam('team-123', 'Test Team')
@@ -160,13 +160,13 @@ describe('TeamsCredentialManager', () => {
160
160
  expect(config).toBeNull()
161
161
  })
162
162
 
163
- test('isTokenExpired returns true when no config exists', async () => {
163
+ it('isTokenExpired returns true when no config exists', async () => {
164
164
  const manager = setup()
165
165
  const expired = await manager.isTokenExpired()
166
166
  expect(expired).toBe(true)
167
167
  })
168
168
 
169
- test('isTokenExpired returns true when no token_expires_at is set', async () => {
169
+ it('isTokenExpired returns true when no token_expires_at is set', async () => {
170
170
  const manager = setup()
171
171
  await manager.setToken('test-token', 'work')
172
172
 
@@ -174,7 +174,7 @@ describe('TeamsCredentialManager', () => {
174
174
  expect(expired).toBe(true)
175
175
  })
176
176
 
177
- test('isTokenExpired returns true when token is expired', async () => {
177
+ it('isTokenExpired returns true when token is expired', async () => {
178
178
  const manager = setup()
179
179
  const pastDate = new Date(Date.now() - 60000).toISOString()
180
180
  await manager.setToken('test-token', 'work', pastDate)
@@ -183,7 +183,7 @@ describe('TeamsCredentialManager', () => {
183
183
  expect(expired).toBe(true)
184
184
  })
185
185
 
186
- test('isTokenExpired returns false when token is not expired', async () => {
186
+ it('isTokenExpired returns false when token is not expired', async () => {
187
187
  const manager = setup()
188
188
  const futureDate = new Date(Date.now() + 3600000).toISOString()
189
189
  await manager.setToken('test-token', 'work', futureDate)
@@ -192,7 +192,7 @@ describe('TeamsCredentialManager', () => {
192
192
  expect(expired).toBe(false)
193
193
  })
194
194
 
195
- test('multiple operations preserve existing data', async () => {
195
+ it('multiple operations preserve existing data', async () => {
196
196
  const manager = setup()
197
197
  await manager.setToken('token-1', 'work', '2025-12-31T23:59:59Z')
198
198
  await manager.setCurrentTeam('team-1', 'Team One')
@@ -1,4 +1,4 @@
1
- import { afterEach, beforeEach, describe, expect, spyOn, test } from 'bun:test'
1
+ import { afterEach, beforeEach, describe, expect, spyOn, it } from 'bun:test'
2
2
 
3
3
  import { TeamsClient } from './client'
4
4
  import { TeamsCredentialManager } from './credential-manager'
@@ -16,7 +16,7 @@ beforeEach(() => {
16
16
  loadConfigSpy = spyOn(TeamsCredentialManager.prototype, 'loadConfig').mockResolvedValue(null)
17
17
 
18
18
  extractSpy = spyOn(TeamsTokenExtractor.prototype, 'extract').mockResolvedValue([
19
- { token: 'test-teams-token', accountType: 'work' },
19
+ { token: 'test-teams-token', accountType: 'work', accountTypeKnown: true },
20
20
  ])
21
21
 
22
22
  testAuthSpy = spyOn(TeamsClient.prototype, 'testAuth').mockResolvedValue({
@@ -44,7 +44,7 @@ afterEach(() => {
44
44
  })
45
45
 
46
46
  describe('ensureTeamsAuth', () => {
47
- test('skips extraction when token exists and not expired', async () => {
47
+ it('skips extraction when token exists and not expired', async () => {
48
48
  // given
49
49
  loadConfigSpy.mockResolvedValue({
50
50
  current_account: 'work',
@@ -66,7 +66,7 @@ describe('ensureTeamsAuth', () => {
66
66
  expect(extractSpy).not.toHaveBeenCalled()
67
67
  })
68
68
 
69
- test('extracts when no config exists', async () => {
69
+ it('extracts when no config exists', async () => {
70
70
  // given
71
71
  loadConfigSpy.mockResolvedValue(null)
72
72
 
@@ -94,7 +94,7 @@ describe('ensureTeamsAuth', () => {
94
94
  )
95
95
  })
96
96
 
97
- test('re-extracts when token is expired', async () => {
97
+ it('re-extracts when token is expired', async () => {
98
98
  // given
99
99
  loadConfigSpy.mockResolvedValue({
100
100
  current_account: 'work',
@@ -124,7 +124,7 @@ describe('ensureTeamsAuth', () => {
124
124
  )
125
125
  })
126
126
 
127
- test('sets first team as current', async () => {
127
+ it('sets first team as current', async () => {
128
128
  // when
129
129
  await ensureTeamsAuth()
130
130
 
@@ -138,7 +138,7 @@ describe('ensureTeamsAuth', () => {
138
138
  )
139
139
  })
140
140
 
141
- test('saves token_expires_at', async () => {
141
+ it('saves token_expires_at', async () => {
142
142
  // when
143
143
  const before = Date.now()
144
144
  await ensureTeamsAuth()
@@ -151,7 +151,7 @@ describe('ensureTeamsAuth', () => {
151
151
  expect(expiresAt).toBeLessThanOrEqual(after + 60 * 60 * 1000 + 1)
152
152
  })
153
153
 
154
- test('does not save when extraction returns null', async () => {
154
+ it('does not save when extraction returns null', async () => {
155
155
  // given
156
156
  extractSpy.mockResolvedValue([])
157
157
 
@@ -163,7 +163,7 @@ describe('ensureTeamsAuth', () => {
163
163
  expect(saveConfigSpy).not.toHaveBeenCalled()
164
164
  })
165
165
 
166
- test('does not save when no teams found', async () => {
166
+ it('does not save when no teams found', async () => {
167
167
  // given
168
168
  listTeamsSpy.mockResolvedValue([])
169
169
 
@@ -174,7 +174,7 @@ describe('ensureTeamsAuth', () => {
174
174
  expect(saveConfigSpy).not.toHaveBeenCalled()
175
175
  })
176
176
 
177
- test('silently handles extraction failure', async () => {
177
+ it('silently handles extraction failure', async () => {
178
178
  // given
179
179
  extractSpy.mockRejectedValue(new Error('Teams not found'))
180
180
 
@@ -185,7 +185,7 @@ describe('ensureTeamsAuth', () => {
185
185
  expect(saveConfigSpy).not.toHaveBeenCalled()
186
186
  })
187
187
 
188
- test('silently handles auth validation failure', async () => {
188
+ it('silently handles auth validation failure', async () => {
189
189
  // given
190
190
  testAuthSpy.mockRejectedValue(new Error('401 Unauthorized'))
191
191
 
@@ -196,11 +196,11 @@ describe('ensureTeamsAuth', () => {
196
196
  expect(saveConfigSpy).not.toHaveBeenCalled()
197
197
  })
198
198
 
199
- test('extracts and saves multiple accounts', async () => {
199
+ it('extracts and saves multiple accounts', async () => {
200
200
  // given
201
201
  extractSpy.mockResolvedValue([
202
- { token: 'work-token', accountType: 'work' },
203
- { token: 'personal-token', accountType: 'personal' },
202
+ { token: 'work-token', accountType: 'work', accountTypeKnown: true },
203
+ { token: 'personal-token', accountType: 'personal', accountTypeKnown: true },
204
204
  ])
205
205
 
206
206
  testAuthSpy
@@ -226,11 +226,11 @@ describe('ensureTeamsAuth', () => {
226
226
  )
227
227
  })
228
228
 
229
- test('skips failed account but saves successful ones', async () => {
229
+ it('skips failed account but saves successful ones', async () => {
230
230
  // given
231
231
  extractSpy.mockResolvedValue([
232
- { token: 'work-token', accountType: 'work' },
233
- { token: 'bad-token', accountType: 'personal' },
232
+ { token: 'work-token', accountType: 'work', accountTypeKnown: true },
233
+ { token: 'bad-token', accountType: 'personal', accountTypeKnown: true },
234
234
  ])
235
235
 
236
236
  testAuthSpy
@@ -248,7 +248,58 @@ describe('ensureTeamsAuth', () => {
248
248
  expect(savedConfig.accounts.personal).toBeUndefined()
249
249
  })
250
250
 
251
- test('re-extracts when token is empty string', async () => {
251
+ // Regression for #163: browser-sourced tokens arrive with accountTypeKnown=false and
252
+ // a guessed accountType of 'work'. If the work endpoint rejects them, we must probe
253
+ // the personal endpoint before giving up — otherwise personal accounts logged in via
254
+ // browser would always fail validation.
255
+ it('reclassifies browser-sourced token from work to personal when work probe fails', async () => {
256
+ // given: extractor returns a token guessed as work but with unknown flag
257
+ extractSpy.mockResolvedValue([{ token: 'browser-token', accountType: 'work', accountTypeKnown: false }])
258
+
259
+ // first testAuth call (work) fails, second (personal) succeeds
260
+ testAuthSpy
261
+ .mockRejectedValueOnce(new Error('HTTP 403'))
262
+ .mockResolvedValueOnce({ id: 'user-p', displayName: 'Personal User' })
263
+
264
+ listTeamsSpy.mockResolvedValueOnce([{ id: 'team-p', name: 'Personal Chat' }])
265
+
266
+ // when
267
+ await ensureTeamsAuth()
268
+
269
+ // then: saved under 'personal', not 'work'
270
+ const savedConfig = saveConfigSpy.mock.calls[0][0]
271
+ expect(savedConfig.accounts.personal).toBeDefined()
272
+ expect(savedConfig.accounts.personal.account_type).toBe('personal')
273
+ expect(savedConfig.accounts.personal.token).toBe('browser-token')
274
+ expect(savedConfig.accounts.work).toBeUndefined()
275
+ })
276
+
277
+ // Regression for #163: when a known-type desktop token and an unknown-type browser
278
+ // token are both extracted, the loop must not overwrite the desktop account's data.
279
+ it('does not overwrite existing account when a later token reclassifies to same type', async () => {
280
+ // given: desktop personal token and browser token that probes to personal
281
+ extractSpy.mockResolvedValue([
282
+ { token: 'desktop-personal-token', accountType: 'personal', accountTypeKnown: true },
283
+ { token: 'browser-token', accountType: 'work', accountTypeKnown: false },
284
+ ])
285
+
286
+ testAuthSpy
287
+ .mockResolvedValueOnce({ id: 'user-p', displayName: 'Desktop Personal' })
288
+ .mockRejectedValueOnce(new Error('HTTP 403'))
289
+ .mockResolvedValueOnce({ id: 'user-p', displayName: 'Browser Personal' })
290
+
291
+ listTeamsSpy.mockResolvedValueOnce([{ id: 'team-p', name: 'Personal' }])
292
+
293
+ // when
294
+ await ensureTeamsAuth()
295
+
296
+ // then: desktop token wins; browser token is skipped because personal already exists
297
+ const savedConfig = saveConfigSpy.mock.calls[0][0]
298
+ expect(savedConfig.accounts.personal.token).toBe('desktop-personal-token')
299
+ expect(savedConfig.accounts.work).toBeUndefined()
300
+ })
301
+
302
+ it('re-extracts when token is empty string', async () => {
252
303
  // given
253
304
  loadConfigSpy.mockResolvedValue({
254
305
  current_account: 'work',
@@ -3,7 +3,7 @@ import { warn } from '@/shared/utils/stderr'
3
3
  import { TeamsClient } from './client'
4
4
  import { TeamsCredentialManager } from './credential-manager'
5
5
  import { TeamsTokenExtractor } from './token-extractor'
6
- import type { TeamsAccount, TeamsConfig } from './types'
6
+ import type { TeamsAccount, TeamsAccountType, TeamsConfig } from './types'
7
7
 
8
8
  export async function ensureTeamsAuth(): Promise<void> {
9
9
  try {
@@ -20,15 +20,14 @@ export async function ensureTeamsAuth(): Promise<void> {
20
20
  current_account: config?.current_account ?? null,
21
21
  accounts: { ...config?.accounts },
22
22
  }
23
+ const addedTypes = new Set<TeamsAccountType>()
23
24
 
24
- for (const { token, accountType } of extracted) {
25
+ for (const { token, accountType: extractedType, accountTypeKnown } of extracted) {
25
26
  try {
26
- const client = await new TeamsClient().login({
27
- token,
28
- accountType,
29
- region: config?.accounts[accountType]?.region,
30
- })
31
- await client.testAuth()
27
+ const resolved = await resolveAccountType(token, extractedType, accountTypeKnown, config)
28
+ const { client, accountType } = resolved
29
+
30
+ if (addedTypes.has(accountType)) continue
32
31
 
33
32
  const teams = await client.listTeams()
34
33
  if (accountType !== 'personal' && teams.length === 0) continue
@@ -38,23 +37,24 @@ export async function ensureTeamsAuth(): Promise<void> {
38
37
  teamMap[team.id] = { team_id: team.id, team_name: team.name }
39
38
  }
40
39
 
41
- const existing = newConfig.accounts[accountType]
40
+ const existing: TeamsAccount | undefined = newConfig.accounts[accountType]
42
41
  const account: TeamsAccount = {
43
42
  token,
44
43
  token_expires_at: new Date(Date.now() + 60 * 60 * 1000).toISOString(),
45
44
  region: client.getRegion(),
46
45
  account_type: accountType,
47
46
  user_name: existing?.user_name,
48
- current_team: existing?.current_team ?? teams[0].id,
47
+ current_team: existing?.current_team ?? teams[0]?.id ?? null,
49
48
  teams: teamMap,
50
49
  }
51
50
 
52
51
  newConfig.accounts[accountType] = account
52
+ addedTypes.add(accountType)
53
53
  if (!newConfig.current_account) {
54
54
  newConfig.current_account = accountType
55
55
  }
56
56
  } catch (error) {
57
- warn(`[agent-teams] Skipping ${accountType} account: ${(error as Error).message}`)
57
+ warn(`[agent-teams] Skipping ${extractedType} account: ${(error as Error).message}`)
58
58
  }
59
59
  }
60
60
 
@@ -64,6 +64,34 @@ export async function ensureTeamsAuth(): Promise<void> {
64
64
  } catch {}
65
65
  }
66
66
 
67
+ async function resolveAccountType(
68
+ token: string,
69
+ extractedType: TeamsAccountType,
70
+ accountTypeKnown: boolean,
71
+ config: TeamsConfig | null,
72
+ ): Promise<{ client: TeamsClient; accountType: TeamsAccountType }> {
73
+ const candidates: TeamsAccountType[] = [extractedType]
74
+ if (!accountTypeKnown) {
75
+ candidates.push(extractedType === 'work' ? 'personal' : 'work')
76
+ }
77
+
78
+ let lastError: Error | null = null
79
+ for (const candidate of candidates) {
80
+ try {
81
+ const client = await new TeamsClient().login({
82
+ token,
83
+ accountType: candidate,
84
+ region: config?.accounts[candidate]?.region,
85
+ })
86
+ await client.testAuth()
87
+ return { client, accountType: candidate }
88
+ } catch (error) {
89
+ lastError = error as Error
90
+ }
91
+ }
92
+ throw lastError ?? new Error('Token validation failed')
93
+ }
94
+
67
95
  function hasValidToken(config: TeamsConfig): boolean {
68
96
  const key = TeamsCredentialManager.accountOverride ?? config.current_account
69
97
  if (!key) return false
@@ -1,4 +1,4 @@
1
- import { expect, test } from 'bun:test'
1
+ import { expect, it } from 'bun:test'
2
2
 
3
3
  import {
4
4
  TeamsAccountSchema,
@@ -17,58 +17,58 @@ import {
17
17
  TeamsUserSchema,
18
18
  } from '@/platforms/teams/index'
19
19
 
20
- test('TeamsClient is exported from barrel', () => {
20
+ it('TeamsClient is exported from barrel', () => {
21
21
  expect(typeof TeamsClient).toBe('function')
22
22
  })
23
23
 
24
- test('TeamsError is exported from barrel', () => {
24
+ it('TeamsError is exported from barrel', () => {
25
25
  expect(typeof TeamsError).toBe('function')
26
26
  })
27
27
 
28
- test('TeamsCredentialManager is exported from barrel', () => {
28
+ it('TeamsCredentialManager is exported from barrel', () => {
29
29
  expect(typeof TeamsCredentialManager).toBe('function')
30
30
  })
31
31
 
32
- test('TeamsTeamSchema is exported from barrel', () => {
32
+ it('TeamsTeamSchema is exported from barrel', () => {
33
33
  expect(typeof TeamsTeamSchema.parse).toBe('function')
34
34
  })
35
35
 
36
- test('TeamsChannelSchema is exported from barrel', () => {
36
+ it('TeamsChannelSchema is exported from barrel', () => {
37
37
  expect(typeof TeamsChannelSchema.parse).toBe('function')
38
38
  })
39
39
 
40
- test('TeamsMessageSchema is exported from barrel', () => {
40
+ it('TeamsMessageSchema is exported from barrel', () => {
41
41
  expect(typeof TeamsMessageSchema.parse).toBe('function')
42
42
  })
43
43
 
44
- test('TeamsUserSchema is exported from barrel', () => {
44
+ it('TeamsUserSchema is exported from barrel', () => {
45
45
  expect(typeof TeamsUserSchema.parse).toBe('function')
46
46
  })
47
47
 
48
- test('TeamsReactionSchema is exported from barrel', () => {
48
+ it('TeamsReactionSchema is exported from barrel', () => {
49
49
  expect(typeof TeamsReactionSchema.parse).toBe('function')
50
50
  })
51
51
 
52
- test('TeamsFileSchema is exported from barrel', () => {
52
+ it('TeamsFileSchema is exported from barrel', () => {
53
53
  expect(typeof TeamsFileSchema.parse).toBe('function')
54
54
  })
55
55
 
56
- test('TeamsCredentialsSchema is exported from barrel', () => {
56
+ it('TeamsCredentialsSchema is exported from barrel', () => {
57
57
  expect(typeof TeamsCredentialsSchema.parse).toBe('function')
58
58
  })
59
59
 
60
- test('TeamsAccountTypeSchema is exported from barrel', () => {
60
+ it('TeamsAccountTypeSchema is exported from barrel', () => {
61
61
  expect(typeof TeamsAccountTypeSchema.parse).toBe('function')
62
62
  })
63
63
 
64
- test('TeamsAccountSchema is exported from barrel', () => {
64
+ it('TeamsAccountSchema is exported from barrel', () => {
65
65
  expect(typeof TeamsAccountSchema.parse).toBe('function')
66
66
  })
67
67
 
68
- test('TeamsConfigSchema is exported from barrel', () => {
68
+ it('TeamsConfigSchema is exported from barrel', () => {
69
69
  expect(typeof TeamsConfigSchema.parse).toBe('function')
70
70
  })
71
71
 
72
- test('TeamsConfigLegacySchema is exported from barrel', () => {
72
+ it('TeamsConfigLegacySchema is exported from barrel', () => {
73
73
  expect(typeof TeamsConfigLegacySchema.parse).toBe('function')
74
74
  })