agent-messenger 2.1.0 → 2.3.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 (217) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/.env.template +35 -17
  3. package/README.md +7 -7
  4. package/bun.lock +31 -7
  5. package/dist/package.json +5 -3
  6. package/dist/src/platforms/channeltalk/commands/auth.d.ts.map +1 -1
  7. package/dist/src/platforms/channeltalk/commands/auth.js +35 -28
  8. package/dist/src/platforms/channeltalk/commands/auth.js.map +1 -1
  9. package/dist/src/platforms/channeltalk/ensure-auth.js +6 -6
  10. package/dist/src/platforms/channeltalk/ensure-auth.js.map +1 -1
  11. package/dist/src/platforms/channeltalk/token-extractor.d.ts +23 -1
  12. package/dist/src/platforms/channeltalk/token-extractor.d.ts.map +1 -1
  13. package/dist/src/platforms/channeltalk/token-extractor.js +299 -29
  14. package/dist/src/platforms/channeltalk/token-extractor.js.map +1 -1
  15. package/dist/src/platforms/discord/commands/auth.d.ts.map +1 -1
  16. package/dist/src/platforms/discord/commands/auth.js +57 -49
  17. package/dist/src/platforms/discord/commands/auth.js.map +1 -1
  18. package/dist/src/platforms/discord/ensure-auth.js +3 -3
  19. package/dist/src/platforms/discord/ensure-auth.js.map +1 -1
  20. package/dist/src/platforms/discord/token-extractor.d.ts +6 -1
  21. package/dist/src/platforms/discord/token-extractor.d.ts.map +1 -1
  22. package/dist/src/platforms/discord/token-extractor.js +167 -14
  23. package/dist/src/platforms/discord/token-extractor.js.map +1 -1
  24. package/dist/src/platforms/instagram/client.d.ts +2 -0
  25. package/dist/src/platforms/instagram/client.d.ts.map +1 -1
  26. package/dist/src/platforms/instagram/client.js +2 -2
  27. package/dist/src/platforms/instagram/client.js.map +1 -1
  28. package/dist/src/platforms/instagram/commands/auth.d.ts.map +1 -1
  29. package/dist/src/platforms/instagram/commands/auth.js +107 -14
  30. package/dist/src/platforms/instagram/commands/auth.js.map +1 -1
  31. package/dist/src/platforms/instagram/ensure-auth.d.ts.map +1 -1
  32. package/dist/src/platforms/instagram/ensure-auth.js +57 -11
  33. package/dist/src/platforms/instagram/ensure-auth.js.map +1 -1
  34. package/dist/src/platforms/instagram/index.d.ts +1 -0
  35. package/dist/src/platforms/instagram/index.d.ts.map +1 -1
  36. package/dist/src/platforms/instagram/index.js +1 -0
  37. package/dist/src/platforms/instagram/index.js.map +1 -1
  38. package/dist/src/platforms/instagram/token-extractor.d.ts +44 -0
  39. package/dist/src/platforms/instagram/token-extractor.d.ts.map +1 -0
  40. package/dist/src/platforms/instagram/token-extractor.js +407 -0
  41. package/dist/src/platforms/instagram/token-extractor.js.map +1 -0
  42. package/dist/src/platforms/kakaotalk/client.d.ts.map +1 -1
  43. package/dist/src/platforms/kakaotalk/client.js +2 -1
  44. package/dist/src/platforms/kakaotalk/client.js.map +1 -1
  45. package/dist/src/platforms/kakaotalk/commands/auth.d.ts.map +1 -1
  46. package/dist/src/platforms/kakaotalk/commands/auth.js +14 -13
  47. package/dist/src/platforms/kakaotalk/commands/auth.js.map +1 -1
  48. package/dist/src/platforms/kakaotalk/protocol/connection.d.ts.map +1 -1
  49. package/dist/src/platforms/kakaotalk/protocol/connection.js +2 -1
  50. package/dist/src/platforms/kakaotalk/protocol/connection.js.map +1 -1
  51. package/dist/src/platforms/line/client.d.ts.map +1 -1
  52. package/dist/src/platforms/line/client.js +36 -9
  53. package/dist/src/platforms/line/client.js.map +1 -1
  54. package/dist/src/platforms/line/commands/auth.d.ts.map +1 -1
  55. package/dist/src/platforms/line/commands/auth.js +6 -5
  56. package/dist/src/platforms/line/commands/auth.js.map +1 -1
  57. package/dist/src/platforms/slack/commands/auth.d.ts.map +1 -1
  58. package/dist/src/platforms/slack/commands/auth.js +11 -10
  59. package/dist/src/platforms/slack/commands/auth.js.map +1 -1
  60. package/dist/src/platforms/slack/token-extractor.d.ts +9 -0
  61. package/dist/src/platforms/slack/token-extractor.d.ts.map +1 -1
  62. package/dist/src/platforms/slack/token-extractor.js +300 -23
  63. package/dist/src/platforms/slack/token-extractor.js.map +1 -1
  64. package/dist/src/platforms/teams/commands/auth.d.ts.map +1 -1
  65. package/dist/src/platforms/teams/commands/auth.js +9 -8
  66. package/dist/src/platforms/teams/commands/auth.js.map +1 -1
  67. package/dist/src/platforms/teams/ensure-auth.d.ts.map +1 -1
  68. package/dist/src/platforms/teams/ensure-auth.js +2 -1
  69. package/dist/src/platforms/teams/ensure-auth.js.map +1 -1
  70. package/dist/src/platforms/teams/token-extractor.d.ts +5 -0
  71. package/dist/src/platforms/teams/token-extractor.d.ts.map +1 -1
  72. package/dist/src/platforms/teams/token-extractor.js +161 -29
  73. package/dist/src/platforms/teams/token-extractor.js.map +1 -1
  74. package/dist/src/platforms/telegram/client.d.ts.map +1 -1
  75. package/dist/src/platforms/telegram/client.js +25 -7
  76. package/dist/src/platforms/telegram/client.js.map +1 -1
  77. package/dist/src/platforms/telegram/commands/auth.d.ts.map +1 -1
  78. package/dist/src/platforms/telegram/commands/auth.js +6 -5
  79. package/dist/src/platforms/telegram/commands/auth.js.map +1 -1
  80. package/dist/src/platforms/webex/client.d.ts +12 -0
  81. package/dist/src/platforms/webex/client.d.ts.map +1 -1
  82. package/dist/src/platforms/webex/client.js +168 -1
  83. package/dist/src/platforms/webex/client.js.map +1 -1
  84. package/dist/src/platforms/webex/commands/auth.d.ts +4 -0
  85. package/dist/src/platforms/webex/commands/auth.d.ts.map +1 -1
  86. package/dist/src/platforms/webex/commands/auth.js +50 -4
  87. package/dist/src/platforms/webex/commands/auth.js.map +1 -1
  88. package/dist/src/platforms/webex/credential-manager.js +1 -1
  89. package/dist/src/platforms/webex/credential-manager.js.map +1 -1
  90. package/dist/src/platforms/webex/encryption.d.ts +10 -0
  91. package/dist/src/platforms/webex/encryption.d.ts.map +1 -0
  92. package/dist/src/platforms/webex/encryption.js +49 -0
  93. package/dist/src/platforms/webex/encryption.js.map +1 -0
  94. package/dist/src/platforms/webex/ensure-auth.d.ts.map +1 -1
  95. package/dist/src/platforms/webex/ensure-auth.js +25 -5
  96. package/dist/src/platforms/webex/ensure-auth.js.map +1 -1
  97. package/dist/src/platforms/webex/index.d.ts +2 -0
  98. package/dist/src/platforms/webex/index.d.ts.map +1 -1
  99. package/dist/src/platforms/webex/index.js +1 -0
  100. package/dist/src/platforms/webex/index.js.map +1 -1
  101. package/dist/src/platforms/webex/token-extractor.d.ts +29 -0
  102. package/dist/src/platforms/webex/token-extractor.d.ts.map +1 -0
  103. package/dist/src/platforms/webex/token-extractor.js +393 -0
  104. package/dist/src/platforms/webex/token-extractor.js.map +1 -0
  105. package/dist/src/platforms/webex/types.d.ts +8 -1
  106. package/dist/src/platforms/webex/types.d.ts.map +1 -1
  107. package/dist/src/platforms/webex/types.js +4 -1
  108. package/dist/src/platforms/webex/types.js.map +1 -1
  109. package/dist/src/platforms/whatsapp/client.d.ts.map +1 -1
  110. package/dist/src/platforms/whatsapp/client.js +6 -2
  111. package/dist/src/platforms/whatsapp/client.js.map +1 -1
  112. package/dist/src/shared/utils/derived-key-cache.d.ts +1 -1
  113. package/dist/src/shared/utils/derived-key-cache.d.ts.map +1 -1
  114. package/dist/src/shared/utils/error-handler.d.ts +1 -1
  115. package/dist/src/shared/utils/error-handler.d.ts.map +1 -1
  116. package/dist/src/shared/utils/error-handler.js +3 -2
  117. package/dist/src/shared/utils/error-handler.js.map +1 -1
  118. package/dist/src/shared/utils/stderr.d.ts +5 -0
  119. package/dist/src/shared/utils/stderr.d.ts.map +1 -0
  120. package/dist/src/shared/utils/stderr.js +18 -0
  121. package/dist/src/shared/utils/stderr.js.map +1 -0
  122. package/docs/content/docs/cli/channeltalk.mdx +7 -7
  123. package/docs/content/docs/cli/discord.mdx +3 -3
  124. package/docs/content/docs/cli/instagram.mdx +28 -6
  125. package/docs/content/docs/cli/slack.mdx +2 -2
  126. package/docs/content/docs/cli/teams.mdx +6 -4
  127. package/docs/content/docs/cli/webex.mdx +32 -11
  128. package/e2e/README.md +132 -8
  129. package/e2e/channeltalk.e2e.test.ts +2 -7
  130. package/e2e/channeltalkbot.e2e.test.ts +2 -6
  131. package/e2e/config.ts +172 -10
  132. package/e2e/helpers.ts +7 -0
  133. package/e2e/instagram.e2e.test.ts +97 -0
  134. package/e2e/kakaotalk.e2e.test.ts +74 -0
  135. package/e2e/line.e2e.test.ts +92 -0
  136. package/e2e/teams.e2e.test.ts +46 -1
  137. package/e2e/telegram.e2e.test.ts +84 -0
  138. package/e2e/webex.e2e.test.ts +190 -0
  139. package/e2e/whatsapp.e2e.test.ts +90 -0
  140. package/e2e/whatsappbot.e2e.test.ts +78 -0
  141. package/package.json +5 -3
  142. package/skills/agent-channeltalk/SKILL.md +9 -9
  143. package/skills/agent-channeltalk/references/authentication.md +21 -18
  144. package/skills/agent-channeltalkbot/SKILL.md +1 -1
  145. package/skills/agent-discord/SKILL.md +5 -5
  146. package/skills/agent-discord/references/authentication.md +8 -8
  147. package/skills/agent-discordbot/SKILL.md +1 -1
  148. package/skills/agent-instagram/SKILL.md +51 -9
  149. package/skills/agent-instagram/references/authentication.md +35 -3
  150. package/skills/agent-kakaotalk/SKILL.md +1 -1
  151. package/skills/agent-line/SKILL.md +1 -1
  152. package/skills/agent-slack/SKILL.md +5 -5
  153. package/skills/agent-slack/references/authentication.md +8 -8
  154. package/skills/agent-slackbot/SKILL.md +1 -1
  155. package/skills/agent-teams/SKILL.md +6 -6
  156. package/skills/agent-teams/references/authentication.md +8 -8
  157. package/skills/agent-telegram/SKILL.md +1 -1
  158. package/skills/agent-webex/SKILL.md +35 -15
  159. package/skills/agent-webex/references/authentication.md +63 -9
  160. package/skills/agent-webex/references/common-patterns.md +6 -3
  161. package/skills/agent-whatsapp/SKILL.md +1 -1
  162. package/skills/agent-whatsappbot/SKILL.md +1 -1
  163. package/src/platforms/channeltalk/commands/auth.test.ts +5 -5
  164. package/src/platforms/channeltalk/commands/auth.ts +38 -32
  165. package/src/platforms/channeltalk/ensure-auth.test.ts +6 -6
  166. package/src/platforms/channeltalk/ensure-auth.ts +6 -6
  167. package/src/platforms/channeltalk/token-extractor.test.ts +182 -15
  168. package/src/platforms/channeltalk/token-extractor.ts +344 -30
  169. package/src/platforms/discord/commands/auth.test.ts +3 -3
  170. package/src/platforms/discord/commands/auth.ts +58 -54
  171. package/src/platforms/discord/ensure-auth.test.ts +3 -3
  172. package/src/platforms/discord/ensure-auth.ts +3 -3
  173. package/src/platforms/discord/token-extractor.test.ts +199 -27
  174. package/src/platforms/discord/token-extractor.ts +190 -17
  175. package/src/platforms/instagram/client.ts +2 -2
  176. package/src/platforms/instagram/commands/auth.ts +133 -14
  177. package/src/platforms/instagram/ensure-auth.ts +63 -12
  178. package/src/platforms/instagram/index.ts +1 -0
  179. package/src/platforms/instagram/token-extractor.test.ts +424 -0
  180. package/src/platforms/instagram/token-extractor.ts +478 -0
  181. package/src/platforms/kakaotalk/client.ts +3 -1
  182. package/src/platforms/kakaotalk/commands/auth.ts +14 -13
  183. package/src/platforms/kakaotalk/protocol/connection.ts +3 -1
  184. package/src/platforms/line/client.ts +39 -14
  185. package/src/platforms/line/commands/auth.ts +7 -6
  186. package/src/platforms/slack/cli.test.ts +6 -5
  187. package/src/platforms/slack/commands/auth.test.ts +11 -7
  188. package/src/platforms/slack/commands/auth.ts +11 -10
  189. package/src/platforms/slack/token-extractor.test.ts +98 -1
  190. package/src/platforms/slack/token-extractor.ts +338 -26
  191. package/src/platforms/teams/commands/auth.ts +9 -8
  192. package/src/platforms/teams/ensure-auth.ts +3 -1
  193. package/src/platforms/teams/token-extractor.test.ts +136 -17
  194. package/src/platforms/teams/token-extractor.ts +182 -31
  195. package/src/platforms/telegram/client.test.ts +134 -0
  196. package/src/platforms/telegram/client.ts +27 -6
  197. package/src/platforms/telegram/commands/auth.ts +6 -5
  198. package/src/platforms/webex/client.test.ts +314 -0
  199. package/src/platforms/webex/client.ts +231 -1
  200. package/src/platforms/webex/commands/auth.ts +71 -4
  201. package/src/platforms/webex/commands/member.test.ts +10 -1
  202. package/src/platforms/webex/commands/message.test.ts +9 -5
  203. package/src/platforms/webex/commands/snapshot.test.ts +13 -4
  204. package/src/platforms/webex/commands/space.test.ts +12 -2
  205. package/src/platforms/webex/credential-manager.ts +1 -1
  206. package/src/platforms/webex/encryption.ts +53 -0
  207. package/src/platforms/webex/ensure-auth.test.ts +4 -0
  208. package/src/platforms/webex/ensure-auth.ts +27 -4
  209. package/src/platforms/webex/index.ts +2 -0
  210. package/src/platforms/webex/token-extractor.test.ts +327 -0
  211. package/src/platforms/webex/token-extractor.ts +460 -0
  212. package/src/platforms/webex/types.ts +8 -2
  213. package/src/platforms/webex/typings/node-jose.d.ts +27 -0
  214. package/src/platforms/whatsapp/client.ts +11 -7
  215. package/src/shared/utils/derived-key-cache.ts +1 -1
  216. package/src/shared/utils/error-handler.ts +4 -2
  217. package/src/shared/utils/stderr.ts +22 -0
