agent-messenger 2.10.2 → 2.11.1

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 (330) 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 +21 -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 +71 -29
  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/index.d.ts +3 -1
  199. package/dist/src/shared/chromium/index.d.ts.map +1 -1
  200. package/dist/src/shared/chromium/index.js +2 -1
  201. package/dist/src/shared/chromium/index.js.map +1 -1
  202. package/dist/src/shared/utils/cli-output.d.ts +7 -0
  203. package/dist/src/shared/utils/cli-output.d.ts.map +1 -0
  204. package/dist/src/shared/utils/cli-output.js +7 -0
  205. package/dist/src/shared/utils/cli-output.js.map +1 -0
  206. package/dist/src/tui/app.d.ts.map +1 -1
  207. package/dist/src/tui/app.js +73 -20
  208. package/dist/src/tui/app.js.map +1 -1
  209. package/docs/content/docs/cli/channeltalk.mdx +4 -0
  210. package/docs/content/docs/cli/discord.mdx +5 -0
  211. package/docs/content/docs/cli/instagram.mdx +3 -0
  212. package/docs/content/docs/cli/slack.mdx +5 -0
  213. package/docs/content/docs/cli/slackbot.mdx +60 -22
  214. package/docs/content/docs/cli/teams.mdx +5 -0
  215. package/docs/content/docs/cli/webex.mdx +3 -0
  216. package/docs/content/docs/sdk/channeltalkbot.mdx +38 -1
  217. package/docs/content/docs/sdk/discordbot.mdx +501 -0
  218. package/docs/content/docs/sdk/meta.json +2 -0
  219. package/docs/content/docs/sdk/slackbot.mdx +576 -0
  220. package/e2e/README.md +1 -1
  221. package/e2e/config.ts +9 -4
  222. package/examples/discordbot-listen.ts +65 -0
  223. package/examples/slackbot-listen.ts +65 -0
  224. package/package.json +21 -1
  225. package/skills/agent-channeltalk/SKILL.md +5 -1
  226. package/skills/agent-channeltalk/references/authentication.md +5 -1
  227. package/skills/agent-channeltalkbot/SKILL.md +17 -3
  228. package/skills/agent-channeltalkbot/references/authentication.md +7 -5
  229. package/skills/agent-discord/SKILL.md +5 -1
  230. package/skills/agent-discord/references/authentication.md +7 -1
  231. package/skills/agent-discordbot/SKILL.md +13 -2
  232. package/skills/agent-discordbot/references/common-patterns.md +1 -1
  233. package/skills/agent-instagram/SKILL.md +7 -1
  234. package/skills/agent-instagram/references/authentication.md +6 -0
  235. package/skills/agent-kakaotalk/SKILL.md +1 -1
  236. package/skills/agent-line/SKILL.md +1 -1
  237. package/skills/agent-slack/SKILL.md +5 -1
  238. package/skills/agent-slack/references/authentication.md +7 -1
  239. package/skills/agent-slackbot/SKILL.md +56 -4
  240. package/skills/agent-slackbot/references/authentication.md +4 -0
  241. package/skills/agent-teams/SKILL.md +5 -1
  242. package/skills/agent-teams/references/authentication.md +7 -1
  243. package/skills/agent-telegram/SKILL.md +1 -1
  244. package/skills/agent-webex/SKILL.md +7 -1
  245. package/skills/agent-webex/references/authentication.md +6 -0
  246. package/skills/agent-wechatbot/SKILL.md +16 -1
  247. package/skills/agent-wechatbot/references/authentication.md +219 -0
  248. package/skills/agent-wechatbot/references/common-patterns.md +358 -0
  249. package/skills/agent-wechatbot/templates/account-summary.sh +122 -0
  250. package/skills/agent-wechatbot/templates/post-message.sh +122 -0
  251. package/skills/agent-wechatbot/templates/send-template.sh +152 -0
  252. package/skills/agent-whatsapp/SKILL.md +1 -1
  253. package/skills/agent-whatsappbot/SKILL.md +30 -1
  254. package/src/platforms/channeltalk/commands/auth.test.ts +15 -3
  255. package/src/platforms/channeltalk/commands/auth.ts +15 -5
  256. package/src/platforms/channeltalk/token-extractor.ts +24 -5
  257. package/src/platforms/channeltalkbot/cli.ts +9 -0
  258. package/src/platforms/channeltalkbot/commands/auth.ts +1 -5
  259. package/src/platforms/channeltalkbot/commands/bot.ts +1 -6
  260. package/src/platforms/channeltalkbot/commands/chat.ts +1 -6
  261. package/src/platforms/channeltalkbot/commands/group.ts +1 -6
  262. package/src/platforms/channeltalkbot/commands/manager.ts +1 -6
  263. package/src/platforms/channeltalkbot/commands/message.ts +1 -6
  264. package/src/platforms/channeltalkbot/commands/whoami.test.ts +2 -0
  265. package/src/platforms/channeltalkbot/commands/whoami.ts +1 -6
  266. package/src/platforms/channeltalkbot/credential-manager.test.ts +96 -2
  267. package/src/platforms/channeltalkbot/credential-manager.ts +37 -4
  268. package/src/platforms/discord/commands/auth.ts +13 -2
  269. package/src/platforms/discord/listener.test.ts +59 -1
  270. package/src/platforms/discord/listener.ts +43 -19
  271. package/src/platforms/discord/token-extractor.ts +30 -6
  272. package/src/platforms/discordbot/cli.ts +10 -0
  273. package/src/platforms/discordbot/client.ts +4 -0
  274. package/src/platforms/discordbot/commands/auth.ts +1 -5
  275. package/src/platforms/discordbot/commands/message.ts +1 -6
  276. package/src/platforms/discordbot/commands/server.ts +1 -5
  277. package/src/platforms/discordbot/commands/whoami.ts +1 -6
  278. package/src/platforms/discordbot/index.test.ts +82 -0
  279. package/src/platforms/discordbot/index.ts +27 -9
  280. package/src/platforms/discordbot/listener.test.ts +1002 -0
  281. package/src/platforms/discordbot/listener.ts +321 -0
  282. package/src/platforms/discordbot/types.ts +163 -0
  283. package/src/platforms/instagram/commands/auth.ts +9 -1
  284. package/src/platforms/instagram/token-extractor.ts +13 -1
  285. package/src/platforms/slack/commands/auth.ts +11 -2
  286. package/src/platforms/slack/token-extractor.test.ts +96 -0
  287. package/src/platforms/slack/token-extractor.ts +76 -13
  288. package/src/platforms/slackbot/cli.ts +13 -1
  289. package/src/platforms/slackbot/client.test.ts +274 -0
  290. package/src/platforms/slackbot/client.ts +130 -2
  291. package/src/platforms/slackbot/commands/auth.ts +1 -5
  292. package/src/platforms/slackbot/commands/file.test.ts +201 -0
  293. package/src/platforms/slackbot/commands/file.ts +212 -0
  294. package/src/platforms/slackbot/commands/index.ts +1 -0
  295. package/src/platforms/slackbot/commands/message.ts +22 -0
  296. package/src/platforms/slackbot/commands/whoami.ts +1 -6
  297. package/src/platforms/slackbot/credential-manager.test.ts +62 -2
  298. package/src/platforms/slackbot/credential-manager.ts +32 -2
  299. package/src/platforms/slackbot/index.test.ts +59 -0
  300. package/src/platforms/slackbot/index.ts +31 -7
  301. package/src/platforms/slackbot/listener.test.ts +1012 -0
  302. package/src/platforms/slackbot/listener.ts +362 -0
  303. package/src/platforms/slackbot/types.ts +224 -1
  304. package/src/platforms/teams/commands/auth.test.ts +1 -1
  305. package/src/platforms/teams/commands/auth.ts +66 -7
  306. package/src/platforms/teams/ensure-auth.test.ts +56 -5
  307. package/src/platforms/teams/ensure-auth.ts +39 -11
  308. package/src/platforms/teams/token-extractor.test.ts +146 -24
  309. package/src/platforms/teams/token-extractor.ts +87 -29
  310. package/src/platforms/webex/commands/auth.ts +13 -2
  311. package/src/platforms/webex/token-extractor.ts +25 -3
  312. package/src/platforms/wechatbot/cli.ts +9 -0
  313. package/src/platforms/wechatbot/commands/auth.ts +1 -5
  314. package/src/platforms/wechatbot/commands/message.ts +1 -6
  315. package/src/platforms/wechatbot/commands/template.ts +1 -6
  316. package/src/platforms/wechatbot/commands/user.ts +1 -6
  317. package/src/platforms/wechatbot/commands/whoami.ts +1 -6
  318. package/src/platforms/whatsappbot/cli.ts +9 -0
  319. package/src/platforms/whatsappbot/commands/auth.ts +1 -5
  320. package/src/platforms/whatsappbot/commands/message.ts +1 -6
  321. package/src/platforms/whatsappbot/commands/template.ts +1 -6
  322. package/src/platforms/whatsappbot/commands/whoami.ts +1 -6
  323. package/src/shared/chromium/browsers.test.ts +80 -0
  324. package/src/shared/chromium/browsers.ts +72 -3
  325. package/src/shared/chromium/cli-options.test.ts +22 -0
  326. package/src/shared/chromium/cli-options.ts +12 -0
  327. package/src/shared/chromium/index.ts +3 -0
  328. package/src/shared/utils/cli-output.test.ts +57 -0
  329. package/src/shared/utils/cli-output.ts +8 -0
  330. package/src/tui/app.ts +129 -20
