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
@@ -13,13 +13,9 @@ let testGroupName = ''
13
13
 
14
14
  describe('ChannelBot E2E Tests', () => {
15
15
  beforeAll(async () => {
16
- if (!CHANNELBOT_TEST_WORKSPACE_ID) {
17
- console.warn(
18
- 'Skipping ChannelBot E2E: set E2E_CHANNELBOT_WORKSPACE_ID to run against a dedicated test workspace.',
19
- )
20
- return
21
- }
22
16
  const group = await validateChannelBotEnvironment()
17
+ if (!group) return
18
+
23
19
  testGroupId = group.groupId
24
20
  testGroupName = group.groupName
25
21
  channelbotAvailable = true
package/e2e/config.ts CHANGED
@@ -114,15 +114,14 @@ export const TEAMS_TEST_TEAM_NAME = process.env.E2E_TEAMS_TEAM_NAME || 'Agent Me
114
114
  export const TEAMS_TEST_CHANNEL_ID = process.env.E2E_TEAMS_CHANNEL_ID || ''
115
115
  export const TEAMS_TEST_CHANNEL = 'e2e-test'
116
116
 
117
- export async function validateTeamsEnvironment() {
118
- const { runCLI, parseJSON } = await import('./helpers')
119
-
117
+ export async function validateTeamsEnvironment(): Promise<boolean> {
120
118
  if (!TEAMS_TEST_TEAM_ID || !TEAMS_TEST_CHANNEL_ID) {
121
- throw new Error(
122
- 'Teams E2E environment not configured. Set E2E_TEAMS_TEAM_ID and E2E_TEAMS_CHANNEL_ID environment variables.',
123
- )
119
+ console.warn('Skipping Teams E2E: set E2E_TEAMS_TEAM_ID and E2E_TEAMS_CHANNEL_ID to run against a dedicated test team.')
120
+ return false
124
121
  }
125
122
 
123
+ const { runCLI, parseJSON } = await import('./helpers')
124
+
126
125
  const result = await runCLI('teams', ['auth', 'status'])
127
126
  if (result.exitCode !== 0) {
128
127
  throw new Error('Teams authentication failed. Please run: agent-teams auth extract')
@@ -144,6 +143,8 @@ export async function validateTeamsEnvironment() {
144
143
  )
145
144
  }
146
145
  }
146
+
147
+ return true
147
148
  }
148
149
 
149
150
  // ChannelBot Test Environment — requires E2E_CHANNELBOT_WORKSPACE_ID to opt-in.
@@ -153,9 +154,10 @@ export const CHANNELBOT_TEST_WORKSPACE_ID = process.env.E2E_CHANNELBOT_WORKSPACE
153
154
  export const CHANNELBOT_TEST_WORKSPACE_NAME = process.env.E2E_CHANNELBOT_WORKSPACE_NAME || ''
154
155
  export const E2E_GROUP_NAME = 'E2E'
155
156
 
156
- export async function validateChannelBotEnvironment(): Promise<{ groupId: string; groupName: string }> {
157
+ export async function validateChannelBotEnvironment(): Promise<{ groupId: string; groupName: string } | null> {
157
158
  if (!CHANNELBOT_TEST_WORKSPACE_ID) {
158
- throw new Error('ChannelBot E2E environment not configured. Set E2E_CHANNELBOT_WORKSPACE_ID.')
159
+ console.warn('Skipping ChannelBot E2E: set E2E_CHANNELBOT_WORKSPACE_ID to run against a dedicated test workspace.')
160
+ return null
159
161
  }
160
162
 
161
163
  const { runCLI, parseJSON } = await import('./helpers')
@@ -189,14 +191,174 @@ export async function validateChannelBotEnvironment(): Promise<{ groupId: string
189
191
  return { groupId: e2eGroup.id, groupName: e2eGroup.name }
190
192
  }
191
193
 
194
+ // Webex Test Environment
195
+ export const WEBEX_TEST_SPACE_ID = process.env.E2E_WEBEX_SPACE_ID || ''
196
+ export const WEBEX_TEST_DM_EMAIL = process.env.E2E_WEBEX_DM_EMAIL || ''
197
+
198
+ export async function validateWebexEnvironment(): Promise<boolean> {
199
+ if (!WEBEX_TEST_SPACE_ID) {
200
+ console.warn('Skipping Webex E2E: set E2E_WEBEX_SPACE_ID to run against a dedicated test space.')
201
+ return false
202
+ }
203
+
204
+ const { runCLI, parseJSON } = await import('./helpers')
205
+
206
+ const result = await runCLI('webex', ['auth', 'status'])
207
+ if (result.exitCode !== 0) {
208
+ throw new Error('Webex authentication failed. Run: agent-webex auth login or agent-webex auth extract')
209
+ }
210
+
211
+ const data = parseJSON<{ authenticated: boolean }>(result.stdout)
212
+ if (!data?.authenticated) {
213
+ throw new Error('Webex not authenticated. Run: agent-webex auth login or agent-webex auth extract')
214
+ }
215
+
216
+ return true
217
+ }
218
+
219
+ // Telegram Test Environment
220
+ export const TELEGRAM_TEST_CHAT_ID = process.env.E2E_TELEGRAM_CHAT_ID || ''
221
+
222
+ export async function validateTelegramEnvironment(): Promise<boolean> {
223
+ if (!TELEGRAM_TEST_CHAT_ID) {
224
+ console.warn('Skipping Telegram E2E: set E2E_TELEGRAM_CHAT_ID to run against a dedicated test chat.')
225
+ return false
226
+ }
227
+
228
+ const { runCLI } = await import('./helpers')
229
+
230
+ const result = await runCLI('telegram', ['auth', 'status'])
231
+ if (result.exitCode !== 0) {
232
+ throw new Error('Telegram authentication failed. Run: agent-telegram auth login')
233
+ }
234
+
235
+ return true
236
+ }
237
+
238
+ // WhatsApp Test Environment
239
+ export const WHATSAPP_TEST_CHAT_ID = process.env.E2E_WHATSAPP_CHAT_ID || ''
240
+
241
+ export async function validateWhatsAppEnvironment(): Promise<boolean> {
242
+ if (!WHATSAPP_TEST_CHAT_ID) {
243
+ console.warn('Skipping WhatsApp E2E: set E2E_WHATSAPP_CHAT_ID to run against a dedicated test chat.')
244
+ return false
245
+ }
246
+
247
+ const { runCLI, parseJSON } = await import('./helpers')
248
+
249
+ const result = await runCLI('whatsapp', ['auth', 'status'])
250
+ if (result.exitCode !== 0) {
251
+ throw new Error('WhatsApp authentication failed. Run: agent-whatsapp auth login')
252
+ }
253
+
254
+ const data = parseJSON<{ valid?: boolean }>(result.stdout)
255
+ if (data && 'valid' in data && !data.valid) {
256
+ throw new Error('WhatsApp credentials invalid. Run: agent-whatsapp auth login')
257
+ }
258
+
259
+ return true
260
+ }
261
+
262
+ // WhatsApp Bot Test Environment
263
+ export const WHATSAPPBOT_TEST_PHONE_NUMBER = process.env.E2E_WHATSAPPBOT_PHONE_NUMBER || ''
264
+
265
+ export async function validateWhatsAppBotEnvironment(): Promise<boolean> {
266
+ if (!WHATSAPPBOT_TEST_PHONE_NUMBER) {
267
+ console.warn('Skipping WhatsApp Bot E2E: set E2E_WHATSAPPBOT_PHONE_NUMBER to run against a dedicated test phone number.')
268
+ return false
269
+ }
270
+
271
+ const { runCLI, parseJSON } = await import('./helpers')
272
+
273
+ const result = await runCLI('whatsappbot', ['auth', 'status'])
274
+ if (result.exitCode !== 0) {
275
+ throw new Error(
276
+ 'WhatsApp Bot authentication failed. Run: agent-whatsappbot auth set <phone-number-id> <access-token>',
277
+ )
278
+ }
279
+
280
+ const data = parseJSON<{ valid: boolean }>(result.stdout)
281
+ if (!data?.valid) {
282
+ throw new Error(
283
+ 'WhatsApp Bot credentials invalid or expired. Run: agent-whatsappbot auth set <phone-number-id> <access-token>',
284
+ )
285
+ }
286
+
287
+ return true
288
+ }
289
+
290
+ // LINE Test Environment
291
+ export const LINE_TEST_CHAT_ID = process.env.E2E_LINE_CHAT_ID || ''
292
+
293
+ export async function validateLineEnvironment(): Promise<boolean> {
294
+ if (!LINE_TEST_CHAT_ID) {
295
+ console.warn('Skipping LINE E2E: set E2E_LINE_CHAT_ID to run against a dedicated test chat.')
296
+ return false
297
+ }
298
+
299
+ const { runCLI } = await import('./helpers')
300
+
301
+ const result = await runCLI('line', ['auth', 'status'])
302
+ if (result.exitCode !== 0) {
303
+ throw new Error('LINE authentication failed. Run: agent-line auth login')
304
+ }
305
+
306
+ return true
307
+ }
308
+
309
+ // Instagram Test Environment
310
+ export const INSTAGRAM_TEST_THREAD_ID = process.env.E2E_INSTAGRAM_THREAD_ID || ''
311
+ export const INSTAGRAM_TEST_USERNAME = process.env.E2E_INSTAGRAM_USERNAME || ''
312
+
313
+ export async function validateInstagramEnvironment(): Promise<boolean> {
314
+ if (!INSTAGRAM_TEST_THREAD_ID) {
315
+ console.warn('Skipping Instagram E2E: set E2E_INSTAGRAM_THREAD_ID to run against a dedicated test thread.')
316
+ return false
317
+ }
318
+
319
+ const { runCLI, parseJSON } = await import('./helpers')
320
+
321
+ const result = await runCLI('instagram', ['auth', 'status'])
322
+ if (result.exitCode !== 0) {
323
+ throw new Error('Instagram authentication failed. Run: agent-instagram auth login or agent-instagram auth extract')
324
+ }
325
+
326
+ const data = parseJSON<{ valid?: boolean }>(result.stdout)
327
+ if (data && 'valid' in data && !data.valid) {
328
+ throw new Error('Instagram credentials invalid. Run: agent-instagram auth login or agent-instagram auth extract')
329
+ }
330
+
331
+ return true
332
+ }
333
+
334
+ // KakaoTalk Test Environment
335
+ export const KAKAOTALK_TEST_CHAT_ID = process.env.E2E_KAKAOTALK_CHAT_ID || ''
336
+
337
+ export async function validateKakaoTalkEnvironment(): Promise<boolean> {
338
+ if (!KAKAOTALK_TEST_CHAT_ID) {
339
+ console.warn('Skipping KakaoTalk E2E: set E2E_KAKAOTALK_CHAT_ID to run against a dedicated test chat.')
340
+ return false
341
+ }
342
+
343
+ const { runCLI } = await import('./helpers')
344
+
345
+ const result = await runCLI('kakaotalk', ['auth', 'status'])
346
+ if (result.exitCode !== 0) {
347
+ throw new Error('KakaoTalk authentication failed. Run: agent-kakaotalk auth login or agent-kakaotalk auth extract')
348
+ }
349
+
350
+ return true
351
+ }
352
+
192
353
  // Channel (user-auth) Test Environment — requires E2E_CHANNEL_WORKSPACE_ID to opt-in.
193
354
  // The E2E group is auto-discovered by name from the workspace's group list.
194
355
  export const CHANNEL_TEST_WORKSPACE_ID = process.env.E2E_CHANNEL_WORKSPACE_ID || ''
195
356
  export const CHANNEL_TEST_WORKSPACE_NAME = process.env.E2E_CHANNEL_WORKSPACE_NAME || ''
196
357
 
197
- export async function validateChannelEnvironment(): Promise<{ groupId: string; groupName: string }> {
358
+ export async function validateChannelEnvironment(): Promise<{ groupId: string; groupName: string } | null> {
198
359
  if (!CHANNEL_TEST_WORKSPACE_ID) {
199
- throw new Error('Channel E2E environment not configured. Set E2E_CHANNEL_WORKSPACE_ID.')
360
+ console.warn('Skipping Channel E2E: set E2E_CHANNEL_WORKSPACE_ID to run against a dedicated test workspace.')
361
+ return null
200
362
  }
201
363
 
202
364
  const { runCLI, parseJSON } = await import('./helpers')
package/e2e/helpers.ts CHANGED
@@ -13,6 +13,13 @@ export async function runCLI(platform: string, args: string[]): Promise<CLIResul
13
13
  teams: 'agent-teams',
14
14
  channeltalkbot: 'agent-channeltalkbot',
15
15
  channeltalk: 'agent-channeltalk',
16
+ webex: 'agent-webex',
17
+ telegram: 'agent-telegram',
18
+ whatsapp: 'agent-whatsapp',
19
+ whatsappbot: 'agent-whatsappbot',
20
+ line: 'agent-line',
21
+ instagram: 'agent-instagram',
22
+ kakaotalk: 'agent-kakaotalk',
16
23
  }
17
24
  const command = commandMap[platform] || platform
18
25
 
@@ -0,0 +1,97 @@
1
+ import { afterEach, beforeAll, describe, expect, test } from 'bun:test'
2
+
3
+ import { INSTAGRAM_TEST_THREAD_ID, INSTAGRAM_TEST_USERNAME, validateInstagramEnvironment } from './config'
4
+ import { generateTestId, parseJSON, runCLI, waitForRateLimit } from './helpers'
5
+
6
+ let instagramAvailable = false
7
+
8
+ describe('Instagram E2E Tests', () => {
9
+ beforeAll(async () => {
10
+ instagramAvailable = await validateInstagramEnvironment()
11
+ })
12
+
13
+ afterEach(async () => {
14
+ await waitForRateLimit()
15
+ })
16
+
17
+ describe('auth', () => {
18
+ test('auth status returns exit code 0', async () => {
19
+ if (!instagramAvailable) return
20
+
21
+ const result = await runCLI('instagram', ['auth', 'status'])
22
+ expect(result.exitCode).toBe(0)
23
+ })
24
+
25
+ test('auth list returns accounts array', async () => {
26
+ if (!instagramAvailable) return
27
+
28
+ const result = await runCLI('instagram', ['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 (!instagramAvailable) return
39
+
40
+ const result = await runCLI('instagram', ['chat', 'list', '--limit', '5'])
41
+ expect(result.exitCode).toBe(0)
42
+
43
+ const data = parseJSON<unknown[] | { chats: unknown[] }>(result.stdout)
44
+ expect(data).toBeDefined()
45
+ })
46
+
47
+ test('chat search returns results', async () => {
48
+ if (!instagramAvailable) return
49
+
50
+ const result = await runCLI('instagram', ['chat', 'search', 'test', '--limit', '5'])
51
+ expect(result.exitCode).toBe(0)
52
+ })
53
+ })
54
+
55
+ describe('message', () => {
56
+ test('message send sends a message to thread', async () => {
57
+ if (!instagramAvailable) return
58
+
59
+ const testId = generateTestId()
60
+ const result = await runCLI('instagram', ['message', 'send', INSTAGRAM_TEST_THREAD_ID, `e2e ${testId}`])
61
+ expect(result.exitCode).toBe(0)
62
+ })
63
+
64
+ test('message list returns messages from thread', async () => {
65
+ if (!instagramAvailable) return
66
+
67
+ const result = await runCLI('instagram', ['message', 'list', INSTAGRAM_TEST_THREAD_ID, '--limit', '5'])
68
+ expect(result.exitCode).toBe(0)
69
+
70
+ const data = parseJSON<unknown[] | { messages: unknown[] }>(result.stdout)
71
+ expect(data).toBeDefined()
72
+ })
73
+
74
+ test('message send-to sends a message to username', async () => {
75
+ if (!instagramAvailable) return
76
+ if (!INSTAGRAM_TEST_USERNAME) return
77
+
78
+ const testId = generateTestId()
79
+ const result = await runCLI('instagram', ['message', 'send-to', INSTAGRAM_TEST_USERNAME, `e2e ${testId}`])
80
+ expect(result.exitCode).toBe(0)
81
+ })
82
+
83
+ test('message search returns results', async () => {
84
+ if (!instagramAvailable) return
85
+
86
+ const result = await runCLI('instagram', ['message', 'search', 'test', '--limit', '5'])
87
+ expect(result.exitCode).toBe(0)
88
+ })
89
+
90
+ test('message search-users returns results', async () => {
91
+ if (!instagramAvailable) return
92
+
93
+ const result = await runCLI('instagram', ['message', 'search-users', 'test'])
94
+ expect(result.exitCode).toBe(0)
95
+ })
96
+ })
97
+ })
@@ -0,0 +1,74 @@
1
+ import { afterEach, beforeAll, describe, expect, test } from 'bun:test'
2
+
3
+ import { KAKAOTALK_TEST_CHAT_ID, validateKakaoTalkEnvironment } from './config'
4
+ import { generateTestId, parseJSON, runCLI, waitForRateLimit } from './helpers'
5
+
6
+ let kakaotalkAvailable = false
7
+
8
+ describe('KakaoTalk E2E Tests', () => {
9
+ beforeAll(async () => {
10
+ kakaotalkAvailable = await validateKakaoTalkEnvironment()
11
+ })
12
+
13
+ afterEach(async () => {
14
+ await waitForRateLimit()
15
+ })
16
+
17
+ describe('auth', () => {
18
+ test('auth status returns valid auth info', async () => {
19
+ if (!kakaotalkAvailable) return
20
+
21
+ const result = await runCLI('kakaotalk', ['auth', 'status'])
22
+ expect(result.exitCode).toBe(0)
23
+ })
24
+
25
+ test('auth list returns accounts array', async () => {
26
+ if (!kakaotalkAvailable) return
27
+
28
+ const result = await runCLI('kakaotalk', ['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 (!kakaotalkAvailable) return
39
+
40
+ const result = await runCLI('kakaotalk', ['chat', 'list'])
41
+ expect(result.exitCode).toBe(0)
42
+
43
+ const data = parseJSON<unknown>(result.stdout)
44
+ expect(data).toBeDefined()
45
+ })
46
+
47
+ test('chat list with search filter returns chats', async () => {
48
+ if (!kakaotalkAvailable) return
49
+
50
+ const result = await runCLI('kakaotalk', ['chat', 'list', '--search', 'test'])
51
+ expect(result.exitCode).toBe(0)
52
+ })
53
+ })
54
+
55
+ describe('message', () => {
56
+ test('message send sends a message to the test chat', async () => {
57
+ if (!kakaotalkAvailable) return
58
+
59
+ const testId = generateTestId()
60
+ const result = await runCLI('kakaotalk', ['message', 'send', KAKAOTALK_TEST_CHAT_ID, `e2e ${testId}`])
61
+ expect(result.exitCode).toBe(0)
62
+ })
63
+
64
+ test('message list returns messages from the test chat', async () => {
65
+ if (!kakaotalkAvailable) return
66
+
67
+ const result = await runCLI('kakaotalk', ['message', 'list', KAKAOTALK_TEST_CHAT_ID, '-n', '5'])
68
+ expect(result.exitCode).toBe(0)
69
+
70
+ const data = parseJSON<unknown>(result.stdout)
71
+ expect(data).toBeDefined()
72
+ })
73
+ })
74
+ })
@@ -0,0 +1,92 @@
1
+ import { afterEach, beforeAll, describe, expect, test } from 'bun:test'
2
+
3
+ import { LINE_TEST_CHAT_ID, validateLineEnvironment } from './config'
4
+ import { generateTestId, parseJSON, runCLI, waitForRateLimit } from './helpers'
5
+
6
+ let lineAvailable = false
7
+
8
+ describe('LINE E2E Tests', () => {
9
+ beforeAll(async () => {
10
+ lineAvailable = await validateLineEnvironment()
11
+ })
12
+
13
+ afterEach(async () => {
14
+ await waitForRateLimit()
15
+ })
16
+
17
+ describe('auth', () => {
18
+ test('auth status returns valid auth info', async () => {
19
+ if (!lineAvailable) return
20
+
21
+ const result = await runCLI('line', ['auth', 'status'])
22
+ expect(result.exitCode).toBe(0)
23
+ })
24
+
25
+ test('auth list returns accounts array', async () => {
26
+ if (!lineAvailable) return
27
+
28
+ const result = await runCLI('line', ['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 (!lineAvailable) return
39
+
40
+ const result = await runCLI('line', ['chat', 'list', '--limit', '5'])
41
+ expect(result.exitCode).toBe(0)
42
+
43
+ const data = parseJSON<unknown>(result.stdout)
44
+ expect(data).toBeDefined()
45
+ })
46
+ })
47
+
48
+ describe('friend', () => {
49
+ test('friend list returns friends', async () => {
50
+ if (!lineAvailable) return
51
+
52
+ const result = await runCLI('line', ['friend', 'list'])
53
+ expect(result.exitCode).toBe(0)
54
+
55
+ const data = parseJSON<unknown>(result.stdout)
56
+ expect(data).toBeDefined()
57
+ })
58
+ })
59
+
60
+ describe('message', () => {
61
+ test('message send sends a message to the test chat', async () => {
62
+ if (!lineAvailable) return
63
+
64
+ const testId = generateTestId()
65
+ const result = await runCLI('line', ['message', 'send', LINE_TEST_CHAT_ID, `e2e ${testId}`])
66
+ expect(result.exitCode).toBe(0)
67
+ })
68
+
69
+ test('message list returns messages from the test chat', async () => {
70
+ if (!lineAvailable) return
71
+
72
+ const result = await runCLI('line', ['message', 'list', LINE_TEST_CHAT_ID, '-n', '5'])
73
+ expect(result.exitCode).toBe(0)
74
+
75
+ const data = parseJSON<unknown>(result.stdout)
76
+ expect(data).toBeDefined()
77
+ })
78
+ })
79
+
80
+ describe('profile', () => {
81
+ test('profile returns current user profile', async () => {
82
+ if (!lineAvailable) return
83
+
84
+ const result = await runCLI('line', ['profile'])
85
+ expect(result.exitCode).toBe(0)
86
+
87
+ const data = parseJSON<Record<string, unknown>>(result.stdout)
88
+ expect(data).toBeDefined()
89
+ expect(typeof data).toBe('object')
90
+ })
91
+ })
92
+ })