@@ -3,6 +3,7 @@ import { describe, test, expect, beforeAll, afterEach } from 'bun:test'
3
3
  import { TEAMS_TEST_CHANNEL_ID, TEAMS_TEST_TEAM_ID, validateTeamsEnvironment } from './config'
4
4
  import { runCLI, parseJSON, generateTestId, waitForRateLimit } from './helpers'
5
5
 
6
+ let teamsAvailable = false
6
7
  let testMessages: string[] = []
7
8
 
8
9
  async function createTeamsMessage(text: string): Promise<string> {
@@ -28,7 +29,7 @@ async function cleanupTeamsMessages(ids: string[]) {
28
29
 
29
30
  describe('Teams E2E Tests', () => {
30
31
  beforeAll(async () => {
31
- await validateTeamsEnvironment()
32
+ teamsAvailable = await validateTeamsEnvironment()
32
33
  })
33
34
 
34
35
  afterEach(async () => {
@@ -41,6 +42,8 @@ describe('Teams E2E Tests', () => {
41
42
 
42
43
  describe('auth', () => {
43
44
  test('auth status returns authenticated team info', async () => {
45
+ if (!teamsAvailable) return
46
+
44
47
  const result = await runCLI('teams', ['auth', 'status'])
45
48
  expect(result.exitCode).toBe(0)
46
49
 
@@ -54,6 +57,8 @@ describe('Teams E2E Tests', () => {
54
57
 
55
58
  describe('team', () => {
56
59
  test('team list returns array', async () => {
60
+ if (!teamsAvailable) return
61
+
57
62
  const result = await runCLI('teams', ['team', 'list'])
58
63
  expect(result.exitCode).toBe(0)
59
64
 
@@ -62,6 +67,8 @@ describe('Teams E2E Tests', () => {
62
67
  })
63
68
 
64
69
  test('team current returns current team', async () => {
70
+ if (!teamsAvailable) return
71
+
65
72
  const result = await runCLI('teams', ['team', 'current'])
66
73
  expect(result.exitCode).toBe(0)
67
74
 
@@ -70,6 +77,8 @@ describe('Teams E2E Tests', () => {
70
77
  })
71
78
 
72
79
  test('team info returns team details', async () => {
80
+ if (!teamsAvailable) return
81
+
73
82
  const result = await runCLI('teams', ['team', 'info', TEAMS_TEST_TEAM_ID])
74
83
  expect(result.exitCode).toBe(0)
75
84
 
@@ -81,6 +90,8 @@ describe('Teams E2E Tests', () => {
81
90
 
82
91
  describe('message', () => {
83
92
  test('message send creates message', async () => {
93
+ if (!teamsAvailable) return
94
+
84
95
  const testId = generateTestId()
85
96
  const result = await runCLI('teams', [
86
97
  'message',
@@ -98,6 +109,8 @@ describe('Teams E2E Tests', () => {
98
109
  })
99
110
 
100
111
  test('message list returns messages array', async () => {
112
+ if (!teamsAvailable) return
113
+
101
114
  const result = await runCLI('teams', [
102
115
  'message',
103
116
  'list',
@@ -113,6 +126,8 @@ describe('Teams E2E Tests', () => {
113
126
  })
114
127
 
115
128
  test('message get retrieves specific message', async () => {
129
+ if (!teamsAvailable) return
130
+
116
131
  const testId = generateTestId()
117
132
  const id = await createTeamsMessage(`Get test ${testId}`)
118
133
  testMessages.push(id)
@@ -127,6 +142,8 @@ describe('Teams E2E Tests', () => {
127
142
  })
128
143
 
129
144
  test('message delete removes message', async () => {
145
+ if (!teamsAvailable) return
146
+
130
147
  const testId = generateTestId()
131
148
  const id = await createTeamsMessage(`Delete me ${testId}`)
132
149
 
@@ -144,6 +161,8 @@ describe('Teams E2E Tests', () => {
144
161
  })
145
162
 
146
163
  test('message command does not register update subcommand', async () => {
164
+ if (!teamsAvailable) return
165
+
147
166
  const result = await runCLI('teams', ['message', '--help'])
148
167
  expect(result.exitCode).toBe(0)
149
168
  expect(result.stdout).not.toContain('update')
@@ -152,6 +171,8 @@ describe('Teams E2E Tests', () => {
152
171
 
153
172
  describe('channel', () => {
154
173
  test('channel list returns channels array', async () => {
174
+ if (!teamsAvailable) return
175
+
155
176
  const result = await runCLI('teams', ['channel', 'list', TEAMS_TEST_TEAM_ID])
156
177
  expect(result.exitCode).toBe(0)
157
178
 
@@ -160,6 +181,8 @@ describe('Teams E2E Tests', () => {
160
181
  })
161
182
 
162
183
  test('channel info returns channel details', async () => {
184
+ if (!teamsAvailable) return
185
+
163
186
  const result = await runCLI('teams', ['channel', 'info', TEAMS_TEST_TEAM_ID, TEAMS_TEST_CHANNEL_ID])
164
187
  expect(result.exitCode).toBe(0)
165
188
 
@@ -168,6 +191,8 @@ describe('Teams E2E Tests', () => {
168
191
  })
169
192
 
170
193
  test('channel history returns messages', async () => {
194
+ if (!teamsAvailable) return
195
+
171
196
  const result = await runCLI('teams', [
172
197
  'channel',
173
198
  'history',
@@ -185,6 +210,8 @@ describe('Teams E2E Tests', () => {
185
210
 
186
211
  describe('user', () => {
187
212
  test('user list returns users array', async () => {
213
+ if (!teamsAvailable) return
214
+
188
215
  const result = await runCLI('teams', ['user', 'list', TEAMS_TEST_TEAM_ID])
189
216
  expect(result.exitCode).toBe(0)
190
217
 
@@ -193,6 +220,8 @@ describe('Teams E2E Tests', () => {
193
220
  })
194
221
 
195
222
  test('user me returns current user', async () => {
223
+ if (!teamsAvailable) return
224
+
196
225
  const result = await runCLI('teams', ['user', 'me'])
197
226
  expect(result.exitCode).toBe(0)
198
227
 
@@ -202,6 +231,8 @@ describe('Teams E2E Tests', () => {
202
231
  })
203
232
 
204
233
  test('user info returns user details', async () => {
234
+ if (!teamsAvailable) return
235
+
205
236
  const meResult = await runCLI('teams', ['user', 'me'])
206
237
  expect(meResult.exitCode).toBe(0)
207
238
 
@@ -220,6 +251,8 @@ describe('Teams E2E Tests', () => {
220
251
 
221
252
  describe('reaction', () => {
222
253
  test('reaction add/remove lifecycle', async () => {
254
+ if (!teamsAvailable) return
255
+
223
256
  const testId = generateTestId()
224
257
  const id = await createTeamsMessage(`Reaction test ${testId}`)
225
258
  testMessages.push(id)
@@ -256,6 +289,8 @@ describe('Teams E2E Tests', () => {
256
289
  }, 15000)
257
290
 
258
291
  test('reaction command does not register list subcommand', async () => {
292
+ if (!teamsAvailable) return
293
+
259
294
  const result = await runCLI('teams', ['reaction', '--help'])
260
295
  expect(result.exitCode).toBe(0)
261
296
  expect(result.stdout).not.toContain('list')
@@ -264,6 +299,8 @@ describe('Teams E2E Tests', () => {
264
299
 
265
300
  describe('file', () => {
266
301
  test('file list returns files array', async () => {
302
+ if (!teamsAvailable) return
303
+
267
304
  const result = await runCLI('teams', ['file', 'list', TEAMS_TEST_TEAM_ID, TEAMS_TEST_CHANNEL_ID])
268
305
  expect(result.exitCode).toBe(0)
269
306
 
@@ -272,6 +309,8 @@ describe('Teams E2E Tests', () => {
272
309
  })
273
310
 
274
311
  test('file upload uploads file and file info returns details', async () => {
312
+ if (!teamsAvailable) return
313
+
275
314
  const testId = generateTestId()
276
315
  const testFilePath = `/tmp/teams-e2e-${testId}.txt`
277
316
  await Bun.write(testFilePath, `Teams E2E test file ${testId}`)
@@ -310,6 +349,8 @@ describe('Teams E2E Tests', () => {
310
349
 
311
350
  describe('snapshot', () => {
312
351
  test('snapshot returns full team data', async () => {
352
+ if (!teamsAvailable) return
353
+
313
354
  const result = await runCLI('teams', ['snapshot', '--team-id', TEAMS_TEST_TEAM_ID, '--limit', '2'])
314
355
  expect(result.exitCode).toBe(0)
315
356
 
@@ -319,6 +360,8 @@ describe('Teams E2E Tests', () => {
319
360
  })
320
361
 
321
362
  test('snapshot --channels-only returns only channels', async () => {
363
+ if (!teamsAvailable) return
364
+
322
365
  const result = await runCLI('teams', ['snapshot', '--team-id', TEAMS_TEST_TEAM_ID, '--channels-only'])
323
366
  expect(result.exitCode).toBe(0)
324
367
 
@@ -327,6 +370,8 @@ describe('Teams E2E Tests', () => {
327
370
  })
328
371
 
329
372
  test('snapshot --users-only returns only users', async () => {
373
+ if (!teamsAvailable) return
374
+
330
375
  const result = await runCLI('teams', ['snapshot', '--team-id', TEAMS_TEST_TEAM_ID, '--users-only'])
331
376
  expect(result.exitCode).toBe(0)
332
377
 
@@ -0,0 +1,84 @@
1
+ import { afterEach, beforeAll, describe, expect, test } from 'bun:test'
2
+
3
+ import { TELEGRAM_TEST_CHAT_ID, validateTelegramEnvironment } from './config'
4
+ import { generateTestId, parseJSON, runCLI, waitForRateLimit } from './helpers'
5
+
6
+ let telegramAvailable = false
7
+
8
+ describe('Telegram E2E Tests', () => {
9
+ beforeAll(async () => {
10
+ telegramAvailable = await validateTelegramEnvironment()
11
+ })
12
+
13
+ afterEach(async () => {
14
+ await waitForRateLimit()
15
+ })
16
+
17
+ describe('auth', () => {
18
+ test('auth status returns exit code 0', async () => {
19
+ if (!telegramAvailable) return
20
+
21
+ const result = await runCLI('telegram', ['auth', 'status'])
22
+ expect(result.exitCode).toBe(0)
23
+ })
24
+
25
+ test('auth list returns accounts array', async () => {
26
+ if (!telegramAvailable) return
27
+
28
+ const result = await runCLI('telegram', ['auth', 'list'])
29
+ expect(result.exitCode).toBe(0)
30
+
31
+ const data = parseJSON<unknown[]>(result.stdout)
32
+ expect(Array.isArray(data)).toBe(true)
33
+ })
34
+ })
35
+
36
+ describe('chat', () => {
37
+ test('chat list returns chats', async () => {
38
+ if (!telegramAvailable) return
39
+
40
+ const result = await runCLI('telegram', ['chat', 'list', '--limit', '5'])
41
+ expect(result.exitCode).toBe(0)
42
+
43
+ const data = parseJSON<{ chats: unknown[] } | unknown[]>(result.stdout)
44
+ expect(data).toBeTruthy()
45
+ })
46
+
47
+ test('chat search returns results', async () => {
48
+ if (!telegramAvailable) return
49
+
50
+ const result = await runCLI('telegram', ['chat', 'search', 'test', '--limit', '5'])
51
+ expect(result.exitCode).toBe(0)
52
+ })
53
+
54
+ test('chat get returns chat with id', async () => {
55
+ if (!telegramAvailable) return
56
+
57
+ const result = await runCLI('telegram', ['chat', 'get', TELEGRAM_TEST_CHAT_ID])
58
+ expect(result.exitCode).toBe(0)
59
+
60
+ const data = parseJSON<{ id: string | number }>(result.stdout)
61
+ expect(data?.id).toBeTruthy()
62
+ })
63
+ })
64
+
65
+ describe('message', () => {
66
+ test('message send delivers message to chat', async () => {
67
+ if (!telegramAvailable) return
68
+
69
+ const testId = generateTestId()
70
+ const result = await runCLI('telegram', ['message', 'send', TELEGRAM_TEST_CHAT_ID, `e2e ${testId}`])
71
+ expect(result.exitCode).toBe(0)
72
+ })
73
+
74
+ test('message list returns messages', async () => {
75
+ if (!telegramAvailable) return
76
+
77
+ const result = await runCLI('telegram', ['message', 'list', TELEGRAM_TEST_CHAT_ID, '--limit', '5'])
78
+ expect(result.exitCode).toBe(0)
79
+
80
+ const data = parseJSON<{ messages: unknown[] } | unknown[]>(result.stdout)
81
+ expect(data).toBeTruthy()
82
+ })
83
+ })
84
+ })
@@ -0,0 +1,190 @@
1
+ import { afterEach, beforeAll, describe, expect, test } from 'bun:test'
2
+
3
+ import { WEBEX_TEST_SPACE_ID, WEBEX_TEST_DM_EMAIL, validateWebexEnvironment } from './config'
4
+ import { generateTestId, parseJSON, runCLI, waitForRateLimit } from './helpers'
5
+
6
+ let webexAvailable = false
7
+ let testMessages: string[] = []
8
+
9
+ async function cleanupWebexMessages() {
10
+ for (const id of testMessages) {
11
+ try {
12
+ await runCLI('webex', ['message', 'delete', id, '--force'])
13
+ await waitForRateLimit(500)
14
+ } catch {
15
+ // best-effort cleanup
16
+ }
17
+ }
18
+ testMessages = []
19
+ }
20
+
21
+ describe('Webex E2E Tests', () => {
22
+ beforeAll(async () => {
23
+ webexAvailable = await validateWebexEnvironment()
24
+ })
25
+
26
+ afterEach(async () => {
27
+ if (testMessages.length > 0) {
28
+ await cleanupWebexMessages()
29
+ }
30
+ await waitForRateLimit()
31
+ })
32
+
33
+ describe('auth', () => {
34
+ test('auth status returns authenticated', async () => {
35
+ if (!webexAvailable) return
36
+
37
+ const result = await runCLI('webex', ['auth', 'status'])
38
+ expect(result.exitCode).toBe(0)
39
+
40
+ const data = parseJSON<{ authenticated: boolean }>(result.stdout)
41
+ expect(data?.authenticated).toBe(true)
42
+ })
43
+ })
44
+
45
+ describe('message', () => {
46
+ test('message send creates a message', async () => {
47
+ if (!webexAvailable) return
48
+
49
+ const testId = generateTestId()
50
+ const result = await runCLI('webex', ['message', 'send', WEBEX_TEST_SPACE_ID, `e2e ${testId}`])
51
+ expect(result.exitCode).toBe(0)
52
+
53
+ const data = parseJSON<{ id: string }>(result.stdout)
54
+ expect(data?.id).toBeTruthy()
55
+
56
+ if (data?.id) testMessages.push(data.id)
57
+ })
58
+
59
+ test('message list returns messages array', async () => {
60
+ if (!webexAvailable) return
61
+
62
+ const result = await runCLI('webex', ['message', 'list', WEBEX_TEST_SPACE_ID, '--limit', '5'])
63
+ expect(result.exitCode).toBe(0)
64
+
65
+ const data = parseJSON<unknown[]>(result.stdout)
66
+ expect(Array.isArray(data)).toBe(true)
67
+ })
68
+
69
+ test('message get retrieves specific message', async () => {
70
+ if (!webexAvailable) return
71
+
72
+ const testId = generateTestId()
73
+ const sendResult = await runCLI('webex', ['message', 'send', WEBEX_TEST_SPACE_ID, `get test ${testId}`])
74
+ expect(sendResult.exitCode).toBe(0)
75
+
76
+ const sent = parseJSON<{ id: string }>(sendResult.stdout)
77
+ expect(sent?.id).toBeTruthy()
78
+ if (sent?.id) testMessages.push(sent.id)
79
+
80
+ await waitForRateLimit()
81
+
82
+ const result = await runCLI('webex', ['message', 'get', sent!.id])
83
+ expect(result.exitCode).toBe(0)
84
+
85
+ const data = parseJSON<{ id: string; text: string }>(result.stdout)
86
+ expect(data?.text).toContain(testId)
87
+ }, 30000)
88
+
89
+ test('message delete removes message', async () => {
90
+ if (!webexAvailable) return
91
+
92
+ const testId = generateTestId()
93
+ const sendResult = await runCLI('webex', ['message', 'send', WEBEX_TEST_SPACE_ID, `delete me ${testId}`])
94
+ expect(sendResult.exitCode).toBe(0)
95
+
96
+ const sent = parseJSON<{ id: string }>(sendResult.stdout)
97
+ expect(sent?.id).toBeTruthy()
98
+
99
+ await waitForRateLimit()
100
+
101
+ const result = await runCLI('webex', ['message', 'delete', sent!.id, '--force'])
102
+ expect(result.exitCode).toBe(0)
103
+ }, 30000)
104
+
105
+ test('message edit updates message content', async () => {
106
+ if (!webexAvailable) return
107
+
108
+ const testId = generateTestId()
109
+ const sendResult = await runCLI('webex', ['message', 'send', WEBEX_TEST_SPACE_ID, `edit me ${testId}`])
110
+ expect(sendResult.exitCode).toBe(0)
111
+
112
+ const sent = parseJSON<{ id: string }>(sendResult.stdout)
113
+ expect(sent?.id).toBeTruthy()
114
+ if (sent?.id) testMessages.push(sent.id)
115
+
116
+ await waitForRateLimit()
117
+
118
+ const result = await runCLI('webex', ['message', 'edit', sent!.id, WEBEX_TEST_SPACE_ID, `edited ${testId}`])
119
+ expect(result.exitCode).toBe(0)
120
+ }, 30000)
121
+ })
122
+
123
+ describe('space', () => {
124
+ test('space list returns spaces array', async () => {
125
+ if (!webexAvailable) return
126
+
127
+ const result = await runCLI('webex', ['space', 'list', '--limit', '5'])
128
+ expect(result.exitCode).toBe(0)
129
+
130
+ const data = parseJSON<unknown[]>(result.stdout)
131
+ expect(Array.isArray(data)).toBe(true)
132
+ })
133
+
134
+ test('space info returns space details', async () => {
135
+ if (!webexAvailable) return
136
+
137
+ const result = await runCLI('webex', ['space', 'info', WEBEX_TEST_SPACE_ID])
138
+ expect(result.exitCode).toBe(0)
139
+
140
+ const data = parseJSON<{ id: string }>(result.stdout)
141
+ expect(data?.id).toBe(WEBEX_TEST_SPACE_ID)
142
+ })
143
+ })
144
+
145
+ describe('member', () => {
146
+ test('member list returns members array', async () => {
147
+ if (!webexAvailable) return
148
+
149
+ const result = await runCLI('webex', ['member', 'list', WEBEX_TEST_SPACE_ID, '--limit', '5'])
150
+ expect(result.exitCode).toBe(0)
151
+
152
+ const data = parseJSON<unknown[]>(result.stdout)
153
+ expect(Array.isArray(data)).toBe(true)
154
+ })
155
+ })
156
+
157
+ describe('snapshot', () => {
158
+ test('snapshot returns spaces and members', async () => {
159
+ if (!webexAvailable) return
160
+
161
+ const result = await runCLI('webex', ['snapshot', '--limit', '2'])
162
+ expect(result.exitCode).toBe(0)
163
+
164
+ const data = parseJSON<{ spaces: unknown; members: unknown; recent_messages: unknown }>(result.stdout)
165
+ expect(data?.spaces).toBeDefined()
166
+ expect(data?.members).toBeDefined()
167
+ expect(data?.recent_messages).toBeDefined()
168
+ }, 30000)
169
+
170
+ test('snapshot --spaces-only returns only spaces', async () => {
171
+ if (!webexAvailable) return
172
+
173
+ const result = await runCLI('webex', ['snapshot', '--spaces-only'])
174
+ expect(result.exitCode).toBe(0)
175
+
176
+ const data = parseJSON<{ spaces: unknown }>(result.stdout)
177
+ expect(data?.spaces).toBeDefined()
178
+ })
179
+
180
+ test('snapshot --members-only returns only members', async () => {
181
+ if (!webexAvailable) return
182
+
183
+ const result = await runCLI('webex', ['snapshot', '--members-only'])
184
+ expect(result.exitCode).toBe(0)
185
+
186
+ const data = parseJSON<{ members: unknown }>(result.stdout)
187
+ expect(data?.members).toBeDefined()
188
+ })
189
+ })
190
+ })
@@ -0,0 +1,90 @@
1
+ import { afterEach, beforeAll, describe, expect, test } from 'bun:test'
2
+
3
+ import { WHATSAPP_TEST_CHAT_ID, validateWhatsAppEnvironment } from './config'
4
+ import { generateTestId, parseJSON, runCLI, waitForRateLimit } from './helpers'
5
+
6
+ let whatsappAvailable = false
7
+
8
+ describe('WhatsApp E2E Tests', () => {
9
+ beforeAll(async () => {
10
+ whatsappAvailable = await validateWhatsAppEnvironment()
11
+ })
12
+
13
+ afterEach(async () => {
14
+ await waitForRateLimit()
15
+ })
16
+
17
+ describe('auth', () => {
18
+ test('auth status returns exit code 0', async () => {
19
+ if (!whatsappAvailable) return
20
+
21
+ const result = await runCLI('whatsapp', ['auth', 'status'])
22
+ expect(result.exitCode).toBe(0)
23
+ })
24
+
25
+ test('auth list returns accounts array', async () => {
26
+ if (!whatsappAvailable) return
27
+
28
+ const result = await runCLI('whatsapp', ['auth', 'list'])
29
+ expect(result.exitCode).toBe(0)
30
+
31
+ const data = parseJSON<unknown[]>(result.stdout)
32
+ expect(Array.isArray(data)).toBe(true)
33
+ })
34
+ })
35
+
36
+ describe('chat', () => {
37
+ test('chat list returns chats', async () => {
38
+ if (!whatsappAvailable) return
39
+
40
+ const result = await runCLI('whatsapp', ['chat', 'list', '--limit', '5'])
41
+ expect(result.exitCode).toBe(0)
42
+
43
+ const data = parseJSON<{ chats: unknown[] } | unknown[]>(result.stdout)
44
+ expect(data).toBeTruthy()
45
+ })
46
+
47
+ test('chat search returns results', async () => {
48
+ if (!whatsappAvailable) return
49
+
50
+ const result = await runCLI('whatsapp', ['chat', 'search', 'test', '--limit', '5'])
51
+ expect(result.exitCode).toBe(0)
52
+ })
53
+ })
54
+
55
+ describe('message', () => {
56
+ test('message send delivers message to chat', async () => {
57
+ if (!whatsappAvailable) return
58
+
59
+ const testId = generateTestId()
60
+ const result = await runCLI('whatsapp', ['message', 'send', WHATSAPP_TEST_CHAT_ID, `e2e ${testId}`])
61
+ expect(result.exitCode).toBe(0)
62
+ })
63
+
64
+ test('message list returns messages', async () => {
65
+ if (!whatsappAvailable) return
66
+
67
+ const result = await runCLI('whatsapp', ['message', 'list', WHATSAPP_TEST_CHAT_ID, '--limit', '5'])
68
+ expect(result.exitCode).toBe(0)
69
+
70
+ const data = parseJSON<{ messages: unknown[] } | unknown[]>(result.stdout)
71
+ expect(data).toBeTruthy()
72
+ })
73
+
74
+ test('message react adds reaction to message', async () => {
75
+ if (!whatsappAvailable) return
76
+
77
+ const testId = generateTestId()
78
+ const sendResult = await runCLI('whatsapp', ['message', 'send', WHATSAPP_TEST_CHAT_ID, `react ${testId}`])
79
+ expect(sendResult.exitCode).toBe(0)
80
+
81
+ const sent = parseJSON<{ id: string }>(sendResult.stdout)
82
+ expect(sent?.id).toBeTruthy()
83
+
84
+ await waitForRateLimit()
85
+
86
+ const result = await runCLI('whatsapp', ['message', 'react', WHATSAPP_TEST_CHAT_ID, sent!.id, '👍'])
87
+ expect(result.exitCode).toBe(0)
88
+ }, 15000)
89
+ })
90
+ })
@@ -0,0 +1,78 @@
1
+ import { afterEach, beforeAll, describe, expect, test } from 'bun:test'
2
+
3
+ import { WHATSAPPBOT_TEST_PHONE_NUMBER, validateWhatsAppBotEnvironment } from './config'
4
+ import { generateTestId, parseJSON, runCLI, waitForRateLimit } from './helpers'
5
+
6
+ let whatsappbotAvailable = false
7
+
8
+ describe('WhatsApp Bot E2E Tests', () => {
9
+ beforeAll(async () => {
10
+ whatsappbotAvailable = await validateWhatsAppBotEnvironment()
11
+ })
12
+
13
+ afterEach(async () => {
14
+ await waitForRateLimit()
15
+ })
16
+
17
+ describe('auth', () => {
18
+ test('auth status returns valid credentials', async () => {
19
+ if (!whatsappbotAvailable) return
20
+
21
+ const result = await runCLI('whatsappbot', ['auth', 'status'])
22
+ expect(result.exitCode).toBe(0)
23
+
24
+ const data = parseJSON<{ valid: boolean }>(result.stdout)
25
+ expect(data?.valid).toBe(true)
26
+ })
27
+
28
+ test('auth list returns accounts array', async () => {
29
+ if (!whatsappbotAvailable) return
30
+
31
+ const result = await runCLI('whatsappbot', ['auth', 'list'])
32
+ expect(result.exitCode).toBe(0)
33
+
34
+ const data = parseJSON<unknown[]>(result.stdout)
35
+ expect(Array.isArray(data)).toBe(true)
36
+ })
37
+ })
38
+
39
+ describe('message', () => {
40
+ test('message send delivers to test phone number', async () => {
41
+ if (!whatsappbotAvailable) return
42
+
43
+ const testId = generateTestId()
44
+ const result = await runCLI('whatsappbot', ['message', 'send', WHATSAPPBOT_TEST_PHONE_NUMBER, `e2e ${testId}`])
45
+ expect(result.exitCode).toBe(0)
46
+ })
47
+ })
48
+
49
+ describe('template', () => {
50
+ test('template list returns templates', async () => {
51
+ if (!whatsappbotAvailable) return
52
+
53
+ const result = await runCLI('whatsappbot', ['template', 'list', '--limit', '5'])
54
+ expect(result.exitCode).toBe(0)
55
+
56
+ const data = parseJSON<unknown>(result.stdout)
57
+ expect(data).toBeDefined()
58
+ })
59
+
60
+ test('template get returns template details', async () => {
61
+ if (!whatsappbotAvailable) return
62
+
63
+ const listResult = await runCLI('whatsappbot', ['template', 'list', '--limit', '1'])
64
+ expect(listResult.exitCode).toBe(0)
65
+
66
+ const listData = parseJSON<Array<{ name: string }>>(listResult.stdout)
67
+ if (!Array.isArray(listData) || listData.length === 0) return
68
+
69
+ await waitForRateLimit()
70
+
71
+ const result = await runCLI('whatsappbot', ['template', 'get', listData[0].name])
72
+ expect(result.exitCode).toBe(0)
73
+
74
+ const data = parseJSON<{ name: string }>(result.stdout)
75
+ expect(data?.name).toBe(listData[0].name)
76
+ }, 30000)
77
+ })
78
+ })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-messenger",
3
- "version": "2.1.0",
3
+ "version": "2.3.0",
4
4
  "description": "Multi-platform messaging CLI for AI agents (Slack, Discord, Teams, Webex, Telegram, WhatsApp, LINE, Instagram, KakaoTalk, Channel Talk)",
5
5
  "repository": {
6
6
  "type": "git",
@@ -129,21 +129,22 @@
129
129
  "postpublish": "git checkout package.json"
130
130
  },
131
131
  "dependencies": {
132
- "@evex/linejs": "npm:@jsr/evex__linejs",
133
132
  "@hapi/boom": "^10.0.1",
134
133
  "@slack/web-api": "^6.9.0",
135
134
  "@whiskeysockets/baileys": "^7.0.0-rc.9",
136
135
  "better-sqlite3": "^12.0.0",
137
136
  "blessed": "^0.1.81",
138
137
  "bson": "^7.2.0",
139
- "classic-level": "^1.3.0",
138
+ "classic-level": "^3.0.0",
140
139
  "commander": "^11.1.0",
140
+ "node-jose": "^2.2.0",
141
141
  "pino": "^10.3.1",
142
142
  "qrcode": "^1.5.4",
143
143
  "ws": "^8.19.0",
144
144
  "zod": "^4.3.6"
145
145
  },
146
146
  "optionalDependencies": {
147
+ "@evex/linejs": "npm:@jsr/evex__linejs",
147
148
  "koffi": "^2.15.2",
148
149
  "prebuilt-tdlib": "0.1008062.2"
149
150
  },
@@ -153,6 +154,7 @@
153
154
  "@types/bun": "latest",
154
155
  "@types/hapi__boom": "^9.0.1",
155
156
  "@types/node": "^20.10.6",
157
+ "@types/node-jose": "^1.1.13",
156
158
  "@types/qrcode": "^1.5.6",
157
159
  "@types/ws": "^8.18.1",
158
160
  "oxfmt": "^0.36.0",