@@ -0,0 +1,122 @@
1
+ #!/bin/bash
2
+ #
3
+ # account-summary.sh - Generate a summary of the WeChat Official Account, templates, and followers
4
+ #
5
+ # Usage:
6
+ # ./account-summary.sh [--json]
7
+ #
8
+ # Options:
9
+ # --json Output raw JSON instead of formatted text
10
+ #
11
+ # Example:
12
+ # ./account-summary.sh
13
+ # ./account-summary.sh --json > summary.json
14
+
15
+ set -euo pipefail
16
+
17
+ OUTPUT_JSON=false
18
+ if [ $# -gt 0 ] && [ "$1" = "--json" ]; then
19
+ OUTPUT_JSON=true
20
+ fi
21
+
22
+ RED='\033[0;31m'
23
+ GREEN='\033[0;32m'
24
+ YELLOW='\033[1;33m'
25
+ BLUE='\033[0;34m'
26
+ CYAN='\033[0;36m'
27
+ BOLD='\033[1m'
28
+ NC='\033[0m'
29
+
30
+ if ! command -v agent-wechatbot &> /dev/null; then
31
+ echo -e "${RED}Error: agent-wechatbot not found${NC}" >&2
32
+ echo "" >&2
33
+ echo "Install it with:" >&2
34
+ echo " npm install -g agent-messenger" >&2
35
+ exit 1
36
+ fi
37
+
38
+ AUTH_STATUS=$(agent-wechatbot auth status 2>&1) || true
39
+
40
+ if echo "$AUTH_STATUS" | jq -e '.error' > /dev/null 2>&1; then
41
+ echo -e "${RED}Not authenticated!${NC}" >&2
42
+ echo "" >&2
43
+ echo "Run this to authenticate:" >&2
44
+ echo " agent-wechatbot auth set <app-id> <app-secret>" >&2
45
+ exit 1
46
+ fi
47
+
48
+ echo -e "${YELLOW}Fetching templates and followers...${NC}" >&2
49
+ TEMPLATES_RESULT=$(agent-wechatbot template list 2>&1) || true
50
+ USERS_RESULT=$(agent-wechatbot user list 2>&1) || true
51
+
52
+ if [ "$OUTPUT_JSON" = true ]; then
53
+ jq -n \
54
+ --argjson auth "$AUTH_STATUS" \
55
+ --argjson templates "$TEMPLATES_RESULT" \
56
+ --argjson users "$USERS_RESULT" \
57
+ '{"auth": $auth, "templates": $templates, "users": $users}'
58
+ exit 0
59
+ fi
60
+
61
+ APP_ID=$(echo "$AUTH_STATUS" | jq -r '.app_id // "Unknown"')
62
+ ACCOUNT_NAME=$(echo "$AUTH_STATUS" | jq -r '.account_name // "Unknown"')
63
+
64
+ TEMPLATES=$(echo "$TEMPLATES_RESULT" | jq '.template_list // []' 2>/dev/null || echo '[]')
65
+ TEMPLATE_COUNT=$(echo "$TEMPLATES" | jq 'length')
66
+
67
+ FOLLOWER_TOTAL=$(echo "$USERS_RESULT" | jq -r '.total // 0' 2>/dev/null || echo '0')
68
+ FOLLOWER_COUNT=$(echo "$USERS_RESULT" | jq -r '.count // 0' 2>/dev/null || echo '0')
69
+
70
+ echo ""
71
+ echo -e "${BOLD}${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
72
+ echo -e "${BOLD}${BLUE} WeChat Official Account Summary${NC}"
73
+ echo -e "${BOLD}${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
74
+ echo ""
75
+ echo -e "${BOLD}Account:${NC} $ACCOUNT_NAME"
76
+ echo -e "${BOLD}App ID:${NC} $APP_ID"
77
+ echo ""
78
+
79
+ echo -e "${BOLD}${CYAN}Followers${NC}"
80
+ echo " Total: $FOLLOWER_TOTAL"
81
+ echo " This page: $FOLLOWER_COUNT"
82
+ echo ""
83
+
84
+ echo -e "${BOLD}${CYAN}Templates (${TEMPLATE_COUNT} total)${NC}"
85
+ if [ "$TEMPLATE_COUNT" -gt 0 ]; then
86
+ echo "$TEMPLATES" | jq -r '
87
+ .[0:10] |
88
+ .[] |
89
+ " \(.template_id) — \(.title)"
90
+ '
91
+ if [ "$TEMPLATE_COUNT" -gt 10 ]; then
92
+ echo " ... and $((TEMPLATE_COUNT - 10)) more"
93
+ fi
94
+ else
95
+ echo " (no templates approved yet)"
96
+ fi
97
+ echo ""
98
+
99
+ echo -e "${BOLD}${CYAN}Quick Actions:${NC}"
100
+ echo ""
101
+ echo -e " ${GREEN}# Send a customer service message (within 48h window)${NC}"
102
+ echo -e " agent-wechatbot message send oABCD1234 \"Hello!\""
103
+ echo ""
104
+ echo -e " ${GREEN}# Send a template notification (anytime)${NC}"
105
+ FIRST_TEMPLATE=$(echo "$TEMPLATES" | jq -r '.[0].template_id // "TM00001"')
106
+ echo -e " agent-wechatbot template send oABCD1234 $FIRST_TEMPLATE --data '{...}'"
107
+ echo ""
108
+ echo -e " ${GREEN}# List all templates${NC}"
109
+ echo -e " agent-wechatbot template list"
110
+ echo ""
111
+
112
+ echo -e "${BOLD}${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
113
+ echo ""
114
+
115
+ SUMMARY_FILE="account-summary-$(date +%Y%m%d-%H%M%S).json"
116
+ jq -n \
117
+ --argjson auth "$AUTH_STATUS" \
118
+ --argjson templates "$TEMPLATES_RESULT" \
119
+ --argjson users "$USERS_RESULT" \
120
+ '{"auth": $auth, "templates": $templates, "users": $users}' > "$SUMMARY_FILE"
121
+ echo -e "${GREEN}✓ Full data saved to: $SUMMARY_FILE${NC}"
122
+ echo ""
@@ -0,0 +1,122 @@
1
+ #!/bin/bash
2
+ #
3
+ # post-message.sh - Send a customer service message via WeChat Official Account API
4
+ #
5
+ # Usage:
6
+ # ./post-message.sh <openid> <message>
7
+ #
8
+ # Arguments:
9
+ # openid - Recipient OpenID (e.g. oABCD1234)
10
+ # message - Message text to send
11
+ #
12
+ # Example:
13
+ # ./post-message.sh oABCD1234 "Hello from script!"
14
+ # ./post-message.sh oABCD1234 "Thanks for your purchase ✅"
15
+ #
16
+ # Note: Customer service messages only work within the 48-hour interaction window.
17
+ # Outside that window, use template messages via send-template.sh.
18
+
19
+ set -euo pipefail
20
+
21
+ # Check arguments
22
+ if [ $# -lt 2 ]; then
23
+ echo "Usage: $0 <openid> <message>"
24
+ echo ""
25
+ echo "Examples:"
26
+ echo " $0 oABCD1234 'Hello world!'"
27
+ echo " $0 oABCD1234 'Build completed'"
28
+ exit 1
29
+ fi
30
+
31
+ OPENID="$1"
32
+ MESSAGE="$2"
33
+
34
+ # Colors for output
35
+ RED='\033[0;31m'
36
+ GREEN='\033[0;32m'
37
+ YELLOW='\033[1;33m'
38
+ NC='\033[0m' # No Color
39
+
40
+ # Function to send message with retry logic
41
+ send_message() {
42
+ local openid=$1
43
+ local message=$2
44
+ local max_attempts=3
45
+ local attempt=1
46
+
47
+ while [ $attempt -le $max_attempts ]; do
48
+ echo -e "${YELLOW}Attempt $attempt/$max_attempts...${NC}"
49
+
50
+ # Send message and capture result
51
+ RESULT=$(agent-wechatbot message send "$openid" "$message" 2>&1) || true
52
+
53
+ # Check if successful (no error field)
54
+ if ! echo "$RESULT" | jq -e '.error' > /dev/null 2>&1; then
55
+ echo -e "${GREEN}✓ Message sent successfully!${NC}"
56
+ echo ""
57
+ echo "Message details:"
58
+ echo " To OpenID: $openid"
59
+ return 0
60
+ fi
61
+
62
+ # Extract error information
63
+ ERROR_MSG=$(echo "$RESULT" | jq -r '.error // "Unknown error"')
64
+ echo -e "${RED}✗ Failed: $ERROR_MSG${NC}"
65
+
66
+ # Don't retry on certain errors
67
+ if echo "$ERROR_MSG" | grep -qE "40164|IP whitelist"; then
68
+ echo -e "${RED}IP not in WeChat whitelist. Add your server IP in the admin panel.${NC}"
69
+ return 1
70
+ fi
71
+
72
+ if echo "$ERROR_MSG" | grep -qE "48h|48-hour"; then
73
+ echo -e "${YELLOW}Outside 48h window. Use a template message instead:${NC}"
74
+ echo " ./send-template.sh $openid <template-id> --data '...'"
75
+ return 1
76
+ fi
77
+
78
+ # Exponential backoff before retry
79
+ if [ $attempt -lt $max_attempts ]; then
80
+ SLEEP_TIME=$((attempt * 2))
81
+ echo "Retrying in ${SLEEP_TIME}s..."
82
+ sleep $SLEEP_TIME
83
+ fi
84
+
85
+ attempt=$((attempt + 1))
86
+ done
87
+
88
+ echo -e "${RED}Failed after $max_attempts attempts${NC}"
89
+ return 1
90
+ }
91
+
92
+ # Check if agent-wechatbot is installed
93
+ if ! command -v agent-wechatbot &> /dev/null; then
94
+ echo -e "${RED}Error: agent-wechatbot not found${NC}"
95
+ echo ""
96
+ echo "Install it with:"
97
+ echo " npm install -g agent-messenger"
98
+ exit 1
99
+ fi
100
+
101
+ # Check authentication
102
+ echo "Checking authentication..."
103
+ AUTH_STATUS=$(agent-wechatbot auth status 2>&1) || true
104
+
105
+ if echo "$AUTH_STATUS" | jq -e '.error' > /dev/null 2>&1; then
106
+ echo -e "${RED}Not authenticated!${NC}"
107
+ echo ""
108
+ echo "Run this to authenticate:"
109
+ echo " agent-wechatbot auth set <app-id> <app-secret>"
110
+ exit 1
111
+ fi
112
+
113
+ APP_ID=$(echo "$AUTH_STATUS" | jq -r '.app_id // "Unknown"')
114
+ echo -e "${GREEN}✓ Authenticated (App ID: $APP_ID)${NC}"
115
+ echo ""
116
+
117
+ # Send the message
118
+ echo "Sending message to $OPENID..."
119
+ echo "Message: $MESSAGE"
120
+ echo ""
121
+
122
+ send_message "$OPENID" "$MESSAGE"
@@ -0,0 +1,152 @@
1
+ #!/bin/bash
2
+ #
3
+ # send-template.sh - Send a WeChat template message via Official Account API
4
+ #
5
+ # Usage:
6
+ # ./send-template.sh <openid> <template-id> --data <json> [--url <url>]
7
+ #
8
+ # Arguments:
9
+ # openid - Recipient follower OpenID (e.g. oABCD1234)
10
+ # template-id - Pre-approved template ID (e.g. TM00001)
11
+ #
12
+ # Options:
13
+ # --data <json> - Required. JSON object with template parameters.
14
+ # Format: {"<param>":{"value":"<text>","color":"<#hex>"}}
15
+ # --url <url> - Optional. URL the message links to when tapped.
16
+ #
17
+ # Example:
18
+ # ./send-template.sh oABCD1234 TM00001 \
19
+ # --data '{"order_id":{"value":"ORD-9876"},"customer_name":{"value":"Alice"}}'
20
+ #
21
+ # ./send-template.sh oABCD1234 TM00001 \
22
+ # --data '{"status":{"value":"shipped","color":"#00AA00"}}' \
23
+ # --url "https://example.com/orders/9876"
24
+
25
+ set -euo pipefail
26
+
27
+ if [ $# -lt 2 ]; then
28
+ echo "Usage: $0 <openid> <template-id> --data <json> [--url <url>]"
29
+ echo ""
30
+ echo "Examples:"
31
+ echo " $0 oABCD1234 TM00001 --data '{\"order_id\":{\"value\":\"ORD-001\"}}'"
32
+ echo " $0 oABCD1234 TM00001 --data '{...}' --url https://example.com/path"
33
+ exit 1
34
+ fi
35
+
36
+ OPENID="$1"
37
+ TEMPLATE_ID="$2"
38
+ shift 2
39
+
40
+ DATA=""
41
+ URL=""
42
+
43
+ while [ $# -gt 0 ]; do
44
+ case "$1" in
45
+ --data)
46
+ if [ $# -lt 2 ]; then
47
+ echo "Error: --data requires a JSON value"
48
+ exit 1
49
+ fi
50
+ DATA="$2"
51
+ shift 2
52
+ ;;
53
+ --url)
54
+ if [ $# -lt 2 ]; then
55
+ echo "Error: --url requires a value"
56
+ exit 1
57
+ fi
58
+ URL="$2"
59
+ shift 2
60
+ ;;
61
+ *)
62
+ echo "Unknown option: $1"
63
+ exit 1
64
+ ;;
65
+ esac
66
+ done
67
+
68
+ if [ -z "$DATA" ]; then
69
+ echo "Error: --data is required"
70
+ exit 1
71
+ fi
72
+
73
+ RED='\033[0;31m'
74
+ GREEN='\033[0;32m'
75
+ YELLOW='\033[1;33m'
76
+ NC='\033[0m'
77
+
78
+ # Check if agent-wechatbot is installed
79
+ if ! command -v agent-wechatbot &> /dev/null; then
80
+ echo -e "${RED}Error: agent-wechatbot not found${NC}"
81
+ echo ""
82
+ echo "Install it with:"
83
+ echo " npm install -g agent-messenger"
84
+ exit 1
85
+ fi
86
+
87
+ # Check authentication
88
+ echo "Checking authentication..."
89
+ AUTH_STATUS=$(agent-wechatbot auth status 2>&1) || true
90
+
91
+ if echo "$AUTH_STATUS" | jq -e '.error' > /dev/null 2>&1; then
92
+ echo -e "${RED}Not authenticated!${NC}"
93
+ echo ""
94
+ echo "Run this to authenticate:"
95
+ echo " agent-wechatbot auth set <app-id> <app-secret>"
96
+ exit 1
97
+ fi
98
+
99
+ APP_ID=$(echo "$AUTH_STATUS" | jq -r '.app_id // "Unknown"')
100
+ echo -e "${GREEN}✓ Authenticated (App ID: $APP_ID)${NC}"
101
+ echo ""
102
+
103
+ # Send template message with retry
104
+ max_attempts=3
105
+ attempt=1
106
+
107
+ echo "Sending template '$TEMPLATE_ID' to $OPENID..."
108
+ if [ -n "$URL" ]; then
109
+ echo "URL: $URL"
110
+ fi
111
+ echo ""
112
+
113
+ while [ $attempt -le $max_attempts ]; do
114
+ echo -e "${YELLOW}Attempt $attempt/$max_attempts...${NC}"
115
+
116
+ if [ -n "$URL" ]; then
117
+ RESULT=$(agent-wechatbot template send "$OPENID" "$TEMPLATE_ID" --data "$DATA" --url "$URL" 2>&1) || true
118
+ else
119
+ RESULT=$(agent-wechatbot template send "$OPENID" "$TEMPLATE_ID" --data "$DATA" 2>&1) || true
120
+ fi
121
+
122
+ if ! echo "$RESULT" | jq -e '.error' > /dev/null 2>&1; then
123
+ echo -e "${GREEN}✓ Template message sent successfully!${NC}"
124
+ echo ""
125
+ echo "Message details:"
126
+ echo " To OpenID: $OPENID"
127
+ echo " Template: $TEMPLATE_ID"
128
+ if [ -n "$URL" ]; then
129
+ echo " URL: $URL"
130
+ fi
131
+ exit 0
132
+ fi
133
+
134
+ ERROR_MSG=$(echo "$RESULT" | jq -r '.error // "Unknown error"')
135
+ echo -e "${RED}✗ Failed: $ERROR_MSG${NC}"
136
+
137
+ # Don't retry on permanent errors
138
+ if echo "$ERROR_MSG" | grep -qE "40164|IP whitelist|40125|Invalid App"; then
139
+ exit 1
140
+ fi
141
+
142
+ if [ $attempt -lt $max_attempts ]; then
143
+ SLEEP_TIME=$((attempt * 2))
144
+ echo "Retrying in ${SLEEP_TIME}s..."
145
+ sleep $SLEEP_TIME
146
+ fi
147
+
148
+ attempt=$((attempt + 1))
149
+ done
150
+
151
+ echo -e "${RED}Failed after $max_attempts attempts${NC}"
152
+ exit 1
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: agent-whatsapp
3
3
  description: Interact with WhatsApp - send messages, read chats, manage conversations
4
- version: 2.10.2
4
+ version: 2.11.1
5
5
  allowed-tools: Bash(agent-whatsapp:*)
6
6
  metadata:
7
7
  openclaw:
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: agent-whatsappbot
3
3
  description: Interact with WhatsApp using Cloud API credentials - send messages, manage templates
4
- version: 2.10.2
4
+ version: 2.11.1
5
5
  allowed-tools: Bash(agent-whatsappbot:*)
6
6
  metadata:
7
7
  openclaw:
@@ -245,6 +245,8 @@ agent-whatsappbot template list --pretty
245
245
 
246
246
  ## Common Patterns
247
247
 
248
+ See `references/common-patterns.md` for additional workflows.
249
+
248
250
  ### Send a notification outside the 24h window
249
251
 
250
252
  Template messages are required when the customer hasn't messaged you in the last 24 hours. Always check your available templates first:
@@ -286,6 +288,14 @@ agent-whatsappbot message send-template 15559876543 deployment_alert \
286
288
  --components '[{"type":"body","parameters":[{"type":"text","text":"v2.1.0"},{"type":"text","text":"production"},{"type":"text","text":"success"}]}]'
287
289
  ```
288
290
 
291
+ ## Templates
292
+
293
+ See `templates/` directory for runnable examples:
294
+
295
+ - `post-message.sh` - Send messages with error handling and retries
296
+ - `account-summary.sh` - Generate account and template summary
297
+ - `send-template.sh` - Send a template message with parameters
298
+
289
299
  ## Error Handling
290
300
 
291
301
  All commands return consistent error format:
@@ -318,6 +328,20 @@ Config format:
318
328
  }
319
329
  ```
320
330
 
331
+ ## Key Differences from agent-whatsapp
332
+
333
+ | Feature | agent-whatsapp | agent-whatsappbot |
334
+ | ----------------- | ------------------------------------ | ---------------------------------- |
335
+ | Auth type | User account (Baileys, QR/pairing) | Cloud API (Phone Number ID + Token) |
336
+ | Token source | Pairing flow with phone number | Meta Business Manager |
337
+ | Read messages | Yes | No (webhook-only inbound) |
338
+ | Group chats | Yes | No |
339
+ | Template messages | No | Yes (required outside 24h window) |
340
+ | Free-form text | Anytime | Only within 24h customer window |
341
+ | Media uploads | Direct (local files) | URL only |
342
+ | Multi-account | Multi-phone, single CLI session | Multi-account by Phone Number ID |
343
+ | CI/CD friendly | Requires phone, pairing flow | Yes (just set token) |
344
+
321
345
  ## Limitations
322
346
 
323
347
  - **Cannot list or read received messages** — WhatsApp Cloud API delivers inbound messages via webhooks only. This CLI is send-only.
@@ -378,3 +402,8 @@ WhatsApp enforces rate limits based on your business tier. The CLI automatically
378
402
  - Use full international format without `+` prefix (e.g., `15551234567` not `+1-555-123-4567`)
379
403
  - If outside the 24h window, use `message send-template` instead of `message send`
380
404
  - Check that your WhatsApp Business account is active and not restricted
405
+
406
+ ## References
407
+
408
+ - [Authentication Guide](references/authentication.md)
409
+ - [Common Patterns](references/common-patterns.md)
@@ -20,6 +20,9 @@ const mockListChannels = mock(() =>
20
20
  ]),
21
21
  )
22
22
  const mockExtract = mock(() => Promise.resolve([{ accountCookie: 'fresh-account', sessionCookie: 'fresh-session' }]))
23
+ const mockCreateTokenExtractor = mock((_browserProfile?: string[]) => ({
24
+ extract: mockExtract,
25
+ }))
23
26
 
24
27
  import {
25
28
  clearAction,
@@ -89,9 +92,7 @@ setChannelAuthCommandDependenciesForTesting({
89
92
  return true
90
93
  },
91
94
  }),
92
- createTokenExtractor: () => ({
93
- extract: mockExtract,
94
- }),
95
+ createTokenExtractor: mockCreateTokenExtractor,
95
96
  })
