agent-messenger 2.3.0 → 2.5.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 (438) hide show
  1. package/.claude-plugin/README.md +16 -16
  2. package/.claude-plugin/marketplace.json +29 -29
  3. package/.claude-plugin/plugin.json +5 -5
  4. package/.github/workflows/release.yml +0 -12
  5. package/CONTRIBUTING.md +1 -1
  6. package/README.md +11 -8
  7. package/bun.lock +70 -110
  8. package/bunfig.toml +3 -0
  9. package/dist/package.json +11 -3
  10. package/dist/src/platforms/channeltalk/cli.d.ts.map +1 -1
  11. package/dist/src/platforms/channeltalk/cli.js +2 -1
  12. package/dist/src/platforms/channeltalk/cli.js.map +1 -1
  13. package/dist/src/platforms/channeltalk/commands/index.d.ts +1 -0
  14. package/dist/src/platforms/channeltalk/commands/index.d.ts.map +1 -1
  15. package/dist/src/platforms/channeltalk/commands/index.js +1 -0
  16. package/dist/src/platforms/channeltalk/commands/index.js.map +1 -1
  17. package/dist/src/platforms/channeltalk/commands/whoami.d.ts +22 -0
  18. package/dist/src/platforms/channeltalk/commands/whoami.d.ts.map +1 -0
  19. package/dist/src/platforms/channeltalk/commands/whoami.js +40 -0
  20. package/dist/src/platforms/channeltalk/commands/whoami.js.map +1 -0
  21. package/dist/src/platforms/channeltalkbot/cli.d.ts.map +1 -1
  22. package/dist/src/platforms/channeltalkbot/cli.js +2 -1
  23. package/dist/src/platforms/channeltalkbot/cli.js.map +1 -1
  24. package/dist/src/platforms/channeltalkbot/commands/index.d.ts +1 -0
  25. package/dist/src/platforms/channeltalkbot/commands/index.d.ts.map +1 -1
  26. package/dist/src/platforms/channeltalkbot/commands/index.js +1 -0
  27. package/dist/src/platforms/channeltalkbot/commands/index.js.map +1 -1
  28. package/dist/src/platforms/channeltalkbot/commands/whoami.d.ts +13 -0
  29. package/dist/src/platforms/channeltalkbot/commands/whoami.d.ts.map +1 -0
  30. package/dist/src/platforms/channeltalkbot/commands/whoami.js +31 -0
  31. package/dist/src/platforms/channeltalkbot/commands/whoami.js.map +1 -0
  32. package/dist/src/platforms/discord/cli.d.ts.map +1 -1
  33. package/dist/src/platforms/discord/cli.js +2 -1
  34. package/dist/src/platforms/discord/cli.js.map +1 -1
  35. package/dist/src/platforms/discord/commands/index.d.ts +1 -0
  36. package/dist/src/platforms/discord/commands/index.d.ts.map +1 -1
  37. package/dist/src/platforms/discord/commands/index.js +1 -0
  38. package/dist/src/platforms/discord/commands/index.js.map +1 -1
  39. package/dist/src/platforms/discord/commands/whoami.d.ts +6 -0
  40. package/dist/src/platforms/discord/commands/whoami.d.ts.map +1 -0
  41. package/dist/src/platforms/discord/commands/whoami.js +33 -0
  42. package/dist/src/platforms/discord/commands/whoami.js.map +1 -0
  43. package/dist/src/platforms/discordbot/cli.d.ts.map +1 -1
  44. package/dist/src/platforms/discordbot/cli.js +2 -1
  45. package/dist/src/platforms/discordbot/cli.js.map +1 -1
  46. package/dist/src/platforms/discordbot/client.js +2 -2
  47. package/dist/src/platforms/discordbot/client.js.map +1 -1
  48. package/dist/src/platforms/discordbot/commands/index.d.ts +1 -0
  49. package/dist/src/platforms/discordbot/commands/index.d.ts.map +1 -1
  50. package/dist/src/platforms/discordbot/commands/index.js +1 -0
  51. package/dist/src/platforms/discordbot/commands/index.js.map +1 -1
  52. package/dist/src/platforms/discordbot/commands/whoami.d.ts +14 -0
  53. package/dist/src/platforms/discordbot/commands/whoami.d.ts.map +1 -0
  54. package/dist/src/platforms/discordbot/commands/whoami.js +32 -0
  55. package/dist/src/platforms/discordbot/commands/whoami.js.map +1 -0
  56. package/dist/src/platforms/instagram/cli.d.ts.map +1 -1
  57. package/dist/src/platforms/instagram/cli.js +2 -1
  58. package/dist/src/platforms/instagram/cli.js.map +1 -1
  59. package/dist/src/platforms/instagram/client.d.ts +6 -0
  60. package/dist/src/platforms/instagram/client.d.ts.map +1 -1
  61. package/dist/src/platforms/instagram/client.js +12 -0
  62. package/dist/src/platforms/instagram/client.js.map +1 -1
  63. package/dist/src/platforms/instagram/commands/index.d.ts +1 -0
  64. package/dist/src/platforms/instagram/commands/index.d.ts.map +1 -1
  65. package/dist/src/platforms/instagram/commands/index.js +1 -0
  66. package/dist/src/platforms/instagram/commands/index.js.map +1 -1
  67. package/dist/src/platforms/instagram/commands/whoami.d.ts +7 -0
  68. package/dist/src/platforms/instagram/commands/whoami.d.ts.map +1 -0
  69. package/dist/src/platforms/instagram/commands/whoami.js +19 -0
  70. package/dist/src/platforms/instagram/commands/whoami.js.map +1 -0
  71. package/dist/src/platforms/kakaotalk/cli.d.ts.map +1 -1
  72. package/dist/src/platforms/kakaotalk/cli.js +2 -1
  73. package/dist/src/platforms/kakaotalk/cli.js.map +1 -1
  74. package/dist/src/platforms/kakaotalk/client.d.ts +2 -1
  75. package/dist/src/platforms/kakaotalk/client.d.ts.map +1 -1
  76. package/dist/src/platforms/kakaotalk/client.js +225 -23
  77. package/dist/src/platforms/kakaotalk/client.js.map +1 -1
  78. package/dist/src/platforms/kakaotalk/commands/index.d.ts +1 -0
  79. package/dist/src/platforms/kakaotalk/commands/index.d.ts.map +1 -1
  80. package/dist/src/platforms/kakaotalk/commands/index.js +1 -0
  81. package/dist/src/platforms/kakaotalk/commands/index.js.map +1 -1
  82. package/dist/src/platforms/kakaotalk/commands/whoami.d.ts +3 -0
  83. package/dist/src/platforms/kakaotalk/commands/whoami.d.ts.map +1 -0
  84. package/dist/src/platforms/kakaotalk/commands/whoami.js +19 -0
  85. package/dist/src/platforms/kakaotalk/commands/whoami.js.map +1 -0
  86. package/dist/src/platforms/kakaotalk/index.d.ts +2 -2
  87. package/dist/src/platforms/kakaotalk/index.d.ts.map +1 -1
  88. package/dist/src/platforms/kakaotalk/index.js +1 -1
  89. package/dist/src/platforms/kakaotalk/index.js.map +1 -1
  90. package/dist/src/platforms/kakaotalk/protocol/session.d.ts +4 -2
  91. package/dist/src/platforms/kakaotalk/protocol/session.d.ts.map +1 -1
  92. package/dist/src/platforms/kakaotalk/protocol/session.js +27 -7
  93. package/dist/src/platforms/kakaotalk/protocol/session.js.map +1 -1
  94. package/dist/src/platforms/kakaotalk/protocol/types.d.ts +17 -0
  95. package/dist/src/platforms/kakaotalk/protocol/types.d.ts.map +1 -1
  96. package/dist/src/platforms/kakaotalk/protocol/types.js.map +1 -1
  97. package/dist/src/platforms/kakaotalk/types.d.ts +28 -0
  98. package/dist/src/platforms/kakaotalk/types.d.ts.map +1 -1
  99. package/dist/src/platforms/kakaotalk/types.js +14 -0
  100. package/dist/src/platforms/kakaotalk/types.js.map +1 -1
  101. package/dist/src/platforms/line/cli.js +2 -2
  102. package/dist/src/platforms/line/cli.js.map +1 -1
  103. package/dist/src/platforms/line/client.d.ts.map +1 -1
  104. package/dist/src/platforms/line/client.js +9 -36
  105. package/dist/src/platforms/line/client.js.map +1 -1
  106. package/dist/src/platforms/line/commands/auth.d.ts.map +1 -1
  107. package/dist/src/platforms/line/commands/auth.js +9 -47
  108. package/dist/src/platforms/line/commands/auth.js.map +1 -1
  109. package/dist/src/platforms/line/commands/index.d.ts +1 -1
  110. package/dist/src/platforms/line/commands/index.d.ts.map +1 -1
  111. package/dist/src/platforms/line/commands/index.js +1 -1
  112. package/dist/src/platforms/line/commands/index.js.map +1 -1
  113. package/dist/src/platforms/line/commands/whoami.d.ts +3 -0
  114. package/dist/src/platforms/line/commands/whoami.d.ts.map +1 -0
  115. package/dist/src/platforms/line/commands/{profile.js → whoami.js} +5 -5
  116. package/dist/src/platforms/line/commands/whoami.js.map +1 -0
  117. package/dist/src/platforms/slack/cli.d.ts.map +1 -1
  118. package/dist/src/platforms/slack/cli.js +2 -1
  119. package/dist/src/platforms/slack/cli.js.map +1 -1
  120. package/dist/src/platforms/slack/commands/index.d.ts +1 -0
  121. package/dist/src/platforms/slack/commands/index.d.ts.map +1 -1
  122. package/dist/src/platforms/slack/commands/index.js +1 -0
  123. package/dist/src/platforms/slack/commands/index.js.map +1 -1
  124. package/dist/src/platforms/slack/commands/whoami.d.ts +6 -0
  125. package/dist/src/platforms/slack/commands/whoami.d.ts.map +1 -0
  126. package/dist/src/platforms/slack/commands/whoami.js +39 -0
  127. package/dist/src/platforms/slack/commands/whoami.js.map +1 -0
  128. package/dist/src/platforms/slackbot/cli.d.ts.map +1 -1
  129. package/dist/src/platforms/slackbot/cli.js +2 -1
  130. package/dist/src/platforms/slackbot/cli.js.map +1 -1
  131. package/dist/src/platforms/slackbot/commands/index.d.ts +1 -0
  132. package/dist/src/platforms/slackbot/commands/index.d.ts.map +1 -1
  133. package/dist/src/platforms/slackbot/commands/index.js +1 -0
  134. package/dist/src/platforms/slackbot/commands/index.js.map +1 -1
  135. package/dist/src/platforms/slackbot/commands/whoami.d.ts +14 -0
  136. package/dist/src/platforms/slackbot/commands/whoami.d.ts.map +1 -0
  137. package/dist/src/platforms/slackbot/commands/whoami.js +32 -0
  138. package/dist/src/platforms/slackbot/commands/whoami.js.map +1 -0
  139. package/dist/src/platforms/teams/cli.d.ts.map +1 -1
  140. package/dist/src/platforms/teams/cli.js +2 -1
  141. package/dist/src/platforms/teams/cli.js.map +1 -1
  142. package/dist/src/platforms/teams/commands/index.d.ts +1 -0
  143. package/dist/src/platforms/teams/commands/index.d.ts.map +1 -1
  144. package/dist/src/platforms/teams/commands/index.js +1 -0
  145. package/dist/src/platforms/teams/commands/index.js.map +1 -1
  146. package/dist/src/platforms/teams/commands/reaction.d.ts.map +1 -1
  147. package/dist/src/platforms/teams/commands/reaction.js +2 -0
  148. package/dist/src/platforms/teams/commands/reaction.js.map +1 -1
  149. package/dist/src/platforms/teams/commands/whoami.d.ts +6 -0
  150. package/dist/src/platforms/teams/commands/whoami.d.ts.map +1 -0
  151. package/dist/src/platforms/teams/commands/whoami.js +30 -0
  152. package/dist/src/platforms/teams/commands/whoami.js.map +1 -0
  153. package/dist/src/platforms/telegram/cli.d.ts.map +1 -1
  154. package/dist/src/platforms/telegram/cli.js +2 -1
  155. package/dist/src/platforms/telegram/cli.js.map +1 -1
  156. package/dist/src/platforms/telegram/commands/index.d.ts +1 -0
  157. package/dist/src/platforms/telegram/commands/index.d.ts.map +1 -1
  158. package/dist/src/platforms/telegram/commands/index.js +1 -0
  159. package/dist/src/platforms/telegram/commands/index.js.map +1 -1
  160. package/dist/src/platforms/telegram/commands/whoami.d.ts +7 -0
  161. package/dist/src/platforms/telegram/commands/whoami.d.ts.map +1 -0
  162. package/dist/src/platforms/telegram/commands/whoami.js +27 -0
  163. package/dist/src/platforms/telegram/commands/whoami.js.map +1 -0
  164. package/dist/src/platforms/webex/cli.d.ts.map +1 -1
  165. package/dist/src/platforms/webex/cli.js +2 -1
  166. package/dist/src/platforms/webex/cli.js.map +1 -1
  167. package/dist/src/platforms/webex/commands/index.d.ts +1 -0
  168. package/dist/src/platforms/webex/commands/index.d.ts.map +1 -1
  169. package/dist/src/platforms/webex/commands/index.js +1 -0
  170. package/dist/src/platforms/webex/commands/index.js.map +1 -1
  171. package/dist/src/platforms/webex/commands/message.js +1 -1
  172. package/dist/src/platforms/webex/commands/message.js.map +1 -1
  173. package/dist/src/platforms/webex/commands/whoami.d.ts +6 -0
  174. package/dist/src/platforms/webex/commands/whoami.d.ts.map +1 -0
  175. package/dist/src/platforms/webex/commands/whoami.js +30 -0
  176. package/dist/src/platforms/webex/commands/whoami.js.map +1 -0
  177. package/dist/src/platforms/wechatbot/cli.d.ts +5 -0
  178. package/dist/src/platforms/wechatbot/cli.d.ts.map +1 -0
  179. package/dist/src/platforms/wechatbot/cli.js +19 -0
  180. package/dist/src/platforms/wechatbot/cli.js.map +1 -0
  181. package/dist/src/platforms/wechatbot/client.d.ts +36 -0
  182. package/dist/src/platforms/wechatbot/client.d.ts.map +1 -0
  183. package/dist/src/platforms/wechatbot/client.js +208 -0
  184. package/dist/src/platforms/wechatbot/client.js.map +1 -0
  185. package/dist/src/platforms/wechatbot/commands/auth.d.ts +28 -0
  186. package/dist/src/platforms/wechatbot/commands/auth.d.ts.map +1 -0
  187. package/dist/src/platforms/wechatbot/commands/auth.js +164 -0
  188. package/dist/src/platforms/wechatbot/commands/auth.js.map +1 -0
  189. package/dist/src/platforms/wechatbot/commands/index.d.ts +6 -0
  190. package/dist/src/platforms/wechatbot/commands/index.d.ts.map +1 -0
  191. package/dist/src/platforms/wechatbot/commands/index.js +6 -0
  192. package/dist/src/platforms/wechatbot/commands/index.js.map +1 -0
  193. package/dist/src/platforms/wechatbot/commands/message.d.ts +18 -0
  194. package/dist/src/platforms/wechatbot/commands/message.d.ts.map +1 -0
  195. package/dist/src/platforms/wechatbot/commands/message.js +80 -0
  196. package/dist/src/platforms/wechatbot/commands/message.js.map +1 -0
  197. package/dist/src/platforms/wechatbot/commands/shared.d.ts +9 -0
  198. package/dist/src/platforms/wechatbot/commands/shared.d.ts.map +1 -0
  199. package/dist/src/platforms/wechatbot/commands/shared.js +13 -0
  200. package/dist/src/platforms/wechatbot/commands/shared.js.map +1 -0
  201. package/dist/src/platforms/wechatbot/commands/template.d.ts +19 -0
  202. package/dist/src/platforms/wechatbot/commands/template.d.ts.map +1 -0
  203. package/dist/src/platforms/wechatbot/commands/template.js +76 -0
  204. package/dist/src/platforms/wechatbot/commands/template.js.map +1 -0
  205. package/dist/src/platforms/wechatbot/commands/user.d.ts +20 -0
  206. package/dist/src/platforms/wechatbot/commands/user.d.ts.map +1 -0
  207. package/dist/src/platforms/wechatbot/commands/user.js +53 -0
  208. package/dist/src/platforms/wechatbot/commands/user.js.map +1 -0
  209. package/dist/src/platforms/wechatbot/commands/whoami.d.ts +12 -0
  210. package/dist/src/platforms/wechatbot/commands/whoami.d.ts.map +1 -0
  211. package/dist/src/platforms/wechatbot/commands/whoami.js +33 -0
  212. package/dist/src/platforms/wechatbot/commands/whoami.js.map +1 -0
  213. package/dist/src/platforms/wechatbot/credential-manager.d.ts +17 -0
  214. package/dist/src/platforms/wechatbot/credential-manager.d.ts.map +1 -0
  215. package/dist/src/platforms/wechatbot/credential-manager.js +121 -0
  216. package/dist/src/platforms/wechatbot/credential-manager.js.map +1 -0
  217. package/dist/src/platforms/wechatbot/index.d.ts +5 -0
  218. package/dist/src/platforms/wechatbot/index.d.ts.map +1 -0
  219. package/dist/src/platforms/wechatbot/index.js +4 -0
  220. package/dist/src/platforms/wechatbot/index.js.map +1 -0
  221. package/dist/src/platforms/wechatbot/types.d.ts +94 -0
  222. package/dist/src/platforms/wechatbot/types.d.ts.map +1 -0
  223. package/dist/src/platforms/wechatbot/types.js +54 -0
  224. package/dist/src/platforms/wechatbot/types.js.map +1 -0
  225. package/dist/src/platforms/whatsapp/cli.d.ts.map +1 -1
  226. package/dist/src/platforms/whatsapp/cli.js +2 -1
  227. package/dist/src/platforms/whatsapp/cli.js.map +1 -1
  228. package/dist/src/platforms/whatsapp/client.d.ts +9 -0
  229. package/dist/src/platforms/whatsapp/client.d.ts.map +1 -1
  230. package/dist/src/platforms/whatsapp/client.js +143 -21
  231. package/dist/src/platforms/whatsapp/client.js.map +1 -1
  232. package/dist/src/platforms/whatsapp/commands/auth.d.ts.map +1 -1
  233. package/dist/src/platforms/whatsapp/commands/auth.js +133 -60
  234. package/dist/src/platforms/whatsapp/commands/auth.js.map +1 -1
  235. package/dist/src/platforms/whatsapp/commands/index.d.ts +1 -0
  236. package/dist/src/platforms/whatsapp/commands/index.d.ts.map +1 -1
  237. package/dist/src/platforms/whatsapp/commands/index.js +1 -0
  238. package/dist/src/platforms/whatsapp/commands/index.js.map +1 -1
  239. package/dist/src/platforms/whatsapp/commands/shared.js +2 -2
  240. package/dist/src/platforms/whatsapp/commands/shared.js.map +1 -1
  241. package/dist/src/platforms/whatsapp/commands/whoami.d.ts +7 -0
  242. package/dist/src/platforms/whatsapp/commands/whoami.d.ts.map +1 -0
  243. package/dist/src/platforms/whatsapp/commands/whoami.js +19 -0
  244. package/dist/src/platforms/whatsapp/commands/whoami.js.map +1 -0
  245. package/dist/src/platforms/whatsapp/credential-manager.d.ts.map +1 -1
  246. package/dist/src/platforms/whatsapp/credential-manager.js +14 -8
  247. package/dist/src/platforms/whatsapp/credential-manager.js.map +1 -1
  248. package/dist/src/platforms/whatsapp/ensure-auth.js +2 -2
  249. package/dist/src/platforms/whatsapp/ensure-auth.js.map +1 -1
  250. package/dist/src/platforms/whatsappbot/cli.d.ts.map +1 -1
  251. package/dist/src/platforms/whatsappbot/cli.js +2 -1
  252. package/dist/src/platforms/whatsappbot/cli.js.map +1 -1
  253. package/dist/src/platforms/whatsappbot/commands/index.d.ts +1 -0
  254. package/dist/src/platforms/whatsappbot/commands/index.d.ts.map +1 -1
  255. package/dist/src/platforms/whatsappbot/commands/index.js +1 -0
  256. package/dist/src/platforms/whatsappbot/commands/index.js.map +1 -1
  257. package/dist/src/platforms/whatsappbot/commands/whoami.d.ts +17 -0
  258. package/dist/src/platforms/whatsappbot/commands/whoami.d.ts.map +1 -0
  259. package/dist/src/platforms/whatsappbot/commands/whoami.js +39 -0
  260. package/dist/src/platforms/whatsappbot/commands/whoami.js.map +1 -0
  261. package/dist/src/shared/utils/qr.d.ts +15 -0
  262. package/dist/src/shared/utils/qr.d.ts.map +1 -0
  263. package/dist/src/shared/utils/qr.js +74 -0
  264. package/dist/src/shared/utils/qr.js.map +1 -0
  265. package/dist/src/tui/adapters/whatsapp-adapter.d.ts.map +1 -1
  266. package/dist/src/tui/adapters/whatsapp-adapter.js +20 -15
  267. package/dist/src/tui/adapters/whatsapp-adapter.js.map +1 -1
  268. package/docs/content/docs/agent-skills.mdx +4 -4
  269. package/docs/content/docs/cli/channeltalk.mdx +12 -1
  270. package/docs/content/docs/cli/channeltalkbot.mdx +10 -1
  271. package/docs/content/docs/cli/discord.mdx +11 -1
  272. package/docs/content/docs/cli/discordbot.mdx +10 -1
  273. package/docs/content/docs/cli/instagram.mdx +12 -1
  274. package/docs/content/docs/cli/kakaotalk.mdx +25 -1
  275. package/docs/content/docs/cli/line.mdx +5 -5
  276. package/docs/content/docs/cli/meta.json +1 -0
  277. package/docs/content/docs/cli/slack.mdx +11 -1
  278. package/docs/content/docs/cli/slackbot.mdx +10 -1
  279. package/docs/content/docs/cli/teams.mdx +11 -1
  280. package/docs/content/docs/cli/telegram.mdx +11 -0
  281. package/docs/content/docs/cli/webex.mdx +11 -1
  282. package/docs/content/docs/cli/wechatbot.mdx +188 -0
  283. package/docs/content/docs/cli/whatsapp.mdx +37 -8
  284. package/docs/content/docs/cli/whatsappbot.mdx +10 -1
  285. package/docs/content/docs/sdk/meta.json +1 -1
  286. package/docs/content/docs/sdk/wechatbot.mdx +282 -0
  287. package/docs/content/docs/tui.mdx +1 -1
  288. package/docs/src/app/page.tsx +5 -5
  289. package/package.json +11 -3
  290. package/skills/agent-channeltalk/SKILL.md +12 -1
  291. package/skills/agent-channeltalkbot/SKILL.md +10 -1
  292. package/skills/agent-discord/SKILL.md +11 -1
  293. package/skills/agent-discordbot/SKILL.md +10 -1
  294. package/skills/agent-instagram/SKILL.md +12 -1
  295. package/skills/agent-kakaotalk/SKILL.md +30 -1
  296. package/skills/agent-kakaotalk/references/common-patterns.md +1 -1
  297. package/skills/agent-line/SKILL.md +11 -15
  298. package/skills/agent-line/references/authentication.md +13 -4
  299. package/skills/agent-slack/SKILL.md +11 -1
  300. package/skills/agent-slackbot/SKILL.md +10 -1
  301. package/skills/agent-teams/SKILL.md +11 -1
  302. package/skills/agent-telegram/SKILL.md +6 -1
  303. package/skills/agent-webex/SKILL.md +11 -1
  304. package/skills/agent-wechatbot/SKILL.md +394 -0
  305. package/skills/agent-whatsapp/SKILL.md +63 -15
  306. package/skills/agent-whatsapp/references/authentication.md +36 -6
  307. package/skills/agent-whatsappbot/SKILL.md +10 -1
  308. package/src/platforms/channeltalk/cli.ts +2 -0
  309. package/src/platforms/channeltalk/commands/index.ts +1 -0
  310. package/src/platforms/channeltalk/commands/whoami.test.ts +64 -0
  311. package/src/platforms/channeltalk/commands/whoami.ts +62 -0
  312. package/src/platforms/channeltalkbot/cli.ts +2 -0
  313. package/src/platforms/channeltalkbot/commands/index.ts +1 -0
  314. package/src/platforms/channeltalkbot/commands/whoami.test.ts +104 -0
  315. package/src/platforms/channeltalkbot/commands/whoami.ts +42 -0
  316. package/src/platforms/discord/cli.ts +2 -0
  317. package/src/platforms/discord/commands/index.ts +1 -0
  318. package/src/platforms/discord/commands/whoami.test.ts +91 -0
  319. package/src/platforms/discord/commands/whoami.ts +36 -0
  320. package/src/platforms/discord/credential-manager.test.ts +18 -1
  321. package/src/platforms/discordbot/cli.ts +2 -0
  322. package/src/platforms/discordbot/client.ts +2 -2
  323. package/src/platforms/discordbot/commands/index.ts +1 -0
  324. package/src/platforms/discordbot/commands/whoami.test.ts +96 -0
  325. package/src/platforms/discordbot/commands/whoami.ts +44 -0
  326. package/src/platforms/instagram/cli.ts +2 -1
  327. package/src/platforms/instagram/client.ts +13 -0
  328. package/src/platforms/instagram/commands/auth.test.ts +216 -0
  329. package/src/platforms/instagram/commands/chat.test.ts +123 -0
  330. package/src/platforms/instagram/commands/index.ts +1 -0
  331. package/src/platforms/instagram/commands/message.test.ts +174 -0
  332. package/src/platforms/instagram/commands/whoami.test.ts +60 -0
  333. package/src/platforms/instagram/commands/whoami.ts +21 -0
  334. package/src/platforms/kakaotalk/cli.ts +2 -1
  335. package/src/platforms/kakaotalk/client.test.ts +182 -14
  336. package/src/platforms/kakaotalk/client.ts +261 -27
  337. package/src/platforms/kakaotalk/commands/auth.test.ts +299 -0
  338. package/src/platforms/kakaotalk/commands/chat.test.ts +97 -0
  339. package/src/platforms/kakaotalk/commands/index.ts +1 -0
  340. package/src/platforms/kakaotalk/commands/message.test.ts +113 -0
  341. package/src/platforms/kakaotalk/commands/whoami.test.ts +116 -0
  342. package/src/platforms/kakaotalk/commands/whoami.ts +21 -0
  343. package/src/platforms/kakaotalk/index.test.ts +5 -0
  344. package/src/platforms/kakaotalk/index.ts +2 -0
  345. package/src/platforms/kakaotalk/protocol/session.ts +29 -7
  346. package/src/platforms/kakaotalk/protocol/types.ts +9 -0
  347. package/src/platforms/kakaotalk/types.ts +30 -0
  348. package/src/platforms/line/cli.ts +2 -2
  349. package/src/platforms/line/client.ts +14 -39
  350. package/src/platforms/line/commands/auth.test.ts +141 -0
  351. package/src/platforms/line/commands/auth.ts +37 -61
  352. package/src/platforms/line/commands/chat.test.ts +110 -0
  353. package/src/platforms/line/commands/friend.test.ts +98 -0
  354. package/src/platforms/line/commands/index.ts +1 -1
  355. package/src/platforms/line/commands/message.test.ts +119 -0
  356. package/src/platforms/line/commands/whoami.test.ts +85 -0
  357. package/src/platforms/line/commands/{profile.ts → whoami.ts} +4 -4
  358. package/src/platforms/slack/cli.ts +2 -0
  359. package/src/platforms/slack/commands/index.ts +1 -0
  360. package/src/platforms/slack/commands/whoami.test.ts +126 -0
  361. package/src/platforms/slack/commands/whoami.ts +40 -0
  362. package/src/platforms/slackbot/cli.ts +2 -1
  363. package/src/platforms/slackbot/commands/channel.test.ts +139 -0
  364. package/src/platforms/slackbot/commands/index.ts +1 -0
  365. package/src/platforms/slackbot/commands/message.test.ts +226 -0
  366. package/src/platforms/slackbot/commands/reaction.test.ts +90 -0
  367. package/src/platforms/slackbot/commands/user.test.ts +143 -0
  368. package/src/platforms/slackbot/commands/whoami.test.ts +102 -0
  369. package/src/platforms/slackbot/commands/whoami.ts +44 -0
  370. package/src/platforms/teams/cli.ts +2 -0
  371. package/src/platforms/teams/commands/index.ts +1 -0
  372. package/src/platforms/teams/commands/reaction.test.ts +45 -61
  373. package/src/platforms/teams/commands/reaction.ts +2 -0
  374. package/src/platforms/teams/commands/whoami.test.ts +83 -0
  375. package/src/platforms/teams/commands/whoami.ts +33 -0
  376. package/src/platforms/telegram/cli.ts +2 -1
  377. package/src/platforms/telegram/commands/chat.test.ts +125 -0
  378. package/src/platforms/telegram/commands/index.ts +1 -0
  379. package/src/platforms/telegram/commands/message.test.ts +92 -0
  380. package/src/platforms/telegram/commands/whoami.test.ts +75 -0
  381. package/src/platforms/telegram/commands/whoami.ts +29 -0
  382. package/src/platforms/webex/cli.ts +2 -1
  383. package/src/platforms/webex/commands/auth.test.ts +58 -46
  384. package/src/platforms/webex/commands/index.ts +1 -0
  385. package/src/platforms/webex/commands/member.test.ts +60 -57
  386. package/src/platforms/webex/commands/message.test.ts +74 -121
  387. package/src/platforms/webex/commands/message.ts +1 -1
  388. package/src/platforms/webex/commands/snapshot.test.ts +54 -45
  389. package/src/platforms/webex/commands/space.test.ts +46 -49
  390. package/src/platforms/webex/commands/whoami.test.ts +113 -0
  391. package/src/platforms/webex/commands/whoami.ts +31 -0
  392. package/src/platforms/webex/credential-manager.test.ts +0 -1
  393. package/src/platforms/wechatbot/cli.ts +25 -0
  394. package/src/platforms/wechatbot/client.test.ts +497 -0
  395. package/src/platforms/wechatbot/client.ts +268 -0
  396. package/src/platforms/wechatbot/commands/auth.test.ts +211 -0
  397. package/src/platforms/wechatbot/commands/auth.ts +203 -0
  398. package/src/platforms/wechatbot/commands/index.ts +5 -0
  399. package/src/platforms/wechatbot/commands/message.test.ts +155 -0
  400. package/src/platforms/wechatbot/commands/message.ts +104 -0
  401. package/src/platforms/wechatbot/commands/shared.ts +22 -0
  402. package/src/platforms/wechatbot/commands/template.test.ts +199 -0
  403. package/src/platforms/wechatbot/commands/template.ts +102 -0
  404. package/src/platforms/wechatbot/commands/user.test.ts +165 -0
  405. package/src/platforms/wechatbot/commands/user.ts +75 -0
  406. package/src/platforms/wechatbot/commands/whoami.test.ts +109 -0
  407. package/src/platforms/wechatbot/commands/whoami.ts +43 -0
  408. package/src/platforms/wechatbot/credential-manager.test.ts +255 -0
  409. package/src/platforms/wechatbot/credential-manager.ts +148 -0
  410. package/src/platforms/wechatbot/index.test.ts +49 -0
  411. package/src/platforms/wechatbot/index.ts +19 -0
  412. package/src/platforms/wechatbot/types.test.ts +223 -0
  413. package/src/platforms/wechatbot/types.ts +107 -0
  414. package/src/platforms/whatsapp/cli.ts +2 -1
  415. package/src/platforms/whatsapp/client.ts +180 -37
  416. package/src/platforms/whatsapp/commands/auth.test.ts +311 -0
  417. package/src/platforms/whatsapp/commands/auth.ts +194 -84
  418. package/src/platforms/whatsapp/commands/chat.test.ts +198 -0
  419. package/src/platforms/whatsapp/commands/index.ts +1 -0
  420. package/src/platforms/whatsapp/commands/message.test.ts +231 -0
  421. package/src/platforms/whatsapp/commands/shared.ts +2 -2
  422. package/src/platforms/whatsapp/commands/whoami.test.ts +59 -0
  423. package/src/platforms/whatsapp/commands/whoami.ts +21 -0
  424. package/src/platforms/whatsapp/credential-manager.test.ts +20 -0
  425. package/src/platforms/whatsapp/credential-manager.ts +17 -8
  426. package/src/platforms/whatsapp/ensure-auth.ts +2 -2
  427. package/src/platforms/whatsappbot/cli.ts +2 -1
  428. package/src/platforms/whatsappbot/commands/auth.test.ts +217 -0
  429. package/src/platforms/whatsappbot/commands/index.ts +1 -0
  430. package/src/platforms/whatsappbot/commands/message.test.ts +198 -0
  431. package/src/platforms/whatsappbot/commands/template.test.ts +112 -0
  432. package/src/platforms/whatsappbot/commands/whoami.test.ts +100 -0
  433. package/src/platforms/whatsappbot/commands/whoami.ts +57 -0
  434. package/src/shared/utils/qr.ts +92 -0
  435. package/src/tui/adapters/whatsapp-adapter.ts +19 -16
  436. package/dist/src/platforms/line/commands/profile.d.ts +0 -3
  437. package/dist/src/platforms/line/commands/profile.d.ts.map +0 -1
  438. package/dist/src/platforms/line/commands/profile.js.map +0 -1
