agent-messenger 2.31.0 → 2.32.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/README.md +14 -1
  3. package/bun.lock +7 -0
  4. package/dist/package.json +2 -1
  5. package/dist/src/platforms/channeltalk/token-extractor.d.ts.map +1 -1
  6. package/dist/src/platforms/channeltalk/token-extractor.js +67 -18
  7. package/dist/src/platforms/channeltalk/token-extractor.js.map +1 -1
  8. package/dist/src/platforms/discord/client.d.ts +11 -2
  9. package/dist/src/platforms/discord/client.d.ts.map +1 -1
  10. package/dist/src/platforms/discord/client.js +109 -4
  11. package/dist/src/platforms/discord/client.js.map +1 -1
  12. package/dist/src/platforms/discord/commands/channel.d.ts.map +1 -1
  13. package/dist/src/platforms/discord/commands/channel.js +3 -2
  14. package/dist/src/platforms/discord/commands/channel.js.map +1 -1
  15. package/dist/src/platforms/discord/commands/mention.d.ts +5 -0
  16. package/dist/src/platforms/discord/commands/mention.d.ts.map +1 -1
  17. package/dist/src/platforms/discord/commands/mention.js +60 -4
  18. package/dist/src/platforms/discord/commands/mention.js.map +1 -1
  19. package/dist/src/platforms/discord/commands/reaction.js +1 -1
  20. package/dist/src/platforms/discord/commands/reaction.js.map +1 -1
  21. package/dist/src/platforms/discord/commands/snapshot.d.ts.map +1 -1
  22. package/dist/src/platforms/discord/commands/snapshot.js +7 -6
  23. package/dist/src/platforms/discord/commands/snapshot.js.map +1 -1
  24. package/dist/src/platforms/discord/index.d.ts +1 -1
  25. package/dist/src/platforms/discord/index.d.ts.map +1 -1
  26. package/dist/src/platforms/discord/index.js.map +1 -1
  27. package/dist/src/platforms/discord/listener.d.ts +4 -1
  28. package/dist/src/platforms/discord/listener.d.ts.map +1 -1
  29. package/dist/src/platforms/discord/listener.js +28 -1
  30. package/dist/src/platforms/discord/listener.js.map +1 -1
  31. package/dist/src/platforms/discord/types.d.ts +60 -9
  32. package/dist/src/platforms/discord/types.d.ts.map +1 -1
  33. package/dist/src/platforms/discord/types.js +58 -7
  34. package/dist/src/platforms/discord/types.js.map +1 -1
  35. package/dist/src/platforms/slack/index.d.ts +1 -0
  36. package/dist/src/platforms/slack/index.d.ts.map +1 -1
  37. package/dist/src/platforms/slack/index.js.map +1 -1
  38. package/dist/src/platforms/slack/qr-confirmation.d.ts +19 -0
  39. package/dist/src/platforms/slack/qr-confirmation.d.ts.map +1 -0
  40. package/dist/src/platforms/slack/qr-confirmation.js +68 -0
  41. package/dist/src/platforms/slack/qr-confirmation.js.map +1 -0
  42. package/dist/src/platforms/slack/qr-cookie-jar.d.ts +7 -0
  43. package/dist/src/platforms/slack/qr-cookie-jar.d.ts.map +1 -0
  44. package/dist/src/platforms/slack/qr-cookie-jar.js +48 -0
  45. package/dist/src/platforms/slack/qr-cookie-jar.js.map +1 -0
  46. package/dist/src/platforms/slack/qr-http-login.d.ts +2 -1
  47. package/dist/src/platforms/slack/qr-http-login.d.ts.map +1 -1
  48. package/dist/src/platforms/slack/qr-http-login.js +88 -53
  49. package/dist/src/platforms/slack/qr-http-login.js.map +1 -1
  50. package/docs/content/docs/cli/channeltalk.mdx +4 -4
  51. package/docs/content/docs/cli/discord.mdx +7 -0
  52. package/docs/content/docs/sdk/discord.mdx +38 -0
  53. package/e2e/README.md +2 -2
  54. package/e2e/discord.e2e.test.ts +16 -2
  55. package/package.json +2 -1
  56. package/skills/agent-channeltalk/SKILL.md +5 -5
  57. package/skills/agent-channeltalk/references/authentication.md +9 -5
  58. package/skills/agent-channeltalkbot/SKILL.md +1 -1
  59. package/skills/agent-discord/SKILL.md +26 -4
  60. package/skills/agent-discord/references/common-patterns.md +7 -3
  61. package/skills/agent-discordbot/SKILL.md +1 -1
  62. package/skills/agent-imessage/SKILL.md +1 -1
  63. package/skills/agent-instagram/SKILL.md +1 -1
  64. package/skills/agent-kakaotalk/SKILL.md +1 -1
  65. package/skills/agent-line/SKILL.md +1 -1
  66. package/skills/agent-slack/SKILL.md +25 -2
  67. package/skills/agent-slackbot/SKILL.md +1 -1
  68. package/skills/agent-teams/SKILL.md +1 -1
  69. package/skills/agent-telegram/SKILL.md +1 -1
  70. package/skills/agent-telegrambot/SKILL.md +1 -1
  71. package/skills/agent-webex/SKILL.md +1 -1
  72. package/skills/agent-webexbot/SKILL.md +1 -1
  73. package/skills/agent-wechatbot/SKILL.md +1 -1
  74. package/skills/agent-whatsapp/SKILL.md +1 -1
  75. package/skills/agent-whatsappbot/SKILL.md +1 -1
  76. package/src/platforms/channeltalk/token-extractor.test.ts +235 -0
  77. package/src/platforms/channeltalk/token-extractor.ts +81 -22
  78. package/src/platforms/discord/client.test.ts +230 -9
  79. package/src/platforms/discord/client.ts +122 -5
  80. package/src/platforms/discord/commands/channel.test.ts +33 -23
  81. package/src/platforms/discord/commands/channel.ts +3 -2
  82. package/src/platforms/discord/commands/mention.test.ts +84 -0
  83. package/src/platforms/discord/commands/mention.ts +78 -15
  84. package/src/platforms/discord/commands/reaction.test.ts +1 -1
  85. package/src/platforms/discord/commands/reaction.ts +1 -1
  86. package/src/platforms/discord/commands/snapshot.test.ts +80 -2
  87. package/src/platforms/discord/commands/snapshot.ts +7 -6
  88. package/src/platforms/discord/index.ts +3 -0
  89. package/src/platforms/discord/listener.test.ts +69 -2
  90. package/src/platforms/discord/listener.ts +31 -2
  91. package/src/platforms/discord/types.test.ts +56 -0
  92. package/src/platforms/discord/types.ts +91 -10
  93. package/src/platforms/slack/index.ts +1 -0
  94. package/src/platforms/slack/qr-confirmation.ts +86 -0
  95. package/src/platforms/slack/qr-cookie-jar.ts +54 -0
  96. package/src/platforms/slack/qr-http-login-2fa.test.ts +398 -0
  97. package/src/platforms/slack/qr-http-login.test.ts +10 -18
  98. package/src/platforms/slack/qr-http-login.ts +109 -52
