agent-messenger 2.7.0 → 2.9.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 (553) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/.github/workflows/ci.yml +6 -0
  3. package/.oxfmtrc.json +13 -1
  4. package/.oxlintrc.json +10 -1
  5. package/README.md +1 -12
  6. package/dist/package.json +59 -58
  7. package/dist/src/platforms/channeltalk/client.d.ts.map +1 -1
  8. package/dist/src/platforms/channeltalk/client.js +2 -2
  9. package/dist/src/platforms/channeltalk/client.js.map +1 -1
  10. package/dist/src/platforms/channeltalk/commands/auth.d.ts.map +1 -1
  11. package/dist/src/platforms/channeltalk/commands/auth.js.map +1 -1
  12. package/dist/src/platforms/channeltalk/commands/message.d.ts.map +1 -1
  13. package/dist/src/platforms/channeltalk/commands/message.js.map +1 -1
  14. package/dist/src/platforms/channeltalk/commands/snapshot.d.ts +4 -2
  15. package/dist/src/platforms/channeltalk/commands/snapshot.d.ts.map +1 -1
  16. package/dist/src/platforms/channeltalk/commands/snapshot.js +86 -31
  17. package/dist/src/platforms/channeltalk/commands/snapshot.js.map +1 -1
  18. package/dist/src/platforms/channeltalk/ensure-auth.d.ts.map +1 -1
  19. package/dist/src/platforms/channeltalk/ensure-auth.js.map +1 -1
  20. package/dist/src/platforms/channeltalk/token-extractor.d.ts +9 -23
  21. package/dist/src/platforms/channeltalk/token-extractor.d.ts.map +1 -1
  22. package/dist/src/platforms/channeltalk/token-extractor.js +109 -341
  23. package/dist/src/platforms/channeltalk/token-extractor.js.map +1 -1
  24. package/dist/src/platforms/channeltalkbot/client.d.ts +1 -1
  25. package/dist/src/platforms/channeltalkbot/client.d.ts.map +1 -1
  26. package/dist/src/platforms/channeltalkbot/client.js +4 -4
  27. package/dist/src/platforms/channeltalkbot/client.js.map +1 -1
  28. package/dist/src/platforms/channeltalkbot/commands/auth.d.ts.map +1 -1
  29. package/dist/src/platforms/channeltalkbot/commands/auth.js +4 -1
  30. package/dist/src/platforms/channeltalkbot/commands/auth.js.map +1 -1
  31. package/dist/src/platforms/channeltalkbot/commands/shared.d.ts.map +1 -1
  32. package/dist/src/platforms/channeltalkbot/commands/shared.js.map +1 -1
  33. package/dist/src/platforms/channeltalkbot/commands/snapshot.d.ts +3 -1
  34. package/dist/src/platforms/channeltalkbot/commands/snapshot.d.ts.map +1 -1
  35. package/dist/src/platforms/channeltalkbot/commands/snapshot.js +110 -60
  36. package/dist/src/platforms/channeltalkbot/commands/snapshot.js.map +1 -1
  37. package/dist/src/platforms/discord/commands/auth.js.map +1 -1
  38. package/dist/src/platforms/discord/commands/snapshot.d.ts +1 -0
  39. package/dist/src/platforms/discord/commands/snapshot.d.ts.map +1 -1
  40. package/dist/src/platforms/discord/commands/snapshot.js +48 -34
  41. package/dist/src/platforms/discord/commands/snapshot.js.map +1 -1
  42. package/dist/src/platforms/discord/commands/whoami.d.ts.map +1 -1
  43. package/dist/src/platforms/discord/commands/whoami.js.map +1 -1
  44. package/dist/src/platforms/discord/token-extractor.d.ts +2 -10
  45. package/dist/src/platforms/discord/token-extractor.d.ts.map +1 -1
  46. package/dist/src/platforms/discord/token-extractor.js +38 -172
  47. package/dist/src/platforms/discord/token-extractor.js.map +1 -1
  48. package/dist/src/platforms/discordbot/client.d.ts.map +1 -1
  49. package/dist/src/platforms/discordbot/client.js.map +1 -1
  50. package/dist/src/platforms/discordbot/commands/snapshot.d.ts +2 -0
  51. package/dist/src/platforms/discordbot/commands/snapshot.d.ts.map +1 -1
  52. package/dist/src/platforms/discordbot/commands/snapshot.js +46 -34
  53. package/dist/src/platforms/discordbot/commands/snapshot.js.map +1 -1
  54. package/dist/src/platforms/instagram/cli.d.ts.map +1 -1
  55. package/dist/src/platforms/instagram/cli.js +1 -4
  56. package/dist/src/platforms/instagram/cli.js.map +1 -1
  57. package/dist/src/platforms/instagram/client.d.ts.map +1 -1
  58. package/dist/src/platforms/instagram/client.js +8 -7
  59. package/dist/src/platforms/instagram/client.js.map +1 -1
  60. package/dist/src/platforms/instagram/commands/auth.d.ts.map +1 -1
  61. package/dist/src/platforms/instagram/commands/auth.js.map +1 -1
  62. package/dist/src/platforms/instagram/commands/chat.d.ts.map +1 -1
  63. package/dist/src/platforms/instagram/commands/chat.js.map +1 -1
  64. package/dist/src/platforms/instagram/commands/message.d.ts.map +1 -1
  65. package/dist/src/platforms/instagram/commands/message.js.map +1 -1
  66. package/dist/src/platforms/instagram/commands/shared.d.ts.map +1 -1
  67. package/dist/src/platforms/instagram/commands/shared.js.map +1 -1
  68. package/dist/src/platforms/instagram/credential-manager.d.ts.map +1 -1
  69. package/dist/src/platforms/instagram/credential-manager.js +1 -1
  70. package/dist/src/platforms/instagram/credential-manager.js.map +1 -1
  71. package/dist/src/platforms/instagram/ensure-auth.d.ts.map +1 -1
  72. package/dist/src/platforms/instagram/ensure-auth.js.map +1 -1
  73. package/dist/src/platforms/instagram/token-extractor.d.ts +7 -19
  74. package/dist/src/platforms/instagram/token-extractor.d.ts.map +1 -1
  75. package/dist/src/platforms/instagram/token-extractor.js +44 -270
  76. package/dist/src/platforms/instagram/token-extractor.js.map +1 -1
  77. package/dist/src/platforms/instagram/types.d.ts.map +1 -1
  78. package/dist/src/platforms/instagram/types.js +4 -2
  79. package/dist/src/platforms/instagram/types.js.map +1 -1
  80. package/dist/src/platforms/kakaotalk/auth/kakao-login.d.ts.map +1 -1
  81. package/dist/src/platforms/kakaotalk/auth/kakao-login.js +18 -4
  82. package/dist/src/platforms/kakaotalk/auth/kakao-login.js.map +1 -1
  83. package/dist/src/platforms/kakaotalk/client.d.ts.map +1 -1
  84. package/dist/src/platforms/kakaotalk/client.js +3 -3
  85. package/dist/src/platforms/kakaotalk/client.js.map +1 -1
  86. package/dist/src/platforms/kakaotalk/commands/auth.d.ts.map +1 -1
  87. package/dist/src/platforms/kakaotalk/commands/auth.js +15 -9
  88. package/dist/src/platforms/kakaotalk/commands/auth.js.map +1 -1
  89. package/dist/src/platforms/kakaotalk/commands/shared.d.ts.map +1 -1
  90. package/dist/src/platforms/kakaotalk/commands/shared.js.map +1 -1
  91. package/dist/src/platforms/kakaotalk/protocol/connection.d.ts.map +1 -1
  92. package/dist/src/platforms/kakaotalk/protocol/connection.js.map +1 -1
  93. package/dist/src/platforms/kakaotalk/protocol/crypto.js +1 -1
  94. package/dist/src/platforms/kakaotalk/protocol/crypto.js.map +1 -1
  95. package/dist/src/platforms/kakaotalk/protocol/session.d.ts.map +1 -1
  96. package/dist/src/platforms/kakaotalk/protocol/session.js +1 -3
  97. package/dist/src/platforms/kakaotalk/protocol/session.js.map +1 -1
  98. package/dist/src/platforms/kakaotalk/token-extractor.js +5 -2
  99. package/dist/src/platforms/kakaotalk/token-extractor.js.map +1 -1
  100. package/dist/src/platforms/kakaotalk/types.d.ts.map +1 -1
  101. package/dist/src/platforms/kakaotalk/types.js +4 -2
  102. package/dist/src/platforms/kakaotalk/types.js.map +1 -1
  103. package/dist/src/platforms/line/cli.d.ts.map +1 -1
  104. package/dist/src/platforms/line/cli.js +1 -4
  105. package/dist/src/platforms/line/cli.js.map +1 -1
  106. package/dist/src/platforms/line/client.d.ts.map +1 -1
  107. package/dist/src/platforms/line/client.js +5 -13
  108. package/dist/src/platforms/line/client.js.map +1 -1
  109. package/dist/src/platforms/line/commands/chat.d.ts.map +1 -1
  110. package/dist/src/platforms/line/commands/chat.js.map +1 -1
  111. package/dist/src/platforms/line/commands/message.d.ts.map +1 -1
  112. package/dist/src/platforms/line/commands/message.js.map +1 -1
  113. package/dist/src/platforms/line/listener.js +1 -1
  114. package/dist/src/platforms/line/listener.js.map +1 -1
  115. package/dist/src/platforms/slack/cli.d.ts.map +1 -1
  116. package/dist/src/platforms/slack/cli.js.map +1 -1
  117. package/dist/src/platforms/slack/client-mappers.d.ts +14 -0
  118. package/dist/src/platforms/slack/client-mappers.d.ts.map +1 -0
  119. package/dist/src/platforms/slack/client-mappers.js +245 -0
  120. package/dist/src/platforms/slack/client-mappers.js.map +1 -0
  121. package/dist/src/platforms/slack/client.d.ts +0 -1
  122. package/dist/src/platforms/slack/client.d.ts.map +1 -1
  123. package/dist/src/platforms/slack/client.js +41 -455
  124. package/dist/src/platforms/slack/client.js.map +1 -1
  125. package/dist/src/platforms/slack/commands/channel.d.ts.map +1 -1
  126. package/dist/src/platforms/slack/commands/channel.js.map +1 -1
  127. package/dist/src/platforms/slack/commands/emoji.d.ts.map +1 -1
  128. package/dist/src/platforms/slack/commands/emoji.js +1 -3
  129. package/dist/src/platforms/slack/commands/emoji.js.map +1 -1
  130. package/dist/src/platforms/slack/commands/message.d.ts.map +1 -1
  131. package/dist/src/platforms/slack/commands/message.js.map +1 -1
  132. package/dist/src/platforms/slack/commands/reminder.d.ts.map +1 -1
  133. package/dist/src/platforms/slack/commands/reminder.js.map +1 -1
  134. package/dist/src/platforms/slack/commands/snapshot.d.ts.map +1 -1
  135. package/dist/src/platforms/slack/commands/snapshot.js +75 -55
  136. package/dist/src/platforms/slack/commands/snapshot.js.map +1 -1
  137. package/dist/src/platforms/slack/commands/user.d.ts.map +1 -1
  138. package/dist/src/platforms/slack/commands/user.js.map +1 -1
  139. package/dist/src/platforms/slack/commands/usergroup.d.ts.map +1 -1
  140. package/dist/src/platforms/slack/commands/usergroup.js.map +1 -1
  141. package/dist/src/platforms/slack/commands/whoami.d.ts.map +1 -1
  142. package/dist/src/platforms/slack/commands/whoami.js.map +1 -1
  143. package/dist/src/platforms/slack/token-extractor.d.ts +2 -6
  144. package/dist/src/platforms/slack/token-extractor.d.ts.map +1 -1
  145. package/dist/src/platforms/slack/token-extractor.js +35 -229
  146. package/dist/src/platforms/slack/token-extractor.js.map +1 -1
  147. package/dist/src/platforms/slackbot/cli.d.ts.map +1 -1
  148. package/dist/src/platforms/slackbot/cli.js +1 -1
  149. package/dist/src/platforms/slackbot/cli.js.map +1 -1
  150. package/dist/src/platforms/teams/client.d.ts.map +1 -1
  151. package/dist/src/platforms/teams/client.js +1 -1
  152. package/dist/src/platforms/teams/client.js.map +1 -1
  153. package/dist/src/platforms/teams/commands/auth.d.ts.map +1 -1
  154. package/dist/src/platforms/teams/commands/auth.js +4 -1
  155. package/dist/src/platforms/teams/commands/auth.js.map +1 -1
  156. package/dist/src/platforms/teams/commands/snapshot.d.ts +1 -0
  157. package/dist/src/platforms/teams/commands/snapshot.d.ts.map +1 -1
  158. package/dist/src/platforms/teams/commands/snapshot.js +44 -31
  159. package/dist/src/platforms/teams/commands/snapshot.js.map +1 -1
  160. package/dist/src/platforms/teams/commands/whoami.d.ts.map +1 -1
  161. package/dist/src/platforms/teams/commands/whoami.js.map +1 -1
  162. package/dist/src/platforms/teams/token-extractor.d.ts +6 -18
  163. package/dist/src/platforms/teams/token-extractor.d.ts.map +1 -1
  164. package/dist/src/platforms/teams/token-extractor.js +71 -324
  165. package/dist/src/platforms/teams/token-extractor.js.map +1 -1
  166. package/dist/src/platforms/telegram/cli.d.ts.map +1 -1
  167. package/dist/src/platforms/telegram/cli.js +1 -4
  168. package/dist/src/platforms/telegram/cli.js.map +1 -1
  169. package/dist/src/platforms/telegram/client.d.ts.map +1 -1
  170. package/dist/src/platforms/telegram/client.js.map +1 -1
  171. package/dist/src/platforms/telegram/commands/auth.d.ts.map +1 -1
  172. package/dist/src/platforms/telegram/commands/auth.js +1 -1
  173. package/dist/src/platforms/telegram/commands/auth.js.map +1 -1
  174. package/dist/src/platforms/telegram/commands/chat.d.ts.map +1 -1
  175. package/dist/src/platforms/telegram/commands/chat.js.map +1 -1
  176. package/dist/src/platforms/telegram/commands/message.d.ts.map +1 -1
  177. package/dist/src/platforms/telegram/commands/message.js.map +1 -1
  178. package/dist/src/platforms/telegram/commands/whoami.js +1 -1
  179. package/dist/src/platforms/telegram/commands/whoami.js.map +1 -1
  180. package/dist/src/platforms/telegram/credential-manager.d.ts.map +1 -1
  181. package/dist/src/platforms/telegram/credential-manager.js +6 -2
  182. package/dist/src/platforms/telegram/credential-manager.js.map +1 -1
  183. package/dist/src/platforms/telegram/my-telegram-org.js.map +1 -1
  184. package/dist/src/platforms/webex/cli.d.ts.map +1 -1
  185. package/dist/src/platforms/webex/cli.js +1 -4
  186. package/dist/src/platforms/webex/cli.js.map +1 -1
  187. package/dist/src/platforms/webex/client.d.ts.map +1 -1
  188. package/dist/src/platforms/webex/client.js +3 -7
  189. package/dist/src/platforms/webex/client.js.map +1 -1
  190. package/dist/src/platforms/webex/commands/auth.d.ts.map +1 -1
  191. package/dist/src/platforms/webex/commands/auth.js +1 -3
  192. package/dist/src/platforms/webex/commands/auth.js.map +1 -1
  193. package/dist/src/platforms/webex/commands/member.d.ts.map +1 -1
  194. package/dist/src/platforms/webex/commands/member.js +1 -3
  195. package/dist/src/platforms/webex/commands/member.js.map +1 -1
  196. package/dist/src/platforms/webex/commands/message.d.ts.map +1 -1
  197. package/dist/src/platforms/webex/commands/message.js.map +1 -1
  198. package/dist/src/platforms/webex/commands/snapshot.d.ts +1 -0
  199. package/dist/src/platforms/webex/commands/snapshot.d.ts.map +1 -1
  200. package/dist/src/platforms/webex/commands/snapshot.js +14 -7
  201. package/dist/src/platforms/webex/commands/snapshot.js.map +1 -1
  202. package/dist/src/platforms/webex/commands/space.d.ts.map +1 -1
  203. package/dist/src/platforms/webex/commands/space.js.map +1 -1
  204. package/dist/src/platforms/webex/commands/whoami.d.ts.map +1 -1
  205. package/dist/src/platforms/webex/commands/whoami.js.map +1 -1
  206. package/dist/src/platforms/webex/credential-manager.d.ts.map +1 -1
  207. package/dist/src/platforms/webex/credential-manager.js.map +1 -1
  208. package/dist/src/platforms/webex/ensure-auth.d.ts.map +1 -1
  209. package/dist/src/platforms/webex/ensure-auth.js +1 -3
  210. package/dist/src/platforms/webex/ensure-auth.js.map +1 -1
  211. package/dist/src/platforms/webex/index.d.ts +1 -1
  212. package/dist/src/platforms/webex/index.d.ts.map +1 -1
  213. package/dist/src/platforms/webex/index.js.map +1 -1
  214. package/dist/src/platforms/webex/markdown-to-html.js.map +1 -1
  215. package/dist/src/platforms/webex/token-extractor.d.ts.map +1 -1
  216. package/dist/src/platforms/webex/token-extractor.js +5 -14
  217. package/dist/src/platforms/webex/token-extractor.js.map +1 -1
  218. package/dist/src/platforms/wechatbot/client.d.ts.map +1 -1
  219. package/dist/src/platforms/wechatbot/client.js.map +1 -1
  220. package/dist/src/platforms/wechatbot/commands/message.d.ts.map +1 -1
  221. package/dist/src/platforms/wechatbot/commands/message.js.map +1 -1
  222. package/dist/src/platforms/whatsapp/cli.d.ts.map +1 -1
  223. package/dist/src/platforms/whatsapp/cli.js +1 -4
  224. package/dist/src/platforms/whatsapp/cli.js.map +1 -1
  225. package/dist/src/platforms/whatsapp/commands/chat.d.ts.map +1 -1
  226. package/dist/src/platforms/whatsapp/commands/chat.js.map +1 -1
  227. package/dist/src/platforms/whatsapp/commands/message.d.ts.map +1 -1
  228. package/dist/src/platforms/whatsapp/commands/message.js.map +1 -1
  229. package/dist/src/platforms/whatsapp/commands/shared.d.ts.map +1 -1
  230. package/dist/src/platforms/whatsapp/commands/shared.js.map +1 -1
  231. package/dist/src/platforms/whatsapp/credential-manager.d.ts.map +1 -1
  232. package/dist/src/platforms/whatsapp/credential-manager.js +1 -1
  233. package/dist/src/platforms/whatsapp/credential-manager.js.map +1 -1
  234. package/dist/src/platforms/whatsapp/ensure-auth.d.ts.map +1 -1
  235. package/dist/src/platforms/whatsapp/ensure-auth.js.map +1 -1
  236. package/dist/src/platforms/whatsappbot/client.d.ts.map +1 -1
  237. package/dist/src/platforms/whatsappbot/client.js +2 -2
  238. package/dist/src/platforms/whatsappbot/client.js.map +1 -1
  239. package/dist/src/platforms/whatsappbot/commands/auth.d.ts.map +1 -1
  240. package/dist/src/platforms/whatsappbot/commands/auth.js +4 -1
  241. package/dist/src/platforms/whatsappbot/commands/auth.js.map +1 -1
  242. package/dist/src/platforms/whatsappbot/commands/message.d.ts.map +1 -1
  243. package/dist/src/platforms/whatsappbot/commands/message.js.map +1 -1
  244. package/dist/src/platforms/whatsappbot/commands/shared.d.ts.map +1 -1
  245. package/dist/src/platforms/whatsappbot/commands/shared.js.map +1 -1
  246. package/dist/src/shared/chromium/browsers.d.ts +7 -0
  247. package/dist/src/shared/chromium/browsers.d.ts.map +1 -0
  248. package/dist/src/shared/chromium/browsers.js +89 -0
  249. package/dist/src/shared/chromium/browsers.js.map +1 -0
  250. package/dist/src/shared/chromium/cookie-reader.d.ts +20 -0
  251. package/dist/src/shared/chromium/cookie-reader.d.ts.map +1 -0
  252. package/dist/src/shared/chromium/cookie-reader.js +99 -0
  253. package/dist/src/shared/chromium/cookie-reader.js.map +1 -0
  254. package/dist/src/shared/chromium/decryptor.d.ts +42 -0
  255. package/dist/src/shared/chromium/decryptor.d.ts.map +1 -0
  256. package/dist/src/shared/chromium/decryptor.js +205 -0
  257. package/dist/src/shared/chromium/decryptor.js.map +1 -0
  258. package/dist/src/shared/chromium/index.d.ts +6 -0
  259. package/dist/src/shared/chromium/index.d.ts.map +1 -0
  260. package/dist/src/shared/chromium/index.js +4 -0
  261. package/dist/src/shared/chromium/index.js.map +1 -0
  262. package/dist/src/shared/chromium/types.d.ts +11 -0
  263. package/dist/src/shared/chromium/types.d.ts.map +1 -0
  264. package/dist/src/shared/chromium/types.js +2 -0
  265. package/dist/src/shared/chromium/types.js.map +1 -0
  266. package/dist/src/shared/utils/derived-key-cache.d.ts +1 -1
  267. package/dist/src/shared/utils/derived-key-cache.d.ts.map +1 -1
  268. package/dist/src/shared/utils/linux-keyring.js +4 -1
  269. package/dist/src/shared/utils/linux-keyring.js.map +1 -1
  270. package/dist/src/tui/adapters/kakaotalk-adapter.d.ts.map +1 -1
  271. package/dist/src/tui/adapters/kakaotalk-adapter.js +6 -1
  272. package/dist/src/tui/adapters/kakaotalk-adapter.js.map +1 -1
  273. package/dist/src/tui/adapters/telegram-adapter.js +1 -1
  274. package/dist/src/tui/adapters/telegram-adapter.js.map +1 -1
  275. package/dist/src/tui/adapters/webex-adapter.js +1 -1
  276. package/dist/src/tui/adapters/webex-adapter.js.map +1 -1
  277. package/dist/src/tui/app.d.ts.map +1 -1
  278. package/dist/src/tui/app.js +112 -23
  279. package/dist/src/tui/app.js.map +1 -1
  280. package/dist/src/tui/utils.d.ts.map +1 -1
  281. package/dist/src/tui/utils.js +11 -13
  282. package/dist/src/tui/utils.js.map +1 -1
  283. package/dist/src/tui/views/channel-picker.d.ts.map +1 -1
  284. package/dist/src/tui/views/channel-picker.js.map +1 -1
  285. package/dist/src/tui/views/workspace-picker.d.ts.map +1 -1
  286. package/dist/src/tui/views/workspace-picker.js.map +1 -1
  287. package/docs/content/docs/agent-skills.mdx +0 -10
  288. package/docs/content/docs/cli/channeltalk.mdx +42 -30
  289. package/docs/content/docs/cli/channeltalkbot.mdx +23 -13
  290. package/docs/content/docs/cli/discord.mdx +23 -7
  291. package/docs/content/docs/cli/discordbot.mdx +23 -7
  292. package/docs/content/docs/cli/instagram.mdx +4 -4
  293. package/docs/content/docs/cli/kakaotalk.mdx +9 -8
  294. package/docs/content/docs/cli/line.mdx +14 -14
  295. package/docs/content/docs/cli/slack.mdx +24 -7
  296. package/docs/content/docs/cli/teams.mdx +24 -8
  297. package/docs/content/docs/cli/webex.mdx +34 -21
  298. package/docs/content/docs/cli/wechatbot.mdx +12 -11
  299. package/docs/content/docs/cli/whatsapp.mdx +5 -4
  300. package/docs/content/docs/cli/whatsappbot.mdx +11 -11
  301. package/docs/content/docs/index.mdx +7 -7
  302. package/docs/content/docs/meta.json +1 -9
  303. package/docs/content/docs/sdk/channeltalk.mdx +5 -6
  304. package/docs/content/docs/sdk/channeltalkbot.mdx +6 -12
  305. package/docs/content/docs/sdk/discord.mdx +36 -43
  306. package/docs/content/docs/sdk/instagram.mdx +18 -18
  307. package/docs/content/docs/sdk/kakaotalk.mdx +27 -18
  308. package/docs/content/docs/sdk/line.mdx +8 -13
  309. package/docs/content/docs/sdk/meta.json +14 -1
  310. package/docs/content/docs/sdk/slack.mdx +36 -42
  311. package/docs/content/docs/sdk/teams.mdx +2 -8
  312. package/docs/content/docs/sdk/webex.mdx +2 -12
  313. package/docs/content/docs/sdk/wechatbot.mdx +1 -5
  314. package/docs/content/docs/sdk/whatsapp.mdx +10 -19
  315. package/docs/content/docs/sdk/whatsappbot.mdx +2 -10
  316. package/docs/content/docs/tui.mdx +23 -23
  317. package/docs/src/app/page.tsx +353 -108
  318. package/e2e/channeltalkbot.e2e.test.ts +1 -5
  319. package/e2e/config.ts +6 -2
  320. package/package.json +59 -58
  321. package/scripts/prepublish.ts +1 -3
  322. package/skills/agent-channeltalk/SKILL.md +19 -9
  323. package/skills/agent-channeltalk/references/common-patterns.md +10 -9
  324. package/skills/agent-channeltalkbot/SKILL.md +19 -9
  325. package/skills/agent-channeltalkbot/references/common-patterns.md +10 -9
  326. package/skills/agent-discord/SKILL.md +18 -9
  327. package/skills/agent-discord/references/common-patterns.md +8 -7
  328. package/skills/agent-discordbot/SKILL.md +18 -9
  329. package/skills/agent-instagram/SKILL.md +1 -1
  330. package/skills/agent-kakaotalk/SKILL.md +1 -1
  331. package/skills/agent-line/SKILL.md +1 -1
  332. package/skills/agent-slack/SKILL.md +19 -10
  333. package/skills/agent-slack/references/common-patterns.md +4 -7
  334. package/skills/agent-slackbot/SKILL.md +1 -1
  335. package/skills/agent-teams/SKILL.md +18 -9
  336. package/skills/agent-teams/references/common-patterns.md +9 -7
  337. package/skills/agent-telegram/SKILL.md +1 -1
  338. package/skills/agent-webex/SKILL.md +13 -4
  339. package/skills/agent-webex/references/common-patterns.md +8 -2
  340. package/skills/agent-wechatbot/SKILL.md +1 -1
  341. package/skills/agent-whatsapp/SKILL.md +1 -1
  342. package/skills/agent-whatsappbot/SKILL.md +1 -1
  343. package/src/platforms/channeltalk/client.test.ts +116 -29
  344. package/src/platforms/channeltalk/client.ts +26 -6
  345. package/src/platforms/channeltalk/commands/auth.test.ts +5 -5
  346. package/src/platforms/channeltalk/commands/auth.ts +19 -5
  347. package/src/platforms/channeltalk/commands/message.test.ts +2 -6
  348. package/src/platforms/channeltalk/commands/message.ts +5 -1
  349. package/src/platforms/channeltalk/commands/snapshot.test.ts +77 -30
  350. package/src/platforms/channeltalk/commands/snapshot.ts +112 -34
  351. package/src/platforms/channeltalk/ensure-auth.test.ts +20 -17
  352. package/src/platforms/channeltalk/ensure-auth.ts +6 -7
  353. package/src/platforms/channeltalk/index.ts +0 -1
  354. package/src/platforms/channeltalk/token-extractor.test.ts +33 -25
  355. package/src/platforms/channeltalk/token-extractor.ts +120 -372
  356. package/src/platforms/channeltalkbot/client.test.ts +1 -3
  357. package/src/platforms/channeltalkbot/client.ts +39 -13
  358. package/src/platforms/channeltalkbot/commands/auth.test.ts +3 -1
  359. package/src/platforms/channeltalkbot/commands/auth.ts +4 -1
  360. package/src/platforms/channeltalkbot/commands/bot.test.ts +13 -5
  361. package/src/platforms/channeltalkbot/commands/message.test.ts +12 -6
  362. package/src/platforms/channeltalkbot/commands/shared.ts +6 -2
  363. package/src/platforms/channeltalkbot/commands/snapshot.test.ts +43 -13
  364. package/src/platforms/channeltalkbot/commands/snapshot.ts +131 -64
  365. package/src/platforms/channeltalkbot/credential-manager.test.ts +1 -1
  366. package/src/platforms/channeltalkbot/index.test.ts +0 -2
  367. package/src/platforms/channeltalkbot/index.ts +0 -1
  368. package/src/platforms/discord/commands/auth.test.ts +6 -4
  369. package/src/platforms/discord/commands/auth.ts +14 -14
  370. package/src/platforms/discord/commands/snapshot.test.ts +1 -1
  371. package/src/platforms/discord/commands/snapshot.ts +58 -42
  372. package/src/platforms/discord/commands/whoami.test.ts +2 -4
  373. package/src/platforms/discord/commands/whoami.ts +2 -0
  374. package/src/platforms/discord/ensure-auth.test.ts +5 -3
  375. package/src/platforms/discord/index.ts +0 -1
  376. package/src/platforms/discord/listener.test.ts +7 -1
  377. package/src/platforms/discord/token-extractor.test.ts +18 -12
  378. package/src/platforms/discord/token-extractor.ts +46 -190
  379. package/src/platforms/discordbot/client.ts +1 -4
  380. package/src/platforms/discordbot/commands/auth.test.ts +3 -1
  381. package/src/platforms/discordbot/commands/channel.test.ts +3 -1
  382. package/src/platforms/discordbot/commands/message.test.ts +3 -1
  383. package/src/platforms/discordbot/commands/server.test.ts +3 -1
  384. package/src/platforms/discordbot/commands/snapshot.test.ts +43 -19
  385. package/src/platforms/discordbot/commands/snapshot.ts +54 -37
  386. package/src/platforms/discordbot/commands/thread.test.ts +3 -1
  387. package/src/platforms/discordbot/commands/user.test.ts +3 -1
  388. package/src/platforms/instagram/cli.ts +1 -4
  389. package/src/platforms/instagram/client.test.ts +3 -8
  390. package/src/platforms/instagram/client.ts +39 -34
  391. package/src/platforms/instagram/commands/auth.test.ts +13 -12
  392. package/src/platforms/instagram/commands/auth.ts +136 -71
  393. package/src/platforms/instagram/commands/chat.test.ts +21 -24
  394. package/src/platforms/instagram/commands/chat.ts +2 -0
  395. package/src/platforms/instagram/commands/message.test.ts +29 -24
  396. package/src/platforms/instagram/commands/message.ts +3 -4
  397. package/src/platforms/instagram/commands/shared.ts +2 -5
  398. package/src/platforms/instagram/commands/whoami.test.ts +4 -6
  399. package/src/platforms/instagram/credential-manager.ts +2 -6
  400. package/src/platforms/instagram/ensure-auth.test.ts +1 -4
  401. package/src/platforms/instagram/ensure-auth.ts +6 -3
  402. package/src/platforms/instagram/listener.test.ts +7 -3
  403. package/src/platforms/instagram/token-extractor.test.ts +4 -16
  404. package/src/platforms/instagram/token-extractor.ts +55 -309
  405. package/src/platforms/instagram/types.test.ts +2 -6
  406. package/src/platforms/instagram/types.ts +4 -2
  407. package/src/platforms/kakaotalk/auth/kakao-login.ts +30 -8
  408. package/src/platforms/kakaotalk/client.test.ts +37 -25
  409. package/src/platforms/kakaotalk/client.ts +23 -12
  410. package/src/platforms/kakaotalk/commands/auth.test.ts +6 -18
  411. package/src/platforms/kakaotalk/commands/auth.ts +101 -47
  412. package/src/platforms/kakaotalk/commands/chat.test.ts +8 -11
  413. package/src/platforms/kakaotalk/commands/message.test.ts +15 -24
  414. package/src/platforms/kakaotalk/commands/shared.ts +1 -0
  415. package/src/platforms/kakaotalk/commands/whoami.test.ts +6 -10
  416. package/src/platforms/kakaotalk/credential-manager.test.ts +1 -4
  417. package/src/platforms/kakaotalk/index.test.ts +1 -0
  418. package/src/platforms/kakaotalk/index.ts +0 -2
  419. package/src/platforms/kakaotalk/listener.test.ts +7 -1
  420. package/src/platforms/kakaotalk/protocol/connection.ts +4 -1
  421. package/src/platforms/kakaotalk/protocol/crypto.ts +1 -1
  422. package/src/platforms/kakaotalk/protocol/session.ts +12 -6
  423. package/src/platforms/kakaotalk/token-extractor.ts +5 -5
  424. package/src/platforms/kakaotalk/types.ts +8 -7
  425. package/src/platforms/line/cli.ts +1 -4
  426. package/src/platforms/line/client.ts +12 -20
  427. package/src/platforms/line/commands/auth.test.ts +2 -1
  428. package/src/platforms/line/commands/chat.test.ts +2 -1
  429. package/src/platforms/line/commands/chat.ts +1 -4
  430. package/src/platforms/line/commands/friend.test.ts +2 -1
  431. package/src/platforms/line/commands/message.test.ts +2 -1
  432. package/src/platforms/line/commands/message.ts +2 -9
  433. package/src/platforms/line/commands/whoami.test.ts +2 -1
  434. package/src/platforms/line/credential-manager.test.ts +1 -2
  435. package/src/platforms/line/index.test.ts +1 -0
  436. package/src/platforms/line/listener.ts +1 -1
  437. package/src/platforms/line/types.test.ts +1 -0
  438. package/src/platforms/slack/cli.ts +3 -1
  439. package/src/platforms/slack/client-mappers.ts +297 -0
  440. package/src/platforms/slack/client.test.ts +532 -17
  441. package/src/platforms/slack/client.ts +69 -458
  442. package/src/platforms/slack/commands/channel.ts +1 -4
  443. package/src/platforms/slack/commands/emoji.test.ts +6 -4
  444. package/src/platforms/slack/commands/emoji.ts +20 -22
  445. package/src/platforms/slack/commands/message.ts +6 -1
  446. package/src/platforms/slack/commands/pin.test.ts +14 -12
  447. package/src/platforms/slack/commands/reminder.ts +7 -6
  448. package/src/platforms/slack/commands/snapshot.test.ts +63 -8
  449. package/src/platforms/slack/commands/snapshot.ts +98 -66
  450. package/src/platforms/slack/commands/user.ts +6 -1
  451. package/src/platforms/slack/commands/usergroup.test.ts +3 -3
  452. package/src/platforms/slack/commands/usergroup.ts +10 -7
  453. package/src/platforms/slack/commands/whoami.test.ts +1 -1
  454. package/src/platforms/slack/commands/whoami.ts +2 -0
  455. package/src/platforms/slack/index.ts +0 -2
  456. package/src/platforms/slack/listener.test.ts +1 -0
  457. package/src/platforms/slack/token-extractor.test.ts +7 -12
  458. package/src/platforms/slack/token-extractor.ts +47 -255
  459. package/src/platforms/slackbot/cli.ts +8 -1
  460. package/src/platforms/slackbot/commands/auth.test.ts +3 -1
  461. package/src/platforms/teams/client.ts +1 -1
  462. package/src/platforms/teams/commands/auth.test.ts +1 -1
  463. package/src/platforms/teams/commands/auth.ts +4 -1
  464. package/src/platforms/teams/commands/snapshot.test.ts +1 -1
  465. package/src/platforms/teams/commands/snapshot.ts +53 -38
  466. package/src/platforms/teams/commands/whoami.test.ts +2 -4
  467. package/src/platforms/teams/commands/whoami.ts +2 -0
  468. package/src/platforms/teams/index.ts +0 -1
  469. package/src/platforms/teams/token-extractor.ts +82 -350
  470. package/src/platforms/telegram/app-config.test.ts +1 -0
  471. package/src/platforms/telegram/chat-utils.test.ts +5 -1
  472. package/src/platforms/telegram/cli.ts +2 -4
  473. package/src/platforms/telegram/client.test.ts +16 -3
  474. package/src/platforms/telegram/client.ts +14 -4
  475. package/src/platforms/telegram/commands/auth.test.ts +1 -0
  476. package/src/platforms/telegram/commands/auth.ts +3 -4
  477. package/src/platforms/telegram/commands/chat.test.ts +2 -5
  478. package/src/platforms/telegram/commands/chat.ts +1 -0
  479. package/src/platforms/telegram/commands/message.test.ts +2 -5
  480. package/src/platforms/telegram/commands/message.ts +1 -0
  481. package/src/platforms/telegram/commands/shared.test.ts +1 -0
  482. package/src/platforms/telegram/commands/whoami.test.ts +5 -7
  483. package/src/platforms/telegram/commands/whoami.ts +1 -1
  484. package/src/platforms/telegram/credential-manager.test.ts +1 -0
  485. package/src/platforms/telegram/credential-manager.ts +11 -2
  486. package/src/platforms/telegram/my-telegram-org.ts +6 -2
  487. package/src/platforms/telegram/types.test.ts +1 -0
  488. package/src/platforms/webex/app-config.test.ts +1 -0
  489. package/src/platforms/webex/cli.ts +1 -4
  490. package/src/platforms/webex/client.test.ts +4 -12
  491. package/src/platforms/webex/client.ts +14 -52
  492. package/src/platforms/webex/commands/auth.test.ts +7 -1
  493. package/src/platforms/webex/commands/auth.ts +12 -15
  494. package/src/platforms/webex/commands/member.test.ts +1 -3
  495. package/src/platforms/webex/commands/member.ts +14 -19
  496. package/src/platforms/webex/commands/message.ts +4 -15
  497. package/src/platforms/webex/commands/snapshot.test.ts +42 -4
  498. package/src/platforms/webex/commands/snapshot.ts +19 -11
  499. package/src/platforms/webex/commands/space.test.ts +3 -3
  500. package/src/platforms/webex/commands/space.ts +2 -9
  501. package/src/platforms/webex/commands/whoami.test.ts +12 -5
  502. package/src/platforms/webex/commands/whoami.ts +2 -0
  503. package/src/platforms/webex/credential-manager.ts +11 -2
  504. package/src/platforms/webex/ensure-auth.ts +1 -3
  505. package/src/platforms/webex/index.ts +1 -7
  506. package/src/platforms/webex/markdown-to-html.test.ts +6 -18
  507. package/src/platforms/webex/markdown-to-html.ts +8 -8
  508. package/src/platforms/webex/token-extractor.ts +6 -29
  509. package/src/platforms/wechatbot/client.test.ts +6 -2
  510. package/src/platforms/wechatbot/client.ts +6 -1
  511. package/src/platforms/wechatbot/commands/auth.test.ts +3 -7
  512. package/src/platforms/wechatbot/commands/message.test.ts +1 -4
  513. package/src/platforms/wechatbot/commands/message.ts +5 -1
  514. package/src/platforms/wechatbot/commands/template.test.ts +1 -4
  515. package/src/platforms/wechatbot/commands/user.test.ts +2 -7
  516. package/src/platforms/whatsapp/cli.ts +1 -4
  517. package/src/platforms/whatsapp/commands/auth.test.ts +19 -22
  518. package/src/platforms/whatsapp/commands/chat.test.ts +21 -24
  519. package/src/platforms/whatsapp/commands/chat.ts +2 -0
  520. package/src/platforms/whatsapp/commands/message.test.ts +22 -24
  521. package/src/platforms/whatsapp/commands/message.ts +3 -5
  522. package/src/platforms/whatsapp/commands/shared.ts +2 -5
  523. package/src/platforms/whatsapp/commands/whoami.test.ts +2 -2
  524. package/src/platforms/whatsapp/credential-manager.ts +2 -6
  525. package/src/platforms/whatsapp/ensure-auth.test.ts +1 -4
  526. package/src/platforms/whatsapp/ensure-auth.ts +14 -6
  527. package/src/platforms/whatsapp/index.ts +0 -2
  528. package/src/platforms/whatsappbot/client.test.ts +13 -7
  529. package/src/platforms/whatsappbot/client.ts +18 -4
  530. package/src/platforms/whatsappbot/commands/auth.ts +4 -1
  531. package/src/platforms/whatsappbot/commands/message.test.ts +12 -2
  532. package/src/platforms/whatsappbot/commands/message.ts +16 -3
  533. package/src/platforms/whatsappbot/commands/shared.ts +3 -1
  534. package/src/platforms/whatsappbot/commands/whoami.test.ts +1 -3
  535. package/src/platforms/whatsappbot/index.ts +0 -2
  536. package/src/shared/chromium/browsers.test.ts +274 -0
  537. package/src/shared/chromium/browsers.ts +86 -0
  538. package/src/shared/chromium/cookie-reader.test.ts +274 -0
  539. package/src/shared/chromium/cookie-reader.ts +111 -0
  540. package/src/shared/chromium/decryptor.test.ts +449 -0
  541. package/src/shared/chromium/decryptor.ts +227 -0
  542. package/src/shared/chromium/index.ts +11 -0
  543. package/src/shared/chromium/types.ts +11 -0
  544. package/src/shared/utils/derived-key-cache.ts +1 -1
  545. package/src/shared/utils/linux-keyring.ts +4 -4
  546. package/src/tui/adapters/kakaotalk-adapter.ts +6 -1
  547. package/src/tui/adapters/telegram-adapter.ts +1 -1
  548. package/src/tui/adapters/webex-adapter.ts +1 -1
  549. package/src/tui/app.ts +149 -59
  550. package/src/tui/utils.test.ts +144 -145
  551. package/src/tui/utils.ts +27 -29
  552. package/src/tui/views/channel-picker.ts +1 -1
  553. package/src/tui/views/workspace-picker.ts +1 -1