@@ -0,0 +1,198 @@
1
+ import { beforeEach, describe, expect, mock, test } from 'bun:test'
2
+
3
+ const mockSendTextMessage = mock(() =>
4
+ Promise.resolve({
5
+ messaging_product: 'whatsapp',
6
+ contacts: [{ input: '+1234567890', wa_id: '1234567890' }],
7
+ messages: [{ id: 'wamid.test123' }],
8
+ }),
9
+ )
10
+
11
+ const mockSendTemplateMessage = mock(() =>
12
+ Promise.resolve({
13
+ messaging_product: 'whatsapp',
14
+ contacts: [{ input: '+1234567890', wa_id: '1234567890' }],
15
+ messages: [{ id: 'wamid.template123' }],
16
+ }),
17
+ )
18
+
19
+ const mockSendReaction = mock(() =>
20
+ Promise.resolve({
21
+ messaging_product: 'whatsapp',
22
+ contacts: [{ input: '+1234567890', wa_id: '1234567890' }],
23
+ messages: [{ id: 'wamid.reaction123' }],
24
+ }),
25
+ )
26
+
27
+ const mockSendImageMessage = mock(() =>
28
+ Promise.resolve({
29
+ messaging_product: 'whatsapp',
30
+ contacts: [{ input: '+1234567890', wa_id: '1234567890' }],
31
+ messages: [{ id: 'wamid.image123' }],
32
+ }),
33
+ )
34
+
35
+ const mockSendDocumentMessage = mock(() =>
36
+ Promise.resolve({
37
+ messaging_product: 'whatsapp',
38
+ contacts: [{ input: '+1234567890', wa_id: '1234567890' }],
39
+ messages: [{ id: 'wamid.doc123' }],
40
+ }),
41
+ )
42
+
43
+ const mockClient = {
44
+ sendTextMessage: mockSendTextMessage,
45
+ sendTemplateMessage: mockSendTemplateMessage,
46
+ sendReaction: mockSendReaction,
47
+ sendImageMessage: mockSendImageMessage,
48
+ sendDocumentMessage: mockSendDocumentMessage,
49
+ }
50
+
51
+ mock.module('./shared', () => ({
52
+ getClient: async () => mockClient,
53
+ }))
54
+
55
+ import { sendAction, sendDocumentAction, sendImageAction, sendReactionAction, sendTemplateAction } from './message'
56
+
57
+ describe('message commands', () => {
58
+ beforeEach(() => {
59
+ mockSendTextMessage.mockClear()
60
+ mockSendTemplateMessage.mockClear()
61
+ mockSendReaction.mockClear()
62
+ mockSendImageMessage.mockClear()
63
+ mockSendDocumentMessage.mockClear()
64
+ })
65
+
66
+ describe('sendAction', () => {
67
+ test('sends a text message and returns result', async () => {
68
+ const result = await sendAction('+1234567890', 'Hello!', {})
69
+
70
+ expect(result.messaging_product).toBe('whatsapp')
71
+ expect(result.messages).toHaveLength(1)
72
+ expect(result.messages?.[0].id).toBe('wamid.test123')
73
+ expect(mockSendTextMessage).toHaveBeenCalledWith('+1234567890', 'Hello!')
74
+ })
75
+
76
+ test('returns error when client throws', async () => {
77
+ mockSendTextMessage.mockImplementationOnce(() => Promise.reject(new Error('Network error')))
78
+
79
+ const result = await sendAction('+1234567890', 'Hello!', {})
80
+
81
+ expect(result.error).toBe('Network error')
82
+ })
83
+ })
84
+
85
+ describe('sendTemplateAction', () => {
86
+ test('sends a template message with default language', async () => {
87
+ const result = await sendTemplateAction('+1234567890', 'hello_world', {})
88
+
89
+ expect(result.messaging_product).toBe('whatsapp')
90
+ expect(result.messages?.[0].id).toBe('wamid.template123')
91
+ expect(mockSendTemplateMessage).toHaveBeenCalledWith('+1234567890', 'hello_world', 'en_US', undefined)
92
+ })
93
+
94
+ test('sends a template message with custom language', async () => {
95
+ const result = await sendTemplateAction('+1234567890', 'hello_world', { language: 'pt_BR' })
96
+
97
+ expect(mockSendTemplateMessage).toHaveBeenCalledWith('+1234567890', 'hello_world', 'pt_BR', undefined)
98
+ expect(result.error).toBeUndefined()
99
+ })
100
+
101
+ test('parses and passes components JSON', async () => {
102
+ const components = [{ type: 'body', parameters: [{ type: 'text', text: 'World' }] }]
103
+ const result = await sendTemplateAction('+1234567890', 'hello_world', {
104
+ components: JSON.stringify(components),
105
+ })
106
+
107
+ expect(mockSendTemplateMessage).toHaveBeenCalledWith('+1234567890', 'hello_world', 'en_US', components)
108
+ expect(result.error).toBeUndefined()
109
+ })
110
+
111
+ test('returns error for invalid components JSON', async () => {
112
+ const result = await sendTemplateAction('+1234567890', 'hello_world', {
113
+ components: 'not-valid-json',
114
+ })
115
+
116
+ expect(result.error).toBe('Invalid --components JSON')
117
+ })
118
+
119
+ test('returns error when client throws', async () => {
120
+ mockSendTemplateMessage.mockImplementationOnce(() => Promise.reject(new Error('Template not found')))
121
+
122
+ const result = await sendTemplateAction('+1234567890', 'missing_template', {})
123
+
124
+ expect(result.error).toBe('Template not found')
125
+ })
126
+ })
127
+
128
+ describe('sendReactionAction', () => {
129
+ test('sends a reaction and returns result', async () => {
130
+ const result = await sendReactionAction('+1234567890', 'wamid.msg123', '👍', {})
131
+
132
+ expect(result.messaging_product).toBe('whatsapp')
133
+ expect(result.messages?.[0].id).toBe('wamid.reaction123')
134
+ expect(mockSendReaction).toHaveBeenCalledWith('+1234567890', 'wamid.msg123', '👍')
135
+ })
136
+
137
+ test('returns error when client throws', async () => {
138
+ mockSendReaction.mockImplementationOnce(() => Promise.reject(new Error('Message not found')))
139
+
140
+ const result = await sendReactionAction('+1234567890', 'wamid.bad', '👍', {})
141
+
142
+ expect(result.error).toBe('Message not found')
143
+ })
144
+ })
145
+
146
+ describe('sendImageAction', () => {
147
+ test('sends an image message and returns result', async () => {
148
+ const result = await sendImageAction('+1234567890', 'https://example.com/image.jpg', {})
149
+
150
+ expect(result.messaging_product).toBe('whatsapp')
151
+ expect(result.messages?.[0].id).toBe('wamid.image123')
152
+ expect(mockSendImageMessage).toHaveBeenCalledWith('+1234567890', 'https://example.com/image.jpg', undefined)
153
+ })
154
+
155
+ test('passes caption when provided', async () => {
156
+ const result = await sendImageAction('+1234567890', 'https://example.com/image.jpg', { caption: 'My photo' })
157
+
158
+ expect(mockSendImageMessage).toHaveBeenCalledWith('+1234567890', 'https://example.com/image.jpg', 'My photo')
159
+ expect(result.error).toBeUndefined()
160
+ })
161
+
162
+ test('returns error when client throws', async () => {
163
+ mockSendImageMessage.mockImplementationOnce(() => Promise.reject(new Error('Invalid URL')))
164
+
165
+ const result = await sendImageAction('+1234567890', 'bad-url', {})
166
+
167
+ expect(result.error).toBe('Invalid URL')
168
+ })
169
+ })
170
+
171
+ describe('sendDocumentAction', () => {
172
+ test('sends a document message and returns result', async () => {
173
+ const result = await sendDocumentAction('+1234567890', 'https://example.com/doc.pdf', {})
174
+
175
+ expect(result.messaging_product).toBe('whatsapp')
176
+ expect(result.messages?.[0].id).toBe('wamid.doc123')
177
+ expect(mockSendDocumentMessage).toHaveBeenCalledWith('+1234567890', 'https://example.com/doc.pdf', undefined, undefined)
178
+ })
179
+
180
+ test('passes filename and caption when provided', async () => {
181
+ const result = await sendDocumentAction('+1234567890', 'https://example.com/doc.pdf', {
182
+ filename: 'report.pdf',
183
+ caption: 'Monthly report',
184
+ })
185
+
186
+ expect(mockSendDocumentMessage).toHaveBeenCalledWith('+1234567890', 'https://example.com/doc.pdf', 'report.pdf', 'Monthly report')
187
+ expect(result.error).toBeUndefined()
188
+ })
189
+
190
+ test('returns error when client throws', async () => {
191
+ mockSendDocumentMessage.mockImplementationOnce(() => Promise.reject(new Error('Upload failed')))
192
+
193
+ const result = await sendDocumentAction('+1234567890', 'https://example.com/doc.pdf', {})
194
+
195
+ expect(result.error).toBe('Upload failed')
196
+ })
197
+ })
198
+ })
@@ -0,0 +1,112 @@
1
+ import { beforeEach, describe, expect, mock, test } from 'bun:test'
2
+
3
+ import type { WhatsAppBotTemplate } from '../types'
4
+
5
+ const mockTemplates: WhatsAppBotTemplate[] = [
6
+ {
7
+ name: 'hello_world',
8
+ status: 'APPROVED',
9
+ category: 'UTILITY',
10
+ language: 'en_US',
11
+ components: [{ type: 'BODY', text: 'Hello World!' }],
12
+ },
13
+ {
14
+ name: 'order_confirmation',
15
+ status: 'APPROVED',
16
+ category: 'TRANSACTIONAL',
17
+ language: 'en_US',
18
+ components: [{ type: 'BODY', text: 'Your order {{1}} has been confirmed.' }],
19
+ },
20
+ ]
21
+
22
+ const mockListTemplates = mock(() => Promise.resolve(mockTemplates))
23
+ const mockGetTemplate = mock((name: string) => {
24
+ const template = mockTemplates.find((t) => t.name === name)
25
+ if (!template) {
26
+ return Promise.reject(new Error(`Template "${name}" not found`))
27
+ }
28
+ return Promise.resolve(template)
29
+ })
30
+
31
+ const mockClient = {
32
+ listTemplates: mockListTemplates,
33
+ getTemplate: mockGetTemplate,
34
+ }
35
+
36
+ mock.module('./shared', () => ({
37
+ getClient: async () => mockClient,
38
+ }))
39
+
40
+ import { getAction, listAction } from './template'
41
+
42
+ describe('template commands', () => {
43
+ beforeEach(() => {
44
+ mockListTemplates.mockClear()
45
+ mockGetTemplate.mockClear()
46
+ })
47
+
48
+ describe('listAction', () => {
49
+ test('returns all templates', async () => {
50
+ const result = await listAction({})
51
+
52
+ expect(result.templates).toHaveLength(2)
53
+ expect(result.templates?.[0].name).toBe('hello_world')
54
+ expect(result.templates?.[1].name).toBe('order_confirmation')
55
+ expect(mockListTemplates).toHaveBeenCalledWith(undefined)
56
+ })
57
+
58
+ test('passes limit when provided', async () => {
59
+ const result = await listAction({ limit: '1' })
60
+
61
+ expect(mockListTemplates).toHaveBeenCalledWith({ limit: 1 })
62
+ expect(result.error).toBeUndefined()
63
+ })
64
+
65
+ test('returns error for invalid limit', async () => {
66
+ const result = await listAction({ limit: 'abc' })
67
+
68
+ expect(result.error).toBeDefined()
69
+ expect(result.error).toContain('Invalid --limit')
70
+ })
71
+
72
+ test('returns error for zero limit', async () => {
73
+ const result = await listAction({ limit: '0' })
74
+
75
+ expect(result.error).toBeDefined()
76
+ expect(result.error).toContain('Invalid --limit')
77
+ })
78
+
79
+ test('returns error when client throws', async () => {
80
+ mockListTemplates.mockImplementationOnce(() => Promise.reject(new Error('API error')))
81
+
82
+ const result = await listAction({})
83
+
84
+ expect(result.error).toBe('API error')
85
+ })
86
+ })
87
+
88
+ describe('getAction', () => {
89
+ test('returns a specific template by name', async () => {
90
+ const result = await getAction('hello_world', {})
91
+
92
+ expect(result.template).toBeDefined()
93
+ expect(result.template?.name).toBe('hello_world')
94
+ expect(result.template?.status).toBe('APPROVED')
95
+ expect(mockGetTemplate).toHaveBeenCalledWith('hello_world')
96
+ })
97
+
98
+ test('returns error when template not found', async () => {
99
+ const result = await getAction('nonexistent_template', {})
100
+
101
+ expect(result.error).toContain('nonexistent_template')
102
+ })
103
+
104
+ test('returns error when client throws', async () => {
105
+ mockGetTemplate.mockImplementationOnce(() => Promise.reject(new Error('Network error')))
106
+
107
+ const result = await getAction('hello_world', {})
108
+
109
+ expect(result.error).toBe('Network error')
110
+ })
111
+ })
112
+ })
@@ -0,0 +1,100 @@
1
+ import { afterEach, beforeEach, describe, expect, mock, test } from 'bun:test'
2
+ import { existsSync, rmSync } from 'node:fs'
3
+ import { mkdir } from 'node:fs/promises'
4
+ import { tmpdir } from 'node:os'
5
+ import { join } from 'node:path'
6
+
7
+ const mockVerifyToken = mock(() =>
8
+ Promise.resolve({ verified_name: 'Test Business' }),
9
+ )
10
+
11
+ mock.module('../client', () => ({
12
+ WhatsAppBotClient: class MockWhatsAppBotClient {
13
+ async login(_credentials?: { phoneNumberId: string; accessToken: string }) {
14
+ return this
15
+ }
16
+ verifyToken = mockVerifyToken
17
+ },
18
+ }))
19
+
20
+ // Re-import whoamiAction AFTER mock.module so the mock applies
21
+ const { whoamiAction } = await import('./whoami')
22
+
23
+ import { WhatsAppBotCredentialManager } from '../credential-manager'
24
+
25
+ describe('whoami command', () => {
26
+ let tempDir: string
27
+
28
+ beforeEach(async () => {
29
+ tempDir = join(tmpdir(), `whatsappbot-whoami-test-${Date.now()}`)
30
+ await mkdir(tempDir, { recursive: true })
31
+ mockVerifyToken.mockClear()
32
+ })
33
+
34
+ afterEach(() => {
35
+ if (existsSync(tempDir)) {
36
+ rmSync(tempDir, { recursive: true })
37
+ }
38
+ })
39
+
40
+ test('returns phone number id, account name, and verified name', async () => {
41
+ const manager = new WhatsAppBotCredentialManager(tempDir)
42
+ await manager.setCredentials({
43
+ phone_number_id: '12345678901',
44
+ account_name: 'Test Business',
45
+ access_token: 'EAAtest-token',
46
+ })
47
+
48
+ const result = await whoamiAction({ _credManager: manager })
49
+
50
+ expect(result.phone_number_id).toBe('12345678901')
51
+ expect(result.account_name).toBe('Test Business')
52
+ expect(result.verified_name).toBe('Test Business')
53
+ expect(result.error).toBeUndefined()
54
+ })
55
+
56
+ test('returns info for specific --account', async () => {
57
+ const manager = new WhatsAppBotCredentialManager(tempDir)
58
+ await manager.setCredentials({
59
+ phone_number_id: '11111111111',
60
+ account_name: 'Account A',
61
+ access_token: 'token-a',
62
+ })
63
+ await manager.setCredentials({
64
+ phone_number_id: '22222222222',
65
+ account_name: 'Account B',
66
+ access_token: 'token-b',
67
+ })
68
+
69
+ const result = await whoamiAction({ account: '11111111111', _credManager: manager })
70
+
71
+ expect(result.phone_number_id).toBe('11111111111')
72
+ expect(result.account_name).toBe('Account A')
73
+ expect(result.verified_name).toBe('Test Business')
74
+ })
75
+
76
+ test('returns error when verifyToken fails', async () => {
77
+ mockVerifyToken.mockImplementationOnce(() => Promise.reject(new Error('Invalid token')))
78
+
79
+ const manager = new WhatsAppBotCredentialManager(tempDir)
80
+ await manager.setCredentials({
81
+ phone_number_id: '12345678901',
82
+ account_name: 'Test Business',
83
+ access_token: 'bad-token',
84
+ })
85
+
86
+ const result = await whoamiAction({ _credManager: manager })
87
+
88
+ expect(result.error).toBeDefined()
89
+ expect(result.error).toContain('Invalid token')
90
+ })
91
+
92
+ test('returns error when no credentials', async () => {
93
+ const manager = new WhatsAppBotCredentialManager(tempDir)
94
+
95
+ const result = await whoamiAction({ _credManager: manager })
96
+
97
+ expect(result.error).toBeDefined()
98
+ expect(result.error).toContain('No credentials')
99
+ })
100
+ })
@@ -0,0 +1,57 @@
1
+ import { Command } from 'commander'
2
+
3
+ import { formatOutput } from '@/shared/utils/output'
4
+
5
+ import { WhatsAppBotClient } from '../client'
6
+ import { WhatsAppBotCredentialManager } from '../credential-manager'
7
+
8
+ interface WhoamiOptions {
9
+ account?: string
10
+ pretty?: boolean
11
+ _credManager?: WhatsAppBotCredentialManager
12
+ }
13
+
14
+ interface WhoamiResult {
15
+ phone_number_id?: string | null
16
+ account_name?: string | null
17
+ verified_name?: string
18
+ error?: string
19
+ }
20
+
21
+ export async function whoamiAction(options: WhoamiOptions): Promise<WhoamiResult> {
22
+ try {
23
+ const credManager = options._credManager ?? new WhatsAppBotCredentialManager()
24
+ const creds = await credManager.getCredentials(options.account)
25
+
26
+ if (!creds) {
27
+ return { error: 'No credentials. Run "auth set <phone-number-id> <access-token>" first.' }
28
+ }
29
+
30
+ const client = await new WhatsAppBotClient().login({
31
+ phoneNumberId: creds.phone_number_id,
32
+ accessToken: creds.access_token,
33
+ })
34
+ const verified = await client.verifyToken()
35
+
36
+ return {
37
+ phone_number_id: creds.phone_number_id,
38
+ account_name: creds.account_name ?? null,
39
+ verified_name: verified.verified_name,
40
+ }
41
+ } catch (error) {
42
+ return { error: (error as Error).message }
43
+ }
44
+ }
45
+
46
+ function cliOutput(result: WhoamiResult, pretty?: boolean): void {
47
+ console.log(formatOutput(result, pretty))
48
+ if (result.error) process.exit(1)
49
+ }
50
+
51
+ export const whoamiCommand = new Command('whoami')
52
+ .description('Show current authenticated bot')
53
+ .option('--account <id>', 'Account ID to use')
54
+ .option('--pretty', 'Pretty print JSON output')
55
+ .action(async (opts: WhoamiOptions) => {
56
+ cliOutput(await whoamiAction(opts), opts.pretty)
57
+ })
@@ -0,0 +1,92 @@
1
+ import { execSync } from 'node:child_process'
2
+ import { writeFileSync, unlinkSync } from 'node:fs'
3
+ import { tmpdir } from 'node:os'
4
+ import { join } from 'node:path'
5
+
6
+ import QRCode from 'qrcode'
7
+
8
+ import { info } from './stderr'
9
+
10
+ export interface QRDisplayOptions {
11
+ platform: string
12
+ brandColor: string
13
+ scanInstruction: string
14
+ }
15
+
16
+ export async function createQRHtmlFile(url: string, options: QRDisplayOptions): Promise<string | null> {
17
+ try {
18
+ const svgString = await QRCode.toString(url, { type: 'svg', margin: 2 })
19
+ const html = `<!DOCTYPE html>
20
+ <html><head><meta charset="utf-8"><title>${options.platform} QR Login</title>
21
+ <style>body{display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:100vh;margin:0;font-family:-apple-system,system-ui,sans-serif;background:${options.brandColor}}
22
+ .card{background:#fff;border-radius:16px;padding:40px;text-align:center;box-shadow:0 4px 24px rgba(0,0,0,.15)}
23
+ h1{margin:0 0 8px;font-size:22px;color:#111}p{margin:0 0 24px;color:#666;font-size:14px}
24
+ svg{width:280px;height:280px}</style></head>
25
+ <body><div class="card"><h1>${options.platform} Login</h1><p>${options.scanInstruction}</p>${svgString}</div></body></html>`
26
+
27
+ const htmlPath = join(tmpdir(), `${options.platform.toLowerCase()}-qr-${Date.now()}.html`)
28
+ writeFileSync(htmlPath, html)
29
+ setTimeout(() => {
30
+ try {
31
+ unlinkSync(htmlPath)
32
+ } catch {}
33
+ }, 300_000).unref()
34
+ return htmlPath
35
+ } catch {
36
+ return null
37
+ }
38
+ }
39
+
40
+ export function openInBrowser(filePath: string): void {
41
+ try {
42
+ if (process.platform === 'darwin') {
43
+ execSync(`open "${filePath}"`, { stdio: 'ignore' })
44
+ } else if (process.platform === 'win32') {
45
+ execSync(`start "" "${filePath}"`, { stdio: 'ignore' })
46
+ } else {
47
+ execSync(`xdg-open "${filePath}"`, { stdio: 'ignore' })
48
+ }
49
+ } catch {}
50
+ }
51
+
52
+ export async function renderTerminalQR(data: string): Promise<string> {
53
+ return QRCode.toString(data, { type: 'terminal', small: true })
54
+ }
55
+
56
+ export async function displayQR(
57
+ data: string,
58
+ options: QRDisplayOptions & {
59
+ interactive: boolean
60
+ openBrowser?: boolean
61
+ formatOutput: (obj: Record<string, unknown>, pretty?: boolean) => string
62
+ pretty?: boolean
63
+ },
64
+ ): Promise<void> {
65
+ const shouldOpenBrowser = options.openBrowser ?? options.interactive
66
+ const htmlPath = await createQRHtmlFile(data, options)
67
+ if (htmlPath && shouldOpenBrowser) openInBrowser(htmlPath)
68
+
69
+ if (options.interactive) {
70
+ try {
71
+ const qrAscii = await renderTerminalQR(data)
72
+ info(`\n${options.scanInstruction}:\n`)
73
+ info(qrAscii)
74
+ } catch {
75
+ info(`\nOpen the QR code in the browser window, or scan this URL:\n${data}\n`)
76
+ }
77
+ } else {
78
+ console.log(
79
+ options.formatOutput(
80
+ {
81
+ next_action: 'scan_qr',
82
+ qr_url: data,
83
+ qr_html_path: htmlPath,
84
+ message: htmlPath
85
+ ? `QR code opened in browser. ${options.scanInstruction}`
86
+ : `QR code generated. Open qr_url to scan.`,
87
+ },
88
+ options.pretty,
89
+ ),
90
+ )
91
+ }
92
+ }
@@ -1,5 +1,6 @@
1
1
  import { WhatsAppClient } from '@/platforms/whatsapp/client'