96
97
 
97
98
  describe('channel auth commands', () => {
@@ -105,6 +106,7 @@ describe('channel auth commands', () => {
105
106
  mockGetAccount.mockReset()
106
107
  mockListChannels.mockReset()
107
108
  mockExtract.mockReset()
109
+ mockCreateTokenExtractor.mockReset()
108
110
 
109
111
  mockGetAccount.mockImplementation(() => Promise.resolve({ id: 'acct-1', name: 'Alice' }))
110
112
  mockListChannels.mockImplementation(() =>
@@ -116,6 +118,9 @@ describe('channel auth commands', () => {
116
118
  mockExtract.mockImplementation(() =>
117
119
  Promise.resolve([{ accountCookie: 'fresh-account', sessionCookie: 'fresh-session' }]),
118
120
  )
121
+ mockCreateTokenExtractor.mockImplementation((_browserProfile?: string[]) => ({
122
+ extract: mockExtract,
123
+ }))
119
124
  })
120
125
 
121
126
  describe('extractAction', () => {
@@ -136,6 +141,13 @@ describe('channel auth commands', () => {
136
141
  expect(workspaceStore.get('ws-2')?.account_cookie).toBe('fresh-account')
137
142
  })
138
143
 
144
+ it('passes custom browser profile paths to the token extractor', async () => {
145
+ await extractAction({ browserProfile: ['/tmp/profile-a', '/tmp/profile-b'] })
146
+
147
+ expect(mockCreateTokenExtractor).toHaveBeenCalledWith(['/tmp/profile-a', '/tmp/profile-b'])
148
+ expect(mockExtract).toHaveBeenCalledTimes(1)
149
+ })
150
+
139
151
  it('preserves current workspace if it still exists after re-extraction', async () => {
140
152
  workspaceStore.set('ws-2', {
141
153
  workspace_id: 'ws-2',
@@ -1,5 +1,6 @@
1
1
  import { Command } from 'commander'
2
2
 
3
+ import { collectBrowserProfileOption } from '@/shared/chromium'
3
4
  import { formatOutput } from '@/shared/utils/output'
4
5
 
5
6
  import { ChannelClient } from '../client'
@@ -9,6 +10,7 @@ import { ChannelTokenExtractor } from '../token-extractor'
9
10
  interface ActionOptions {
10
11
  workspace?: string
11
12
  pretty?: boolean
13
+ browserProfile?: string[]
12
14
  _credManager?: ChannelCredentialManager
13
15
  }
14
16
 
@@ -60,7 +62,8 @@ let createChannelClient: (
60
62
 
61
63
  let createCredentialManager = (): ChannelCredentialManagerLike => new ChannelCredentialManager()
62
64
 
63
- let createTokenExtractor = (): ChannelTokenExtractorLike => new ChannelTokenExtractor()
65
+ let createTokenExtractor = (browserProfile?: string[]): ChannelTokenExtractorLike =>
66
+ new ChannelTokenExtractor(undefined, browserProfile)
64
67
 
65
68
  export function setChannelAuthCommandDependenciesForTesting(dependencies: {
66
69
  createChannelClient?: (
@@ -68,7 +71,7 @@ export function setChannelAuthCommandDependenciesForTesting(dependencies: {
68
71
  sessionCookie?: string,
69
72
  ) => ChannelClientLike | Promise<ChannelClientLike>
70
73
  createCredentialManager?: () => ChannelCredentialManagerLike
71
- createTokenExtractor?: () => ChannelTokenExtractorLike
74
+ createTokenExtractor?: (browserProfile?: string[]) => ChannelTokenExtractorLike
72
75
  }): void {
73
76
  if (dependencies.createChannelClient) createChannelClient = dependencies.createChannelClient
74
77
  if (dependencies.createCredentialManager) createCredentialManager = dependencies.createCredentialManager
@@ -79,13 +82,14 @@ export function resetChannelAuthCommandDependenciesForTesting(): void {
79
82
  createChannelClient = async (accountCookie: string, sessionCookie?: string): Promise<ChannelClientLike> =>
80
83
  new ChannelClient().login({ accountCookie, sessionCookie })
81
84
  createCredentialManager = (): ChannelCredentialManagerLike => new ChannelCredentialManager()
82
- createTokenExtractor = (): ChannelTokenExtractorLike => new ChannelTokenExtractor()
85
+ createTokenExtractor = (browserProfile?: string[]): ChannelTokenExtractorLike =>
86
+ new ChannelTokenExtractor(undefined, browserProfile)
83
87
  }
84
88
 
85
89
  export async function extractAction(options: ActionOptions = {}): Promise<ExtractResult | ErrorResult> {
86
90
  try {
87
91
  const credManager = options._credManager ?? createCredentialManager()
88
- const extractor = createTokenExtractor()
92
+ const extractor = createTokenExtractor(options.browserProfile)
89
93
  const extracted = await extractor.extract()
90
94
 
91
95
  if (extracted.length === 0) {
@@ -270,7 +274,13 @@ export function createAuthCommand(): Command {
270
274
  new Command('extract')
271
275
  .description('Extract cookies from Channel Talk desktop app or a supported Chromium browser')
272
276
  .option('--pretty', 'Pretty print JSON output')
273
- .action(async (opts: { pretty?: boolean }) => {
277
+ .option(
278
+ '--browser-profile <path>',
279
+ 'Additional Chromium profile/user-data directory to scan (repeatable, comma-separated supported)',
280
+ collectBrowserProfileOption,
281
+ [],
282
+ )
283
+ .action(async (opts: { pretty?: boolean; browserProfile?: string[] }) => {
274
284
  cliOutput(await extractAction(opts), opts.pretty)
275
285
  }),
276
286
  )
@@ -12,6 +12,7 @@ import {
12
12
  discoverBrowserProfileDirs,
13
13
  findLocalStatePath,
14
14
  getBrowserBasePath,
15
+ getAgentBrowserProfileDirs,
15
16
  } from '@/shared/chromium'
16
17
  import type { KeychainVariant } from '@/shared/chromium'
17
18
 
@@ -29,9 +30,11 @@ export class ChannelTokenExtractor {
29
30
  private platform: NodeJS.Platform
30
31
  private decryptor: ChromiumCookieDecryptor
31
32
  private cookieReader: ChromiumCookieReader
33
+ private customBrowserProfileDirs: string[]
32
34
 
33
- constructor(platform?: NodeJS.Platform) {
35
+ constructor(platform?: NodeJS.Platform, customBrowserProfileDirs?: string[]) {
34
36
  this.platform = platform ?? process.platform
37
+ this.customBrowserProfileDirs = customBrowserProfileDirs ?? []
35
38
  this.cookieReader = new ChromiumCookieReader()
36
39
  this.decryptor = new ChromiumCookieDecryptor({ platform: this.platform })
37
40
  }
@@ -94,6 +97,11 @@ export class ChannelTokenExtractor {
94
97
  }
95
98
  }
96
99
 
100
+ for (const profileDir of getAgentBrowserProfileDirs({ customProfileDirs: this.customBrowserProfileDirs })) {
101
+ paths.push(join(profileDir, 'Cookies'))
102
+ paths.push(join(profileDir, 'Network', 'Cookies'))
103
+ }
104
+
97
105
  return paths
98
106
  }
99
107
 
@@ -105,16 +113,27 @@ export class ChannelTokenExtractor {
105
113
  const results: ExtractedChannelToken[] = []
106
114
  const seenAccounts = new Set<string>()
107
115
 
116
+ if (this.customBrowserProfileDirs.length > 0) {
117
+ for (const browserResult of await this.extractAllFromBrowserPaths()) {
118
+ if (!seenAccounts.has(browserResult.accountCookie)) {
119
+ seenAccounts.add(browserResult.accountCookie)
120
+ results.push(browserResult)
121
+ }
122
+ }
123
+ }
124
+
108
125
  const desktopResult = await this.extractFromDesktopApp()
109
126
  if (desktopResult && !seenAccounts.has(desktopResult.accountCookie)) {
110
127
  seenAccounts.add(desktopResult.accountCookie)
111
128
  results.push(desktopResult)
112
129
  }
113
130
 
114
- for (const browserResult of await this.extractAllFromBrowserPaths()) {
115
- if (!seenAccounts.has(browserResult.accountCookie)) {
116
- seenAccounts.add(browserResult.accountCookie)
117
- results.push(browserResult)
131
+ if (this.customBrowserProfileDirs.length === 0) {
132
+ for (const browserResult of await this.extractAllFromBrowserPaths()) {
133
+ if (!seenAccounts.has(browserResult.accountCookie)) {
134
+ seenAccounts.add(browserResult.accountCookie)
135
+ results.push(browserResult)
136
+ }
118
137
  }
119
138
  }
120
139
 
@@ -23,6 +23,15 @@ program
23
23
  .option('--pretty', 'Pretty-print JSON output')
24
24
  .option('--workspace <id>', 'Workspace ID to use')
25
25
  .option('--bot <name>', 'Bot name to use for sending messages')
26
+ .hook('preAction', (thisCmd, actionCmd) => {
27
+ for (const [key, value] of Object.entries(thisCmd.opts())) {
28
+ if (value === undefined) continue
29
+ const source = actionCmd.getOptionValueSource(key)
30
+ if (source === undefined || source === 'default') {
31
+ actionCmd.setOptionValue(key, value)
32
+ }
33
+ }
34
+ })
26
35
 
27
36
  program.addCommand(authCommand)
28
37
  program.addCommand(whoamiCommand)
@@ -1,5 +1,6 @@
1
1
  import { Command } from 'commander'
2
2
 
3
+ import { cliOutput } from '@/shared/utils/cli-output'
3
4
  import { formatOutput } from '@/shared/utils/output'
4
5
 
5
6
  import { ChannelBotClient } from '../client'
@@ -158,11 +159,6 @@ export async function botAction(name: string, options: ActionOptions): Promise<A
158
159
  }
159
160
  }
160
161
 
161
- function cliOutput(result: ActionResult, pretty?: boolean, exitOnError = true): void {
162
- console.log(formatOutput(result, pretty))
163
- if (result.error && exitOnError) process.exit(1)
164
- }
165
-
166
162
  export const authCommand = new Command('auth')
167
163
  .description('Authentication commands')
168
164
  .addCommand(