agent-messenger 2.10.1 → 2.11.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/.env.template +4 -1
- package/README.md +77 -27
- package/bun.lock +26 -0
- package/dist/package.json +14 -1
- package/dist/src/platforms/channeltalk/commands/auth.d.ts +2 -1
- package/dist/src/platforms/channeltalk/commands/auth.d.ts.map +1 -1
- package/dist/src/platforms/channeltalk/commands/auth.js +5 -3
- package/dist/src/platforms/channeltalk/commands/auth.js.map +1 -1
- package/dist/src/platforms/channeltalk/token-extractor.d.ts +2 -1
- package/dist/src/platforms/channeltalk/token-extractor.d.ts.map +1 -1
- package/dist/src/platforms/channeltalk/token-extractor.js +22 -6
- package/dist/src/platforms/channeltalk/token-extractor.js.map +1 -1
- package/dist/src/platforms/channeltalkbot/cli.d.ts.map +1 -1
- package/dist/src/platforms/channeltalkbot/cli.js +11 -1
- package/dist/src/platforms/channeltalkbot/cli.js.map +1 -1
- package/dist/src/platforms/channeltalkbot/commands/auth.d.ts.map +1 -1
- package/dist/src/platforms/channeltalkbot/commands/auth.js +1 -5
- package/dist/src/platforms/channeltalkbot/commands/auth.js.map +1 -1
- package/dist/src/platforms/channeltalkbot/commands/bot.d.ts.map +1 -1
- package/dist/src/platforms/channeltalkbot/commands/bot.js +1 -6
- package/dist/src/platforms/channeltalkbot/commands/bot.js.map +1 -1
- package/dist/src/platforms/channeltalkbot/commands/chat.d.ts.map +1 -1
- package/dist/src/platforms/channeltalkbot/commands/chat.js +1 -6
- package/dist/src/platforms/channeltalkbot/commands/chat.js.map +1 -1
- package/dist/src/platforms/channeltalkbot/commands/group.d.ts.map +1 -1
- package/dist/src/platforms/channeltalkbot/commands/group.js +1 -6
- package/dist/src/platforms/channeltalkbot/commands/group.js.map +1 -1
- package/dist/src/platforms/channeltalkbot/commands/manager.d.ts.map +1 -1
- package/dist/src/platforms/channeltalkbot/commands/manager.js +1 -6
- package/dist/src/platforms/channeltalkbot/commands/manager.js.map +1 -1
- package/dist/src/platforms/channeltalkbot/commands/message.d.ts.map +1 -1
- package/dist/src/platforms/channeltalkbot/commands/message.js +1 -6
- package/dist/src/platforms/channeltalkbot/commands/message.js.map +1 -1
- package/dist/src/platforms/channeltalkbot/commands/whoami.d.ts.map +1 -1
- package/dist/src/platforms/channeltalkbot/commands/whoami.js +1 -6
- package/dist/src/platforms/channeltalkbot/commands/whoami.js.map +1 -1
- package/dist/src/platforms/channeltalkbot/credential-manager.d.ts +5 -0
- package/dist/src/platforms/channeltalkbot/credential-manager.d.ts.map +1 -1
- package/dist/src/platforms/channeltalkbot/credential-manager.js +34 -4
- package/dist/src/platforms/channeltalkbot/credential-manager.js.map +1 -1
- package/dist/src/platforms/discord/commands/auth.d.ts +1 -0
- package/dist/src/platforms/discord/commands/auth.d.ts.map +1 -1
- package/dist/src/platforms/discord/commands/auth.js +3 -1
- package/dist/src/platforms/discord/commands/auth.js.map +1 -1
- package/dist/src/platforms/discord/listener.d.ts +2 -0
- package/dist/src/platforms/discord/listener.d.ts.map +1 -1
- package/dist/src/platforms/discord/listener.js +51 -21
- package/dist/src/platforms/discord/listener.js.map +1 -1
- package/dist/src/platforms/discord/token-extractor.d.ts +2 -1
- package/dist/src/platforms/discord/token-extractor.d.ts.map +1 -1
- package/dist/src/platforms/discord/token-extractor.js +21 -6
- package/dist/src/platforms/discord/token-extractor.js.map +1 -1
- package/dist/src/platforms/discordbot/cli.d.ts.map +1 -1
- package/dist/src/platforms/discordbot/cli.js +12 -1
- package/dist/src/platforms/discordbot/cli.js.map +1 -1
- package/dist/src/platforms/discordbot/client.d.ts +3 -0
- package/dist/src/platforms/discordbot/client.d.ts.map +1 -1
- package/dist/src/platforms/discordbot/client.js +3 -0
- package/dist/src/platforms/discordbot/client.js.map +1 -1
- package/dist/src/platforms/discordbot/commands/auth.d.ts.map +1 -1
- package/dist/src/platforms/discordbot/commands/auth.js +1 -5
- package/dist/src/platforms/discordbot/commands/auth.js.map +1 -1
- package/dist/src/platforms/discordbot/commands/message.d.ts.map +1 -1
- package/dist/src/platforms/discordbot/commands/message.js +1 -6
- package/dist/src/platforms/discordbot/commands/message.js.map +1 -1
- package/dist/src/platforms/discordbot/commands/server.d.ts.map +1 -1
- package/dist/src/platforms/discordbot/commands/server.js +1 -4
- package/dist/src/platforms/discordbot/commands/server.js.map +1 -1
- package/dist/src/platforms/discordbot/commands/whoami.d.ts.map +1 -1
- package/dist/src/platforms/discordbot/commands/whoami.js +1 -6
- package/dist/src/platforms/discordbot/commands/whoami.js.map +1 -1
- package/dist/src/platforms/discordbot/index.d.ts +3 -1
- package/dist/src/platforms/discordbot/index.d.ts.map +1 -1
- package/dist/src/platforms/discordbot/index.js +2 -1
- package/dist/src/platforms/discordbot/index.js.map +1 -1
- package/dist/src/platforms/discordbot/listener.d.ts +43 -0
- package/dist/src/platforms/discordbot/listener.d.ts.map +1 -0
- package/dist/src/platforms/discordbot/listener.js +292 -0
- package/dist/src/platforms/discordbot/listener.js.map +1 -0
- package/dist/src/platforms/discordbot/types.d.ts +161 -0
- package/dist/src/platforms/discordbot/types.d.ts.map +1 -1
- package/dist/src/platforms/discordbot/types.js +34 -0
- package/dist/src/platforms/discordbot/types.js.map +1 -1
- package/dist/src/platforms/instagram/commands/auth.d.ts.map +1 -1
- package/dist/src/platforms/instagram/commands/auth.js +3 -1
- package/dist/src/platforms/instagram/commands/auth.js.map +1 -1
- package/dist/src/platforms/instagram/token-extractor.d.ts +2 -1
- package/dist/src/platforms/instagram/token-extractor.d.ts.map +1 -1
- package/dist/src/platforms/instagram/token-extractor.js +11 -2
- package/dist/src/platforms/instagram/token-extractor.js.map +1 -1
- package/dist/src/platforms/slack/commands/auth.d.ts.map +1 -1
- package/dist/src/platforms/slack/commands/auth.js +4 -2
- package/dist/src/platforms/slack/commands/auth.js.map +1 -1
- package/dist/src/platforms/slack/token-extractor.d.ts +4 -1
- package/dist/src/platforms/slack/token-extractor.d.ts.map +1 -1
- package/dist/src/platforms/slack/token-extractor.js +64 -15
- package/dist/src/platforms/slack/token-extractor.js.map +1 -1
- package/dist/src/platforms/slackbot/cli.d.ts.map +1 -1
- package/dist/src/platforms/slackbot/cli.js +15 -3
- package/dist/src/platforms/slackbot/cli.js.map +1 -1
- package/dist/src/platforms/slackbot/client.d.ts +22 -1
- package/dist/src/platforms/slackbot/client.d.ts.map +1 -1
- package/dist/src/platforms/slackbot/client.js +104 -1
- package/dist/src/platforms/slackbot/client.js.map +1 -1
- package/dist/src/platforms/slackbot/commands/auth.d.ts.map +1 -1
- package/dist/src/platforms/slackbot/commands/auth.js +1 -5
- package/dist/src/platforms/slackbot/commands/auth.js.map +1 -1
- package/dist/src/platforms/slackbot/commands/file.d.ts +3 -0
- package/dist/src/platforms/slackbot/commands/file.d.ts.map +1 -0
- package/dist/src/platforms/slackbot/commands/file.js +164 -0
- package/dist/src/platforms/slackbot/commands/file.js.map +1 -0
- 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/message.d.ts.map +1 -1
- package/dist/src/platforms/slackbot/commands/message.js +19 -0
- package/dist/src/platforms/slackbot/commands/message.js.map +1 -1
- package/dist/src/platforms/slackbot/commands/whoami.d.ts.map +1 -1
- package/dist/src/platforms/slackbot/commands/whoami.js +1 -6
- package/dist/src/platforms/slackbot/commands/whoami.js.map +1 -1
- package/dist/src/platforms/slackbot/credential-manager.d.ts +1 -0
- package/dist/src/platforms/slackbot/credential-manager.d.ts.map +1 -1
- package/dist/src/platforms/slackbot/credential-manager.js +30 -2
- package/dist/src/platforms/slackbot/credential-manager.js.map +1 -1
- package/dist/src/platforms/slackbot/index.d.ts +4 -1
- package/dist/src/platforms/slackbot/index.d.ts.map +1 -1
- package/dist/src/platforms/slackbot/index.js +1 -0
- package/dist/src/platforms/slackbot/index.js.map +1 -1
- package/dist/src/platforms/slackbot/listener.d.ts +44 -0
- package/dist/src/platforms/slackbot/listener.d.ts.map +1 -0
- package/dist/src/platforms/slackbot/listener.js +313 -0
- package/dist/src/platforms/slackbot/listener.js.map +1 -0
- package/dist/src/platforms/slackbot/types.d.ts +196 -1
- package/dist/src/platforms/slackbot/types.d.ts.map +1 -1
- package/dist/src/platforms/slackbot/types.js +4 -1
- package/dist/src/platforms/slackbot/types.js.map +1 -1
- package/dist/src/platforms/teams/commands/auth.d.ts +1 -0
- package/dist/src/platforms/teams/commands/auth.d.ts.map +1 -1
- package/dist/src/platforms/teams/commands/auth.js +37 -6
- package/dist/src/platforms/teams/commands/auth.js.map +1 -1
- package/dist/src/platforms/teams/ensure-auth.js +31 -9
- package/dist/src/platforms/teams/ensure-auth.js.map +1 -1
- package/dist/src/platforms/teams/token-extractor.d.ts +4 -1
- package/dist/src/platforms/teams/token-extractor.d.ts.map +1 -1
- package/dist/src/platforms/teams/token-extractor.js +80 -31
- package/dist/src/platforms/teams/token-extractor.js.map +1 -1
- package/dist/src/platforms/webex/commands/auth.d.ts +1 -0
- package/dist/src/platforms/webex/commands/auth.d.ts.map +1 -1
- package/dist/src/platforms/webex/commands/auth.js +3 -1
- package/dist/src/platforms/webex/commands/auth.js.map +1 -1
- package/dist/src/platforms/webex/token-extractor.d.ts +3 -1
- package/dist/src/platforms/webex/token-extractor.d.ts.map +1 -1
- package/dist/src/platforms/webex/token-extractor.js +16 -2
- package/dist/src/platforms/webex/token-extractor.js.map +1 -1
- package/dist/src/platforms/wechatbot/cli.d.ts.map +1 -1
- package/dist/src/platforms/wechatbot/cli.js +11 -1
- package/dist/src/platforms/wechatbot/cli.js.map +1 -1
- package/dist/src/platforms/wechatbot/commands/auth.d.ts.map +1 -1
- package/dist/src/platforms/wechatbot/commands/auth.js +1 -5
- package/dist/src/platforms/wechatbot/commands/auth.js.map +1 -1
- package/dist/src/platforms/wechatbot/commands/message.d.ts.map +1 -1
- package/dist/src/platforms/wechatbot/commands/message.js +1 -6
- package/dist/src/platforms/wechatbot/commands/message.js.map +1 -1
- package/dist/src/platforms/wechatbot/commands/template.d.ts.map +1 -1
- package/dist/src/platforms/wechatbot/commands/template.js +1 -6
- package/dist/src/platforms/wechatbot/commands/template.js.map +1 -1
- package/dist/src/platforms/wechatbot/commands/user.d.ts.map +1 -1
- package/dist/src/platforms/wechatbot/commands/user.js +1 -6
- package/dist/src/platforms/wechatbot/commands/user.js.map +1 -1
- package/dist/src/platforms/wechatbot/commands/whoami.d.ts.map +1 -1
- package/dist/src/platforms/wechatbot/commands/whoami.js +1 -6
- package/dist/src/platforms/wechatbot/commands/whoami.js.map +1 -1
- package/dist/src/platforms/whatsappbot/cli.d.ts.map +1 -1
- package/dist/src/platforms/whatsappbot/cli.js +11 -1
- package/dist/src/platforms/whatsappbot/cli.js.map +1 -1
- package/dist/src/platforms/whatsappbot/commands/auth.d.ts.map +1 -1
- package/dist/src/platforms/whatsappbot/commands/auth.js +1 -5
- package/dist/src/platforms/whatsappbot/commands/auth.js.map +1 -1
- package/dist/src/platforms/whatsappbot/commands/message.d.ts.map +1 -1
- package/dist/src/platforms/whatsappbot/commands/message.js +1 -6
- package/dist/src/platforms/whatsappbot/commands/message.js.map +1 -1
- package/dist/src/platforms/whatsappbot/commands/template.d.ts.map +1 -1
- package/dist/src/platforms/whatsappbot/commands/template.js +1 -6
- package/dist/src/platforms/whatsappbot/commands/template.js.map +1 -1
- package/dist/src/platforms/whatsappbot/commands/whoami.d.ts.map +1 -1
- package/dist/src/platforms/whatsappbot/commands/whoami.js +1 -6
- package/dist/src/platforms/whatsappbot/commands/whoami.js.map +1 -1
- package/dist/src/shared/chromium/browsers.d.ts +8 -0
- package/dist/src/shared/chromium/browsers.d.ts.map +1 -1
- package/dist/src/shared/chromium/browsers.js +58 -3
- package/dist/src/shared/chromium/browsers.js.map +1 -1
- package/dist/src/shared/chromium/cli-options.d.ts +5 -0
- package/dist/src/shared/chromium/cli-options.d.ts.map +1 -0
- package/dist/src/shared/chromium/cli-options.js +8 -0
- package/dist/src/shared/chromium/cli-options.js.map +1 -0
- package/dist/src/shared/chromium/decryptor.d.ts +6 -0
- package/dist/src/shared/chromium/decryptor.d.ts.map +1 -1
- package/dist/src/shared/chromium/decryptor.js +26 -6
- package/dist/src/shared/chromium/decryptor.js.map +1 -1
- package/dist/src/shared/chromium/index.d.ts +3 -1
- package/dist/src/shared/chromium/index.d.ts.map +1 -1
- package/dist/src/shared/chromium/index.js +2 -1
- package/dist/src/shared/chromium/index.js.map +1 -1
- package/dist/src/shared/utils/cli-output.d.ts +7 -0
- package/dist/src/shared/utils/cli-output.d.ts.map +1 -0
- package/dist/src/shared/utils/cli-output.js +7 -0
- package/dist/src/shared/utils/cli-output.js.map +1 -0
- package/dist/src/tui/app.d.ts.map +1 -1
- package/dist/src/tui/app.js +73 -20
- package/dist/src/tui/app.js.map +1 -1
- package/docs/content/docs/cli/channeltalk.mdx +4 -0
- package/docs/content/docs/cli/discord.mdx +5 -0
- package/docs/content/docs/cli/instagram.mdx +3 -0
- package/docs/content/docs/cli/slack.mdx +5 -0
- package/docs/content/docs/cli/slackbot.mdx +60 -22
- package/docs/content/docs/cli/teams.mdx +5 -0
- package/docs/content/docs/cli/webex.mdx +3 -0
- package/docs/content/docs/sdk/channeltalkbot.mdx +38 -1
- package/docs/content/docs/sdk/discordbot.mdx +501 -0
- package/docs/content/docs/sdk/meta.json +2 -0
- package/docs/content/docs/sdk/slackbot.mdx +576 -0
- package/e2e/README.md +1 -1
- package/e2e/channeltalk.e2e.test.ts +13 -13
- package/e2e/channeltalkbot.e2e.test.ts +13 -13
- package/e2e/config.ts +9 -4
- package/e2e/discord.e2e.test.ts +24 -24
- package/e2e/discordbot.e2e.test.ts +16 -16
- package/e2e/instagram.e2e.test.ts +10 -10
- package/e2e/kakaotalk.e2e.test.ts +7 -7
- package/e2e/line.e2e.test.ts +8 -8
- package/e2e/slack.e2e.test.ts +34 -34
- package/e2e/slackbot.e2e.test.ts +14 -14
- package/e2e/teams.e2e.test.ts +23 -23
- package/e2e/telegram.e2e.test.ts +8 -8
- package/e2e/webex.e2e.test.ts +14 -14
- package/e2e/whatsapp.e2e.test.ts +8 -8
- package/e2e/whatsappbot.e2e.test.ts +6 -6
- package/examples/discordbot-listen.ts +65 -0
- package/examples/slackbot-listen.ts +65 -0
- package/package.json +14 -1
- package/skills/agent-channeltalk/SKILL.md +5 -1
- package/skills/agent-channeltalk/references/authentication.md +5 -1
- package/skills/agent-channeltalkbot/SKILL.md +17 -3
- package/skills/agent-channeltalkbot/references/authentication.md +7 -5
- package/skills/agent-discord/SKILL.md +5 -1
- package/skills/agent-discord/references/authentication.md +7 -1
- package/skills/agent-discordbot/SKILL.md +13 -2
- package/skills/agent-discordbot/references/common-patterns.md +1 -1
- package/skills/agent-instagram/SKILL.md +7 -1
- package/skills/agent-instagram/references/authentication.md +6 -0
- package/skills/agent-kakaotalk/SKILL.md +1 -1
- package/skills/agent-line/SKILL.md +1 -1
- package/skills/agent-slack/SKILL.md +5 -1
- package/skills/agent-slack/references/authentication.md +7 -1
- package/skills/agent-slackbot/SKILL.md +56 -4
- package/skills/agent-slackbot/references/authentication.md +4 -0
- package/skills/agent-teams/SKILL.md +5 -1
- package/skills/agent-teams/references/authentication.md +7 -1
- package/skills/agent-telegram/SKILL.md +1 -1
- package/skills/agent-webex/SKILL.md +7 -1
- package/skills/agent-webex/references/authentication.md +6 -0
- package/skills/agent-wechatbot/SKILL.md +16 -1
- package/skills/agent-wechatbot/references/authentication.md +219 -0
- package/skills/agent-wechatbot/references/common-patterns.md +358 -0
- package/skills/agent-wechatbot/templates/account-summary.sh +122 -0
- package/skills/agent-wechatbot/templates/post-message.sh +122 -0
- package/skills/agent-wechatbot/templates/send-template.sh +152 -0
- package/skills/agent-whatsapp/SKILL.md +1 -1
- package/skills/agent-whatsappbot/SKILL.md +30 -1
- package/src/platforms/channeltalk/client.test.ts +26 -26
- package/src/platforms/channeltalk/commands/auth.test.ts +31 -19
- package/src/platforms/channeltalk/commands/auth.ts +15 -5
- package/src/platforms/channeltalk/commands/bot.test.ts +2 -2
- package/src/platforms/channeltalk/commands/chat.test.ts +3 -3
- package/src/platforms/channeltalk/commands/group.test.ts +4 -4
- package/src/platforms/channeltalk/commands/manager.test.ts +2 -2
- package/src/platforms/channeltalk/commands/message.test.ts +17 -17
- package/src/platforms/channeltalk/commands/snapshot.test.ts +7 -7
- package/src/platforms/channeltalk/commands/whoami.test.ts +3 -3
- package/src/platforms/channeltalk/credential-manager.test.ts +18 -18
- package/src/platforms/channeltalk/ensure-auth.test.ts +5 -5
- package/src/platforms/channeltalk/index.test.ts +23 -23
- package/src/platforms/channeltalk/token-extractor.test.ts +21 -21
- package/src/platforms/channeltalk/token-extractor.ts +24 -5
- package/src/platforms/channeltalk/types.test.ts +12 -12
- package/src/platforms/channeltalkbot/cli.ts +9 -0
- package/src/platforms/channeltalkbot/client.test.ts +14 -14
- package/src/platforms/channeltalkbot/commands/auth.test.ts +16 -16
- package/src/platforms/channeltalkbot/commands/auth.ts +1 -5
- package/src/platforms/channeltalkbot/commands/bot.test.ts +6 -6
- package/src/platforms/channeltalkbot/commands/bot.ts +1 -6
- package/src/platforms/channeltalkbot/commands/chat.test.ts +9 -9
- package/src/platforms/channeltalkbot/commands/chat.ts +1 -6
- package/src/platforms/channeltalkbot/commands/group.test.ts +6 -6
- package/src/platforms/channeltalkbot/commands/group.ts +1 -6
- package/src/platforms/channeltalkbot/commands/manager.test.ts +3 -3
- package/src/platforms/channeltalkbot/commands/manager.ts +1 -6
- package/src/platforms/channeltalkbot/commands/message.test.ts +10 -10
- package/src/platforms/channeltalkbot/commands/message.ts +1 -6
- package/src/platforms/channeltalkbot/commands/snapshot.test.ts +7 -7
- package/src/platforms/channeltalkbot/commands/whoami.test.ts +6 -4
- package/src/platforms/channeltalkbot/commands/whoami.ts +1 -6
- package/src/platforms/channeltalkbot/credential-manager.test.ts +123 -29
- package/src/platforms/channeltalkbot/credential-manager.ts +37 -4
- package/src/platforms/channeltalkbot/index.test.ts +15 -15
- package/src/platforms/discord/client.test.ts +28 -28
- package/src/platforms/discord/commands/auth.test.ts +7 -7
- package/src/platforms/discord/commands/auth.ts +13 -2
- package/src/platforms/discord/commands/channel.test.ts +7 -7
- package/src/platforms/discord/commands/dm.test.ts +4 -4
- package/src/platforms/discord/commands/file.test.ts +4 -4
- package/src/platforms/discord/commands/friend.test.ts +6 -6
- package/src/platforms/discord/commands/member.test.ts +5 -5
- package/src/platforms/discord/commands/mention.test.ts +5 -5
- package/src/platforms/discord/commands/message.test.ts +9 -9
- package/src/platforms/discord/commands/note.test.ts +6 -6
- package/src/platforms/discord/commands/profile.test.ts +4 -4
- package/src/platforms/discord/commands/reaction.test.ts +5 -5
- package/src/platforms/discord/commands/server.test.ts +7 -7
- package/src/platforms/discord/commands/snapshot.test.ts +6 -6
- package/src/platforms/discord/commands/thread.test.ts +6 -6
- package/src/platforms/discord/commands/user.test.ts +5 -5
- package/src/platforms/discord/commands/whoami.test.ts +6 -6
- package/src/platforms/discord/credential-manager.test.ts +16 -16
- package/src/platforms/discord/ensure-auth.test.ts +8 -8
- package/src/platforms/discord/index.test.ts +17 -17
- package/src/platforms/discord/listener.test.ts +92 -34
- package/src/platforms/discord/listener.ts +43 -19
- package/src/platforms/discord/token-extractor.test.ts +53 -53
- package/src/platforms/discord/token-extractor.ts +30 -6
- package/src/platforms/discord/types.test.ts +26 -26
- package/src/platforms/discordbot/cli.ts +10 -0
- package/src/platforms/discordbot/client.test.ts +31 -31
- package/src/platforms/discordbot/client.ts +4 -0
- package/src/platforms/discordbot/commands/auth.test.ts +18 -18
- package/src/platforms/discordbot/commands/auth.ts +1 -5
- package/src/platforms/discordbot/commands/channel.test.ts +11 -11
- package/src/platforms/discordbot/commands/file.test.ts +7 -7
- package/src/platforms/discordbot/commands/message.test.ts +25 -25
- package/src/platforms/discordbot/commands/message.ts +1 -6
- package/src/platforms/discordbot/commands/reaction.test.ts +6 -6
- package/src/platforms/discordbot/commands/server.test.ts +12 -12
- package/src/platforms/discordbot/commands/server.ts +1 -5
- package/src/platforms/discordbot/commands/snapshot.test.ts +13 -13
- package/src/platforms/discordbot/commands/thread.test.ts +10 -10
- package/src/platforms/discordbot/commands/user.test.ts +9 -9
- package/src/platforms/discordbot/commands/whoami.test.ts +4 -4
- package/src/platforms/discordbot/commands/whoami.ts +1 -6
- package/src/platforms/discordbot/credential-manager.test.ts +28 -28
- package/src/platforms/discordbot/index.test.ts +82 -0
- package/src/platforms/discordbot/index.ts +27 -9
- package/src/platforms/discordbot/listener.test.ts +1002 -0
- package/src/platforms/discordbot/listener.ts +321 -0
- package/src/platforms/discordbot/types.ts +163 -0
- package/src/platforms/instagram/client.test.ts +18 -18
- package/src/platforms/instagram/commands/auth.test.ts +11 -11
- package/src/platforms/instagram/commands/auth.ts +9 -1
- package/src/platforms/instagram/commands/chat.test.ts +6 -6
- package/src/platforms/instagram/commands/message.test.ts +11 -11
- package/src/platforms/instagram/commands/shared.test.ts +12 -12
- package/src/platforms/instagram/commands/whoami.test.ts +3 -3
- package/src/platforms/instagram/credential-manager.test.ts +21 -21
- package/src/platforms/instagram/ensure-auth.test.ts +4 -4
- package/src/platforms/instagram/index.test.ts +9 -9
- package/src/platforms/instagram/listener.test.ts +8 -8
- package/src/platforms/instagram/token-extractor.test.ts +35 -35
- package/src/platforms/instagram/token-extractor.ts +13 -1
- package/src/platforms/kakaotalk/client.test.ts +33 -33
- package/src/platforms/kakaotalk/commands/auth.test.ts +11 -11
- package/src/platforms/kakaotalk/commands/chat.test.ts +6 -6
- package/src/platforms/kakaotalk/commands/message.test.ts +7 -7
- package/src/platforms/kakaotalk/commands/whoami.test.ts +5 -5
- package/src/platforms/kakaotalk/credential-manager.test.ts +15 -15
- package/src/platforms/kakaotalk/index.test.ts +15 -15
- package/src/platforms/kakaotalk/listener.test.ts +17 -17
- package/src/platforms/line/client.test.ts +17 -17
- package/src/platforms/line/commands/auth.test.ts +8 -8
- package/src/platforms/line/commands/chat.test.ts +7 -7
- package/src/platforms/line/commands/friend.test.ts +6 -6
- package/src/platforms/line/commands/message.test.ts +7 -7
- package/src/platforms/line/commands/whoami.test.ts +6 -6
- package/src/platforms/line/credential-manager.test.ts +17 -17
- package/src/platforms/line/index.test.ts +10 -10
- package/src/platforms/line/listener.test.ts +15 -15
- package/src/platforms/line/types.test.ts +14 -14
- package/src/platforms/slack/cli.test.ts +8 -8
- package/src/platforms/slack/client.test.ts +151 -151
- package/src/platforms/slack/commands/activity.test.ts +13 -13
- package/src/platforms/slack/commands/auth.test.ts +34 -34
- package/src/platforms/slack/commands/auth.ts +11 -2
- package/src/platforms/slack/commands/bookmark.test.ts +9 -9
- package/src/platforms/slack/commands/channel.test.ts +17 -17
- package/src/platforms/slack/commands/drafts.test.ts +7 -7
- package/src/platforms/slack/commands/emoji.test.ts +3 -3
- package/src/platforms/slack/commands/file.test.ts +12 -12
- package/src/platforms/slack/commands/message.test.ts +19 -19
- package/src/platforms/slack/commands/pin.test.ts +7 -7
- package/src/platforms/slack/commands/reaction.test.ts +10 -10
- package/src/platforms/slack/commands/reminder.test.ts +9 -9
- package/src/platforms/slack/commands/saved.test.ts +7 -7
- package/src/platforms/slack/commands/sections.test.ts +5 -5
- package/src/platforms/slack/commands/snapshot.test.ts +13 -13
- package/src/platforms/slack/commands/unread.test.ts +6 -6
- package/src/platforms/slack/commands/user.test.ts +10 -10
- package/src/platforms/slack/commands/usergroup.test.ts +15 -15
- package/src/platforms/slack/commands/whoami.test.ts +6 -6
- package/src/platforms/slack/commands/workspace.test.ts +26 -26
- package/src/platforms/slack/credential-manager.test.ts +14 -14
- package/src/platforms/slack/ensure-auth.test.ts +21 -21
- package/src/platforms/slack/index.test.ts +12 -12
- package/src/platforms/slack/listener.test.ts +17 -17
- package/src/platforms/slack/token-extractor-node.test.ts +2 -2
- package/src/platforms/slack/token-extractor.test.ts +133 -37
- package/src/platforms/slack/token-extractor.ts +76 -13
- package/src/platforms/slack/types.test.ts +21 -21
- package/src/platforms/slackbot/cli.ts +13 -1
- package/src/platforms/slackbot/client.test.ts +296 -22
- package/src/platforms/slackbot/client.ts +130 -2
- package/src/platforms/slackbot/commands/auth.test.ts +14 -14
- package/src/platforms/slackbot/commands/auth.ts +1 -5
- package/src/platforms/slackbot/commands/channel.test.ts +7 -7
- package/src/platforms/slackbot/commands/file.test.ts +201 -0
- package/src/platforms/slackbot/commands/file.ts +212 -0
- package/src/platforms/slackbot/commands/index.ts +1 -0
- package/src/platforms/slackbot/commands/message.test.ts +13 -13
- package/src/platforms/slackbot/commands/message.ts +22 -0
- package/src/platforms/slackbot/commands/reaction.test.ts +6 -6
- package/src/platforms/slackbot/commands/user.test.ts +7 -7
- package/src/platforms/slackbot/commands/whoami.test.ts +4 -4
- package/src/platforms/slackbot/commands/whoami.ts +1 -6
- package/src/platforms/slackbot/credential-manager.test.ts +83 -23
- package/src/platforms/slackbot/credential-manager.ts +32 -2
- package/src/platforms/slackbot/index.test.ts +59 -0
- package/src/platforms/slackbot/index.ts +31 -7
- package/src/platforms/slackbot/listener.test.ts +1012 -0
- package/src/platforms/slackbot/listener.ts +362 -0
- package/src/platforms/slackbot/types.test.ts +7 -7
- package/src/platforms/slackbot/types.ts +224 -1
- package/src/platforms/teams/client.test.ts +30 -30
- package/src/platforms/teams/commands/auth.test.ts +9 -9
- package/src/platforms/teams/commands/auth.ts +66 -7
- package/src/platforms/teams/commands/channel.test.ts +7 -7
- package/src/platforms/teams/commands/file.test.ts +4 -4
- package/src/platforms/teams/commands/message.test.ts +5 -5
- package/src/platforms/teams/commands/reaction.test.ts +4 -4
- package/src/platforms/teams/commands/snapshot.test.ts +7 -7
- package/src/platforms/teams/commands/team.test.ts +8 -8
- package/src/platforms/teams/commands/user.test.ts +4 -4
- package/src/platforms/teams/commands/whoami.test.ts +6 -6
- package/src/platforms/teams/credential-manager.test.ts +17 -17
- package/src/platforms/teams/ensure-auth.test.ts +69 -18
- package/src/platforms/teams/ensure-auth.ts +39 -11
- package/src/platforms/teams/index.test.ts +15 -15
- package/src/platforms/teams/token-extractor.test.ts +251 -69
- package/src/platforms/teams/token-extractor.ts +94 -31
- package/src/platforms/teams/types.test.ts +26 -26
- package/src/platforms/telegram/app-config.test.ts +4 -4
- package/src/platforms/telegram/chat-utils.test.ts +12 -12
- package/src/platforms/telegram/client.test.ts +4 -4
- package/src/platforms/telegram/commands/auth.test.ts +16 -16
- package/src/platforms/telegram/commands/chat.test.ts +9 -9
- package/src/platforms/telegram/commands/message.test.ts +6 -6
- package/src/platforms/telegram/commands/shared.test.ts +3 -3
- package/src/platforms/telegram/commands/whoami.test.ts +3 -3
- package/src/platforms/telegram/credential-manager.test.ts +10 -10
- package/src/platforms/telegram/types.test.ts +6 -6
- package/src/platforms/webex/app-config.test.ts +8 -8
- package/src/platforms/webex/cli.test.ts +5 -5
- package/src/platforms/webex/client.test.ts +65 -65
- package/src/platforms/webex/commands/auth.test.ts +18 -18
- package/src/platforms/webex/commands/auth.ts +13 -2
- package/src/platforms/webex/commands/member.test.ts +5 -5
- package/src/platforms/webex/commands/message.test.ts +12 -12
- package/src/platforms/webex/commands/snapshot.test.ts +5 -5
- package/src/platforms/webex/commands/space.test.ts +10 -10
- package/src/platforms/webex/commands/whoami.test.ts +6 -6
- package/src/platforms/webex/credential-manager.test.ts +22 -22
- package/src/platforms/webex/encryption.test.ts +4 -4
- package/src/platforms/webex/ensure-auth.test.ts +5 -5
- package/src/platforms/webex/index.test.ts +5 -5
- package/src/platforms/webex/markdown-to-html.test.ts +33 -33
- package/src/platforms/webex/token-extractor.test.ts +23 -23
- package/src/platforms/webex/token-extractor.ts +25 -3
- package/src/platforms/webex/types.test.ts +27 -27
- package/src/platforms/wechatbot/cli.ts +9 -0
- package/src/platforms/wechatbot/client.test.ts +27 -27
- package/src/platforms/wechatbot/commands/auth.test.ts +15 -15
- package/src/platforms/wechatbot/commands/auth.ts +1 -5
- package/src/platforms/wechatbot/commands/message.test.ts +8 -8
- package/src/platforms/wechatbot/commands/message.ts +1 -6
- package/src/platforms/wechatbot/commands/template.test.ts +9 -9
- package/src/platforms/wechatbot/commands/template.ts +1 -6
- package/src/platforms/wechatbot/commands/user.test.ts +7 -7
- package/src/platforms/wechatbot/commands/user.ts +1 -6
- package/src/platforms/wechatbot/commands/whoami.test.ts +5 -5
- package/src/platforms/wechatbot/commands/whoami.ts +1 -6
- package/src/platforms/wechatbot/credential-manager.test.ts +18 -18
- package/src/platforms/wechatbot/index.test.ts +10 -10
- package/src/platforms/wechatbot/types.test.ts +25 -25
- package/src/platforms/whatsapp/commands/auth.test.ts +13 -13
- package/src/platforms/whatsapp/commands/chat.test.ts +8 -8
- package/src/platforms/whatsapp/commands/message.test.ts +10 -10
- package/src/platforms/whatsapp/commands/whoami.test.ts +3 -3
- package/src/platforms/whatsapp/credential-manager.test.ts +23 -23
- package/src/platforms/whatsapp/ensure-auth.test.ts +4 -4
- package/src/platforms/whatsapp/index.test.ts +8 -8
- package/src/platforms/whatsapp/types.test.ts +42 -42
- package/src/platforms/whatsappbot/cli.ts +9 -0
- package/src/platforms/whatsappbot/client.test.ts +27 -27
- package/src/platforms/whatsappbot/commands/auth.test.ts +14 -14
- package/src/platforms/whatsappbot/commands/auth.ts +1 -5
- package/src/platforms/whatsappbot/commands/message.test.ts +16 -16
- package/src/platforms/whatsappbot/commands/message.ts +1 -6
- package/src/platforms/whatsappbot/commands/template.test.ts +9 -9
- package/src/platforms/whatsappbot/commands/template.ts +1 -6
- package/src/platforms/whatsappbot/commands/whoami.test.ts +5 -5
- package/src/platforms/whatsappbot/commands/whoami.ts +1 -6
- package/src/platforms/whatsappbot/credential-manager.test.ts +18 -18
- package/src/platforms/whatsappbot/index.test.ts +7 -7
- package/src/platforms/whatsappbot/types.test.ts +18 -18
- package/src/shared/chromium/browsers.test.ts +102 -22
- package/src/shared/chromium/browsers.ts +72 -3
- package/src/shared/chromium/cli-options.test.ts +22 -0
- package/src/shared/chromium/cli-options.ts +12 -0
- package/src/shared/chromium/cookie-reader.test.ts +13 -13
- package/src/shared/chromium/decryptor.test.ts +97 -32
- package/src/shared/chromium/decryptor.ts +27 -6
- package/src/shared/chromium/index.ts +3 -0
- package/src/shared/utils/cli-output.test.ts +57 -0
- package/src/shared/utils/cli-output.ts +8 -0
- package/src/shared/utils/concurrency.test.ts +6 -6
- package/src/shared/utils/derived-key-cache.test.ts +11 -11
- package/src/tui/app.ts +129 -20
- package/src/tui/utils.test.ts +31 -31
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, mock,
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, mock, it } from 'bun:test'
|
|
2
2
|
import { existsSync, rmSync } from 'node:fs'
|
|
3
3
|
import { mkdir } from 'node:fs/promises'
|
|
4
4
|
import { tmpdir } from 'node:os'
|
|
@@ -67,7 +67,7 @@ describe('snapshot command', () => {
|
|
|
67
67
|
})
|
|
68
68
|
|
|
69
69
|
describe('snapshotAction', () => {
|
|
70
|
-
|
|
70
|
+
it('brief snapshot returns workspace, groups (names), chat counts, and hint', async () => {
|
|
71
71
|
const manager = new ChannelBotCredentialManager(tempDir)
|
|
72
72
|
const result = await snapshotAction({ _credManager: manager })
|
|
73
73
|
|
|
@@ -85,7 +85,7 @@ describe('snapshot command', () => {
|
|
|
85
85
|
expect(mockGetGroupMessages).not.toHaveBeenCalled()
|
|
86
86
|
})
|
|
87
87
|
|
|
88
|
-
|
|
88
|
+
it('full snapshot returns workspace, groups, user_chats, managers, bots', async () => {
|
|
89
89
|
const manager = new ChannelBotCredentialManager(tempDir)
|
|
90
90
|
const result = await snapshotAction({ full: true, _credManager: manager })
|
|
91
91
|
|
|
@@ -99,7 +99,7 @@ describe('snapshot command', () => {
|
|
|
99
99
|
expect(result.bots).toBeDefined()
|
|
100
100
|
})
|
|
101
101
|
|
|
102
|
-
|
|
102
|
+
it('groups-only flag skips user_chats, managers, bots', async () => {
|
|
103
103
|
const manager = new ChannelBotCredentialManager(tempDir)
|
|
104
104
|
const result = await snapshotAction({ full: true, groupsOnly: true, _credManager: manager })
|
|
105
105
|
|
|
@@ -111,7 +111,7 @@ describe('snapshot command', () => {
|
|
|
111
111
|
expect(result.bots).toBeUndefined()
|
|
112
112
|
})
|
|
113
113
|
|
|
114
|
-
|
|
114
|
+
it('chats-only flag skips groups, managers, bots', async () => {
|
|
115
115
|
const manager = new ChannelBotCredentialManager(tempDir)
|
|
116
116
|
const result = await snapshotAction({ full: true, chatsOnly: true, _credManager: manager })
|
|
117
117
|
|
|
@@ -123,7 +123,7 @@ describe('snapshot command', () => {
|
|
|
123
123
|
expect(result.bots).toBeUndefined()
|
|
124
124
|
})
|
|
125
125
|
|
|
126
|
-
|
|
126
|
+
it('full groups include recent messages', async () => {
|
|
127
127
|
const manager = new ChannelBotCredentialManager(tempDir)
|
|
128
128
|
const result = await snapshotAction({ full: true, groupsOnly: true, limit: 3, _credManager: manager })
|
|
129
129
|
|
|
@@ -131,7 +131,7 @@ describe('snapshot command', () => {
|
|
|
131
131
|
expect(result.groups?.[0].messages?.[0].id).toBe('msg1')
|
|
132
132
|
})
|
|
133
133
|
|
|
134
|
-
|
|
134
|
+
it('full user_chats includes counts and recent opened', async () => {
|
|
135
135
|
const manager = new ChannelBotCredentialManager(tempDir)
|
|
136
136
|
const result = await snapshotAction({ full: true, chatsOnly: true, _credManager: manager })
|
|
137
137
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, mock,
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, mock, it } from 'bun:test'
|
|
2
2
|
import { existsSync, rmSync } from 'node:fs'
|
|
3
3
|
import { mkdir } from 'node:fs/promises'
|
|
4
4
|
import { tmpdir } from 'node:os'
|
|
@@ -35,6 +35,8 @@ describe('whoami command', () => {
|
|
|
35
35
|
originalEnv = { ...process.env }
|
|
36
36
|
delete process.env.E2E_CHANNELBOT_ACCESS_KEY
|
|
37
37
|
delete process.env.E2E_CHANNELBOT_ACCESS_SECRET
|
|
38
|
+
delete process.env.E2E_CHANNELTALKBOT_ACCESS_KEY
|
|
39
|
+
delete process.env.E2E_CHANNELTALKBOT_ACCESS_SECRET
|
|
38
40
|
mockGetChannel.mockClear()
|
|
39
41
|
})
|
|
40
42
|
|
|
@@ -45,7 +47,7 @@ describe('whoami command', () => {
|
|
|
45
47
|
process.env = originalEnv
|
|
46
48
|
})
|
|
47
49
|
|
|
48
|
-
|
|
50
|
+
it('returns channel info for current workspace', async () => {
|
|
49
51
|
const manager = new ChannelBotCredentialManager(tempDir)
|
|
50
52
|
await manager.setCredentials({
|
|
51
53
|
workspace_id: 'workspace1',
|
|
@@ -63,7 +65,7 @@ describe('whoami command', () => {
|
|
|
63
65
|
expect(result.error).toBeUndefined()
|
|
64
66
|
})
|
|
65
67
|
|
|
66
|
-
|
|
68
|
+
it('returns channel info for specific --workspace', async () => {
|
|
67
69
|
const manager = new ChannelBotCredentialManager(tempDir)
|
|
68
70
|
await manager.setCredentials({
|
|
69
71
|
workspace_id: 'workspace1',
|
|
@@ -85,7 +87,7 @@ describe('whoami command', () => {
|
|
|
85
87
|
expect(mockGetChannel).toHaveBeenCalledTimes(1)
|
|
86
88
|
})
|
|
87
89
|
|
|
88
|
-
|
|
90
|
+
it('returns error when client throws', async () => {
|
|
89
91
|
mockGetChannel.mockImplementationOnce(() => Promise.reject(new Error('API Error')))
|
|
90
92
|
|
|
91
93
|
const manager = new ChannelBotCredentialManager(tempDir)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Command } from 'commander'
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { cliOutput } from '@/shared/utils/cli-output'
|
|
4
4
|
|
|
5
5
|
import type { WorkspaceOption } from './shared'
|
|
6
6
|
import { getClient } from './shared'
|
|
@@ -28,11 +28,6 @@ export async function whoamiAction(options: WorkspaceOption): Promise<WhoamiResu
|
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
function cliOutput(result: WhoamiResult, pretty?: boolean): void {
|
|
32
|
-
console.log(formatOutput(result, pretty))
|
|
33
|
-
if (result.error) process.exit(1)
|
|
34
|
-
}
|
|
35
|
-
|
|
36
31
|
export const whoamiCommand = new Command('whoami')
|
|
37
32
|
.description('Show current authenticated bot')
|
|
38
33
|
.option('--workspace <id>', 'Workspace ID to use')
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect,
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it } from 'bun:test'
|
|
2
2
|
import { existsSync, rmSync } from 'node:fs'
|
|
3
|
-
import { mkdir, stat } from 'node:fs/promises'
|
|
3
|
+
import { mkdir, readFile, stat, writeFile } from 'node:fs/promises'
|
|
4
4
|
import { tmpdir } from 'node:os'
|
|
5
5
|
import { join } from 'node:path'
|
|
6
6
|
|
|
@@ -36,10 +36,12 @@ describe('ChannelBotCredentialManager', () => {
|
|
|
36
36
|
}
|
|
37
37
|
delete process.env.E2E_CHANNELBOT_ACCESS_KEY
|
|
38
38
|
delete process.env.E2E_CHANNELBOT_ACCESS_SECRET
|
|
39
|
+
delete process.env.E2E_CHANNELTALKBOT_ACCESS_KEY
|
|
40
|
+
delete process.env.E2E_CHANNELTALKBOT_ACCESS_SECRET
|
|
39
41
|
})
|
|
40
42
|
|
|
41
43
|
describe('load', () => {
|
|
42
|
-
|
|
44
|
+
it('returns empty config when no file exists', async () => {
|
|
43
45
|
const config = await manager.load()
|
|
44
46
|
|
|
45
47
|
expect(config.current).toBeNull()
|
|
@@ -49,7 +51,7 @@ describe('ChannelBotCredentialManager', () => {
|
|
|
49
51
|
})
|
|
50
52
|
|
|
51
53
|
describe('save and load', () => {
|
|
52
|
-
|
|
54
|
+
it('persists config to file', async () => {
|
|
53
55
|
const config = {
|
|
54
56
|
current: { workspace_id: 'ch_abc123' },
|
|
55
57
|
workspaces: {
|
|
@@ -71,11 +73,11 @@ describe('ChannelBotCredentialManager', () => {
|
|
|
71
73
|
})
|
|
72
74
|
|
|
73
75
|
describe('getCredentials', () => {
|
|
74
|
-
|
|
76
|
+
it('returns null when no credentials exist', async () => {
|
|
75
77
|
expect(await manager.getCredentials()).toBeNull()
|
|
76
78
|
})
|
|
77
79
|
|
|
78
|
-
|
|
80
|
+
it('returns current workspace credentials', async () => {
|
|
79
81
|
await manager.setCredentials(WORKSPACE_A)
|
|
80
82
|
|
|
81
83
|
const creds = await manager.getCredentials()
|
|
@@ -83,7 +85,7 @@ describe('ChannelBotCredentialManager', () => {
|
|
|
83
85
|
expect(creds).toEqual(WORKSPACE_A)
|
|
84
86
|
})
|
|
85
87
|
|
|
86
|
-
|
|
88
|
+
it('returns specific workspace by id', async () => {
|
|
87
89
|
await manager.setCredentials(WORKSPACE_A)
|
|
88
90
|
await manager.setCredentials(WORKSPACE_B)
|
|
89
91
|
|
|
@@ -92,7 +94,7 @@ describe('ChannelBotCredentialManager', () => {
|
|
|
92
94
|
expect(creds).toEqual(WORKSPACE_A)
|
|
93
95
|
})
|
|
94
96
|
|
|
95
|
-
|
|
97
|
+
it('returns null for non-existent workspace id', async () => {
|
|
96
98
|
await manager.setCredentials(WORKSPACE_A)
|
|
97
99
|
|
|
98
100
|
const creds = await manager.getCredentials('nonexistent')
|
|
@@ -100,7 +102,7 @@ describe('ChannelBotCredentialManager', () => {
|
|
|
100
102
|
expect(creds).toBeNull()
|
|
101
103
|
})
|
|
102
104
|
|
|
103
|
-
|
|
105
|
+
it('env vars take precedence when no workspaceId specified', async () => {
|
|
104
106
|
await manager.setCredentials(WORKSPACE_A)
|
|
105
107
|
|
|
106
108
|
process.env.E2E_CHANNELBOT_ACCESS_KEY = 'env-key'
|
|
@@ -114,7 +116,7 @@ describe('ChannelBotCredentialManager', () => {
|
|
|
114
116
|
expect(creds?.workspace_name).toBe('env')
|
|
115
117
|
})
|
|
116
118
|
|
|
117
|
-
|
|
119
|
+
it('env vars ignored when workspaceId explicitly provided', async () => {
|
|
118
120
|
await manager.setCredentials(WORKSPACE_A)
|
|
119
121
|
|
|
120
122
|
process.env.E2E_CHANNELBOT_ACCESS_KEY = 'env-key'
|
|
@@ -129,7 +131,7 @@ describe('ChannelBotCredentialManager', () => {
|
|
|
129
131
|
})
|
|
130
132
|
|
|
131
133
|
describe('setCredentials', () => {
|
|
132
|
-
|
|
134
|
+
it('stores workspace and sets as current', async () => {
|
|
133
135
|
await manager.setCredentials(WORKSPACE_A)
|
|
134
136
|
|
|
135
137
|
const config = await manager.load()
|
|
@@ -137,7 +139,7 @@ describe('ChannelBotCredentialManager', () => {
|
|
|
137
139
|
expect(config.workspaces['ch_abc123']).toEqual(WORKSPACE_A)
|
|
138
140
|
})
|
|
139
141
|
|
|
140
|
-
|
|
142
|
+
it('stores multiple workspaces', async () => {
|
|
141
143
|
await manager.setCredentials(WORKSPACE_A)
|
|
142
144
|
await manager.setCredentials(WORKSPACE_B)
|
|
143
145
|
|
|
@@ -146,7 +148,7 @@ describe('ChannelBotCredentialManager', () => {
|
|
|
146
148
|
expect(config.current).toEqual({ workspace_id: 'ch_def456' })
|
|
147
149
|
})
|
|
148
150
|
|
|
149
|
-
|
|
151
|
+
it('overwrites existing workspace with same id', async () => {
|
|
150
152
|
await manager.setCredentials(WORKSPACE_A)
|
|
151
153
|
const updated = { ...WORKSPACE_A, workspace_name: 'Updated Company A' }
|
|
152
154
|
await manager.setCredentials(updated)
|
|
@@ -158,7 +160,7 @@ describe('ChannelBotCredentialManager', () => {
|
|
|
158
160
|
})
|
|
159
161
|
|
|
160
162
|
describe('listAll', () => {
|
|
161
|
-
|
|
163
|
+
it('returns all workspaces with current flag', async () => {
|
|
162
164
|
await manager.setCredentials(WORKSPACE_A)
|
|
163
165
|
await manager.setCredentials(WORKSPACE_B)
|
|
164
166
|
|
|
@@ -169,7 +171,7 @@ describe('ChannelBotCredentialManager', () => {
|
|
|
169
171
|
expect(all.find((w) => w.workspace_id === 'ch_def456')?.is_current).toBe(true)
|
|
170
172
|
})
|
|
171
173
|
|
|
172
|
-
|
|
174
|
+
it('returns empty array when no workspaces exist', async () => {
|
|
173
175
|
const all = await manager.listAll()
|
|
174
176
|
|
|
175
177
|
expect(all).toEqual([])
|
|
@@ -177,7 +179,7 @@ describe('ChannelBotCredentialManager', () => {
|
|
|
177
179
|
})
|
|
178
180
|
|
|
179
181
|
describe('setCurrent', () => {
|
|
180
|
-
|
|
182
|
+
it('switches current workspace', async () => {
|
|
181
183
|
await manager.setCredentials(WORKSPACE_A)
|
|
182
184
|
await manager.setCredentials(WORKSPACE_B)
|
|
183
185
|
|
|
@@ -188,13 +190,13 @@ describe('ChannelBotCredentialManager', () => {
|
|
|
188
190
|
expect(creds?.workspace_id).toBe('ch_abc123')
|
|
189
191
|
})
|
|
190
192
|
|
|
191
|
-
|
|
193
|
+
it('returns false for unknown workspace', async () => {
|
|
192
194
|
expect(await manager.setCurrent('nonexistent')).toBe(false)
|
|
193
195
|
})
|
|
194
196
|
})
|
|
195
197
|
|
|
196
198
|
describe('removeWorkspace', () => {
|
|
197
|
-
|
|
199
|
+
it('removes a workspace by id', async () => {
|
|
198
200
|
await manager.setCredentials(WORKSPACE_A)
|
|
199
201
|
await manager.setCredentials(WORKSPACE_B)
|
|
200
202
|
|
|
@@ -205,7 +207,7 @@ describe('ChannelBotCredentialManager', () => {
|
|
|
205
207
|
expect(Object.keys(config.workspaces)).toEqual(['ch_def456'])
|
|
206
208
|
})
|
|
207
209
|
|
|
208
|
-
|
|
210
|
+
it('clears current when current workspace removed', async () => {
|
|
209
211
|
await manager.setCredentials(WORKSPACE_A)
|
|
210
212
|
|
|
211
213
|
await manager.removeWorkspace('ch_abc123')
|
|
@@ -214,11 +216,11 @@ describe('ChannelBotCredentialManager', () => {
|
|
|
214
216
|
expect(config.current).toBeNull()
|
|
215
217
|
})
|
|
216
218
|
|
|
217
|
-
|
|
219
|
+
it('returns false for unknown workspace', async () => {
|
|
218
220
|
expect(await manager.removeWorkspace('nonexistent')).toBe(false)
|
|
219
221
|
})
|
|
220
222
|
|
|
221
|
-
|
|
223
|
+
it('does not clear current if removing non-current workspace', async () => {
|
|
222
224
|
await manager.setCredentials(WORKSPACE_A)
|
|
223
225
|
await manager.setCredentials(WORKSPACE_B)
|
|
224
226
|
|
|
@@ -230,7 +232,7 @@ describe('ChannelBotCredentialManager', () => {
|
|
|
230
232
|
})
|
|
231
233
|
|
|
232
234
|
describe('clearCredentials', () => {
|
|
233
|
-
|
|
235
|
+
it('removes all credentials', async () => {
|
|
234
236
|
await manager.setCredentials(WORKSPACE_A)
|
|
235
237
|
await manager.setCredentials(WORKSPACE_B)
|
|
236
238
|
|
|
@@ -244,13 +246,13 @@ describe('ChannelBotCredentialManager', () => {
|
|
|
244
246
|
})
|
|
245
247
|
|
|
246
248
|
describe('getDefaultBot', () => {
|
|
247
|
-
|
|
249
|
+
it('returns null initially', async () => {
|
|
248
250
|
const bot = await manager.getDefaultBot()
|
|
249
251
|
|
|
250
252
|
expect(bot).toBeNull()
|
|
251
253
|
})
|
|
252
254
|
|
|
253
|
-
|
|
255
|
+
it('returns default bot name', async () => {
|
|
254
256
|
await manager.setDefaultBot('my-bot')
|
|
255
257
|
|
|
256
258
|
const bot = await manager.getDefaultBot()
|
|
@@ -260,7 +262,7 @@ describe('ChannelBotCredentialManager', () => {
|
|
|
260
262
|
})
|
|
261
263
|
|
|
262
264
|
describe('setDefaultBot', () => {
|
|
263
|
-
|
|
265
|
+
it('saves and retrieves default bot', async () => {
|
|
264
266
|
await manager.setDefaultBot('my-bot')
|
|
265
267
|
|
|
266
268
|
const bot = await manager.getDefaultBot()
|
|
@@ -268,7 +270,7 @@ describe('ChannelBotCredentialManager', () => {
|
|
|
268
270
|
expect(bot).toBe('my-bot')
|
|
269
271
|
})
|
|
270
272
|
|
|
271
|
-
|
|
273
|
+
it('updates existing default bot', async () => {
|
|
272
274
|
await manager.setDefaultBot('bot-1')
|
|
273
275
|
await manager.setDefaultBot('bot-2')
|
|
274
276
|
|
|
@@ -277,7 +279,7 @@ describe('ChannelBotCredentialManager', () => {
|
|
|
277
279
|
expect(bot).toBe('bot-2')
|
|
278
280
|
})
|
|
279
281
|
|
|
280
|
-
|
|
282
|
+
it('scopes default bot to current workspace', async () => {
|
|
281
283
|
// given
|
|
282
284
|
await manager.setCredentials(WORKSPACE_A)
|
|
283
285
|
await manager.setDefaultBot('bot-a')
|
|
@@ -296,13 +298,105 @@ describe('ChannelBotCredentialManager', () => {
|
|
|
296
298
|
})
|
|
297
299
|
|
|
298
300
|
describe('file permissions', () => {
|
|
299
|
-
|
|
301
|
+
it('saves file with secure permissions (600)', async () => {
|
|
300
302
|
await manager.setCredentials(WORKSPACE_A)
|
|
301
303
|
|
|
302
|
-
const credPath = join(tempDir, '
|
|
304
|
+
const credPath = join(tempDir, 'channeltalkbot-credentials.json')
|
|
303
305
|
const stats = await stat(credPath)
|
|
304
306
|
|
|
305
307
|
expect(stats.mode & 0o777).toBe(0o600)
|
|
306
308
|
})
|
|
307
309
|
})
|
|
310
|
+
|
|
311
|
+
describe('legacy filename migration', () => {
|
|
312
|
+
it('renames channelbot-credentials.json to channeltalkbot-credentials.json on load', async () => {
|
|
313
|
+
const legacyPath = join(tempDir, 'channelbot-credentials.json')
|
|
314
|
+
const newPath = join(tempDir, 'channeltalkbot-credentials.json')
|
|
315
|
+
const legacyConfig = {
|
|
316
|
+
current: { workspace_id: WORKSPACE_A.workspace_id },
|
|
317
|
+
workspaces: { [WORKSPACE_A.workspace_id]: WORKSPACE_A },
|
|
318
|
+
default_bot: null,
|
|
319
|
+
}
|
|
320
|
+
await writeFile(legacyPath, JSON.stringify(legacyConfig))
|
|
321
|
+
|
|
322
|
+
const config = await manager.load()
|
|
323
|
+
|
|
324
|
+
expect(config.workspaces[WORKSPACE_A.workspace_id]).toEqual(WORKSPACE_A)
|
|
325
|
+
expect(existsSync(legacyPath)).toBe(false)
|
|
326
|
+
expect(existsSync(newPath)).toBe(true)
|
|
327
|
+
const migrated = JSON.parse(await readFile(newPath, 'utf-8'))
|
|
328
|
+
expect(migrated.workspaces[WORKSPACE_A.workspace_id]).toEqual(WORKSPACE_A)
|
|
329
|
+
})
|
|
330
|
+
|
|
331
|
+
it('does not overwrite an existing channeltalkbot-credentials.json', async () => {
|
|
332
|
+
const legacyPath = join(tempDir, 'channelbot-credentials.json')
|
|
333
|
+
const newPath = join(tempDir, 'channeltalkbot-credentials.json')
|
|
334
|
+
await writeFile(legacyPath, JSON.stringify({ workspaces: { stale: WORKSPACE_A } }))
|
|
335
|
+
const newConfig = {
|
|
336
|
+
current: { workspace_id: WORKSPACE_B.workspace_id },
|
|
337
|
+
workspaces: { [WORKSPACE_B.workspace_id]: WORKSPACE_B },
|
|
338
|
+
default_bot: null,
|
|
339
|
+
}
|
|
340
|
+
await writeFile(newPath, JSON.stringify(newConfig))
|
|
341
|
+
|
|
342
|
+
const config = await manager.load()
|
|
343
|
+
|
|
344
|
+
expect(config.workspaces[WORKSPACE_B.workspace_id]).toEqual(WORKSPACE_B)
|
|
345
|
+
expect(config.workspaces['stale']).toBeUndefined()
|
|
346
|
+
expect(existsSync(legacyPath)).toBe(true)
|
|
347
|
+
})
|
|
348
|
+
|
|
349
|
+
it('does not write back to legacy path when migration fails (no split-brain)', async () => {
|
|
350
|
+
const legacyPath = join(tempDir, 'channelbot-credentials.json')
|
|
351
|
+
const newPath = join(tempDir, 'channeltalkbot-credentials.json')
|
|
352
|
+
await writeFile(legacyPath, JSON.stringify({ workspaces: {}, default_bot: null }))
|
|
353
|
+
|
|
354
|
+
// Inject a rename that fails on first call to simulate a concurrent migration losing the race.
|
|
355
|
+
class FailingMigrationManager extends ChannelBotCredentialManager {
|
|
356
|
+
constructor(dir: string) {
|
|
357
|
+
super(dir)
|
|
358
|
+
let called = false
|
|
359
|
+
this.renameFile = async () => {
|
|
360
|
+
if (!called) {
|
|
361
|
+
called = true
|
|
362
|
+
throw new Error('ENOENT: simulated concurrent rename winner')
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
const failingManager = new FailingMigrationManager(tempDir)
|
|
368
|
+
|
|
369
|
+
await failingManager.load()
|
|
370
|
+
await failingManager.setCredentials(WORKSPACE_A)
|
|
371
|
+
|
|
372
|
+
// After failure, the manager must write to the NEW path, never re-create the legacy file.
|
|
373
|
+
expect(existsSync(newPath)).toBe(true)
|
|
374
|
+
const persisted = JSON.parse(await readFile(newPath, 'utf-8'))
|
|
375
|
+
expect(persisted.workspaces[WORKSPACE_A.workspace_id]).toEqual(WORKSPACE_A)
|
|
376
|
+
})
|
|
377
|
+
})
|
|
378
|
+
|
|
379
|
+
describe('env var prefix compatibility', () => {
|
|
380
|
+
it('prefers E2E_CHANNELTALKBOT_* over E2E_CHANNELBOT_*', async () => {
|
|
381
|
+
process.env.E2E_CHANNELBOT_ACCESS_KEY = 'old-key'
|
|
382
|
+
process.env.E2E_CHANNELBOT_ACCESS_SECRET = 'old-secret'
|
|
383
|
+
process.env.E2E_CHANNELTALKBOT_ACCESS_KEY = 'new-key'
|
|
384
|
+
process.env.E2E_CHANNELTALKBOT_ACCESS_SECRET = 'new-secret'
|
|
385
|
+
|
|
386
|
+
const creds = await manager.getCredentials()
|
|
387
|
+
|
|
388
|
+
expect(creds?.access_key).toBe('new-key')
|
|
389
|
+
expect(creds?.access_secret).toBe('new-secret')
|
|
390
|
+
})
|
|
391
|
+
|
|
392
|
+
it('falls back to E2E_CHANNELBOT_* when E2E_CHANNELTALKBOT_* is unset', async () => {
|
|
393
|
+
process.env.E2E_CHANNELBOT_ACCESS_KEY = 'legacy-key'
|
|
394
|
+
process.env.E2E_CHANNELBOT_ACCESS_SECRET = 'legacy-secret'
|
|
395
|
+
|
|
396
|
+
const creds = await manager.getCredentials()
|
|
397
|
+
|
|
398
|
+
expect(creds?.access_key).toBe('legacy-key')
|
|
399
|
+
expect(creds?.access_secret).toBe('legacy-secret')
|
|
400
|
+
})
|
|
401
|
+
})
|
|
308
402
|
})
|
|
@@ -1,21 +1,30 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs'
|
|
2
|
-
import { chmod, mkdir, readFile, writeFile } from 'node:fs/promises'
|
|
2
|
+
import { chmod, mkdir, readFile, rename, writeFile } from 'node:fs/promises'
|
|
3
3
|
import { homedir } from 'node:os'
|
|
4
4
|
import { join } from 'node:path'
|
|
5
5
|
|
|
6
6
|
import type { ChannelBotConfig, ChannelBotCredentials, ChannelBotWorkspaceEntry } from './types'
|
|
7
7
|
import { ChannelBotConfigSchema } from './types'
|
|
8
8
|
|
|
9
|
+
const LEGACY_FILENAME = 'channelbot-credentials.json'
|
|
10
|
+
const CREDENTIALS_FILENAME = 'channeltalkbot-credentials.json'
|
|
11
|
+
|
|
9
12
|
export class ChannelBotCredentialManager {
|
|
10
13
|
private configDir: string
|
|
11
14
|
private credentialsPath: string
|
|
15
|
+
private legacyPath: string
|
|
16
|
+
private migratedLegacyFile = false
|
|
17
|
+
protected renameFile: typeof rename = rename
|
|
12
18
|
|
|
13
19
|
constructor(configDir?: string) {
|
|
14
20
|
this.configDir = configDir ?? join(homedir(), '.config', 'agent-messenger')
|
|
15
|
-
this.credentialsPath = join(this.configDir,
|
|
21
|
+
this.credentialsPath = join(this.configDir, CREDENTIALS_FILENAME)
|
|
22
|
+
this.legacyPath = join(this.configDir, LEGACY_FILENAME)
|
|
16
23
|
}
|
|
17
24
|
|
|
18
25
|
async load(): Promise<ChannelBotConfig> {
|
|
26
|
+
await this.migrateLegacyFileIfNeeded()
|
|
27
|
+
|
|
19
28
|
if (!existsSync(this.credentialsPath)) {
|
|
20
29
|
return { current: null, workspaces: {}, default_bot: null }
|
|
21
30
|
}
|
|
@@ -34,6 +43,30 @@ export class ChannelBotCredentialManager {
|
|
|
34
43
|
return parsed.data
|
|
35
44
|
}
|
|
36
45
|
|
|
46
|
+
private async migrateLegacyFileIfNeeded(): Promise<void> {
|
|
47
|
+
if (this.migratedLegacyFile) return
|
|
48
|
+
if (existsSync(this.credentialsPath)) {
|
|
49
|
+
this.migratedLegacyFile = true
|
|
50
|
+
return
|
|
51
|
+
}
|
|
52
|
+
if (!existsSync(this.legacyPath)) {
|
|
53
|
+
this.migratedLegacyFile = true
|
|
54
|
+
return
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
await this.renameFile(this.legacyPath, this.credentialsPath)
|
|
58
|
+
process.stderr.write(
|
|
59
|
+
`[agent-channeltalkbot] Migrated credentials: ${LEGACY_FILENAME} -> ${CREDENTIALS_FILENAME}\n`,
|
|
60
|
+
)
|
|
61
|
+
} catch {
|
|
62
|
+
// Rename failed. If a concurrent process succeeded, the new file now exists — use it.
|
|
63
|
+
// Otherwise (real failure: permissions, etc.) keep the new path; load() will return
|
|
64
|
+
// empty config and the user can re-run `auth set`. Never fall back to writing the
|
|
65
|
+
// legacy path, which would resurrect the split-brain we are migrating away from.
|
|
66
|
+
}
|
|
67
|
+
this.migratedLegacyFile = true
|
|
68
|
+
}
|
|
69
|
+
|
|
37
70
|
async save(config: ChannelBotConfig): Promise<void> {
|
|
38
71
|
await mkdir(this.configDir, { recursive: true })
|
|
39
72
|
await writeFile(this.credentialsPath, JSON.stringify(config, null, 2), { mode: 0o600 })
|
|
@@ -41,8 +74,8 @@ export class ChannelBotCredentialManager {
|
|
|
41
74
|
}
|
|
42
75
|
|
|
43
76
|
async getCredentials(workspaceId?: string): Promise<ChannelBotCredentials | null> {
|
|
44
|
-
const envAccessKey = process.env.E2E_CHANNELBOT_ACCESS_KEY
|
|
45
|
-
const envAccessSecret = process.env.E2E_CHANNELBOT_ACCESS_SECRET
|
|
77
|
+
const envAccessKey = process.env.E2E_CHANNELTALKBOT_ACCESS_KEY ?? process.env.E2E_CHANNELBOT_ACCESS_KEY
|
|
78
|
+
const envAccessSecret = process.env.E2E_CHANNELTALKBOT_ACCESS_SECRET ?? process.env.E2E_CHANNELBOT_ACCESS_SECRET
|
|
46
79
|
|
|
47
80
|
if (envAccessKey && envAccessSecret && !workspaceId) {
|
|
48
81
|
return {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { expect,
|
|
1
|
+
import { expect, it } from 'bun:test'
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
ChannelBotBotSchema,
|
|
@@ -17,58 +17,58 @@ import {
|
|
|
17
17
|
MessageBlockSchema,
|
|
18
18
|
} from '@/platforms/channeltalkbot/index'
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
it('ChannelBotClient is exported from barrel', () => {
|
|
21
21
|
expect(typeof ChannelBotClient).toBe('function')
|
|
22
22
|
})
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
it('ChannelBotError is exported from barrel', () => {
|
|
25
25
|
expect(typeof ChannelBotError).toBe('function')
|
|
26
26
|
})
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
it('ChannelBotCredentialManager is exported from barrel', () => {
|
|
29
29
|
expect(typeof ChannelBotCredentialManager).toBe('function')
|
|
30
30
|
})
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
it('ChannelBotBotSchema is exported from barrel', () => {
|
|
33
33
|
expect(typeof ChannelBotBotSchema.parse).toBe('function')
|
|
34
34
|
})
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
it('ChannelBotChannelSchema is exported from barrel', () => {
|
|
37
37
|
expect(typeof ChannelBotChannelSchema.parse).toBe('function')
|
|
38
38
|
})
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
it('ChannelBotConfigSchema is exported from barrel', () => {
|
|
41
41
|
expect(typeof ChannelBotConfigSchema.parse).toBe('function')
|
|
42
42
|
})
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
it('ChannelBotCredentialsSchema is exported from barrel', () => {
|
|
45
45
|
expect(typeof ChannelBotCredentialsSchema.parse).toBe('function')
|
|
46
46
|
})
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
it('ChannelBotGroupSchema is exported from barrel', () => {
|
|
49
49
|
expect(typeof ChannelBotGroupSchema.parse).toBe('function')
|
|
50
50
|
})
|
|
51
51
|
|
|
52
|
-
|
|
52
|
+
it('ChannelBotManagerSchema is exported from barrel', () => {
|
|
53
53
|
expect(typeof ChannelBotManagerSchema.parse).toBe('function')
|
|
54
54
|
})
|
|
55
55
|
|
|
56
|
-
|
|
56
|
+
it('ChannelBotMessageSchema is exported from barrel', () => {
|
|
57
57
|
expect(typeof ChannelBotMessageSchema.parse).toBe('function')
|
|
58
58
|
})
|
|
59
59
|
|
|
60
|
-
|
|
60
|
+
it('ChannelBotUserChatSchema is exported from barrel', () => {
|
|
61
61
|
expect(typeof ChannelBotUserChatSchema.parse).toBe('function')
|
|
62
62
|
})
|
|
63
63
|
|
|
64
|
-
|
|
64
|
+
it('ChannelBotUserSchema is exported from barrel', () => {
|
|
65
65
|
expect(typeof ChannelBotUserSchema.parse).toBe('function')
|
|
66
66
|
})
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
it('ChannelBotWorkspaceEntrySchema is exported from barrel', () => {
|
|
69
69
|
expect(typeof ChannelBotWorkspaceEntrySchema.parse).toBe('function')
|
|
70
70
|
})
|
|
71
71
|
|
|
72
|
-
|
|
72
|
+
it('MessageBlockSchema is exported from barrel', () => {
|
|
73
73
|
expect(typeof MessageBlockSchema.parse).toBe('function')
|
|
74
74
|
})
|