2
2
  import { WhatsAppCredentialManager } from '@/platforms/whatsapp/credential-manager'
3
+ import { renderTerminalQR } from '@/shared/utils/qr'
3
4
 
4
5
  import type { AuthHint, AuthIO, PlatformAdapter, UnifiedChannel, UnifiedMessage, Workspace } from './types'
5
6
 
@@ -80,35 +81,38 @@ export class WhatsAppAdapter implements PlatformAdapter {
80
81
 
81
82
  getAuthHint(): AuthHint {
82
83
  return {
83
- command: 'agent-whatsapp auth login',
84
- description: 'Run the command below and link your WhatsApp account using the pairing code.',
84
+ command: 'agent-whatsapp auth login --qr',
85
+ description: 'Run the command below and scan the QR code with WhatsApp on your phone.',
85
86
  }
86
87
  }
87
88
 
88
89
  async authenticate(io: AuthIO): Promise<void> {
89
- const { createAccountId } = await import('@/platforms/whatsapp/types')
90
-
91
- const phone = await io.prompt('Phone number (e.g. +12025551234)')
92
- if (!phone) throw new Error('Phone number is required')
93
-
94
- io.print('Connecting...')
95
- const accountId = createAccountId(phone)
90
+ io.print('Generating QR code...')
91
+ const accountId = 'qr-default'
92
+ const existingPaths = this.credManager.getAccountPaths(accountId)
93
+ const { rm } = await import('node:fs/promises')
94
+ await rm(existingPaths.auth_dir, { recursive: true, force: true })
96
95
  const paths = await this.credManager.ensureAccountPaths(accountId)
97
96
  const client = await new WhatsAppClient().login({ authDir: paths.auth_dir })
98
97
 
99
98
  let waitForAuth: () => Promise<void>
100
99
  try {
101
- const result = await client.connectForPairing(phone)
100
+ const result = await client.connectForQR(async (qr) => {
101
+ io.print('Scan this QR code with WhatsApp on your phone:')
102
+ try {
103
+ const rendered = await renderTerminalQR(qr)
104
+ io.print(rendered)
105
+ } catch {
106
+ io.print(qr)
107
+ }
108
+ })
102
109
  waitForAuth = result.waitForAuth
103
- const formatted = result.code.length === 8 ? `${result.code.slice(0, 4)}-${result.code.slice(4)}` : result.code
104
- io.print(`Pairing code: ${formatted}`)
105
- io.print('Enter this code in WhatsApp > Linked Devices > Link with phone number')
106
110
  } catch (err) {
107
111
  await client.close()
108
112
  throw err
109
113
  }
110
114
 
111
- io.print('Waiting for confirmation...')
115
+ io.print('Waiting for QR code scan...')
112
116
  try {
113
117
  await waitForAuth()
114
118
  } catch (err) {
@@ -119,14 +123,13 @@ export class WhatsAppAdapter implements PlatformAdapter {
119
123
  const now = new Date().toISOString()
120
124
  await this.credManager.setAccount({
121
125
  account_id: accountId,
122
- phone_number: phone,
123
126
  created_at: now,
124
127
  updated_at: now,
125
128
  })
126
129
  await this.credManager.setCurrent(accountId)
127
130
 
128
131
  this.client = client
129
- this.currentAccount = { id: accountId, name: phone }
132
+ this.currentAccount = { id: accountId, name: accountId }
130
133
  }
131
134
 
132
135
  private ensureClient(): WhatsAppClient {
@@ -1,3 +0,0 @@
1
- import { Command } from 'commander';
2
- export declare const profileCommand: Command;
3
- //# sourceMappingURL=profile.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"profile.d.ts","sourceRoot":"","sources":["../../../../../src/platforms/line/commands/profile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAoBnC,eAAO,MAAM,cAAc,SAGH,CAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"profile.js","sourceRoot":"","sources":["../../../../../src/platforms/line/commands/profile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAEnC,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAA;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAEpD,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAEtC,KAAK,UAAU,aAAa,CAAC,OAA6B;IACxD,IAAI,MAA8B,CAAA;IAClC,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,IAAI,UAAU,EAAE,CAAC,KAAK,EAAE,CAAA;QACvC,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,UAAU,EAAE,CAAA;QACzC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAA;IACpD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,WAAW,CAAC,KAAc,CAAC,CAAA;IAC7B,CAAC;YAAS,CAAC;QACT,MAAM,EAAE,KAAK,EAAE,CAAA;IACjB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,OAAO,CAAC,SAAS,CAAC;KACjD,WAAW,CAAC,wBAAwB,CAAC;KACrC,MAAM,CAAC,UAAU,EAAE,0BAA0B,CAAC;KAC9C,MAAM,CAAC,aAAa,CAAC,CAAA"}