@@ -144,8 +144,19 @@ const dm = await client.createDM(userId)
144
144
  const mentions = await client.getMentions()
145
145
  const filtered = await client.getMentions({ limit: 10, guildId: serverId })
146
146
  // → DiscordMention[]
147
+
148
+ // Get only unread mentions — the messages behind Discord's unread-mention badge
149
+ const unread = await client.getUnreadMentions()
150
+ const scoped = await client.getUnreadMentions({ guildId: serverId, limit: 200 })
151
+ // → DiscordUnreadMentionsResult { mentions, count, badgeCount, complete, windowDays }
152
+
153
+ // Snapshot per-channel read state directly (one-shot gateway connect)
154
+ const readState = await client.fetchReadState()
155
+ // → DiscordReadState[] { channelId, lastMessageId, mentionCount }
147
156
  ```
148
157
 
158
+ `getUnreadMentions` correlates recent mention history (Discord's 7-day window) with per-channel read state, returning only mentions newer than each channel's read marker. `count` is the number of enumerated unread mentions; `badgeCount` is Discord's own account-wide unread-mention badge total (not narrowed by `guildId`, since read states carry no guild association); `complete` is `true` when the scan exhausted all available mention history (Discord's 7-day window) and `false` when it stopped early at `limit` or a non-advancing cursor.
159
+
149
160
  ### User Notes
150
161
 
151
162
  ```typescript