@@ -1,9 +1,17 @@
1
1
  import { execSync, spawn } from 'node:child_process'
2
- import { createDecipheriv, pbkdf2Sync } from 'node:crypto'
2
+ import { pbkdf2Sync } from 'node:crypto'
3
3
  import { existsSync, readdirSync, readFileSync } from 'node:fs'
4
4
  import { homedir } from 'node:os'
5
5
  import { join } from 'node:path'
6
6
 
7
+ import {
8
+ BROWSER_KEYCHAIN_VARIANTS,
9
+ CHROMIUM_BROWSERS,
10
+ ChromiumCookieDecryptor,
11
+ discoverBrowserProfileDirs,
12
+ getBrowserBasePath,
13
+ } from '@/shared/chromium'
14
+ import type { KeychainVariant } from '@/shared/chromium'
7
15
  import { DerivedKeyCache } from '@/shared/utils/derived-key-cache'
8
16
  import { lookupLinuxKeyringPassword } from '@/shared/utils/linux-keyring'
9
17
 
@@ -13,11 +21,6 @@ export interface ExtractedDiscordToken {
13
21
 
14
22
  export type DiscordVariant = 'stable' | 'canary' | 'ptb'
15
23
 
16
- interface KeychainVariant {
17
- service: string
18
- account: string
19
- }
20
-
21
24
  interface CDPTarget {
22
25
  id: string
23
26
  type: string
@@ -34,13 +37,6 @@ interface CDPMessage {
34
37
  error?: { code: number; message: string }
35
38
  }
36
39
 
37
- interface BrowserConfig {
38
- name: string
39
- darwin: string
40
- linux: string
41
- win32: string
42
- }
43
-
44
40
  const TOKEN_REGEX = /[\w-]{24,}\.[\w-]{6}\.[\w-]{25,110}/
45
41
  const MFA_TOKEN_REGEX = /mfa\.[\w-]{84}/
46
42
  const ENCRYPTED_PREFIX = 'dQw4w9WgXcQ:'
@@ -62,49 +58,13 @@ const DISCORD_APP_PATHS: Record<DiscordVariant, { darwin: string }> = {
62
58
  ptb: { darwin: '/Applications/Discord PTB.app/Contents/MacOS/Discord PTB' },
63
59
  }
64
60
 
65
- const BROWSERS: BrowserConfig[] = [
66
- {
67
- name: 'Chrome',
68
- darwin: join('Google', 'Chrome'),
69
- linux: 'google-chrome',
70
- win32: join('Google', 'Chrome', 'User Data'),
71
- },
72
- {
73
- name: 'Chrome Canary',
74
- darwin: join('Google', 'Chrome Canary'),
75
- linux: 'google-chrome-unstable',
76
- win32: join('Google', 'Chrome SxS', 'User Data'),
77
- },
78
- {
79
- name: 'Edge',
80
- darwin: 'Microsoft Edge',
81
- linux: 'microsoft-edge',
82
- win32: join('Microsoft', 'Edge', 'User Data'),
83
- },
84
- {
85
- name: 'Arc',
86
- darwin: join('Arc', 'User Data'),
87
- linux: '',
88
- win32: join('Arc', 'User Data'),
89
- },
90
- {
91
- name: 'Brave',
92
- darwin: join('BraveSoftware', 'Brave-Browser'),
93
- linux: join('BraveSoftware', 'Brave-Browser'),
94
- win32: join('BraveSoftware', 'Brave-Browser', 'User Data'),
95
- },
96
- {
97
- name: 'Vivaldi',
98
- darwin: 'Vivaldi',
99
- linux: 'vivaldi',
100
- win32: join('Vivaldi', 'User Data'),
101
- },
102
- {
103
- name: 'Chromium',
104
- darwin: 'Chromium',
105
- linux: 'chromium',
106
- win32: join('Chromium', 'User Data'),
107
- },
61
+ const DISCORD_APP_KEYCHAIN_VARIANTS: KeychainVariant[] = [
62
+ { service: 'discord Safe Storage', account: 'discord Key' },
63
+ { service: 'discordcanary Safe Storage', account: 'discordcanary Key' },
64
+ { service: 'discordptb Safe Storage', account: 'discordptb Key' },
65
+ { service: 'Discord Safe Storage', account: 'Discord' },
66
+ { service: 'Discord Canary Safe Storage', account: 'Discord Canary' },
67
+ { service: 'Discord PTB Safe Storage', account: 'Discord PTB' },
108
68
  ]
109
69
 
110
70
  export class DiscordTokenExtractor {
@@ -113,12 +73,20 @@ export class DiscordTokenExtractor {
113
73
  private killWait: number
114
74
  private keyCache: DerivedKeyCache
115
75
  private cachedKey: Buffer | null = null
76
+ private decryptor: ChromiumCookieDecryptor
116
77
 
117
78
  constructor(platform?: NodeJS.Platform, startupWait?: number, killWait?: number, keyCache?: DerivedKeyCache) {
118
79
  this.platform = platform ?? process.platform
119
80
  this.startupWait = startupWait ?? DISCORD_STARTUP_WAIT
120
81
  this.killWait = killWait ?? 1000
121
82
  this.keyCache = keyCache ?? new DerivedKeyCache()
83
+ this.decryptor = new ChromiumCookieDecryptor({
84
+ platform: this.platform,
85
+ appKeychainVariants: DISCORD_APP_KEYCHAIN_VARIANTS,
86
+ keyCache: this.keyCache,
87
+ keyCachePlatform: 'discord',
88
+ linuxKeyringAppNames: ['discord', 'Discord'],
89
+ })
122
90
  }
123
91
 
124
92
  getDiscordDirs(): string[] {
@@ -147,11 +115,11 @@ export class DiscordTokenExtractor {
147
115
  getBrowserLevelDBDirs(): string[] {
148
116
  const dirs: string[] = []
149
117
 
150
- for (const browser of BROWSERS) {
151
- const browserBase = this.getBrowserBasePath(browser)
118
+ for (const browser of CHROMIUM_BROWSERS) {
119
+ const browserBase = getBrowserBasePath(browser, this.platform)
152
120
  if (!browserBase) continue
153
121
 
154
- const profileDirs = this.discoverProfileDirs(browserBase)
122
+ const profileDirs = discoverBrowserProfileDirs(browserBase)
155
123
  for (const profileDir of profileDirs) {
156
124
  dirs.push(join(profileDir, 'Local Storage', 'leveldb'))
157
125
  }
@@ -160,49 +128,6 @@ export class DiscordTokenExtractor {
160
128
  return dirs
161
129
  }
162
130
 
163
- private getBrowserBasePath(browser: BrowserConfig): string | null {
164
- let relative: string
165
-
166
- switch (this.platform) {
167
- case 'darwin':
168
- relative = browser.darwin
169
- if (!relative) return null
170
- return join(homedir(), 'Library', 'Application Support', relative)
171
- case 'linux':
172
- relative = browser.linux
173
- if (!relative) return null
174
- return join(homedir(), '.config', relative)
175
- case 'win32':
176
- relative = browser.win32
177
- if (!relative) return null
178
- return join(
179
- process.env.LOCALAPPDATA || join(homedir(), 'AppData', 'Local'),
180
- relative,
181
- )
182
- default:
183
- return null
184
- }
185
- }
186
-
187
- private discoverProfileDirs(browserBase: string): string[] {
188
- const dirs: string[] = []
189
-
190
- dirs.push(join(browserBase, 'Default'))
191
-
192
- if (!existsSync(browserBase)) return dirs
193
-
194
- try {
195
- const entries = readdirSync(browserBase, { withFileTypes: true })
196
- for (const entry of entries) {
197
- if (!entry.isDirectory()) continue
198
- if (!/^Profile \d+$/i.test(entry.name)) continue
199
- dirs.push(join(browserBase, entry.name))
200
- }
201
- } catch {}
202
-
203
- return dirs
204
- }
205
-
206
131
  private findBrowserBaseDirForPath(path: string): string | null {
207
132
  const parts = path.split(/[/\\]/)
208
133
  for (let levels = 2; levels <= 5; levels++) {
@@ -214,24 +139,7 @@ export class DiscordTokenExtractor {
214
139
  }
215
140
 
216
141
  getKeychainVariants(): KeychainVariant[] {
217
- return [
218
- // Modern Discord (lowercase)
219
- { service: 'discord Safe Storage', account: 'discord Key' },
220
- { service: 'discordcanary Safe Storage', account: 'discordcanary Key' },
221
- { service: 'discordptb Safe Storage', account: 'discordptb Key' },
222
- // Legacy Discord (capitalized)
223
- { service: 'Discord Safe Storage', account: 'Discord' },
224
- { service: 'Discord Canary Safe Storage', account: 'Discord Canary' },
225
- { service: 'Discord PTB Safe Storage', account: 'Discord PTB' },
226
- // Browser keychain entries for fallback
227
- { service: 'Chrome Safe Storage', account: 'Chrome' },
228
- { service: 'Chrome Canary Safe Storage', account: 'Chrome Canary' },
229
- { service: 'Microsoft Edge Safe Storage', account: 'Microsoft Edge' },
230
- { service: 'Arc Safe Storage', account: 'Arc' },
231
- { service: 'Brave Safe Storage', account: 'Brave' },
232
- { service: 'Vivaldi Safe Storage', account: 'Vivaldi' },
233
- { service: 'Chromium Safe Storage', account: 'Chromium' },
234
- ]
142
+ return [...DISCORD_APP_KEYCHAIN_VARIANTS, ...BROWSER_KEYCHAIN_VARIANTS]
235
143
  }
236
144
 
237
145
  getVariantFromPath(path: string): DiscordVariant {
@@ -283,6 +191,8 @@ export class DiscordTokenExtractor {
283
191
  private async loadCachedKey(): Promise<void> {
284
192
  if (this.platform !== 'darwin') return
285
193
 
194
+ await this.decryptor.loadCachedKey()
195
+
286
196
  const cached = await this.keyCache.get('discord')
287
197
  if (cached) {
288
198
  this.cachedKey = cached
@@ -290,7 +200,7 @@ export class DiscordTokenExtractor {
290
200
  }
291
201
 
292
202
  async clearKeyCache(): Promise<void> {
293
- await this.keyCache.clear('discord')
203
+ await this.decryptor.clearKeyCache()
294
204
  this.cachedKey = null
295
205
  }
296
206
 
@@ -445,27 +355,10 @@ export class DiscordTokenExtractor {
445
355
  const encryptedKey = Buffer.from(localState.os_crypt.encrypted_key, 'base64')
446
356
 
447
357
  const dpapiBlobKey = encryptedKey.subarray(5)
448
- const masterKey = this.decryptDPAPI(dpapiBlobKey)
358
+ const masterKey = this.decryptor.decryptDPAPI(dpapiBlobKey)
449
359
  if (!masterKey) return null
450
360
 
451
- return this.decryptAESGCM(encryptedData, masterKey)
452
- } catch {
453
- return null
454
- }
455
- }
456
-
457
- private decryptDPAPI(encryptedBlob: Buffer): Buffer | null {
458
- try {
459
- const b64 = encryptedBlob.toString('base64')
460
- const psScript = `
461
- Add-Type -AssemblyName System.Security
462
- $bytes = [Convert]::FromBase64String('${b64}')
463
- $decrypted = [Security.Cryptography.ProtectedData]::Unprotect($bytes, $null, 'CurrentUser')
464
- [Convert]::ToBase64String($decrypted)
465
- `.replace(/\n/g, ' ')
466
-
467
- const result = execSync(`powershell -Command "${psScript}"`, { encoding: 'utf8' })
468
- return Buffer.from(result.trim(), 'base64')
361
+ return this.decryptor.decryptAESGCM(encryptedData, masterKey)
469
362
  } catch {
470
363
  return null
471
364
  }
@@ -473,7 +366,7 @@ export class DiscordTokenExtractor {
473
366
 
474
367
  private decryptMacToken(encryptedData: Buffer, discordDir: string): string | null {
475
368
  if (this.cachedKey) {
476
- const decrypted = this.decryptAESCBC(encryptedData, this.cachedKey)
369
+ const decrypted = this.decryptor.decryptAESCBC(encryptedData, this.cachedKey)
477
370
  if (decrypted && this.isValidToken(decrypted)) return decrypted
478
371
  }
479
372
 
@@ -500,7 +393,7 @@ export class DiscordTokenExtractor {
500
393
  ).trim()
501
394
 
502
395
  const key = pbkdf2Sync(password, 'saltysalt', 1003, 16, 'sha1')
503
- const decrypted = this.decryptAESCBC(encryptedData, key)
396
+ const decrypted = this.decryptor.decryptAESCBC(encryptedData, key)
504
397
  if (decrypted && this.isValidToken(decrypted)) {
505
398
  this.cachedKey = key
506
399
  this.keyCache.set('discord', key).catch(() => {})
@@ -514,63 +407,26 @@ export class DiscordTokenExtractor {
514
407
 
515
408
  private decryptLinuxToken(encryptedData: Buffer): string | null {
516
409
  const prefix = encryptedData.subarray(0, 3).toString()
410
+
517
411
  if (prefix === 'v11') {
518
- const result = this.decryptV11LinuxToken(encryptedData)
519
- if (result) return result
412
+ for (const appName of ['discord', 'Discord']) {
413
+ try {
414
+ const keyringPassword = this.getLinuxKeyringPassword(appName)
415
+ const key = pbkdf2Sync(keyringPassword, 'saltysalt', 1, 16, 'sha1')
416
+ const decrypted = this.decryptor.decryptAESCBC(encryptedData, key)
417
+ if (decrypted) return decrypted
418
+ } catch {}
419
+ }
520
420
  }
521
- // v10 or fallback
421
+
522
422
  const key = pbkdf2Sync('peanuts', 'saltysalt', 1, 16, 'sha1')
523
- return this.decryptAESCBC(encryptedData, key)
423
+ return this.decryptor.decryptAESCBC(encryptedData, key)
524
424
  }
525
425
 
526
426
  private getLinuxKeyringPassword(appName: string): string {
527
427
  return lookupLinuxKeyringPassword(appName)
528
428
  }
529
429
 
530
- private decryptV11LinuxToken(encryptedData: Buffer): string | null {
531
- const appNames = ['discord', 'Discord']
532
- for (const appName of appNames) {
533
- try {
534
- const keyringPassword = this.getLinuxKeyringPassword(appName)
535
- const key = pbkdf2Sync(keyringPassword, 'saltysalt', 1, 16, 'sha1')
536
- const result = this.decryptAESCBC(encryptedData, key)
537
- if (result) return result
538
- } catch {}
539
- }
540
- return null
541
- }
542
-
543
- private decryptAESCBC(encryptedData: Buffer, key: Buffer): string | null {
544
- try {
545
- const ciphertext = encryptedData.subarray(3)
546
- const iv = Buffer.alloc(16, 0x20)
547
-
548
- const decipher = createDecipheriv('aes-128-cbc', key, iv)
549
- decipher.setAutoPadding(true)
550
-
551
- const decrypted = Buffer.concat([decipher.update(ciphertext), decipher.final()])
552
- return decrypted.toString('utf8')
553
- } catch {
554
- return null
555
- }
556
- }
557
-
558
- private decryptAESGCM(encryptedData: Buffer, key: Buffer): string | null {
559
- try {
560
- const iv = encryptedData.subarray(3, 15)
561
- const authTag = encryptedData.subarray(-16)
562
- const ciphertext = encryptedData.subarray(15, -16)
563
-
564
- const decipher = createDecipheriv('aes-256-gcm', key, iv)
565
- decipher.setAuthTag(authTag)
566
-
567
- const decrypted = Buffer.concat([decipher.update(ciphertext), decipher.final()])
568
- return decrypted.toString('utf8')
569
- } catch {
570
- return null
571
- }
572
- }
573
-
574
430
  async isDiscordRunning(variant?: DiscordVariant): Promise<boolean> {
575
431
  const variants = variant ? [variant] : (['stable', 'canary', 'ptb'] as DiscordVariant[])
576
432
 
@@ -31,10 +31,7 @@ export class DiscordBotClient {
31
31
  const credManager = new DiscordBotCredentialManager()
32
32
  const creds = await credManager.getCredentials()
33
33
  if (!creds?.token) {
34
- throw new DiscordBotError(
35
- 'No Discord bot credentials found. Run "auth set <token>" first.',
36
- 'no_credentials',
37
- )
34
+ throw new DiscordBotError('No Discord bot credentials found. Run "auth set <token>" first.', 'no_credentials')
38
35
  }
39
36
  return this.login({ token: creds.token })
40
37
  }
@@ -21,7 +21,9 @@ const mockListGuilds = mock(() =>
21
21
 
22
22
  mock.module('../client', () => ({
23
23
  DiscordBotClient: class MockDiscordBotClient {
24
- async login(_credentials?: any) { return this }
24
+ async login(_credentials?: any) {
25
+ return this
26
+ }
25
27
  testAuth = mockTestAuth
26
28
  listGuilds = mockListGuilds
27
29
  },
@@ -31,7 +31,9 @@ const mockResolveChannel = mock((_guildId: string, channel: string) => {
31
31
 
32
32
  mock.module('../client', () => ({
33
33
  DiscordBotClient: class MockDiscordBotClient {
34
- async login(_credentials?: any) { return this }
34
+ async login(_credentials?: any) {
35
+ return this
36
+ }
35
37
  listChannels = mockListChannels
36
38
  getChannel = mockGetChannel
37
39
  resolveChannel = mockResolveChannel
@@ -68,7 +68,9 @@ const mockResolveChannel = mock((_guildId: string, channel: string) => {
68
68
 
69
69
  mock.module('../client', () => ({
70
70
  DiscordBotClient: class MockDiscordBotClient {
71
- async login(_credentials?: any) { return this }
71
+ async login(_credentials?: any) {
72
+ return this
73
+ }
72
74
  sendMessage = mockSendMessage
73
75
  getMessages = mockGetMessages
74
76
  getMessage = mockGetMessage
@@ -22,7 +22,9 @@ const mockGetGuild = mock((guildId: string) =>
22
22
 
23
23
  mock.module('../client', () => ({
24
24
  DiscordBotClient: class MockDiscordBotClient {
25
- async login(_credentials?: any) { return this }
25
+ async login(_credentials?: any) {
26
+ return this
27
+ }
26
28
  listGuilds = mockListGuilds
27
29
  getGuild = mockGetGuild
28
30
  },
@@ -41,7 +41,9 @@ const mockListUsers = mock((_guildId: string) =>
41
41
 
42
42
  mock.module('../client', () => ({
43
43
  DiscordBotClient: class MockDiscordBotClient {
44
- async login(_credentials?: any) { return this }
44
+ async login(_credentials?: any) {
45
+ return this
46
+ }
45
47
  listChannels = mockListChannels
46
48
  getMessages = mockGetMessages
47
49
  listUsers = mockListUsers
@@ -84,23 +86,17 @@ describe('snapshot command', () => {
84
86
  process.env = originalEnv
85
87
  })
86
88
 
87
- describe('default (channels + messages)', () => {
88
- test('returns channels with recent messages', async () => {
89
+ describe('default (brief)', () => {
90
+ test('returns channels with id and name only', async () => {
89
91
  const manager = await setupManager(tempDir)
90
92
 
91
93
  const result = await snapshotAction({ _credManager: manager })
92
94
 
93
95
  expect(result.server_id).toBe('guild1')
94
96
  expect(result.channels).toHaveLength(2)
95
- expect(result.channels?.[0].id).toBe('ch1')
96
- expect(result.channels?.[0].name).toBe('general')
97
- expect(result.channels?.[0].messages).toHaveLength(2)
98
- expect(result.channels?.[0].messages?.[0]).toEqual({
99
- id: 'msg1-ch1',
100
- author: 'alice',
101
- content: 'Hello from ch1',
102
- timestamp: '2025-01-01T00:00:00Z',
103
- })
97
+ expect(result.channels?.[0]).toEqual({ id: 'ch1', name: 'general' })
98
+ expect(result.channels?.[1]).toEqual({ id: 'ch2', name: 'random' })
99
+ expect(result.hint).toBeDefined()
104
100
  })
105
101
 
106
102
  test('filters out non-text channels', async () => {
@@ -112,11 +108,39 @@ describe('snapshot command', () => {
112
108
  expect(channelNames).not.toContain('voice')
113
109
  })
114
110
 
115
- test('fetches messages in parallel for all text channels', async () => {
111
+ test('does not fetch messages', async () => {
116
112
  const manager = await setupManager(tempDir)
117
113
 
118
114
  await snapshotAction({ _credManager: manager })
119
115
 
116
+ expect(mockGetMessages).not.toHaveBeenCalled()
117
+ })
118
+ })
119
+
120
+ describe('--full (channels + messages)', () => {
121
+ test('returns channels with recent messages', async () => {
122
+ const manager = await setupManager(tempDir)
123
+
124
+ const result = await snapshotAction({ _credManager: manager, full: true })
125
+
126
+ expect(result.server_id).toBe('guild1')
127
+ expect(result.channels).toHaveLength(2)
128
+ expect(result.channels?.[0].id).toBe('ch1')
129
+ expect(result.channels?.[0].name).toBe('general')
130
+ expect(result.channels?.[0].messages).toHaveLength(2)
131
+ expect(result.channels?.[0].messages?.[0]).toEqual({
132
+ id: 'msg1-ch1',
133
+ author: 'alice',
134
+ content: 'Hello from ch1',
135
+ timestamp: '2025-01-01T00:00:00Z',
136
+ })
137
+ })
138
+
139
+ test('fetches messages in parallel for all text channels', async () => {
140
+ const manager = await setupManager(tempDir)
141
+
142
+ await snapshotAction({ _credManager: manager, full: true })
143
+
120
144
  expect(mockGetMessages).toHaveBeenCalledTimes(2)
121
145
  expect(mockGetMessages).toHaveBeenCalledWith('ch1', 5)
122
146
  expect(mockGetMessages).toHaveBeenCalledWith('ch2', 5)
@@ -125,7 +149,7 @@ describe('snapshot command', () => {
125
149
  test('respects --limit option', async () => {
126
150
  const manager = await setupManager(tempDir)
127
151
 
128
- await snapshotAction({ _credManager: manager, limit: 10 })
152
+ await snapshotAction({ _credManager: manager, full: true, limit: 10 })
129
153
 
130
154
  expect(mockGetMessages).toHaveBeenCalledWith('ch1', 10)
131
155
  expect(mockGetMessages).toHaveBeenCalledWith('ch2', 10)
@@ -134,17 +158,17 @@ describe('snapshot command', () => {
134
158
  test('defaults limit to 5', async () => {
135
159
  const manager = await setupManager(tempDir)
136
160
 
137
- await snapshotAction({ _credManager: manager })
161
+ await snapshotAction({ _credManager: manager, full: true })
138
162
 
139
163
  expect(mockGetMessages).toHaveBeenCalledWith('ch1', 5)
140
164
  })
141
165
  })
142
166
 
143
- describe('--channels-only', () => {
167
+ describe('--full --channels-only', () => {
144
168
  test('returns only channel list without messages', async () => {
145
169
  const manager = await setupManager(tempDir)
146
170
 
147
- const result = await snapshotAction({ _credManager: manager, channelsOnly: true })
171
+ const result = await snapshotAction({ _credManager: manager, full: true, channelsOnly: true })
148
172
 
149
173
  expect(result.server_id).toBe('guild1')
150
174
  expect(result.channels).toHaveLength(2)
@@ -154,11 +178,11 @@ describe('snapshot command', () => {
154
178
  })
155
179
  })
156
180
 
157
- describe('--users-only', () => {
181
+ describe('--full --users-only', () => {
158
182
  test('returns only user list', async () => {
159
183
  const manager = await setupManager(tempDir)
160
184
 
161
- const result = await snapshotAction({ _credManager: manager, usersOnly: true })
185
+ const result = await snapshotAction({ _credManager: manager, full: true, usersOnly: true })
162
186
 
163
187
  expect(result.server_id).toBe('guild1')
164
188
  expect(result.users).toHaveLength(3)
@@ -10,6 +10,7 @@ import { getClient } from './shared'
10
10
  interface SnapshotOption extends BotOption {
11
11
  channelsOnly?: boolean
12
12
  usersOnly?: boolean
13
+ full?: boolean
13
14
  limit?: number
14
15
  }
15
16
 
@@ -31,6 +32,7 @@ interface SnapshotResult {
31
32
  username: string
32
33
  global_name: string | null
33
34
  }>
35
+ hint?: string
34
36
  error?: string
35
37
  }
36
38
 
@@ -43,53 +45,66 @@ export async function snapshotAction(options: SnapshotOption): Promise<SnapshotR
43
45
  }
44
46
 
45
47
  const client = await getClient(options)
46
- const limit = options.limit ?? 5
47
48
 
48
- if (options.usersOnly) {
49
- const users = await client.listUsers(serverId)
50
- return {
51
- server_id: serverId,
52
- users: users.map((u) => ({
53
- id: u.id,
54
- username: u.username,
55
- global_name: u.global_name ?? null,
56
- })),
49
+ const isFull = options.full || options.channelsOnly || options.usersOnly
50
+ if (isFull) {
51
+ const limit = options.limit ?? 5
52
+
53
+ if (options.usersOnly) {
54
+ const users = await client.listUsers(serverId)
55
+ return {
56
+ server_id: serverId,
57
+ users: users.map((u) => ({
58
+ id: u.id,
59
+ username: u.username,
60
+ global_name: u.global_name ?? null,
61
+ })),
62
+ }
57
63
  }
58
- }
59
64
 
60
- const allChannels = await client.listChannels(serverId)
61
- const textChannels = allChannels.filter((ch) => ch.type === 0)
65
+ const allChannels = await client.listChannels(serverId)
66
+ const textChannels = allChannels.filter((ch) => ch.type === 0)
67
+
68
+ if (options.channelsOnly) {
69
+ return {
70
+ server_id: serverId,
71
+ channels: textChannels.map((ch) => ({
72
+ id: ch.id,
73
+ name: ch.name,
74
+ type: ch.type,
75
+ })),
76
+ }
77
+ }
78
+
79
+ const channelsWithMessages = await Promise.all(
80
+ textChannels.map(async (ch) => {
81
+ const messages = await client.getMessages(ch.id, limit)
82
+ return {
83
+ id: ch.id,
84
+ name: ch.name,
85
+ messages: messages.map((msg) => ({
86
+ id: msg.id,
87
+ author: msg.author.username,
88
+ content: msg.content,
89
+ timestamp: msg.timestamp,
90
+ })),
91
+ }
92
+ }),
93
+ )
62
94
 
63
- if (options.channelsOnly) {
64
95
  return {
65
96
  server_id: serverId,
66
- channels: textChannels.map((ch) => ({
67
- id: ch.id,
68
- name: ch.name,
69
- type: ch.type,
70
- })),
97
+ channels: channelsWithMessages,
71
98
  }
72
99
  }
73
100
 
74
- const channelsWithMessages = await Promise.all(
75
- textChannels.map(async (ch) => {
76
- const messages = await client.getMessages(ch.id, limit)
77
- return {
78
- id: ch.id,
79
- name: ch.name,
80
- messages: messages.map((msg) => ({
81
- id: msg.id,
82
- author: msg.author.username,
83
- content: msg.content,
84
- timestamp: msg.timestamp,
85
- })),
86
- }
87
- }),
88
- )
101
+ const allChannels = await client.listChannels(serverId)
102
+ const textChannels = allChannels.filter((ch) => ch.type === 0)
89
103
 
90
104
  return {
91
105
  server_id: serverId,
92
- channels: channelsWithMessages,
106
+ channels: textChannels.map((ch) => ({ id: ch.id, name: ch.name })),
107
+ hint: "Use 'message list <channel>' for messages, 'channel info <channel>' for channel details, 'user list' for members.",
93
108
  }
94
109
  } catch (error) {
95
110
  return { error: (error as Error).message }
@@ -97,10 +112,11 @@ export async function snapshotAction(options: SnapshotOption): Promise<SnapshotR
97
112
  }
98
113
 
99
114
  export const snapshotCommand = new Command('snapshot')
100
- .description('Server overview for AI agent context')
115
+ .description('Server overview for AI agents (brief by default, use --full for comprehensive data)')
116
+ .option('--full', 'Include messages and members (verbose)')
101
117
  .option('--channels-only', 'List channels only, skip messages')
102
118
  .option('--users-only', 'List users only')
103
- .option('--limit <n>', 'Messages per channel (default: 5)', '5')
119
+ .option('--limit <n>', 'Messages per channel with --full (default: 5)', '5')
104
120
  .option('--server <id>', 'Use specific server')
105
121
  .option('--bot <id>', 'Use specific bot')
106
122
  .option('--pretty', 'Pretty print JSON output')
@@ -108,6 +124,7 @@ export const snapshotCommand = new Command('snapshot')
108
124
  try {
109
125
  const result = await snapshotAction({
110
126
  ...options,
127
+ full: options.full,
111
128
  limit: parseInt(options.limit, 10),
112
129
  })
113
130
  console.log(formatOutput(result, options.pretty))
@@ -29,7 +29,9 @@ const mockResolveChannel = mock((_guildId: string, channel: string) => {
29
29
 
30
30
  mock.module('../client', () => ({
31
31
  DiscordBotClient: class MockDiscordBotClient {
32
- async login(_credentials?: any) { return this }
32
+ async login(_credentials?: any) {
33
+ return this
34
+ }
33
35
  createThread = mockCreateThread
34
36
  archiveThread = mockArchiveThread
35
37
  resolveChannel = mockResolveChannel