agent-messenger 2.4.0 → 2.6.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.
- package/.claude-plugin/plugin.json +1 -1
- package/.github/workflows/ci.yml +35 -0
- package/.github/workflows/release.yml +0 -12
- package/README.md +3 -3
- package/bun.lock +10 -2
- package/dist/package.json +3 -1
- package/dist/src/platforms/channeltalk/cli.d.ts.map +1 -1
- package/dist/src/platforms/channeltalk/cli.js +2 -1
- package/dist/src/platforms/channeltalk/cli.js.map +1 -1
- package/dist/src/platforms/channeltalk/commands/index.d.ts +1 -0
- package/dist/src/platforms/channeltalk/commands/index.d.ts.map +1 -1
- package/dist/src/platforms/channeltalk/commands/index.js +1 -0
- package/dist/src/platforms/channeltalk/commands/index.js.map +1 -1
- package/dist/src/platforms/channeltalk/commands/whoami.d.ts +22 -0
- package/dist/src/platforms/channeltalk/commands/whoami.d.ts.map +1 -0
- package/dist/src/platforms/channeltalk/commands/whoami.js +40 -0
- package/dist/src/platforms/channeltalk/commands/whoami.js.map +1 -0
- package/dist/src/platforms/channeltalkbot/cli.d.ts.map +1 -1
- package/dist/src/platforms/channeltalkbot/cli.js +2 -1
- package/dist/src/platforms/channeltalkbot/cli.js.map +1 -1
- package/dist/src/platforms/channeltalkbot/commands/index.d.ts +1 -0
- package/dist/src/platforms/channeltalkbot/commands/index.d.ts.map +1 -1
- package/dist/src/platforms/channeltalkbot/commands/index.js +1 -0
- package/dist/src/platforms/channeltalkbot/commands/index.js.map +1 -1
- package/dist/src/platforms/channeltalkbot/commands/whoami.d.ts +13 -0
- package/dist/src/platforms/channeltalkbot/commands/whoami.d.ts.map +1 -0
- package/dist/src/platforms/channeltalkbot/commands/whoami.js +31 -0
- package/dist/src/platforms/channeltalkbot/commands/whoami.js.map +1 -0
- package/dist/src/platforms/discord/cli.d.ts.map +1 -1
- package/dist/src/platforms/discord/cli.js +2 -1
- package/dist/src/platforms/discord/cli.js.map +1 -1
- package/dist/src/platforms/discord/commands/index.d.ts +1 -0
- package/dist/src/platforms/discord/commands/index.d.ts.map +1 -1
- package/dist/src/platforms/discord/commands/index.js +1 -0
- package/dist/src/platforms/discord/commands/index.js.map +1 -1
- package/dist/src/platforms/discord/commands/whoami.d.ts +6 -0
- package/dist/src/platforms/discord/commands/whoami.d.ts.map +1 -0
- package/dist/src/platforms/discord/commands/whoami.js +33 -0
- package/dist/src/platforms/discord/commands/whoami.js.map +1 -0
- package/dist/src/platforms/discordbot/cli.d.ts.map +1 -1
- package/dist/src/platforms/discordbot/cli.js +2 -1
- package/dist/src/platforms/discordbot/cli.js.map +1 -1
- package/dist/src/platforms/discordbot/commands/index.d.ts +1 -0
- package/dist/src/platforms/discordbot/commands/index.d.ts.map +1 -1
- package/dist/src/platforms/discordbot/commands/index.js +1 -0
- package/dist/src/platforms/discordbot/commands/index.js.map +1 -1
- package/dist/src/platforms/discordbot/commands/whoami.d.ts +14 -0
- package/dist/src/platforms/discordbot/commands/whoami.d.ts.map +1 -0
- package/dist/src/platforms/discordbot/commands/whoami.js +32 -0
- package/dist/src/platforms/discordbot/commands/whoami.js.map +1 -0
- package/dist/src/platforms/instagram/cli.d.ts.map +1 -1
- package/dist/src/platforms/instagram/cli.js +2 -1
- package/dist/src/platforms/instagram/cli.js.map +1 -1
- package/dist/src/platforms/instagram/client.d.ts +6 -0
- package/dist/src/platforms/instagram/client.d.ts.map +1 -1
- package/dist/src/platforms/instagram/client.js +12 -0
- package/dist/src/platforms/instagram/client.js.map +1 -1
- package/dist/src/platforms/instagram/commands/index.d.ts +1 -0
- package/dist/src/platforms/instagram/commands/index.d.ts.map +1 -1
- package/dist/src/platforms/instagram/commands/index.js +1 -0
- package/dist/src/platforms/instagram/commands/index.js.map +1 -1
- package/dist/src/platforms/instagram/commands/whoami.d.ts +7 -0
- package/dist/src/platforms/instagram/commands/whoami.d.ts.map +1 -0
- package/dist/src/platforms/instagram/commands/whoami.js +19 -0
- package/dist/src/platforms/instagram/commands/whoami.js.map +1 -0
- package/dist/src/platforms/kakaotalk/cli.js +2 -2
- package/dist/src/platforms/kakaotalk/cli.js.map +1 -1
- package/dist/src/platforms/kakaotalk/client.d.ts +4 -1
- package/dist/src/platforms/kakaotalk/client.d.ts.map +1 -1
- package/dist/src/platforms/kakaotalk/client.js +193 -27
- package/dist/src/platforms/kakaotalk/client.js.map +1 -1
- package/dist/src/platforms/kakaotalk/commands/auth.d.ts.map +1 -1
- package/dist/src/platforms/kakaotalk/commands/auth.js +24 -55
- package/dist/src/platforms/kakaotalk/commands/auth.js.map +1 -1
- package/dist/src/platforms/kakaotalk/commands/index.d.ts +1 -1
- package/dist/src/platforms/kakaotalk/commands/index.d.ts.map +1 -1
- package/dist/src/platforms/kakaotalk/commands/index.js +1 -1
- package/dist/src/platforms/kakaotalk/commands/index.js.map +1 -1
- package/dist/src/platforms/kakaotalk/commands/whoami.d.ts +3 -0
- package/dist/src/platforms/kakaotalk/commands/whoami.d.ts.map +1 -0
- package/dist/src/platforms/kakaotalk/commands/{profile.js → whoami.js} +5 -5
- package/dist/src/platforms/kakaotalk/commands/whoami.js.map +1 -0
- package/dist/src/platforms/kakaotalk/credential-manager.d.ts.map +1 -1
- package/dist/src/platforms/kakaotalk/credential-manager.js +1 -0
- package/dist/src/platforms/kakaotalk/credential-manager.js.map +1 -1
- package/dist/src/platforms/kakaotalk/index.d.ts +1 -1
- package/dist/src/platforms/kakaotalk/index.d.ts.map +1 -1
- package/dist/src/platforms/kakaotalk/index.js.map +1 -1
- package/dist/src/platforms/kakaotalk/listener.js +2 -2
- package/dist/src/platforms/kakaotalk/listener.js.map +1 -1
- package/dist/src/platforms/kakaotalk/protocol/config.d.ts +8 -2
- package/dist/src/platforms/kakaotalk/protocol/config.d.ts.map +1 -1
- package/dist/src/platforms/kakaotalk/protocol/config.js +15 -2
- package/dist/src/platforms/kakaotalk/protocol/config.js.map +1 -1
- package/dist/src/platforms/kakaotalk/protocol/session.d.ts +6 -2
- package/dist/src/platforms/kakaotalk/protocol/session.d.ts.map +1 -1
- package/dist/src/platforms/kakaotalk/protocol/session.js +37 -15
- package/dist/src/platforms/kakaotalk/protocol/session.js.map +1 -1
- package/dist/src/platforms/kakaotalk/protocol/types.d.ts +17 -0
- package/dist/src/platforms/kakaotalk/protocol/types.d.ts.map +1 -1
- package/dist/src/platforms/kakaotalk/protocol/types.js.map +1 -1
- package/dist/src/platforms/kakaotalk/types.d.ts +22 -0
- package/dist/src/platforms/kakaotalk/types.d.ts.map +1 -1
- package/dist/src/platforms/kakaotalk/types.js +7 -0
- package/dist/src/platforms/kakaotalk/types.js.map +1 -1
- package/dist/src/platforms/line/cli.js +2 -2
- package/dist/src/platforms/line/cli.js.map +1 -1
- package/dist/src/platforms/line/commands/auth.d.ts.map +1 -1
- package/dist/src/platforms/line/commands/auth.js +9 -59
- package/dist/src/platforms/line/commands/auth.js.map +1 -1
- package/dist/src/platforms/line/commands/index.d.ts +1 -1
- package/dist/src/platforms/line/commands/index.d.ts.map +1 -1
- package/dist/src/platforms/line/commands/index.js +1 -1
- package/dist/src/platforms/line/commands/index.js.map +1 -1
- package/dist/src/platforms/line/commands/whoami.d.ts +3 -0
- package/dist/src/platforms/line/commands/whoami.d.ts.map +1 -0
- package/dist/src/platforms/line/commands/{profile.js → whoami.js} +5 -5
- package/dist/src/platforms/line/commands/whoami.js.map +1 -0
- package/dist/src/platforms/slack/cli.d.ts.map +1 -1
- package/dist/src/platforms/slack/cli.js +2 -1
- package/dist/src/platforms/slack/cli.js.map +1 -1
- package/dist/src/platforms/slack/commands/index.d.ts +1 -0
- package/dist/src/platforms/slack/commands/index.d.ts.map +1 -1
- package/dist/src/platforms/slack/commands/index.js +1 -0
- package/dist/src/platforms/slack/commands/index.js.map +1 -1
- package/dist/src/platforms/slack/commands/whoami.d.ts +6 -0
- package/dist/src/platforms/slack/commands/whoami.d.ts.map +1 -0
- package/dist/src/platforms/slack/commands/whoami.js +39 -0
- package/dist/src/platforms/slack/commands/whoami.js.map +1 -0
- package/dist/src/platforms/slackbot/cli.d.ts.map +1 -1
- package/dist/src/platforms/slackbot/cli.js +2 -1
- package/dist/src/platforms/slackbot/cli.js.map +1 -1
- package/dist/src/platforms/slackbot/commands/index.d.ts +1 -0
- package/dist/src/platforms/slackbot/commands/index.d.ts.map +1 -1
- package/dist/src/platforms/slackbot/commands/index.js +1 -0
- package/dist/src/platforms/slackbot/commands/index.js.map +1 -1
- package/dist/src/platforms/slackbot/commands/whoami.d.ts +14 -0
- package/dist/src/platforms/slackbot/commands/whoami.d.ts.map +1 -0
- package/dist/src/platforms/slackbot/commands/whoami.js +32 -0
- package/dist/src/platforms/slackbot/commands/whoami.js.map +1 -0
- package/dist/src/platforms/teams/cli.d.ts.map +1 -1
- package/dist/src/platforms/teams/cli.js +2 -1
- package/dist/src/platforms/teams/cli.js.map +1 -1
- package/dist/src/platforms/teams/commands/index.d.ts +1 -0
- package/dist/src/platforms/teams/commands/index.d.ts.map +1 -1
- package/dist/src/platforms/teams/commands/index.js +1 -0
- package/dist/src/platforms/teams/commands/index.js.map +1 -1
- package/dist/src/platforms/teams/commands/whoami.d.ts +6 -0
- package/dist/src/platforms/teams/commands/whoami.d.ts.map +1 -0
- package/dist/src/platforms/teams/commands/whoami.js +30 -0
- package/dist/src/platforms/teams/commands/whoami.js.map +1 -0
- package/dist/src/platforms/telegram/cli.d.ts.map +1 -1
- package/dist/src/platforms/telegram/cli.js +2 -1
- package/dist/src/platforms/telegram/cli.js.map +1 -1
- package/dist/src/platforms/telegram/commands/index.d.ts +1 -0
- package/dist/src/platforms/telegram/commands/index.d.ts.map +1 -1
- package/dist/src/platforms/telegram/commands/index.js +1 -0
- package/dist/src/platforms/telegram/commands/index.js.map +1 -1
- package/dist/src/platforms/telegram/commands/whoami.d.ts +7 -0
- package/dist/src/platforms/telegram/commands/whoami.d.ts.map +1 -0
- package/dist/src/platforms/telegram/commands/whoami.js +27 -0
- package/dist/src/platforms/telegram/commands/whoami.js.map +1 -0
- package/dist/src/platforms/webex/cli.d.ts.map +1 -1
- package/dist/src/platforms/webex/cli.js +2 -1
- package/dist/src/platforms/webex/cli.js.map +1 -1
- package/dist/src/platforms/webex/commands/index.d.ts +1 -0
- package/dist/src/platforms/webex/commands/index.d.ts.map +1 -1
- package/dist/src/platforms/webex/commands/index.js +1 -0
- package/dist/src/platforms/webex/commands/index.js.map +1 -1
- package/dist/src/platforms/webex/commands/message.js +1 -1
- package/dist/src/platforms/webex/commands/message.js.map +1 -1
- package/dist/src/platforms/webex/commands/whoami.d.ts +6 -0
- package/dist/src/platforms/webex/commands/whoami.d.ts.map +1 -0
- package/dist/src/platforms/webex/commands/whoami.js +30 -0
- package/dist/src/platforms/webex/commands/whoami.js.map +1 -0
- package/dist/src/platforms/wechatbot/cli.d.ts.map +1 -1
- package/dist/src/platforms/wechatbot/cli.js +2 -1
- package/dist/src/platforms/wechatbot/cli.js.map +1 -1
- package/dist/src/platforms/wechatbot/commands/index.d.ts +1 -0
- package/dist/src/platforms/wechatbot/commands/index.d.ts.map +1 -1
- package/dist/src/platforms/wechatbot/commands/index.js +1 -0
- package/dist/src/platforms/wechatbot/commands/index.js.map +1 -1
- package/dist/src/platforms/wechatbot/commands/whoami.d.ts +12 -0
- package/dist/src/platforms/wechatbot/commands/whoami.d.ts.map +1 -0
- package/dist/src/platforms/wechatbot/commands/whoami.js +33 -0
- package/dist/src/platforms/wechatbot/commands/whoami.js.map +1 -0
- package/dist/src/platforms/whatsapp/cli.d.ts.map +1 -1
- package/dist/src/platforms/whatsapp/cli.js +2 -1
- package/dist/src/platforms/whatsapp/cli.js.map +1 -1
- package/dist/src/platforms/whatsapp/client.d.ts +8 -0
- package/dist/src/platforms/whatsapp/client.d.ts.map +1 -1
- package/dist/src/platforms/whatsapp/client.js +116 -8
- package/dist/src/platforms/whatsapp/client.js.map +1 -1
- package/dist/src/platforms/whatsapp/commands/auth.d.ts.map +1 -1
- package/dist/src/platforms/whatsapp/commands/auth.js +115 -45
- package/dist/src/platforms/whatsapp/commands/auth.js.map +1 -1
- package/dist/src/platforms/whatsapp/commands/index.d.ts +1 -0
- package/dist/src/platforms/whatsapp/commands/index.d.ts.map +1 -1
- package/dist/src/platforms/whatsapp/commands/index.js +1 -0
- package/dist/src/platforms/whatsapp/commands/index.js.map +1 -1
- package/dist/src/platforms/whatsapp/commands/shared.js +2 -2
- package/dist/src/platforms/whatsapp/commands/shared.js.map +1 -1
- package/dist/src/platforms/whatsapp/commands/whoami.d.ts +7 -0
- package/dist/src/platforms/whatsapp/commands/whoami.d.ts.map +1 -0
- package/dist/src/platforms/whatsapp/commands/whoami.js +19 -0
- package/dist/src/platforms/whatsapp/commands/whoami.js.map +1 -0
- package/dist/src/platforms/whatsapp/ensure-auth.js +2 -2
- package/dist/src/platforms/whatsapp/ensure-auth.js.map +1 -1
- package/dist/src/platforms/whatsappbot/cli.d.ts.map +1 -1
- package/dist/src/platforms/whatsappbot/cli.js +2 -1
- package/dist/src/platforms/whatsappbot/cli.js.map +1 -1
- package/dist/src/platforms/whatsappbot/commands/index.d.ts +1 -0
- package/dist/src/platforms/whatsappbot/commands/index.d.ts.map +1 -1
- package/dist/src/platforms/whatsappbot/commands/index.js +1 -0
- package/dist/src/platforms/whatsappbot/commands/index.js.map +1 -1
- package/dist/src/platforms/whatsappbot/commands/whoami.d.ts +17 -0
- package/dist/src/platforms/whatsappbot/commands/whoami.d.ts.map +1 -0
- package/dist/src/platforms/whatsappbot/commands/whoami.js +39 -0
- package/dist/src/platforms/whatsappbot/commands/whoami.js.map +1 -0
- package/dist/src/shared/utils/qr.d.ts +15 -0
- package/dist/src/shared/utils/qr.d.ts.map +1 -0
- package/dist/src/shared/utils/qr.js +74 -0
- package/dist/src/shared/utils/qr.js.map +1 -0
- package/dist/src/tui/adapters/kakaotalk-adapter.d.ts.map +1 -1
- package/dist/src/tui/adapters/kakaotalk-adapter.js +5 -2
- package/dist/src/tui/adapters/kakaotalk-adapter.js.map +1 -1
- package/dist/src/tui/adapters/whatsapp-adapter.d.ts.map +1 -1
- package/dist/src/tui/adapters/whatsapp-adapter.js +20 -15
- package/dist/src/tui/adapters/whatsapp-adapter.js.map +1 -1
- package/docs/content/docs/cli/channeltalk.mdx +11 -0
- package/docs/content/docs/cli/channeltalkbot.mdx +9 -0
- package/docs/content/docs/cli/discord.mdx +10 -0
- package/docs/content/docs/cli/discordbot.mdx +9 -0
- package/docs/content/docs/cli/instagram.mdx +11 -0
- package/docs/content/docs/cli/kakaotalk.mdx +27 -39
- package/docs/content/docs/cli/line.mdx +4 -4
- package/docs/content/docs/cli/slack.mdx +10 -0
- package/docs/content/docs/cli/slackbot.mdx +9 -0
- package/docs/content/docs/cli/teams.mdx +10 -0
- package/docs/content/docs/cli/telegram.mdx +11 -0
- package/docs/content/docs/cli/webex.mdx +10 -0
- package/docs/content/docs/cli/wechatbot.mdx +9 -0
- package/docs/content/docs/cli/whatsapp.mdx +36 -7
- package/docs/content/docs/cli/whatsappbot.mdx +9 -0
- package/e2e/config.ts +1 -1
- package/package.json +3 -1
- package/skills/agent-channeltalk/SKILL.md +12 -1
- package/skills/agent-channeltalkbot/SKILL.md +10 -1
- package/skills/agent-discord/SKILL.md +11 -1
- package/skills/agent-discordbot/SKILL.md +10 -1
- package/skills/agent-instagram/SKILL.md +12 -1
- package/skills/agent-kakaotalk/SKILL.md +24 -70
- package/skills/agent-kakaotalk/references/authentication.md +4 -69
- package/skills/agent-kakaotalk/references/common-patterns.md +14 -1
- package/skills/agent-line/SKILL.md +5 -5
- package/skills/agent-slack/SKILL.md +11 -1
- package/skills/agent-slackbot/SKILL.md +10 -1
- package/skills/agent-teams/SKILL.md +11 -1
- package/skills/agent-telegram/SKILL.md +6 -1
- package/skills/agent-webex/SKILL.md +11 -1
- package/skills/agent-wechatbot/SKILL.md +10 -1
- package/skills/agent-whatsapp/SKILL.md +52 -15
- package/skills/agent-whatsapp/references/authentication.md +36 -6
- package/skills/agent-whatsappbot/SKILL.md +10 -1
- package/src/platforms/channeltalk/cli.ts +2 -0
- package/src/platforms/channeltalk/commands/index.ts +1 -0
- package/src/platforms/channeltalk/commands/whoami.test.ts +64 -0
- package/src/platforms/channeltalk/commands/whoami.ts +62 -0
- package/src/platforms/channeltalkbot/cli.ts +2 -0
- package/src/platforms/channeltalkbot/commands/index.ts +1 -0
- package/src/platforms/channeltalkbot/commands/whoami.test.ts +104 -0
- package/src/platforms/channeltalkbot/commands/whoami.ts +42 -0
- package/src/platforms/discord/cli.ts +2 -0
- package/src/platforms/discord/commands/index.ts +1 -0
- package/src/platforms/discord/commands/whoami.test.ts +91 -0
- package/src/platforms/discord/commands/whoami.ts +36 -0
- package/src/platforms/discordbot/cli.ts +2 -0
- package/src/platforms/discordbot/commands/index.ts +1 -0
- package/src/platforms/discordbot/commands/whoami.test.ts +96 -0
- package/src/platforms/discordbot/commands/whoami.ts +44 -0
- package/src/platforms/instagram/cli.ts +2 -1
- package/src/platforms/instagram/client.ts +13 -0
- package/src/platforms/instagram/commands/chat.test.ts +1 -5
- package/src/platforms/instagram/commands/index.ts +1 -0
- package/src/platforms/instagram/commands/message.test.ts +1 -5
- package/src/platforms/instagram/commands/whoami.test.ts +60 -0
- package/src/platforms/instagram/commands/whoami.ts +21 -0
- package/src/platforms/kakaotalk/cli.ts +2 -2
- package/src/platforms/kakaotalk/client.test.ts +25 -14
- package/src/platforms/kakaotalk/client.ts +228 -33
- package/src/platforms/kakaotalk/commands/auth.ts +22 -73
- package/src/platforms/kakaotalk/commands/index.ts +1 -1
- package/src/platforms/kakaotalk/commands/{profile.test.ts → whoami.test.ts} +37 -5
- package/src/platforms/kakaotalk/commands/{profile.ts → whoami.ts} +4 -4
- package/src/platforms/kakaotalk/credential-manager.ts +1 -0
- package/src/platforms/kakaotalk/index.ts +1 -0
- package/src/platforms/kakaotalk/listener.test.ts +2 -2
- package/src/platforms/kakaotalk/listener.ts +2 -2
- package/src/platforms/kakaotalk/protocol/config.ts +26 -2
- package/src/platforms/kakaotalk/protocol/session.ts +42 -16
- package/src/platforms/kakaotalk/protocol/types.ts +9 -0
- package/src/platforms/kakaotalk/types.ts +16 -0
- package/src/platforms/line/cli.ts +2 -2
- package/src/platforms/line/commands/auth.ts +37 -70
- package/src/platforms/line/commands/index.ts +1 -1
- package/src/platforms/line/commands/{profile.test.ts → whoami.test.ts} +11 -11
- package/src/platforms/line/commands/{profile.ts → whoami.ts} +4 -4
- package/src/platforms/slack/cli.ts +2 -0
- package/src/platforms/slack/commands/index.ts +1 -0
- package/src/platforms/slack/commands/whoami.test.ts +126 -0
- package/src/platforms/slack/commands/whoami.ts +40 -0
- package/src/platforms/slackbot/cli.ts +2 -1
- package/src/platforms/slackbot/commands/index.ts +1 -0
- package/src/platforms/slackbot/commands/whoami.test.ts +102 -0
- package/src/platforms/slackbot/commands/whoami.ts +44 -0
- package/src/platforms/teams/cli.ts +2 -0
- package/src/platforms/teams/commands/index.ts +1 -0
- package/src/platforms/teams/commands/whoami.test.ts +83 -0
- package/src/platforms/teams/commands/whoami.ts +33 -0
- package/src/platforms/telegram/cli.ts +2 -1
- package/src/platforms/telegram/commands/index.ts +1 -0
- package/src/platforms/telegram/commands/whoami.test.ts +75 -0
- package/src/platforms/telegram/commands/whoami.ts +29 -0
- package/src/platforms/webex/cli.ts +2 -1
- package/src/platforms/webex/commands/auth.test.ts +58 -46
- package/src/platforms/webex/commands/index.ts +1 -0
- package/src/platforms/webex/commands/member.test.ts +1 -5
- package/src/platforms/webex/commands/message.test.ts +1 -5
- package/src/platforms/webex/commands/message.ts +1 -1
- package/src/platforms/webex/commands/snapshot.test.ts +1 -5
- package/src/platforms/webex/commands/space.test.ts +1 -5
- package/src/platforms/webex/commands/whoami.test.ts +113 -0
- package/src/platforms/webex/commands/whoami.ts +31 -0
- package/src/platforms/webex/credential-manager.test.ts +0 -1
- package/src/platforms/wechatbot/cli.ts +2 -1
- package/src/platforms/wechatbot/commands/index.ts +1 -0
- package/src/platforms/wechatbot/commands/whoami.test.ts +109 -0
- package/src/platforms/wechatbot/commands/whoami.ts +43 -0
- package/src/platforms/whatsapp/cli.ts +2 -1
- package/src/platforms/whatsapp/client.ts +156 -24
- package/src/platforms/whatsapp/commands/auth.ts +176 -70
- package/src/platforms/whatsapp/commands/index.ts +1 -0
- package/src/platforms/whatsapp/commands/shared.ts +2 -2
- package/src/platforms/whatsapp/commands/whoami.test.ts +59 -0
- package/src/platforms/whatsapp/commands/whoami.ts +21 -0
- package/src/platforms/whatsapp/ensure-auth.ts +2 -2
- package/src/platforms/whatsappbot/cli.ts +2 -1
- package/src/platforms/whatsappbot/commands/index.ts +1 -0
- package/src/platforms/whatsappbot/commands/whoami.test.ts +100 -0
- package/src/platforms/whatsappbot/commands/whoami.ts +57 -0
- package/src/shared/utils/qr.ts +92 -0
- package/src/tui/adapters/kakaotalk-adapter.ts +5 -2
- package/src/tui/adapters/whatsapp-adapter.ts +19 -16
- package/dist/src/platforms/kakaotalk/commands/profile.d.ts +0 -3
- package/dist/src/platforms/kakaotalk/commands/profile.d.ts.map +0 -1
- package/dist/src/platforms/kakaotalk/commands/profile.js.map +0 -1
- package/dist/src/platforms/line/commands/profile.d.ts +0 -3
- package/dist/src/platforms/line/commands/profile.d.ts.map +0 -1
- package/dist/src/platforms/line/commands/profile.js.map +0 -1
|
@@ -5,7 +5,7 @@ import type { Command as CommandType } from 'commander'
|
|
|
5
5
|
import { Command } from 'commander'
|
|
6
6
|
|
|
7
7
|
import pkg from '../../../package.json' with { type: 'json' }
|
|
8
|
-
import { authCommand, chatCommand, messageCommand } from './commands/index'
|
|
8
|
+
import { authCommand, chatCommand, messageCommand, whoamiCommand } from './commands/index'
|
|
9
9
|
import { ensureWhatsAppAuth } from './ensure-auth'
|
|
10
10
|
|
|
11
11
|
function isAuthCommand(command: CommandType): boolean {
|
|
@@ -32,6 +32,7 @@ program.hook('preAction', async (_thisCommand, actionCommand) => {
|
|
|
32
32
|
program.addCommand(authCommand)
|
|
33
33
|
program.addCommand(chatCommand)
|
|
34
34
|
program.addCommand(messageCommand)
|
|
35
|
+
program.addCommand(whoamiCommand)
|
|
35
36
|
|
|
36
37
|
program.parse(process.argv)
|
|
37
38
|
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs'
|
|
2
2
|
import { readFile, writeFile } from 'node:fs/promises'
|
|
3
3
|
import { join } from 'node:path'
|
|
4
|
+
|
|
5
|
+
import { Boom } from '@hapi/boom'
|
|
4
6
|
import makeWASocket, {
|
|
5
7
|
DisconnectReason,
|
|
6
8
|
fetchLatestBaileysVersion,
|
|
@@ -12,8 +14,8 @@ import makeWASocket, {
|
|
|
12
14
|
type WAMessage,
|
|
13
15
|
type WASocket,
|
|
14
16
|
} from '@whiskeysockets/baileys'
|
|
15
|
-
import { Boom } from '@hapi/boom'
|
|
16
17
|
import pino from 'pino'
|
|
18
|
+
|
|
17
19
|
import {
|
|
18
20
|
extractMessageText,
|
|
19
21
|
getMessageType,
|
|
@@ -28,7 +30,12 @@ const MAX_MESSAGES_PER_CHAT = 500
|
|
|
28
30
|
function toTimestampMs(ts: unknown): number {
|
|
29
31
|
if (ts == null) return 0
|
|
30
32
|
if (typeof ts === 'number') return ts * 1000
|
|
31
|
-
if (
|
|
33
|
+
if (
|
|
34
|
+
typeof ts === 'object' &&
|
|
35
|
+
ts !== null &&
|
|
36
|
+
'toNumber' in ts &&
|
|
37
|
+
typeof (ts as Record<string, unknown>).toNumber === 'function'
|
|
38
|
+
) {
|
|
32
39
|
return (ts as { toNumber(): number }).toNumber() * 1000
|
|
33
40
|
}
|
|
34
41
|
const n = Number(ts)
|
|
@@ -44,11 +51,7 @@ function resolveJid(input: string): string {
|
|
|
44
51
|
function summarizeMessage(msg: WAMessage): WhatsAppMessageSummary {
|
|
45
52
|
const jid = msg.key.remoteJid ?? ''
|
|
46
53
|
const isGroup = jid.endsWith('@g.us')
|
|
47
|
-
const from = msg.key.fromMe
|
|
48
|
-
? ''
|
|
49
|
-
: isGroup
|
|
50
|
-
? (msg.key.participant ?? msg.participant ?? jid)
|
|
51
|
-
: jid
|
|
54
|
+
const from = msg.key.fromMe ? '' : isGroup ? (msg.key.participant ?? msg.participant ?? jid) : jid
|
|
52
55
|
|
|
53
56
|
return {
|
|
54
57
|
id: msg.key.id ?? '',
|
|
@@ -62,10 +65,7 @@ function summarizeMessage(msg: WAMessage): WhatsAppMessageSummary {
|
|
|
62
65
|
}
|
|
63
66
|
}
|
|
64
67
|
|
|
65
|
-
function summarizeChat(
|
|
66
|
-
chat: Chat,
|
|
67
|
-
lastMessage?: WhatsAppMessageSummary,
|
|
68
|
-
): WhatsAppChatSummary {
|
|
68
|
+
function summarizeChat(chat: Chat, lastMessage?: WhatsAppMessageSummary): WhatsAppChatSummary {
|
|
69
69
|
const id = chat.id ?? ''
|
|
70
70
|
return {
|
|
71
71
|
id,
|
|
@@ -106,7 +106,7 @@ export class WhatsAppClient {
|
|
|
106
106
|
const account = await manager.getAccount()
|
|
107
107
|
if (!account) {
|
|
108
108
|
throw new WhatsAppError(
|
|
109
|
-
'No WhatsApp credentials found. Run "agent-whatsapp auth login --phone <phone-number>" first.',
|
|
109
|
+
'No WhatsApp credentials found. Run "agent-whatsapp auth login --qr" or "agent-whatsapp auth login --phone <phone-number>" first.',
|
|
110
110
|
'no_credentials',
|
|
111
111
|
)
|
|
112
112
|
}
|
|
@@ -226,10 +226,12 @@ export class WhatsAppClient {
|
|
|
226
226
|
retries++
|
|
227
227
|
if (retries > MAX_RETRIES) {
|
|
228
228
|
clearTimeout(timeout)
|
|
229
|
-
outerReject(
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
229
|
+
outerReject(
|
|
230
|
+
new WhatsAppError(
|
|
231
|
+
`Connection failed after ${MAX_RETRIES} retries: ${lastDisconnect?.error?.message ?? 'unknown'}`,
|
|
232
|
+
'max_retries',
|
|
233
|
+
),
|
|
234
|
+
)
|
|
233
235
|
return
|
|
234
236
|
}
|
|
235
237
|
|
|
@@ -326,10 +328,12 @@ export class WhatsAppClient {
|
|
|
326
328
|
retries++
|
|
327
329
|
if (retries > MAX_RETRIES) {
|
|
328
330
|
clearTimeout(overallTimeout)
|
|
329
|
-
outerReject(
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
331
|
+
outerReject(
|
|
332
|
+
new WhatsAppError(
|
|
333
|
+
`Connection failed after ${MAX_RETRIES} retries: ${lastDisconnect?.error?.message ?? 'unknown'}`,
|
|
334
|
+
'max_retries',
|
|
335
|
+
),
|
|
336
|
+
)
|
|
333
337
|
return
|
|
334
338
|
}
|
|
335
339
|
|
|
@@ -362,8 +366,120 @@ export class WhatsAppClient {
|
|
|
362
366
|
})
|
|
363
367
|
}
|
|
364
368
|
|
|
369
|
+
async connectForQR(onQR: (qr: string) => void | Promise<void>): Promise<{ waitForAuth: () => Promise<void> }> {
|
|
370
|
+
this.ensureAuth()
|
|
371
|
+
this.pendingPromise = new Promise<void>((resolve) => {
|
|
372
|
+
this.pendingResolve = resolve
|
|
373
|
+
})
|
|
374
|
+
|
|
375
|
+
const authCompletePromise = new Promise<void>((resolve, reject) => {
|
|
376
|
+
this.authCompleteResolve = resolve
|
|
377
|
+
this.authCompleteReject = reject
|
|
378
|
+
})
|
|
379
|
+
|
|
380
|
+
const MAX_RETRIES = 5
|
|
381
|
+
let retries = 0
|
|
382
|
+
|
|
383
|
+
return new Promise((outerResolve, outerReject) => {
|
|
384
|
+
let qrEmitted = false
|
|
385
|
+
|
|
386
|
+
const overallTimeout = setTimeout(() => {
|
|
387
|
+
const err = new WhatsAppError('QR auth timed out', 'qr_timeout')
|
|
388
|
+
if (qrEmitted) {
|
|
389
|
+
this.authCompleteReject?.(err)
|
|
390
|
+
} else {
|
|
391
|
+
outerReject(err)
|
|
392
|
+
}
|
|
393
|
+
}, 120_000)
|
|
394
|
+
|
|
395
|
+
const onError = (err: unknown): void => {
|
|
396
|
+
clearTimeout(overallTimeout)
|
|
397
|
+
const error = err instanceof Error ? err : new WhatsAppError(String(err), 'qr_error')
|
|
398
|
+
if (qrEmitted) {
|
|
399
|
+
this.authCompleteReject?.(error)
|
|
400
|
+
} else {
|
|
401
|
+
outerReject(error)
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
const attempt = async (): Promise<void> => {
|
|
406
|
+
const { sock, saveCreds } = await this.createSocket()
|
|
407
|
+
this.setupBufferListeners(sock, saveCreds)
|
|
408
|
+
|
|
409
|
+
sock.ev.on('connection.update', async (update: Partial<ConnectionState>) => {
|
|
410
|
+
const { connection, lastDisconnect, qr } = update
|
|
411
|
+
|
|
412
|
+
if (qr) {
|
|
413
|
+
try {
|
|
414
|
+
await onQR(qr)
|
|
415
|
+
} catch (err) {
|
|
416
|
+
onError(err)
|
|
417
|
+
return
|
|
418
|
+
}
|
|
419
|
+
if (!qrEmitted) {
|
|
420
|
+
qrEmitted = true
|
|
421
|
+
outerResolve({ waitForAuth: () => authCompletePromise })
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
if (connection === 'open') {
|
|
426
|
+
clearTimeout(overallTimeout)
|
|
427
|
+
this.authCompleteResolve?.()
|
|
428
|
+
if (!qrEmitted) {
|
|
429
|
+
qrEmitted = true
|
|
430
|
+
outerResolve({ waitForAuth: async () => {} })
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
if (connection === 'close') {
|
|
435
|
+
this.cleanupSocket(sock)
|
|
436
|
+
|
|
437
|
+
const statusCode = (lastDisconnect?.error as Boom)?.output?.statusCode
|
|
438
|
+
|
|
439
|
+
if (statusCode === DisconnectReason.forbidden) {
|
|
440
|
+
clearTimeout(overallTimeout)
|
|
441
|
+
const err = new WhatsAppError('Account banned or restricted.', 'forbidden')
|
|
442
|
+
if (qrEmitted) {
|
|
443
|
+
this.authCompleteReject?.(err)
|
|
444
|
+
} else {
|
|
445
|
+
outerReject(err)
|
|
446
|
+
}
|
|
447
|
+
return
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
if (qrEmitted) {
|
|
451
|
+
// Post-QR scan: keep reconnecting until auth completes
|
|
452
|
+
setTimeout(() => attempt().catch(onError), 2000)
|
|
453
|
+
return
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
retries++
|
|
457
|
+
if (retries > MAX_RETRIES) {
|
|
458
|
+
clearTimeout(overallTimeout)
|
|
459
|
+
outerReject(
|
|
460
|
+
new WhatsAppError(
|
|
461
|
+
`Connection failed after ${MAX_RETRIES} retries: ${lastDisconnect?.error?.message ?? 'unknown'}`,
|
|
462
|
+
'max_retries',
|
|
463
|
+
),
|
|
464
|
+
)
|
|
465
|
+
return
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
setTimeout(() => attempt().catch(onError), 1000)
|
|
469
|
+
}
|
|
470
|
+
})
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
attempt().catch(onError)
|
|
474
|
+
})
|
|
475
|
+
}
|
|
476
|
+
|
|
365
477
|
private cleanupSocket(sock: WASocket): void {
|
|
366
|
-
try {
|
|
478
|
+
try {
|
|
479
|
+
sock.end(undefined)
|
|
480
|
+
} catch {
|
|
481
|
+
/* already closed */
|
|
482
|
+
}
|
|
367
483
|
}
|
|
368
484
|
|
|
369
485
|
private setupBufferListeners(sock: WASocket, saveCreds: () => Promise<void>): void {
|
|
@@ -475,9 +591,7 @@ export class WhatsAppClient {
|
|
|
475
591
|
async searchChats(query: string, limit?: number): Promise<WhatsAppChatSummary[]> {
|
|
476
592
|
const allChats = await this.listChats()
|
|
477
593
|
const lower = query.toLowerCase()
|
|
478
|
-
const filtered = allChats.filter((c) =>
|
|
479
|
-
c.name.toLowerCase().includes(lower) || c.id.toLowerCase().includes(lower),
|
|
480
|
-
)
|
|
594
|
+
const filtered = allChats.filter((c) => c.name.toLowerCase().includes(lower) || c.id.toLowerCase().includes(lower))
|
|
481
595
|
return limit ? filtered.slice(0, limit) : filtered
|
|
482
596
|
}
|
|
483
597
|
|
|
@@ -515,6 +629,24 @@ export class WhatsAppClient {
|
|
|
515
629
|
return summarizeMessage(result)
|
|
516
630
|
}
|
|
517
631
|
|
|
632
|
+
async getProfile(): Promise<{ id: string; name: string | null; phone_number: string | null }> {
|
|
633
|
+
this.ensureAuth()
|
|
634
|
+
if (!this.sock) {
|
|
635
|
+
throw new WhatsAppError('Not connected. Call connect() first.', 'not_connected')
|
|
636
|
+
}
|
|
637
|
+
const user = this.sock.user
|
|
638
|
+
if (!user) {
|
|
639
|
+
throw new WhatsAppError('Not connected. Call connect() first.', 'not_connected')
|
|
640
|
+
}
|
|
641
|
+
const jid = user.id ?? ''
|
|
642
|
+
const phone = jid.includes(':') ? jid.split(':')[0] : jid.split('@')[0]
|
|
643
|
+
return {
|
|
644
|
+
id: jid,
|
|
645
|
+
name: user.name ?? null,
|
|
646
|
+
phone_number: phone || null,
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
|
|
518
650
|
getSocket(): WASocket | null {
|
|
519
651
|
return this.sock
|
|
520
652
|
}
|
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
import { rm } from 'node:fs/promises'
|
|
2
|
+
|
|
2
3
|
import { Command } from 'commander'
|
|
4
|
+
|
|
3
5
|
import { handleError } from '@/shared/utils/error-handler'
|
|
4
6
|
import { formatOutput } from '@/shared/utils/output'
|
|
7
|
+
import { displayQR } from '@/shared/utils/qr'
|
|
8
|
+
import { info } from '@/shared/utils/stderr'
|
|
9
|
+
|
|
5
10
|
import { WhatsAppClient } from '../client'
|
|
6
11
|
import { WhatsAppCredentialManager } from '../credential-manager'
|
|
7
12
|
import { createAccountId } from '../types'
|
|
8
13
|
|
|
9
14
|
interface LoginOptions {
|
|
10
|
-
phone
|
|
15
|
+
phone?: string
|
|
16
|
+
qr?: boolean
|
|
11
17
|
pretty?: boolean
|
|
12
18
|
}
|
|
13
19
|
|
|
@@ -16,58 +22,145 @@ interface StatusOptions {
|
|
|
16
22
|
pretty?: boolean
|
|
17
23
|
}
|
|
18
24
|
|
|
19
|
-
|
|
25
|
+
function isInteractiveSession(): boolean {
|
|
26
|
+
return Boolean(process.stdin.isTTY && process.stdout.isTTY)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async function loginWithPairingCode(options: LoginOptions & { phone: string }): Promise<void> {
|
|
30
|
+
const manager = new WhatsAppCredentialManager()
|
|
31
|
+
const accountId = createAccountId(options.phone)
|
|
32
|
+
const existingPaths = manager.getAccountPaths(accountId)
|
|
33
|
+
await rm(existingPaths.auth_dir, { recursive: true, force: true })
|
|
34
|
+
const paths = await manager.ensureAccountPaths(accountId)
|
|
35
|
+
const client = await new WhatsAppClient().login({ authDir: paths.auth_dir })
|
|
36
|
+
|
|
37
|
+
let code: string
|
|
38
|
+
let waitForAuth: () => Promise<void>
|
|
39
|
+
|
|
20
40
|
try {
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
await
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
let code: string
|
|
30
|
-
let waitForAuth: () => Promise<void>
|
|
31
|
-
|
|
32
|
-
try {
|
|
33
|
-
const result = await client.connectForPairing(options.phone)
|
|
34
|
-
code = result.code
|
|
35
|
-
waitForAuth = result.waitForAuth
|
|
36
|
-
} catch (err) {
|
|
37
|
-
await client.close()
|
|
38
|
-
throw err
|
|
39
|
-
}
|
|
41
|
+
const result = await client.connectForPairing(options.phone)
|
|
42
|
+
code = result.code
|
|
43
|
+
waitForAuth = result.waitForAuth
|
|
44
|
+
} catch (err) {
|
|
45
|
+
await client.close()
|
|
46
|
+
throw err
|
|
47
|
+
}
|
|
40
48
|
|
|
41
|
-
|
|
49
|
+
const formatted = code.length === 8 ? `${code.slice(0, 4)}-${code.slice(4)}` : code
|
|
42
50
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
51
|
+
console.log(
|
|
52
|
+
formatOutput(
|
|
53
|
+
{
|
|
54
|
+
pairing_code: formatted,
|
|
55
|
+
message: 'Enter this code in WhatsApp > Linked Devices > Link with phone number',
|
|
56
|
+
},
|
|
57
|
+
options.pretty,
|
|
58
|
+
),
|
|
59
|
+
)
|
|
47
60
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
61
|
+
try {
|
|
62
|
+
await waitForAuth()
|
|
63
|
+
} catch (err) {
|
|
64
|
+
await client.close()
|
|
65
|
+
throw err
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const now = new Date().toISOString()
|
|
69
|
+
await manager.setAccount({
|
|
70
|
+
account_id: accountId,
|
|
71
|
+
phone_number: options.phone,
|
|
72
|
+
created_at: now,
|
|
73
|
+
updated_at: now,
|
|
74
|
+
})
|
|
75
|
+
await manager.setCurrent(accountId)
|
|
76
|
+
await client.close()
|
|
77
|
+
|
|
78
|
+
console.log(
|
|
79
|
+
formatOutput(
|
|
80
|
+
{
|
|
81
|
+
authenticated: true,
|
|
82
|
+
account_id: accountId,
|
|
83
|
+
phone_number: options.phone,
|
|
84
|
+
},
|
|
85
|
+
options.pretty,
|
|
86
|
+
),
|
|
87
|
+
)
|
|
88
|
+
process.exit(0)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
async function loginWithQR(options: LoginOptions): Promise<void> {
|
|
92
|
+
const manager = new WhatsAppCredentialManager()
|
|
93
|
+
const accountId = 'qr-default'
|
|
94
|
+
const existingPaths = manager.getAccountPaths(accountId)
|
|
95
|
+
await rm(existingPaths.auth_dir, { recursive: true, force: true })
|
|
96
|
+
const paths = await manager.ensureAccountPaths(accountId)
|
|
97
|
+
const client = await new WhatsAppClient().login({ authDir: paths.auth_dir })
|
|
98
|
+
const interactive = isInteractiveSession()
|
|
99
|
+
|
|
100
|
+
let waitForAuth: () => Promise<void>
|
|
101
|
+
let browserOpened = false
|
|
54
102
|
|
|
55
|
-
|
|
56
|
-
await
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
103
|
+
try {
|
|
104
|
+
const result = await client.connectForQR(async (qr) => {
|
|
105
|
+
await displayQR(qr, {
|
|
106
|
+
platform: 'WhatsApp',
|
|
107
|
+
brandColor: '#25D366',
|
|
108
|
+
scanInstruction: 'Scan with WhatsApp on your phone',
|
|
109
|
+
interactive,
|
|
110
|
+
openBrowser: interactive && !browserOpened,
|
|
111
|
+
formatOutput,
|
|
112
|
+
pretty: options.pretty,
|
|
113
|
+
})
|
|
114
|
+
browserOpened = true
|
|
61
115
|
})
|
|
62
|
-
|
|
116
|
+
waitForAuth = result.waitForAuth
|
|
117
|
+
} catch (err) {
|
|
63
118
|
await client.close()
|
|
119
|
+
throw err
|
|
120
|
+
}
|
|
64
121
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
122
|
+
if (interactive) {
|
|
123
|
+
info('\nWaiting for QR code scan...')
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
try {
|
|
127
|
+
await waitForAuth()
|
|
128
|
+
} catch (err) {
|
|
129
|
+
await client.close()
|
|
130
|
+
throw err
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const now = new Date().toISOString()
|
|
134
|
+
await manager.setAccount({
|
|
135
|
+
account_id: accountId,
|
|
136
|
+
created_at: now,
|
|
137
|
+
updated_at: now,
|
|
138
|
+
})
|
|
139
|
+
await manager.setCurrent(accountId)
|
|
140
|
+
await client.close()
|
|
141
|
+
|
|
142
|
+
console.log(
|
|
143
|
+
formatOutput(
|
|
144
|
+
{
|
|
145
|
+
authenticated: true,
|
|
146
|
+
account_id: accountId,
|
|
147
|
+
},
|
|
148
|
+
options.pretty,
|
|
149
|
+
),
|
|
150
|
+
)
|
|
151
|
+
process.exit(0)
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
async function loginAction(options: LoginOptions): Promise<void> {
|
|
155
|
+
try {
|
|
156
|
+
if (options.qr) {
|
|
157
|
+
await loginWithQR(options)
|
|
158
|
+
} else if (options.phone) {
|
|
159
|
+
await loginWithPairingCode(options as LoginOptions & { phone: string })
|
|
160
|
+
} else {
|
|
161
|
+
console.error('Error: Either --phone or --qr is required')
|
|
162
|
+
process.exit(1)
|
|
163
|
+
}
|
|
71
164
|
} catch (error) {
|
|
72
165
|
handleError(error as Error)
|
|
73
166
|
}
|
|
@@ -79,21 +172,31 @@ async function statusAction(options: StatusOptions): Promise<void> {
|
|
|
79
172
|
const account = await manager.getAccount(options.account)
|
|
80
173
|
|
|
81
174
|
if (!account) {
|
|
82
|
-
console.log(
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
175
|
+
console.log(
|
|
176
|
+
formatOutput(
|
|
177
|
+
{
|
|
178
|
+
error: options.account
|
|
179
|
+
? `WhatsApp account "${options.account}" not found.`
|
|
180
|
+
: 'No WhatsApp account configured. Run "auth login --qr" or "auth login --phone <phone-number>" first.',
|
|
181
|
+
},
|
|
182
|
+
options.pretty,
|
|
183
|
+
),
|
|
184
|
+
)
|
|
87
185
|
process.exit(1)
|
|
88
186
|
}
|
|
89
187
|
|
|
90
|
-
console.log(
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
188
|
+
console.log(
|
|
189
|
+
formatOutput(
|
|
190
|
+
{
|
|
191
|
+
account_id: account.account_id,
|
|
192
|
+
phone_number: account.phone_number,
|
|
193
|
+
name: account.name,
|
|
194
|
+
created_at: account.created_at,
|
|
195
|
+
updated_at: account.updated_at,
|
|
196
|
+
},
|
|
197
|
+
options.pretty,
|
|
198
|
+
),
|
|
199
|
+
)
|
|
97
200
|
} catch (error) {
|
|
98
201
|
handleError(error as Error)
|
|
99
202
|
}
|
|
@@ -104,17 +207,19 @@ async function listAction(options: { pretty?: boolean }): Promise<void> {
|
|
|
104
207
|
const manager = new WhatsAppCredentialManager()
|
|
105
208
|
const accounts = await manager.listAccounts()
|
|
106
209
|
|
|
107
|
-
console.log(
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
210
|
+
console.log(
|
|
211
|
+
formatOutput(
|
|
212
|
+
accounts.map((account) => ({
|
|
213
|
+
account_id: account.account_id,
|
|
214
|
+
phone_number: account.phone_number,
|
|
215
|
+
name: account.name,
|
|
216
|
+
created_at: account.created_at,
|
|
217
|
+
updated_at: account.updated_at,
|
|
218
|
+
is_current: account.is_current,
|
|
219
|
+
})),
|
|
220
|
+
options.pretty,
|
|
221
|
+
),
|
|
222
|
+
)
|
|
118
223
|
} catch (error) {
|
|
119
224
|
handleError(error as Error)
|
|
120
225
|
}
|
|
@@ -175,8 +280,9 @@ export const authCommand = new Command('auth')
|
|
|
175
280
|
.description('WhatsApp authentication commands')
|
|
176
281
|
.addCommand(
|
|
177
282
|
new Command('login')
|
|
178
|
-
.description('Link as a companion device
|
|
179
|
-
.
|
|
283
|
+
.description('Link as a companion device via pairing code (--phone) or QR code (--qr)')
|
|
284
|
+
.option('--phone <number>', 'Phone number in international format (e.g. +12025551234)')
|
|
285
|
+
.option('--qr', 'Link by scanning a QR code instead of entering a pairing code')
|
|
180
286
|
.option('--pretty', 'Pretty print JSON output')
|
|
181
287
|
.action(loginAction),
|
|
182
288
|
)
|
|
@@ -40,8 +40,8 @@ export async function withWhatsAppClient<T>(
|
|
|
40
40
|
formatOutput(
|
|
41
41
|
{
|
|
42
42
|
error: options.account
|
|
43
|
-
? `WhatsApp account "${options.account}" not found. Run "agent-whatsapp auth login --phone <phone-number>" first.`
|
|
44
|
-
: 'Not authenticated. Run "agent-whatsapp auth login --phone <phone-number>" first.',
|
|
43
|
+
? `WhatsApp account "${options.account}" not found. Run "agent-whatsapp auth login --qr" or "agent-whatsapp auth login --phone <phone-number>" first.`
|
|
44
|
+
: 'Not authenticated. Run "agent-whatsapp auth login --qr" or "agent-whatsapp auth login --phone <phone-number>" first.',
|
|
45
45
|
},
|
|
46
46
|
options.pretty,
|
|
47
47
|
),
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, spyOn, test } from 'bun:test'
|
|
2
|
+
|
|
3
|
+
import type { WhatsAppClient } from '../client'
|
|
4
|
+
import * as sharedModule from './shared'
|
|
5
|
+
import { whoamiAction } from './whoami'
|
|
6
|
+
|
|
7
|
+
let mockProfileData: { id: string; name: string | null; phone_number: string | null } = {
|
|
8
|
+
id: '12025551234:1@s.whatsapp.net',
|
|
9
|
+
name: 'Test User',
|
|
10
|
+
phone_number: '12025551234',
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
let withWhatsAppClientSpy: ReturnType<typeof spyOn>
|
|
14
|
+
let consoleLogSpy: ReturnType<typeof spyOn>
|
|
15
|
+
|
|
16
|
+
describe('whoami command', () => {
|
|
17
|
+
beforeEach(() => {
|
|
18
|
+
mockProfileData = {
|
|
19
|
+
id: '12025551234:1@s.whatsapp.net',
|
|
20
|
+
name: 'Test User',
|
|
21
|
+
phone_number: '12025551234',
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
withWhatsAppClientSpy = spyOn(sharedModule, 'withWhatsAppClient').mockImplementation(
|
|
25
|
+
async (_opts, fn) => fn({ getProfile: () => Promise.resolve(mockProfileData) } as unknown as WhatsAppClient),
|
|
26
|
+
)
|
|
27
|
+
consoleLogSpy = spyOn(console, 'log').mockImplementation(() => {})
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
afterEach(() => {
|
|
31
|
+
withWhatsAppClientSpy?.mockRestore()
|
|
32
|
+
consoleLogSpy?.mockRestore()
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
test('outputs profile information', async () => {
|
|
36
|
+
await whoamiAction({})
|
|
37
|
+
|
|
38
|
+
expect(consoleLogSpy).toHaveBeenCalledTimes(1)
|
|
39
|
+
const output = JSON.parse(consoleLogSpy.mock.calls[0][0] as string)
|
|
40
|
+
expect(output.id).toBe('12025551234:1@s.whatsapp.net')
|
|
41
|
+
expect(output.name).toBe('Test User')
|
|
42
|
+
expect(output.phone_number).toBe('12025551234')
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
test('outputs profile with null name', async () => {
|
|
46
|
+
mockProfileData = {
|
|
47
|
+
id: '12025551234@s.whatsapp.net',
|
|
48
|
+
name: null,
|
|
49
|
+
phone_number: '12025551234',
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
await whoamiAction({})
|
|
53
|
+
|
|
54
|
+
expect(consoleLogSpy).toHaveBeenCalledTimes(1)
|
|
55
|
+
const output = JSON.parse(consoleLogSpy.mock.calls[0][0] as string)
|
|
56
|
+
expect(output.id).toBe('12025551234@s.whatsapp.net')
|
|
57
|
+
expect(output.name).toBeNull()
|
|
58
|
+
})
|
|
59
|
+
})
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Command } from 'commander'
|
|
2
|
+
|
|
3
|
+
import { handleError } from '@/shared/utils/error-handler'
|
|
4
|
+
import { formatOutput } from '@/shared/utils/output'
|
|
5
|
+
|
|
6
|
+
import { withWhatsAppClient } from './shared'
|
|
7
|
+
|
|
8
|
+
export async function whoamiAction(options: { account?: string; pretty?: boolean }): Promise<void> {
|
|
9
|
+
try {
|
|
10
|
+
const profile = await withWhatsAppClient(options, (client) => client.getProfile())
|
|
11
|
+
console.log(formatOutput(profile, options.pretty))
|
|
12
|
+
} catch (error) {
|
|
13
|
+
handleError(error as Error)
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const whoamiCommand = new Command('whoami')
|
|
18
|
+
.description('Show current authenticated user')
|
|
19
|
+
.option('--account <id>', 'Use a specific WhatsApp account')
|
|
20
|
+
.option('--pretty', 'Pretty print JSON output')
|
|
21
|
+
.action(whoamiAction)
|
|
@@ -9,7 +9,7 @@ export async function ensureWhatsAppAuth(): Promise<void> {
|
|
|
9
9
|
|
|
10
10
|
if (!account) {
|
|
11
11
|
console.log(formatOutput({
|
|
12
|
-
error: 'Not authenticated. Run "agent-whatsapp auth login --phone <phone-number>" first.',
|
|
12
|
+
error: 'Not authenticated. Run "agent-whatsapp auth login --qr" or "agent-whatsapp auth login --phone <phone-number>" first.',
|
|
13
13
|
}))
|
|
14
14
|
process.exit(1)
|
|
15
15
|
}
|
|
@@ -19,7 +19,7 @@ export async function ensureWhatsAppAuth(): Promise<void> {
|
|
|
19
19
|
|
|
20
20
|
if (!existsSync(credsPath)) {
|
|
21
21
|
console.log(formatOutput({
|
|
22
|
-
error: 'Auth credentials missing. Run "agent-whatsapp auth login --phone <phone-number>" to re-authenticate.',
|
|
22
|
+
error: 'Auth credentials missing. Run "agent-whatsapp auth login --qr" or "agent-whatsapp auth login --phone <phone-number>" to re-authenticate.',
|
|
23
23
|
}))
|
|
24
24
|
process.exit(1)
|
|
25
25
|
}
|