@@ -345,6 +356,9 @@ import type {
345
356
  DiscordReaction,
346
357
  DiscordFile,
347
358
  DiscordMention,
359
+ DiscordReadState,
360
+ DiscordUnreadMention,
361
+ DiscordUnreadMentionsResult,
348
362
  DiscordUserNote,
349
363
  DiscordSearchResult,
350
364
  DiscordSearchResponse,
@@ -478,6 +492,30 @@ for (const mention of mentions) {
478
492
  }
479
493
  ```
480
494
 
495
+ ### Unread Mentions Digest
496
+
497
+ Fetch only unread mentions, reply to each, and mark them read.
498
+
499
+ ```typescript
500
+ import { DiscordClient } from 'agent-messenger/discord'
501
+
502
+ const client = await new DiscordClient().login({ token })
503
+
504
+ const { mentions, count, badgeCount, complete } = await client.getUnreadMentions()
505
+
506
+ console.log(`${count} unread mentions fetched (badge shows ${badgeCount})`)
507
+ if (!complete) {
508
+ console.log('The scan hit the limit — some unread mentions may not have been fetched')
509
+ }
510
+
511
+ for (const mention of mentions) {
512
+ await client.sendMessage(mention.channel_id, `On it <@${mention.author.id}>!`)
513
+
514
+ // Mark the message read so it drops off the unread badge
515
+ await client.ackMessage(mention.channel_id, mention.id)
516
+ }
517
+ ```
518
+
481
519
  ### Search Triage
482
520
 
483
521
  Search for urgent messages, acknowledge with a reaction, and reply with a follow-up.
package/e2e/README.md CHANGED
@@ -199,10 +199,10 @@ When triggering manually, you can select which platform to test:
199
199
  | ------------- | ------------------------------------------ |
200
200
  | `auth` | status |
201
201
  | `server` | list, current, info |
202
- | `message` | send, list, get\*, delete, ack, search |
202
+ | `message` | send, list, get, delete, ack, search |
203
203
  | `channel` | list, info, history |
204
204
  | `user` | list\*, me, info |
205
- | `reaction` | add\*, list\*, remove\* |
205
+ | `reaction` | add, list, remove |
206
206
  | `file` | upload, list, info |
207
207
  | `snapshot` | default\*, --channels-only, --users-only\* |
208
208
 
@@ -83,7 +83,7 @@ describe('Discord E2E Tests', () => {
83
83
  expect(Array.isArray(data)).toBe(true)
84
84
  })
85
85
 
86
- it.skip('message get retrieves specific message (requires bot token)', async () => {
86
+ it('message get retrieves specific message', async () => {
87
87
  const testId = generateTestId()
88
88
  const { id } = await createTestMessage('discord', DISCORD_TEST_CHANNEL_ID, `Get test ${testId}`)
89
89
  testMessages.push(id)
@@ -194,7 +194,7 @@ describe('Discord E2E Tests', () => {
194
194
  })
195
195
 
196
196
  describe('reaction', () => {
197
- it.skip('reaction add/list/remove lifecycle (requires bot token)', async () => {
197
+ it('reaction add/list/remove lifecycle', async () => {
198
198
  const testId = generateTestId()
199
199
  const { id } = await createTestMessage('discord', DISCORD_TEST_CHANNEL_ID, `Reaction test ${testId}`)
200
200
  testMessages.push(id)
@@ -210,12 +210,26 @@ describe('Discord E2E Tests', () => {
210
210
  // List reactions
211
211
  const listResult = await runCLI('discord', ['reaction', 'list', DISCORD_TEST_CHANNEL_ID, id])
212
212
  expect(listResult.exitCode).toBe(0)
213
+ const listed = parseJSON<{ reactions: Array<{ emoji: { name: string | null }; count: number }> }>(
214
+ listResult.stdout,
215
+ )
216
+ const addedReaction = listed?.reactions.find((reaction) => reaction.emoji.name === '👍')
217
+ expect(addedReaction?.count).toBeGreaterThan(0)
213
218
 
214
219
  await waitForRateLimit()
215
220
 
216
221
  // Remove reaction
217
222
  const removeResult = await runCLI('discord', ['reaction', 'remove', DISCORD_TEST_CHANNEL_ID, id, '👍'])
218
223
  expect(removeResult.exitCode).toBe(0)
224
+
225
+ await waitForRateLimit()
226
+
227
+ const afterRemoveResult = await runCLI('discord', ['reaction', 'list', DISCORD_TEST_CHANNEL_ID, id])
228
+ expect(afterRemoveResult.exitCode).toBe(0)
229
+ const afterRemove = parseJSON<{ reactions: Array<{ emoji: { name: string | null }; count: number }> }>(
230
+ afterRemoveResult.stdout,
231
+ )
232
+ expect(afterRemove?.reactions.find((reaction) => reaction.emoji.name === '👍')).toBeUndefined()
219
233
  }, 15000) // Longer timeout for multiple operations
220
234
  })
221
235
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-messenger",
3
- "version": "2.31.0",
3
+ "version": "2.32.1",
4
4
  "description": "Multi-platform messaging CLI for AI agents (Slack, Discord, Teams, Webex, Telegram, Telegram Bot, WhatsApp, LINE, iMessage, Instagram, KakaoTalk, Channel Talk)",
5
5
  "repository": {
6
6
  "type": "git",
@@ -193,6 +193,7 @@
193
193
  "pngjs": "^7.0.0",
194
194
  "qrcode": "^1.5.4",
195
195
  "thrift": "^0.20.0",
196
+ "tough-cookie": "^6.0.2",
196
197
  "tweetnacl": "^1.0.3",
197
198
  "webex-message-handler": "^0.6.10",
198
199
  "ws": "^8.19.0",
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: agent-channeltalk
3
3
  description: Interact with Channel Talk using extracted desktop app or browser credentials - read chats, send messages, search messages, manage groups
4
- version: 2.31.0
4
+ version: 2.32.1
5
5
  allowed-tools: Bash(agent-channeltalk:*)
6
6
  metadata:
7
7
  openclaw:
@@ -438,14 +438,14 @@ npx -y agent-messenger channeltalk snapshot --pretty
438
438
 
439
439
  ### Channel Talk desktop app not found
440
440
 
441
- The CLI looks for the Channel Talk desktop app's cookie database in these locations:
441
+ The CLI looks for the desktop app's cookie database in these locations. The app was rebranded from Channel Talk to Channel Works, so both names are probed, `Channel Works` first.
442
442
 
443
443
  **macOS:**
444
- 1. `~/Library/Containers/com.zoyi.channel.desk.osx/Data/Library/Application Support/Channel Talk/Cookies` (Mac App Store version)
445
- 2. `~/Library/Application Support/Channel Talk/Cookies` (direct download / Electron version)
444
+ 1. `~/Library/Containers/com.zoyi.channel.desk.osx/Data/Library/Application Support/{Channel Works,Channel Talk}/Cookies` (Mac App Store version)
445
+ 2. `~/Library/Application Support/{Channel Works,Channel Talk}/Cookies` (direct download / Electron version)
446
446
 
447
447
  **Windows:**
448
- 1. `%APPDATA%\Channel Talk\Network\Cookies`
448
+ 1. `%APPDATA%\{Channel Works,Channel Talk}\Network\Cookies`
449
449
 
450
450
  If none exist, log in to Channel Talk in a supported Chromium browser (Chrome, Edge, Arc, Brave) or install the desktop app and log in.
451
451
 
@@ -29,7 +29,7 @@ Use `--browser-profile <path>` for agent-browser profiles, custom Chrome user da
29
29
  1. Locates the Channel Talk desktop app's SQLite cookie database
30
30
  2. Scans Chromium browser profiles for Channel Talk cookies when the desktop app isn't found, or when custom `--browser-profile` paths are provided
31
31
  3. Copies the database to a temp file (avoids locking the original)
32
- 4. Reads `x-account` and `ch-session-1` cookies for `*.channel.io`
32
+ 4. Reads `x-account` and `ch-session-1` cookies for `*.channel.io` and `*.channel.works`
33
33
  5. Decrypts encrypted cookies if needed (macOS Keychain, Linux peanuts, Windows DPAPI)
34
34
  6. Validates cookies against the Channel Talk API
35
35
  7. Discovers ALL workspaces you belong to
@@ -48,15 +48,19 @@ When extracting from the desktop app, no Keychain prompt is needed (cookies are
48
48
 
49
49
  ### Platform-Specific Paths
50
50
 
51
+ The desktop app was rebranded from Channel Talk to Channel Works. Both directory names are probed, `Channel Works` first, so upgraded and legacy installs both work.
52
+
51
53
  **macOS (Mac App Store / sandboxed):**
52
54
 
53
55
  ```
56
+ ~/Library/Containers/com.zoyi.channel.desk.osx/Data/Library/Application Support/Channel Works/Cookies
54
57
  ~/Library/Containers/com.zoyi.channel.desk.osx/Data/Library/Application Support/Channel Talk/Cookies
55
58
  ```
56
59
 
57
60
  **macOS (Electron / direct download):**
58
61
 
59
62
  ```
63
+ ~/Library/Application Support/Channel Works/Cookies
60
64
  ~/Library/Application Support/Channel Talk/Cookies
61
65
  ```
62
66
 
@@ -253,10 +257,10 @@ No credentials are configured and auto-extraction failed:
253
257
 
254
258
  The CLI first checks for the desktop app, then falls back to Chromium browsers.
255
259
 
256
- Desktop app paths:
257
- 1. **macOS (Mac App Store)**: `~/Library/Containers/com.zoyi.channel.desk.osx/Data/Library/Application Support/Channel Talk/Cookies`
258
- 2. **macOS (Electron)**: `~/Library/Application Support/Channel Talk/Cookies`
259
- 3. **Windows**: `%APPDATA%/Channel Talk/Network/Cookies`
260
+ Desktop app paths (`Channel Works` is the current name, `Channel Talk` the legacy one; both are probed):
261
+ 1. **macOS (Mac App Store)**: `~/Library/Containers/com.zoyi.channel.desk.osx/Data/Library/Application Support/{Channel Works,Channel Talk}/Cookies`
262
+ 2. **macOS (Electron)**: `~/Library/Application Support/{Channel Works,Channel Talk}/Cookies`
263
+ 3. **Windows**: `%APPDATA%/{Channel Works,Channel Talk}/Network/Cookies`
260
264
 
261
265
  If neither the desktop app nor browser cookies are found:
262
266
 
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: agent-channeltalkbot
3
3
  description: Interact with Channel Talk workspaces using API credentials - send messages, read chats, manage groups and bots
4
- version: 2.31.0
4
+ version: 2.32.1
5
5
  allowed-tools: Bash(agent-channeltalkbot:*)
6
6
  metadata:
7
7
  openclaw:
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: agent-discord
3
3
  description: Interact with Discord servers - send messages, read channels, manage reactions
4
- version: 2.31.0
4
+ version: 2.32.1
5
5
  allowed-tools: Bash(agent-discord:*)
6
6
  metadata:
7
7
  openclaw:
@@ -212,7 +212,9 @@ agent-discord message search "hello" --channel <channel-id> --author <user-id>
212
212
  ### Channel Commands
213
213
 
214
214
  ```bash
215
- # List channels in current server (text channels only)
215
+ # List channels in current server
216
+ # Includes text, announcement, voice/stage (voice channels carry text chat),
217
+ # forum, media, and directory channels. Categories and threads are excluded.
216
218
  agent-discord channel list
217
219
 
218
220
  # Get channel info
@@ -269,8 +271,20 @@ agent-discord dm create <user-id>
269
271
  agent-discord mention list
270
272
  agent-discord mention list --limit 50
271
273
  agent-discord mention list --guild <server-id>
274
+
275
+ # List only unread mentions (the app's unread-mention badge)
276
+ agent-discord mention unread
277
+ agent-discord mention unread --guild <server-id>
278
+ agent-discord mention unread --limit 200
272
279
  ```
273
280
 
281
+ `mention unread` correlates your recent mention history (last 7 days) with Discord's
282
+ per-channel read state, returning only mentions newer than each channel's read marker.
283
+ Output includes `count` (enumerated unread mentions), `badge_count` (Discord's own
284
+ account-wide unread-mention badge total — not narrowed by `--guild`), and `complete`
285
+ (whether the scan reached the end of history within the 7-day window). `badge_count`
286
+ can exceed `count` when unread mentions fall outside the 7-day window.
287
+
274
288
  ### Friend Commands
275
289
 
276
290
  ```bash
@@ -365,9 +379,11 @@ agent-discord snapshot --full --limit 10
365
379
  Default returns brief JSON with:
366
380
 
367
381
  - Server metadata (id, name)
368
- - Channels (id, name) — text channels only
382
+ - Channels (id, name) — all listable channels (text, announcement, voice/stage, forum, media, directory; excludes categories and threads)
369
383
  - Hint for next commands
370
384
 
385
+ > Not every listed channel accepts a direct `message list`. Forum, media, and directory channels are containers or hub views with no direct message timeline — their messages live in child posts/threads. Use text, announcement, voice, or stage channels for `message list`.
386
+
371
387
  With `--full`, returns comprehensive JSON with:
372
388
 
373
389
  - Server metadata (id, name)
@@ -503,6 +519,12 @@ const { results } = await client.searchMessages(serverId, 'deployment', {
503
519
  limit: 5,
504
520
  })
505
521
 
522
+ // List unread mentions (correlates mention history with per-channel read state)
523
+ const { mentions, count, badgeCount, complete } = await client.getUnreadMentions()
524
+ // count = enumerated unread mentions; badgeCount = account-wide badge total;
525
+ // complete = true when all available mentions (7-day window) were scanned,
526
+ // false when the scan stopped early at the limit or a non-advancing cursor
527
+
506
528
  // Create a thread
507
529
  const thread = await client.createThread(channelId, 'Discussion Topic')
508
530
  await client.sendMessage(thread.id, 'First message in thread')
@@ -538,7 +560,7 @@ See the [Discord SDK documentation](https://agent-messenger.dev/docs/sdk/discord
538
560
 
539
561
  ## Limitations
540
562
 
541
- - No voice channel support
563
+ - No voice audio support (voice/stage channels are listed and their embedded text chat is readable, but joining voice or streaming audio is unsupported)
542
564
  - No server management (create/delete channels, roles)
543
565
  - No slash commands
544
566
  - No webhook support
@@ -87,12 +87,16 @@ CHANNEL_COUNT=$(echo "$SNAPSHOT" | jq -r '.channels | length')
87
87
  echo "Server: $SERVER_NAME"
88
88
  echo "Channels: $CHANNEL_COUNT"
89
89
 
90
- # List all text channels
90
+ # List all channels
91
91
  echo -e "\nChannels:"
92
92
  echo "$SNAPSHOT" | jq -r '.channels[] | " #\(.name) (\(.id))"'
93
93
 
94
- # Then drill into a specific channel for recent activity
95
- CHANNEL_ID=$(echo "$SNAPSHOT" | jq -r '.channels[0].id // empty')
94
+ # Then drill into a specific channel for recent activity.
95
+ # Only text (0), announcement (5), voice (2), and stage (13) channels accept
96
+ # `message list`; forum (15), media (16), and directory (14) channels do not.
97
+ # A full snapshot includes `type`, so pick the first message-readable channel.
98
+ FULL=$(agent-discord snapshot --full)
99
+ CHANNEL_ID=$(echo "$FULL" | jq -r '[.channels[] | select(.type == 0 or .type == 5 or .type == 2 or .type == 13)][0].id // empty')
96
100
  if [ -n "$CHANNEL_ID" ]; then
97
101
  echo -e "\nRecent messages:"
98
102
  agent-discord message list "$CHANNEL_ID" --limit 10
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: agent-discordbot
3
3
  description: Interact with Discord servers using bot tokens - send messages, read channels, manage reactions
4
- version: 2.31.0
4
+ version: 2.32.1
5
5
  allowed-tools: Bash(agent-discordbot:*)
6
6
  metadata:
7
7
  openclaw:
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: agent-imessage
3
3
  description: Interact with iMessage on a Mac via the imsg tool - send messages, read chats, watch for new messages
4
- version: 2.31.0
4
+ version: 2.32.1
5
5
  allowed-tools: Bash(agent-imessage:*)
6
6
  metadata:
7
7
  openclaw:
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: agent-instagram
3
3
  description: Interact with Instagram DMs - send messages, read conversations, manage accounts
4
- version: 2.31.0
4
+ version: 2.32.1
5
5
  allowed-tools: Bash(agent-instagram:*)
6
6
  metadata:
7
7
  openclaw:
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: agent-kakaotalk
3
3
  description: Interact with KakaoTalk - send messages, read chats, manage conversations
4
- version: 2.31.0
4
+ version: 2.32.1
5
5
  allowed-tools: Bash(agent-kakaotalk:*)
6
6
  metadata:
7
7
  openclaw:
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: agent-line
3
3
  description: Interact with LINE - send messages, read chats, manage conversations
4
- version: 2.31.0
4
+ version: 2.32.1
5
5
  allowed-tools: Bash(agent-line:*)
6
6
  metadata:
7
7
  openclaw:
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: agent-slack
3
3
  description: Interact with Slack workspaces - send messages, read channels, manage reactions
4
- version: 2.31.0
4
+ version: 2.32.1
5
5
  allowed-tools: Bash(agent-slack:*)
6
6
  metadata:
7
7
  openclaw:
@@ -607,7 +607,30 @@ await new SlackCredentialManager().setWorkspace({
607
607
  })
608
608
  ```
609
609
 
610
- `loginWithQr(dataUrl, options)` accepts an optional `{ debug, fetchImpl, maxRedirects }`. It throws `SlackError` with codes `qr_session_failed` (link expired / no session) or `qr_token_failed` (token could not be retrieved). To decode the QR without logging in, use `decodeSlackQr(dataUrl)` which returns `{ url, workspace, teamId, userId }`.
610
+ `loginWithQr(dataUrl, options)` accepts an optional `{ debug, fetchImpl, maxRedirects, requestConfirmationCode }`. It throws `SlackError` with codes `qr_session_failed` (link expired / no session) or `qr_token_failed` (token could not be retrieved). To decode the QR without logging in, use `decodeSlackQr(dataUrl)` which returns `{ url, workspace, teamId, userId }`.
611
+
612
+ ### Handling Slack confirmation codes (workspace 2FA)
613
+
614
+ Some workspaces make a QR sign-in surface a confirmation-code page (email code, SMS, TOTP, etc.) before issuing the session cookie. Pass `requestConfirmationCode` to complete that step. The callback is only invoked when Slack actually shows a confirmation page — ordinary QR logins that receive the session cookie directly stay prompt-free.
615
+
616
+ ```typescript
617
+ import { loginWithQr, type SlackConfirmationChallenge } from 'agent-messenger/slack'
618
+
619
+ const session = await loginWithQr(dataUrl, {
620
+ requestConfirmationCode: async (challenge: SlackConfirmationChallenge) => {
621
+ // challenge.email is the address Slack sent the code to.
622
+ // challenge.type is the mechanism ("email", "sms", "totp", ...) or null if unknown.
623
+ return await promptUserForCode(challenge)
624
+ },
625
+ })
626
+ ```
627
+
628
+ Contract:
629
+
630
+ - Return the raw code as a `string`. Whitespace is trimmed before submission.
631
+ - Return an empty string (or all whitespace) to abort — `loginWithQr` throws `qr_session_failed` and no code is posted.
632
+ - The code is submitted to the exact `https://<workspace>.slack.com/login/<qrSecret>` endpoint bound to the QR payload. Redirects to a different workspace host or an unexpected pathname reject the flow before the callback is invoked.
633
+ - The callback and `email`/`type` fields never appear in `debug` output.
611
634
 
612
635
  ## SDK: Real-Time Events
613
636
 
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: agent-slackbot
3
3
  description: Interact with Slack workspaces using bot tokens - send messages, read channels, manage reactions
4
- version: 2.31.0
4
+ version: 2.32.1
5
5
  allowed-tools: Bash(agent-slackbot:*)
6
6
  metadata:
7
7
  openclaw:
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: agent-teams
3
3
  description: Interact with Microsoft Teams - send messages, read channels, manage reactions
4
- version: 2.31.0
4
+ version: 2.32.1
5
5
  allowed-tools: Bash(agent-teams:*)
6
6
  metadata:
7
7
  openclaw:
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: agent-telegram
3
3
  description: Interact with Telegram through TDLib - authenticate, inspect chats, and send messages
4
- version: 2.31.0
4
+ version: 2.32.1
5
5
  allowed-tools: Bash(agent-telegram:*)
6
6
  ---
7
7
 
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: agent-telegrambot
3
3
  description: Interact with Telegram using bot tokens - send messages, read chats, manage reactions
4
- version: 2.31.0
4
+ version: 2.32.1
5
5
  allowed-tools: Bash(agent-telegrambot:*)
6
6
  metadata:
7
7
  openclaw:
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: agent-webex
3
3
  description: Interact with Cisco Webex - send messages, read spaces, manage memberships
4
- version: 2.31.0
4
+ version: 2.32.1
5
5
  allowed-tools: Bash(agent-webex:*)
6
6
  metadata:
7
7
  openclaw:
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: agent-webexbot
3
3
  description: Interact with Cisco Webex using bot tokens - send messages, reply in threads, upload and download files, look up people, read spaces, manage memberships, stream real-time events
4
- version: 2.31.0
4
+ version: 2.32.1
5
5
  allowed-tools: Bash(agent-webexbot:*)
6
6
  metadata:
7
7
  openclaw:
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: agent-wechatbot
3
3
  description: Interact with WeChat Official Account using API credentials - send messages, manage templates, list followers
4
- version: 2.31.0
4
+ version: 2.32.1
5
5
  allowed-tools: Bash(agent-wechatbot:*)
6
6
  metadata:
7
7
  openclaw:
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: agent-whatsapp
3
3
  description: Interact with WhatsApp - send messages, read chats, manage conversations
4
- version: 2.31.0
4
+ version: 2.32.1
5
5
  allowed-tools: Bash(agent-whatsapp:*)
6
6
  metadata:
7
7
  openclaw:
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: agent-whatsappbot
3
3
  description: Interact with WhatsApp using Cloud API credentials - send messages, manage templates
4
- version: 2.31.0
4
+ version: 2.32.1
5
5
  allowed-tools: Bash(agent-whatsappbot:*)
6
6
  metadata:
7
7
  openclaw: