Skip to content

Merge upstream (devxoul/agent-messenger main) — 468 commits#1

Merged
code-yeongyu merged 469 commits into
mainfrom
merge-upstream
Mar 23, 2026
Merged

Merge upstream (devxoul/agent-messenger main) — 468 commits#1
code-yeongyu merged 469 commits into
mainfrom
merge-upstream

Conversation

@code-yeongyu
Copy link
Copy Markdown
Owner

@code-yeongyu code-yeongyu commented Mar 23, 2026

Summary

  • Merge 468 commits from devxoul/agent-messenger upstream main into our fork
  • Adds major new platforms: WhatsApp, KakaoTalk, Telegram, ChannelTalk (+ bot variants for Slack, Discord, WhatsApp, ChannelTalk)
  • Includes upstream improvements to existing Slack, Discord, Teams platforms
  • New CI/CD workflows, SDK docs, e2e tests, and skill documentation

Verification

  • ✅ Clean merge (no conflicts)
  • bun install successful
  • bun run build passes (tsc + tsc-alias)
  • ✅ All 1300 tests pass across 107 files

Our Custom Commits Preserved

  • Wave 1-3 API implementations (Slack activity, unread, drafts, sections; Discord DM, threads, reactions, member search, etc.)
  • Skill documentation with practical usage tips

Summary by cubic

Merges 468 upstream commits from devxoul/agent-messenger main into our fork, adding new platforms, bot CLIs, CI/CD, and docs while keeping our custom Slack/Discord features intact.

  • New Features

    • Platforms: WhatsApp, KakaoTalk, Telegram, Channel Talk (beta) + bot CLIs for Slack, Discord, WhatsApp, Channel Talk.
    • Slack/Discord upgrades: DM listing, channel member listing, Linux v11 keyring decryption, token regex fix, stronger type safety.
    • Docs: new docs site structure, CLI guides for all platforms, Slack SDK docs, expanded Skills with templates.
    • CI/CD: split typecheck/lint/test/build, Node runtime verification, new manual Release workflow.
    • E2E: added suites for SlackBot, DiscordBot, Teams, ChannelTalk/ChannelTalkBot; .env.template for config.
    • Kept our Wave 1–3 Slack/Discord API enhancements and skill docs.
  • Migration

    • Lint/format now use oxlint and oxfmt (replace Biome/ESLint). Scripts: bun run typecheck, bun run lint, bun lint:fix, bun run format.
    • Build publishes compiled JS to dist/ via tsc + tsc-alias; prepublish rewrites bin paths. Node users run built CLIs.
    • New CLIs available after install: agent-slackbot, agent-discordbot, agent-telegram, agent-whatsapp, agent-whatsappbot, agent-kakaotalk, agent-channeltalk, agent-channeltalkbot.
    • For E2E, copy .env.template and set required vars to enable Channel Talk/Teams tests.

Written for commit 9e81b74. Summary will update on new commits.

devxoul and others added 30 commits March 9, 2026 21:50
…runners

Add npx and pnpm dlx as package runner options in skills
- Add listDMs() method to SlackClient that calls conversations.list
  with types='im,mpim' to retrieve direct message channels
- Implement actual DM listing in 'channel list --type dm' command
  (previously returned empty array)
- DM output includes channel id, user id, and is_mpim flag
- Cookie is already passed via WebClient headers, so
  conversations.history works for DM channels without changes
… --include-archived for DMs

- Move DM branch before listChannels() call to avoid unnecessary
  public/private channel API request when --type dm is used
- Pass excludeArchived option to listDMs() so --include-archived
  flag is respected for DM listing (uses Slack's exclude_archived param)

Fixes issues identified by cubic-dev-ai review.
On modern Linux desktops with gnome-keyring, Chromium-based apps encrypt
cookies/tokens with a v11 prefix using a password stored in the keyring
via libsecret. The v10 code path only handles the hardcoded 'peanuts'
password, causing auth extraction to fail on most GNOME desktops.

- Slack: add decryptV11CookieLinux() that looks up the keyring password
  via secret-tool for app names ['Slack', 'slack'], derives the AES key
  with PBKDF2(password, 'saltysalt', 1, 16, sha1), and falls back to the
  v10 peanuts key if the keyring is unavailable
- Discord: add decryptV11LinuxToken() with the same pattern for app names
  ['discord', 'Discord'], extracted into decryptLinuxToken() which now
  checks the v11 prefix before falling back to peanuts
- Both methods share a private getLinuxKeyringPassword() helper to make
  the keyring lookup easily testable via spyOn
- Tests cover: keyring-available decryption and peanuts fallback path

Builds on PR agent-messenger#35 which added v10 Linux support.

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…h >24 char base64 segments

Discord user IDs created ~2023+ produce base64-encoded first segments
longer than 24 characters (e.g. user ID 1295726388820709399 encodes to
'MTI5NTcyNjM4ODgyMDcwOTM5OQ' = 26 chars). The previous regex {24} matched
exactly 24 chars, causing the match to start 2 chars late and return a
truncated token that fails API auth with 401.

Change {24} to {24,} so the regex greedily matches the full first segment
regardless of length. Also add a test covering the >24 char case.
…-support

feat(slack): add DM channel listing support
…yring-decryption

Add Linux v11 gnome-keyring/libsecret cookie and token decryption
- Add SlackDM interface to types.ts (follows existing named-type pattern)
- Remove `as any` cast in listDMs() — ch.name is already typed
- Rename excludeArchived to includeArchived to eliminate double-negation
- Use SlackDM type in client.ts return type and local variable
Extract getLinuxKeyringPassword to shared linux-keyring util used by both
Slack and Discord token extractors. DRY up Slack's v11 decryption by
extracting decryptLinuxCookieWithKey helper that both v10 and v11 paths
delegate to. Add TODO for macOS v11 keychain support.
…safety

Fix type safety and consistency in Slack DM listing
…ng-cleanup

Refactor v11 keyring decryption: extract shared helpers
Remove duplicate --pretty option from root commands across all platform
CLIs. Commander consumes root-level options from argv before subcommands
parse them, so the duplicate definition on the root command was eating
the flag before leaf subcommands could see it.
devxoul and others added 28 commits March 22, 2026 00:27
Pins: pinMessage, unpinMessage, listPins
Bookmarks: addBookmark, editBookmark, removeBookmark, listBookmarks
Scheduled messages: scheduleMessage, listScheduledMessages, deleteScheduledMessage
Channel management: createChannel, archiveChannel, setChannelTopic, setChannelPurpose, inviteToChannel, joinChannel, leaveChannel
User enhancements: lookupUserByEmail, getUserProfile, setUserProfile
Message enhancements: postEphemeral, getPermalink
Reminders: addReminder, listReminders, completeReminder, deleteReminder
Misc: deleteFile, listEmoji
Channel: create, archive, set-topic, set-purpose, invite, join, leave
Message: schedule, scheduled-list, scheduled-delete, ephemeral, permalink
User: lookup, profile, set-status
File: delete
Wire pin, bookmark, reminder, emoji commands into CLI.
Document all new commands in SKILL.md and remove outdated limitations.
…workflow patterns

- Validate time args in reminder add, bookmark edit, user set-status expiration
- Add pagination to listScheduledMessages (cursor loop)
- Add pins, bookmarks, scheduled messages, channel management, reminders to README table
- Add --thread, --type, --expiration flags to SKILL.md examples
- Fix ephemeral docs to use <user-id> instead of <user>
- Add scheduling, channel setup, and reminder workflow patterns to common-patterns.md
…d-api

Add extended Slack SDK: pins, bookmarks, scheduled messages, channel management, reminders, and more
Document all 45+ SlackClient methods organized by domain (messages,
channels, users, files, pins, bookmarks, reminders, etc.) with
signatures, parameters, and return types.

Add 6 real-world examples: deploy notifier, project channel setup,
real-time bot, morning digest, triage with search, and file pipeline.
Add missing commands to slack.mdx: auth logout, workspace remove,
message get, message replies, channel history/open/users, and flags
(--thread, --type dm, --cursor). Fix scheduled-delete argument name.
Add --limit flag to slackbot message replies.
Fix 15 broken jq paths in common-patterns.md: remove non-existent
.data wrapper and .success field checks, use correct output shapes
(.ts, .[], .workspace, .recent_messages). Add --cursor pagination
flags to drafts list and saved list in SKILL.md.
Add Pattern 7 (multi-bot setup, switching, per-command override) and
Pattern 8 (fetch single message and thread replies by timestamp).
Expand Slack section with channel management, pins, bookmarks,
reminders, scheduled messages, emoji, user profiles, and activity
tracking. Fix slackbot reaction claim (list does not exist). Add
WhatsApp and WhatsApp Bot sections with skill documentation links.
- Fix WhatsApp Bot section to send-only (no read capability)
- Fix WhatsApp search claim to 'Search chats' (not messages)
- Fix jq -s 'length' to jq 'length' in slackbot patterns
- Remove undocumented message list --thread from CLI docs
- Use positive .ts check instead of .error check in error patterns
- Change 'All methods' to 'Most API methods' for retry claim
- Fix duplicate const messages declaration in SDK example
…extended-api

Update docs and skills for Slack extended API
Redesign docs landing page with glass aesthetic
Add KakaoTalk CLI doc page (docs/cli/kakaotalk.mdx) with auth, commands,
troubleshooting, and limitations. Add KakaoTalk to all aggregate platform
listings across README, plugin config, docs site index, quick-start,
agent-skills page, and landing page (icon, terminal demo, capabilities
table). Also add missing WhatsApp/WhatsApp Bot entries to plugin.json
skills array.
…laim

Add --all and --search <name> options to chat list docs (match CLI
implementation). Fix overly broad 'no Linux support' claim — only auth
extract requires macOS/Windows; auth login works on any platform.
Add KakaoTalk documentation and platform listings
@code-yeongyu code-yeongyu merged commit 11593a3 into main Mar 23, 2026
3 checks passed
code-yeongyu pushed a commit that referenced this pull request May 26, 2026
…e listener

Self-review (explore agent + Oracle) surfaced four must-fix issues. Applied
all four with regression tests:

1. listener.ts handleEnvelope (disconnect case): Slack's `disconnect` envelope
   is the server-requested healthy reconnect signal — the analog of Discord's
   opcode 7, which discordbot/listener.ts resets reconnectAttempts on. We
   were not, so a `refresh_requested` after even one prior failure would
   needlessly extend backoff. Now reset reconnectAttempts = 0 on
   non-terminal disconnect.

2. listener.ts handleEnvelope (disconnect case): per Slack Socket Mode docs,
   `link_disabled` is a terminal disconnect reason — the app/link was
   disabled, so reconnecting is futile and produces a tight loop against a
   permanently-broken Slack-side state. Now emit an error and stop on
   `link_disabled` (and any future TERMINAL_DISCONNECT_REASONS), close the
   socket, and skip reconnect scheduling.

3. listener.ts armHelloTimeout: if the WebSocket opened but Slack never sent
   `hello`, the listener stayed "open but never connected" forever (RFC 6455
   ping/pong kept the socket alive, but no Socket Mode session was ever
   established). Now arm a 10s hello timeout on `open`, clear it on `hello`,
   and force-close the socket if it expires — triggering the standard
   reconnect flow via the close handler.

4. client.ts withRetry + types.ts SlackBotError + listener.ts
   nextReconnectFloorMs: the client's withRetry wrapper was rebuilding
   SlackBotError without the original `retryAfter` field, so rate-limit
   information was lost by the time the listener saw the error. Slack's
   apps.connections.open is rate-limited; honoring the server's
   retry-after hint is the polite thing to do. Now SlackBotError carries
   an optional retryAfter, withRetry preserves it for rate-limit errors,
   and scheduleReconnect uses it as a floor on the next reconnect delay
   (still capped at the existing 30s exponential ceiling, then cleared so
   it only applies once).

Also fixed a small lint issue in the new tests (no-unused-expressions on a
&& short-circuit; replaced with a proper `if`).

Tests added (13 new cases, 138 -> 151 pass):

- "ignores stale close events after stop+start (does not double-schedule
  reconnect)" — sibling listener tests had stale-message guard but not
  stale-close guard; this confirms the close handler's isCurrent check
  also blocks stale connections.
- "stale ack after reconnect targets the new socket guard, not the old
  socket" — explicit coverage of the closed-over (generation, ws) ack
  contract across stop/start.
- "start after stop resets reconnect attempts" + "clears retryAfter floor
  on fresh start" — sibling listeners (slack/listener.test.ts,
  discordbot/listener.test.ts) have the first half; we now do too plus
  the floor clearing.
- "closes the WebSocket when no pong arrives within the timeout" — zombie
  connection coverage (was missing).
- "resets reconnectAttempts on non-terminal disconnect (refresh_requested)"
  + "resets reconnectAttempts on warning disconnect" — verifies fix #1.
- "treats link_disabled as terminal: emits error, stops, no reconnect" —
  verifies fix agent-messenger#2.
- "closes the socket if hello does not arrive within HELLO_TIMEOUT" +
  "clears the hello timer once hello arrives" — verifies fix agent-messenger#3.
- "uses retryAfter as a floor on the next reconnect delay" + "does not
  set floor when retryAfter is absent" + "clears floor after applying it
  once" — verifies fix agent-messenger#4 by spying on setTimeout to capture the actual
  delay scheduled.

Verification:
- bun typecheck — clean.
- bun run lint (oxlint) — 0 warnings, 0 errors.
- oxfmt --check src/platforms/slackbot/ — clean.
- bun test src/platforms/slackbot/ — 151 pass, 0 fail.

Not changed (Oracle flagged but judged out of scope for this self-review):
- Envelope shape validation before creating ack (defensive but no
  observed bug; Slack's protocol always includes envelope_id on ack-able
  envelopes).
- scheduleReconnect generation-awareness (currently only called from
  guarded paths; Oracle agreed it's fragile but not currently broken).
- slack_event firing for slash_commands/interactive (intentional asymmetry
  matching the discordbot pattern where catch-all events only fire for
  the inner Events API event type).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants