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,6 +1,6 @@
|
|
|
1
|
-
import { existsSync, readdirSync } from 'node:fs'
|
|
1
|
+
import { existsSync, readdirSync, readFileSync } from 'node:fs'
|
|
2
2
|
import { homedir } from 'node:os'
|
|
3
|
-
import { join } from 'node:path'
|
|
3
|
+
import { dirname, isAbsolute, join, resolve } from 'node:path'
|
|
4
4
|
|
|
5
5
|
import type { BrowserConfig, KeychainVariant } from './types'
|
|
6
6
|
|
|
@@ -39,6 +39,17 @@ export const BROWSER_KEYCHAIN_VARIANTS: KeychainVariant[] = [
|
|
|
39
39
|
{ service: 'Chromium Safe Storage', account: 'Chromium' },
|
|
40
40
|
]
|
|
41
41
|
|
|
42
|
+
interface AgentBrowserProfileDiscoveryOptions {
|
|
43
|
+
cwd?: string
|
|
44
|
+
env?: NodeJS.ProcessEnv
|
|
45
|
+
homeDir?: string
|
|
46
|
+
customProfileDirs?: string[]
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
type AgentBrowserConfig = {
|
|
50
|
+
profile?: unknown
|
|
51
|
+
}
|
|
52
|
+
|
|
42
53
|
export function getBrowserBasePath(browser: BrowserConfig, platform: NodeJS.Platform): string | null {
|
|
43
54
|
let relative: string
|
|
44
55
|
switch (platform) {
|
|
@@ -70,10 +81,41 @@ export function discoverBrowserProfileDirs(browserBase: string): string[] {
|
|
|
70
81
|
if (!/^Profile \d+$/i.test(entry.name)) continue
|
|
71
82
|
dirs.push(join(browserBase, entry.name))
|
|
72
83
|
}
|
|
73
|
-
} catch {
|
|
84
|
+
} catch {
|
|
85
|
+
return dirs
|
|
86
|
+
}
|
|
74
87
|
return dirs
|
|
75
88
|
}
|
|
76
89
|
|
|
90
|
+
export function getAgentBrowserProfileDirs(options: AgentBrowserProfileDiscoveryOptions = {}): string[] {
|
|
91
|
+
const cwd = options.cwd ?? process.cwd()
|
|
92
|
+
const env = options.env ?? process.env
|
|
93
|
+
const homeDir = options.homeDir ?? homedir()
|
|
94
|
+
if (env.AGENT_MESSENGER_DISABLE_AGENT_BROWSER_PROFILE_DISCOVERY === '1') return []
|
|
95
|
+
|
|
96
|
+
const profileDirs: string[] = []
|
|
97
|
+
|
|
98
|
+
for (const profileDir of options.customProfileDirs ?? []) {
|
|
99
|
+
addAgentBrowserProfileDir(profileDirs, profileDir, cwd)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
addAgentBrowserProfileDir(profileDirs, env.AGENT_BROWSER_PROFILE, cwd)
|
|
103
|
+
|
|
104
|
+
const configPaths = [
|
|
105
|
+
join(homeDir, '.agent-browser', 'config.json'),
|
|
106
|
+
join(cwd, 'agent-browser.json'),
|
|
107
|
+
env.AGENT_BROWSER_CONFIG,
|
|
108
|
+
]
|
|
109
|
+
|
|
110
|
+
for (const configPath of configPaths) {
|
|
111
|
+
if (!configPath) continue
|
|
112
|
+
const config = readAgentBrowserConfig(configPath)
|
|
113
|
+
addAgentBrowserProfileDir(profileDirs, config?.profile, dirname(configPath))
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return dedupePaths(profileDirs.flatMap((profileDir) => [profileDir, ...discoverBrowserProfileDirs(profileDir)]))
|
|
117
|
+
}
|
|
118
|
+
|
|
77
119
|
export function findLocalStatePath(cookieOrProfilePath: string): string | null {
|
|
78
120
|
const parts = cookieOrProfilePath.split(/[/\\]/)
|
|
79
121
|
for (let levels = 2; levels <= 4; levels++) {
|
|
@@ -84,3 +126,30 @@ export function findLocalStatePath(cookieOrProfilePath: string): string | null {
|
|
|
84
126
|
}
|
|
85
127
|
return null
|
|
86
128
|
}
|
|
129
|
+
|
|
130
|
+
function readAgentBrowserConfig(configPath: string): AgentBrowserConfig | null {
|
|
131
|
+
if (!existsSync(configPath)) return null
|
|
132
|
+
try {
|
|
133
|
+
const parsed = JSON.parse(readFileSync(configPath, 'utf8')) as unknown
|
|
134
|
+
if (!parsed || typeof parsed !== 'object') return null
|
|
135
|
+
return parsed as AgentBrowserConfig
|
|
136
|
+
} catch {
|
|
137
|
+
return null
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function addAgentBrowserProfileDir(dirs: string[], profile: unknown, baseDir: string): void {
|
|
142
|
+
if (typeof profile !== 'string' || profile.length === 0) return
|
|
143
|
+
dirs.push(isAbsolute(profile) ? profile : resolve(baseDir, profile))
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function dedupePaths(paths: string[]): string[] {
|
|
147
|
+
const seen = new Set<string>()
|
|
148
|
+
const result: string[] = []
|
|
149
|
+
for (const path of paths) {
|
|
150
|
+
if (seen.has(path)) continue
|
|
151
|
+
seen.add(path)
|
|
152
|
+
result.push(path)
|
|
153
|
+
}
|
|
154
|
+
return result
|
|
155
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { describe, expect, it } from 'bun:test'
|
|
2
|
+
|
|
3
|
+
import { collectBrowserProfileOption } from './cli-options'
|
|
4
|
+
|
|
5
|
+
describe('collectBrowserProfileOption', () => {
|
|
6
|
+
it('collects repeated browser profile options', () => {
|
|
7
|
+
// when
|
|
8
|
+
const first = collectBrowserProfileOption('/tmp/profile-a')
|
|
9
|
+
const second = collectBrowserProfileOption('/tmp/profile-b', first)
|
|
10
|
+
|
|
11
|
+
// then
|
|
12
|
+
expect(second).toEqual(['/tmp/profile-a', '/tmp/profile-b'])
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
it('splits comma-separated browser profile options', () => {
|
|
16
|
+
// when
|
|
17
|
+
const profiles = collectBrowserProfileOption('/tmp/profile-a, /tmp/profile-b,,')
|
|
18
|
+
|
|
19
|
+
// then
|
|
20
|
+
expect(profiles).toEqual(['/tmp/profile-a', '/tmp/profile-b'])
|
|
21
|
+
})
|
|
22
|
+
})
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface BrowserProfileOption {
|
|
2
|
+
browserProfile?: string[]
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export function collectBrowserProfileOption(value: string, previous: string[] = []): string[] {
|
|
6
|
+
const paths = value
|
|
7
|
+
.split(',')
|
|
8
|
+
.map((path) => path.trim())
|
|
9
|
+
.filter((path) => path.length > 0)
|
|
10
|
+
|
|
11
|
+
return [...previous, ...paths]
|
|
12
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Database } from 'bun:sqlite'
|
|
2
|
-
import { afterEach, describe, expect,
|
|
2
|
+
import { afterEach, describe, expect, it } from 'bun:test'
|
|
3
3
|
import { existsSync, mkdtempSync, rmSync } from 'node:fs'
|
|
4
4
|
import { tmpdir } from 'node:os'
|
|
5
5
|
import { join } from 'node:path'
|
|
@@ -31,7 +31,7 @@ describe('ChromiumCookieReader', () => {
|
|
|
31
31
|
})
|
|
32
32
|
|
|
33
33
|
describe('queryAll', () => {
|
|
34
|
-
|
|
34
|
+
it('returns all matching rows from a real SQLite database', async () => {
|
|
35
35
|
// given
|
|
36
36
|
const tempDir = mkdtempSync(join(tmpdir(), 'chromium-cookie-reader-'))
|
|
37
37
|
tempDirs.push(tempDir)
|
|
@@ -55,7 +55,7 @@ describe('ChromiumCookieReader', () => {
|
|
|
55
55
|
])
|
|
56
56
|
})
|
|
57
57
|
|
|
58
|
-
|
|
58
|
+
it('returns empty array when database file does not exist', async () => {
|
|
59
59
|
// given
|
|
60
60
|
const tempDir = mkdtempSync(join(tmpdir(), 'chromium-cookie-reader-'))
|
|
61
61
|
tempDirs.push(tempDir)
|
|
@@ -69,7 +69,7 @@ describe('ChromiumCookieReader', () => {
|
|
|
69
69
|
expect(result).toEqual([])
|
|
70
70
|
})
|
|
71
71
|
|
|
72
|
-
|
|
72
|
+
it('returns empty array when query matches no rows', async () => {
|
|
73
73
|
// given
|
|
74
74
|
const tempDir = mkdtempSync(join(tmpdir(), 'chromium-cookie-reader-'))
|
|
75
75
|
tempDirs.push(tempDir)
|
|
@@ -86,7 +86,7 @@ describe('ChromiumCookieReader', () => {
|
|
|
86
86
|
expect(result).toEqual([])
|
|
87
87
|
})
|
|
88
88
|
|
|
89
|
-
|
|
89
|
+
it('supports parameterized queries with params', async () => {
|
|
90
90
|
// given
|
|
91
91
|
const tempDir = mkdtempSync(join(tmpdir(), 'chromium-cookie-reader-'))
|
|
92
92
|
tempDirs.push(tempDir)
|
|
@@ -108,7 +108,7 @@ describe('ChromiumCookieReader', () => {
|
|
|
108
108
|
expect(result).toEqual([{ name: 'token', value: 'xyz789' }])
|
|
109
109
|
})
|
|
110
110
|
|
|
111
|
-
|
|
111
|
+
it('cleans up temp file after query', async () => {
|
|
112
112
|
// given
|
|
113
113
|
const tempDir = mkdtempSync(join(tmpdir(), 'chromium-cookie-reader-'))
|
|
114
114
|
tempDirs.push(tempDir)
|
|
@@ -135,7 +135,7 @@ describe('ChromiumCookieReader', () => {
|
|
|
135
135
|
})
|
|
136
136
|
|
|
137
137
|
describe('queryFirst', () => {
|
|
138
|
-
|
|
138
|
+
it('returns first matching row from a real SQLite database', async () => {
|
|
139
139
|
// given
|
|
140
140
|
const tempDir = mkdtempSync(join(tmpdir(), 'chromium-cookie-reader-'))
|
|
141
141
|
tempDirs.push(tempDir)
|
|
@@ -156,7 +156,7 @@ describe('ChromiumCookieReader', () => {
|
|
|
156
156
|
expect(result).toEqual({ name: 'session', value: 'abc123' })
|
|
157
157
|
})
|
|
158
158
|
|
|
159
|
-
|
|
159
|
+
it('returns null when database file does not exist', async () => {
|
|
160
160
|
// given
|
|
161
161
|
const tempDir = mkdtempSync(join(tmpdir(), 'chromium-cookie-reader-'))
|
|
162
162
|
tempDirs.push(tempDir)
|
|
@@ -170,7 +170,7 @@ describe('ChromiumCookieReader', () => {
|
|
|
170
170
|
expect(result).toBeNull()
|
|
171
171
|
})
|
|
172
172
|
|
|
173
|
-
|
|
173
|
+
it('returns null when query matches no rows', async () => {
|
|
174
174
|
// given
|
|
175
175
|
const tempDir = mkdtempSync(join(tmpdir(), 'chromium-cookie-reader-'))
|
|
176
176
|
tempDirs.push(tempDir)
|
|
@@ -187,7 +187,7 @@ describe('ChromiumCookieReader', () => {
|
|
|
187
187
|
expect(result).toBeNull()
|
|
188
188
|
})
|
|
189
189
|
|
|
190
|
-
|
|
190
|
+
it('supports parameterized queries with params', async () => {
|
|
191
191
|
// given
|
|
192
192
|
const tempDir = mkdtempSync(join(tmpdir(), 'chromium-cookie-reader-'))
|
|
193
193
|
tempDirs.push(tempDir)
|
|
@@ -211,7 +211,7 @@ describe('ChromiumCookieReader', () => {
|
|
|
211
211
|
})
|
|
212
212
|
|
|
213
213
|
describe('edge cases', () => {
|
|
214
|
-
|
|
214
|
+
it('handles multiple calls to same reader instance', async () => {
|
|
215
215
|
// given
|
|
216
216
|
const tempDir = mkdtempSync(join(tmpdir(), 'chromium-cookie-reader-'))
|
|
217
217
|
tempDirs.push(tempDir)
|
|
@@ -241,7 +241,7 @@ describe('ChromiumCookieReader', () => {
|
|
|
241
241
|
expect(firstRow).toEqual({ name: 'token', value: 'xyz789' })
|
|
242
242
|
})
|
|
243
243
|
|
|
244
|
-
|
|
244
|
+
it('returns empty array for malformed SQL without throwing', async () => {
|
|
245
245
|
// given
|
|
246
246
|
const tempDir = mkdtempSync(join(tmpdir(), 'chromium-cookie-reader-'))
|
|
247
247
|
tempDirs.push(tempDir)
|
|
@@ -256,7 +256,7 @@ describe('ChromiumCookieReader', () => {
|
|
|
256
256
|
expect(result).toEqual([])
|
|
257
257
|
})
|
|
258
258
|
|
|
259
|
-
|
|
259
|
+
it('returns null for malformed SQL without throwing', async () => {
|
|
260
260
|
// given
|
|
261
261
|
const tempDir = mkdtempSync(join(tmpdir(), 'chromium-cookie-reader-'))
|
|
262
262
|
tempDirs.push(tempDir)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { beforeEach, describe, expect, spyOn,
|
|
1
|
+
import { beforeEach, describe, expect, spyOn, it } from 'bun:test'
|
|
2
2
|
import { createCipheriv, pbkdf2Sync, randomBytes } from 'node:crypto'
|
|
3
3
|
|
|
4
4
|
import * as linuxKeyring from '@/shared/utils/linux-keyring'
|
|
@@ -29,7 +29,7 @@ describe('ChromiumCookieDecryptor', () => {
|
|
|
29
29
|
})
|
|
30
30
|
|
|
31
31
|
describe('constructor', () => {
|
|
32
|
-
|
|
32
|
+
it('prepends appKeychainVariants before browser variants', () => {
|
|
33
33
|
// given
|
|
34
34
|
const appVariants = [{ service: 'App Safe Storage', account: 'App' }]
|
|
35
35
|
|
|
@@ -40,7 +40,7 @@ describe('ChromiumCookieDecryptor', () => {
|
|
|
40
40
|
expect((decryptor as any).keychainVariants).toEqual([...appVariants, ...BROWSER_KEYCHAIN_VARIANTS])
|
|
41
41
|
})
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
it('uses only browser variants when no appKeychainVariants provided', () => {
|
|
44
44
|
// given
|
|
45
45
|
const decryptor = new ChromiumCookieDecryptor({ platform: 'darwin' })
|
|
46
46
|
|
|
@@ -50,7 +50,7 @@ describe('ChromiumCookieDecryptor', () => {
|
|
|
50
50
|
})
|
|
51
51
|
|
|
52
52
|
describe('isEncryptedValue', () => {
|
|
53
|
-
|
|
53
|
+
it('returns true for v10 prefix with sufficient length', () => {
|
|
54
54
|
// given
|
|
55
55
|
const decryptor = new ChromiumCookieDecryptor({ platform: 'linux' })
|
|
56
56
|
|
|
@@ -61,7 +61,7 @@ describe('ChromiumCookieDecryptor', () => {
|
|
|
61
61
|
expect(result).toBe(true)
|
|
62
62
|
})
|
|
63
63
|
|
|
64
|
-
|
|
64
|
+
it('returns true for v11 prefix with sufficient length', () => {
|
|
65
65
|
// given
|
|
66
66
|
const decryptor = new ChromiumCookieDecryptor({ platform: 'linux' })
|
|
67
67
|
|
|
@@ -72,7 +72,7 @@ describe('ChromiumCookieDecryptor', () => {
|
|
|
72
72
|
expect(result).toBe(true)
|
|
73
73
|
})
|
|
74
74
|
|
|
75
|
-
|
|
75
|
+
it('returns false for non-v10/v11 prefix', () => {
|
|
76
76
|
// given
|
|
77
77
|
const decryptor = new ChromiumCookieDecryptor({ platform: 'linux' })
|
|
78
78
|
|
|
@@ -83,7 +83,7 @@ describe('ChromiumCookieDecryptor', () => {
|
|
|
83
83
|
expect(result).toBe(false)
|
|
84
84
|
})
|
|
85
85
|
|
|
86
|
-
|
|
86
|
+
it('returns false for too-short buffer (< 4 bytes)', () => {
|
|
87
87
|
// given
|
|
88
88
|
const decryptor = new ChromiumCookieDecryptor({ platform: 'linux' })
|
|
89
89
|
|
|
@@ -94,7 +94,7 @@ describe('ChromiumCookieDecryptor', () => {
|
|
|
94
94
|
expect(result).toBe(false)
|
|
95
95
|
})
|
|
96
96
|
|
|
97
|
-
|
|
97
|
+
it('returns false for null/empty buffer', () => {
|
|
98
98
|
// given
|
|
99
99
|
const decryptor = new ChromiumCookieDecryptor({ platform: 'linux' })
|
|
100
100
|
|
|
@@ -105,7 +105,7 @@ describe('ChromiumCookieDecryptor', () => {
|
|
|
105
105
|
})
|
|
106
106
|
|
|
107
107
|
describe('decryptAESCBC / decryptAESCBCRaw', () => {
|
|
108
|
-
|
|
108
|
+
it('decrypts v10-prefixed AES-128-CBC data with correct key', () => {
|
|
109
109
|
// given
|
|
110
110
|
const decryptor = new ChromiumCookieDecryptor({ platform: 'linux' })
|
|
111
111
|
const encrypted = encryptAESCBC('test-value', peanutsKey)
|
|
@@ -117,7 +117,7 @@ describe('ChromiumCookieDecryptor', () => {
|
|
|
117
117
|
expect(result).toBe('test-value')
|
|
118
118
|
})
|
|
119
119
|
|
|
120
|
-
|
|
120
|
+
it('returns null with wrong key', () => {
|
|
121
121
|
// given
|
|
122
122
|
const decryptor = new ChromiumCookieDecryptor({ platform: 'linux' })
|
|
123
123
|
const encrypted = encryptAESCBC('test-value', peanutsKey)
|
|
@@ -130,7 +130,7 @@ describe('ChromiumCookieDecryptor', () => {
|
|
|
130
130
|
expect(result).toBeNull()
|
|
131
131
|
})
|
|
132
132
|
|
|
133
|
-
|
|
133
|
+
it('returns null for corrupted ciphertext', () => {
|
|
134
134
|
// given
|
|
135
135
|
const decryptor = new ChromiumCookieDecryptor({ platform: 'linux' })
|
|
136
136
|
const encrypted = encryptAESCBC('test-value', peanutsKey)
|
|
@@ -144,7 +144,7 @@ describe('ChromiumCookieDecryptor', () => {
|
|
|
144
144
|
expect(result).toBeNull()
|
|
145
145
|
})
|
|
146
146
|
|
|
147
|
-
|
|
147
|
+
it('decryptAESCBC returns string, decryptAESCBCRaw returns Buffer', () => {
|
|
148
148
|
// given
|
|
149
149
|
const decryptor = new ChromiumCookieDecryptor({ platform: 'linux' })
|
|
150
150
|
const encrypted = encryptAESCBC('test-value', peanutsKey)
|
|
@@ -160,7 +160,7 @@ describe('ChromiumCookieDecryptor', () => {
|
|
|
160
160
|
})
|
|
161
161
|
|
|
162
162
|
describe('decryptAESGCM / decryptAESGCMRaw', () => {
|
|
163
|
-
|
|
163
|
+
it('decrypts v10-prefixed AES-256-GCM data with correct key', () => {
|
|
164
164
|
// given
|
|
165
165
|
const decryptor = new ChromiumCookieDecryptor({ platform: 'win32' })
|
|
166
166
|
const masterKey = randomBytes(32)
|
|
@@ -173,7 +173,7 @@ describe('ChromiumCookieDecryptor', () => {
|
|
|
173
173
|
expect(result).toBe('test-value')
|
|
174
174
|
})
|
|
175
175
|
|
|
176
|
-
|
|
176
|
+
it('returns null with wrong key', () => {
|
|
177
177
|
// given
|
|
178
178
|
const decryptor = new ChromiumCookieDecryptor({ platform: 'win32' })
|
|
179
179
|
const masterKey = randomBytes(32)
|
|
@@ -186,7 +186,7 @@ describe('ChromiumCookieDecryptor', () => {
|
|
|
186
186
|
expect(result).toBeNull()
|
|
187
187
|
})
|
|
188
188
|
|
|
189
|
-
|
|
189
|
+
it('returns null for data shorter than minimum length (3+12+16 = 31 bytes)', () => {
|
|
190
190
|
// given
|
|
191
191
|
const decryptor = new ChromiumCookieDecryptor({ platform: 'win32' })
|
|
192
192
|
|
|
@@ -197,7 +197,7 @@ describe('ChromiumCookieDecryptor', () => {
|
|
|
197
197
|
expect(result).toBeNull()
|
|
198
198
|
})
|
|
199
199
|
|
|
200
|
-
|
|
200
|
+
it('decryptAESGCM returns string, decryptAESGCMRaw returns Buffer', () => {
|
|
201
201
|
// given
|
|
202
202
|
const decryptor = new ChromiumCookieDecryptor({ platform: 'win32' })
|
|
203
203
|
const masterKey = randomBytes(32)
|
|
@@ -214,7 +214,7 @@ describe('ChromiumCookieDecryptor', () => {
|
|
|
214
214
|
})
|
|
215
215
|
|
|
216
216
|
describe('decryptCookie / decryptCookieRaw', () => {
|
|
217
|
-
|
|
217
|
+
it('returns plaintext for non-encrypted values (no v10/v11 prefix)', () => {
|
|
218
218
|
// given
|
|
219
219
|
const decryptor = new ChromiumCookieDecryptor({ platform: 'linux' })
|
|
220
220
|
const plaintext = Buffer.from('plain-cookie')
|
|
@@ -228,7 +228,7 @@ describe('ChromiumCookieDecryptor', () => {
|
|
|
228
228
|
expect(rawResult).toEqual(plaintext)
|
|
229
229
|
})
|
|
230
230
|
|
|
231
|
-
|
|
231
|
+
it('dispatches to Linux decryption for linux platform with v10 prefix', () => {
|
|
232
232
|
// given
|
|
233
233
|
const decryptor = new ChromiumCookieDecryptor({ platform: 'linux' })
|
|
234
234
|
const encrypted = Buffer.from('v10cookie')
|
|
@@ -242,7 +242,7 @@ describe('ChromiumCookieDecryptor', () => {
|
|
|
242
242
|
spy.mockRestore()
|
|
243
243
|
})
|
|
244
244
|
|
|
245
|
-
|
|
245
|
+
it('returns null for unsupported platform (e.g. freebsd)', () => {
|
|
246
246
|
// given
|
|
247
247
|
const decryptor = new ChromiumCookieDecryptor({ platform: 'freebsd' as NodeJS.Platform })
|
|
248
248
|
|
|
@@ -253,7 +253,7 @@ describe('ChromiumCookieDecryptor', () => {
|
|
|
253
253
|
expect(result).toBeNull()
|
|
254
254
|
})
|
|
255
255
|
|
|
256
|
-
|
|
256
|
+
it('decryptCookie returns string, decryptCookieRaw returns Buffer', () => {
|
|
257
257
|
// given
|
|
258
258
|
const decryptor = new ChromiumCookieDecryptor({ platform: 'linux' })
|
|
259
259
|
const encrypted = encryptAESCBC('test-value', peanutsKey)
|
|
@@ -269,7 +269,7 @@ describe('ChromiumCookieDecryptor', () => {
|
|
|
269
269
|
})
|
|
270
270
|
|
|
271
271
|
describe('decryptLinuxCookieRaw', () => {
|
|
272
|
-
|
|
272
|
+
it('decrypts v10-prefixed cookie using peanuts key (known key, verifiable)', () => {
|
|
273
273
|
// given
|
|
274
274
|
const decryptor = new ChromiumCookieDecryptor({ platform: 'linux' })
|
|
275
275
|
const encrypted = encryptAESCBC('linux-cookie', peanutsKey)
|
|
@@ -281,7 +281,7 @@ describe('ChromiumCookieDecryptor', () => {
|
|
|
281
281
|
expect(result).toEqual(Buffer.from('linux-cookie'))
|
|
282
282
|
})
|
|
283
283
|
|
|
284
|
-
|
|
284
|
+
it('falls back to peanuts key for v11 when no keyring app names configured', () => {
|
|
285
285
|
// given
|
|
286
286
|
const decryptor = new ChromiumCookieDecryptor({ platform: 'linux' })
|
|
287
287
|
const encrypted = encryptAESCBC('linux-v11-cookie', peanutsKey, 'v11')
|
|
@@ -295,7 +295,7 @@ describe('ChromiumCookieDecryptor', () => {
|
|
|
295
295
|
})
|
|
296
296
|
|
|
297
297
|
describe('decryptDPAPI', () => {
|
|
298
|
-
|
|
298
|
+
it('returns null on non-win32 platforms', () => {
|
|
299
299
|
// given
|
|
300
300
|
const decryptor = new ChromiumCookieDecryptor({ platform: 'linux' })
|
|
301
301
|
|
|
@@ -307,8 +307,73 @@ describe('ChromiumCookieDecryptor', () => {
|
|
|
307
307
|
})
|
|
308
308
|
})
|
|
309
309
|
|
|
310
|
+
describe('extractDPAPIPayload', () => {
|
|
311
|
+
it('extracts payload wrapped in markers', () => {
|
|
312
|
+
// given
|
|
313
|
+
const b64 = Buffer.from('hello').toString('base64')
|
|
314
|
+
const stdout = `<<<B64>>>${b64}<<<END>>>\r\n`
|
|
315
|
+
|
|
316
|
+
// when
|
|
317
|
+
const result = ChromiumCookieDecryptor.extractDPAPIPayload(stdout)
|
|
318
|
+
|
|
319
|
+
// then
|
|
320
|
+
expect(result).toBe(b64)
|
|
321
|
+
})
|
|
322
|
+
|
|
323
|
+
it('strips CLIXML progress-stream contamination before the payload', () => {
|
|
324
|
+
// given: PowerShell emits CLIXML on first module auto-load
|
|
325
|
+
const b64 = Buffer.from('secret-token').toString('base64')
|
|
326
|
+
const stdout =
|
|
327
|
+
'#< CLIXML\r\n' +
|
|
328
|
+
'<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04">' +
|
|
329
|
+
'<Obj S="progress" RefId="0"><TN RefId="0"><T>System.Management.Automation.PSCustomObject</T>' +
|
|
330
|
+
'<T>System.Object</T></TN><MS><I64 N="SourceId">1</I64><PR N="Record">' +
|
|
331
|
+
'<AV>Preparing modules for first use.</AV><AI>0</AI><Nil /><PI>-1</PI><PC>-1</PC>' +
|
|
332
|
+
'<T>Completed</T><SR>-1</SR><SD> </SD></PR></MS></Obj></Objs>' +
|
|
333
|
+
`<<<B64>>>${b64}<<<END>>>\r\n`
|
|
334
|
+
|
|
335
|
+
// when
|
|
336
|
+
const result = ChromiumCookieDecryptor.extractDPAPIPayload(stdout)
|
|
337
|
+
|
|
338
|
+
// then
|
|
339
|
+
expect(result).toBe(b64)
|
|
340
|
+
})
|
|
341
|
+
|
|
342
|
+
it('tolerates whitespace and line breaks inside the payload', () => {
|
|
343
|
+
// given
|
|
344
|
+
const b64 = Buffer.from('hello').toString('base64')
|
|
345
|
+
const chunked = b64.slice(0, 3) + '\r\n' + b64.slice(3)
|
|
346
|
+
const stdout = `<<<B64>>>${chunked}<<<END>>>`
|
|
347
|
+
|
|
348
|
+
// when
|
|
349
|
+
const result = ChromiumCookieDecryptor.extractDPAPIPayload(stdout)
|
|
350
|
+
|
|
351
|
+
// then
|
|
352
|
+
expect(result).toBe(b64)
|
|
353
|
+
})
|
|
354
|
+
|
|
355
|
+
it('returns null when markers are missing', () => {
|
|
356
|
+
// given: stdout contains only CLIXML noise, no real payload
|
|
357
|
+
const stdout = '#< CLIXML\r\n<Objs></Objs>\r\n'
|
|
358
|
+
|
|
359
|
+
// when
|
|
360
|
+
const result = ChromiumCookieDecryptor.extractDPAPIPayload(stdout)
|
|
361
|
+
|
|
362
|
+
// then
|
|
363
|
+
expect(result).toBeNull()
|
|
364
|
+
})
|
|
365
|
+
|
|
366
|
+
it('returns null when payload between markers is empty', () => {
|
|
367
|
+
// when
|
|
368
|
+
const result = ChromiumCookieDecryptor.extractDPAPIPayload('<<<B64>>><<<END>>>')
|
|
369
|
+
|
|
370
|
+
// then
|
|
371
|
+
expect(result).toBeNull()
|
|
372
|
+
})
|
|
373
|
+
})
|
|
374
|
+
|
|
310
375
|
describe('stripIntegrityHash', () => {
|
|
311
|
-
|
|
376
|
+
it('returns input unchanged when length <= 32', () => {
|
|
312
377
|
// given
|
|
313
378
|
const decrypted = Buffer.alloc(32, 0x41)
|
|
314
379
|
|
|
@@ -319,7 +384,7 @@ describe('ChromiumCookieDecryptor', () => {
|
|
|
319
384
|
expect(result).toEqual(decrypted)
|
|
320
385
|
})
|
|
321
386
|
|
|
322
|
-
|
|
387
|
+
it('strips first 32 bytes when they contain non-printable characters', () => {
|
|
323
388
|
// given
|
|
324
389
|
const hash = Buffer.concat([Buffer.from([0x00, 0x1f, 0xff]), Buffer.alloc(29, 0x01)])
|
|
325
390
|
const value = Buffer.from('cookie-value')
|
|
@@ -331,7 +396,7 @@ describe('ChromiumCookieDecryptor', () => {
|
|
|
331
396
|
expect(result).toEqual(value)
|
|
332
397
|
})
|
|
333
398
|
|
|
334
|
-
|
|
399
|
+
it('returns input unchanged when first 32 bytes are all printable ASCII', () => {
|
|
335
400
|
// given
|
|
336
401
|
const printablePrefix = Buffer.from('12345678901234567890123456789012')
|
|
337
402
|
const decrypted = Buffer.concat([printablePrefix, Buffer.from('cookie-value')])
|
|
@@ -343,7 +408,7 @@ describe('ChromiumCookieDecryptor', () => {
|
|
|
343
408
|
expect(result).toEqual(decrypted)
|
|
344
409
|
})
|
|
345
410
|
|
|
346
|
-
|
|
411
|
+
it('correctly strips binary hash prefix followed by readable cookie value', () => {
|
|
347
412
|
// given
|
|
348
413
|
const hash = randomBytes(32)
|
|
349
414
|
const value = Buffer.from('readable-cookie-value')
|
|
@@ -355,7 +420,7 @@ describe('ChromiumCookieDecryptor', () => {
|
|
|
355
420
|
expect(result).toEqual(value)
|
|
356
421
|
})
|
|
357
422
|
|
|
358
|
-
|
|
423
|
+
it('handles non-printable bytes that would be mangled by UTF-8 conversion (the v130+ fix)', () => {
|
|
359
424
|
// given
|
|
360
425
|
const binaryPrefix = Buffer.from([
|
|
361
426
|
...Array.from({ length: 16 }, (_, i) => i),
|
|
@@ -372,7 +437,7 @@ describe('ChromiumCookieDecryptor', () => {
|
|
|
372
437
|
})
|
|
373
438
|
|
|
374
439
|
describe('loadCachedKey / clearKeyCache', () => {
|
|
375
|
-
|
|
440
|
+
it('loadCachedKey is no-op on non-darwin platform', async () => {
|
|
376
441
|
// given
|
|
377
442
|
const keyCache = {
|
|
378
443
|
get: async () => Buffer.from('should-not-be-used'),
|
|
@@ -392,7 +457,7 @@ describe('ChromiumCookieDecryptor', () => {
|
|
|
392
457
|
expect((decryptor as any).usedCachedKey).toBe(false)
|
|
393
458
|
})
|
|
394
459
|
|
|
395
|
-
|
|
460
|
+
it('loadCachedKey is no-op when no keyCache configured', async () => {
|
|
396
461
|
// given
|
|
397
462
|
const decryptor = new ChromiumCookieDecryptor({ platform: 'darwin', keyCachePlatform: 'slack' })
|
|
398
463
|
|
|
@@ -404,7 +469,7 @@ describe('ChromiumCookieDecryptor', () => {
|
|
|
404
469
|
expect((decryptor as any).usedCachedKey).toBe(false)
|
|
405
470
|
})
|
|
406
471
|
|
|
407
|
-
|
|
472
|
+
it('clearKeyCache resets cached key state', async () => {
|
|
408
473
|
// given
|
|
409
474
|
const clear = async () => {}
|
|
410
475
|
const keyCache = { get: async () => null, clear }
|
|
@@ -426,7 +491,7 @@ describe('ChromiumCookieDecryptor', () => {
|
|
|
426
491
|
})
|
|
427
492
|
|
|
428
493
|
describe('linux v11 keyring behavior', () => {
|
|
429
|
-
|
|
494
|
+
it('uses configured keyring password before falling back', () => {
|
|
430
495
|
// given
|
|
431
496
|
const password = 'secret-from-keyring'
|
|
432
497
|
const key = pbkdf2Sync(password, 'saltysalt', 1, 16, 'sha1')
|
|
@@ -187,22 +187,43 @@ export class ChromiumCookieDecryptor {
|
|
|
187
187
|
if (this.platform !== 'win32') return null
|
|
188
188
|
try {
|
|
189
189
|
const b64Input = encrypted.toString('base64')
|
|
190
|
+
// Silence progress/information/warning streams so PowerShell doesn't emit CLIXML
|
|
191
|
+
// ("#< CLIXML ...") alongside our base64 payload when modules auto-load on first use.
|
|
192
|
+
// Wrap the payload in explicit markers so we can recover it even if stray output leaks in.
|
|
190
193
|
const script = [
|
|
194
|
+
"$ProgressPreference='SilentlyContinue'",
|
|
195
|
+
"$InformationPreference='SilentlyContinue'",
|
|
196
|
+
"$WarningPreference='SilentlyContinue'",
|
|
191
197
|
'Add-Type -AssemblyName System.Security',
|
|
192
198
|
`$d=[System.Security.Cryptography.ProtectedData]::Unprotect([Convert]::FromBase64String("${b64Input}"),$null,[System.Security.Cryptography.DataProtectionScope]::CurrentUser)`,
|
|
193
|
-
'[Convert]::ToBase64String($d)',
|
|
199
|
+
"Write-Host ('<<<B64>>>'+[Convert]::ToBase64String($d)+'<<<END>>>')",
|
|
194
200
|
].join(';')
|
|
195
201
|
const encodedCommand = Buffer.from(script, 'utf16le').toString('base64')
|
|
196
|
-
const
|
|
197
|
-
|
|
198
|
-
timeout: 10000,
|
|
199
|
-
|
|
200
|
-
|
|
202
|
+
const rawResult = execSync(
|
|
203
|
+
`powershell -NoProfile -NonInteractive -OutputFormat Text -EncodedCommand ${encodedCommand}`,
|
|
204
|
+
{ encoding: 'utf8', timeout: 10000 },
|
|
205
|
+
)
|
|
206
|
+
const b64 = ChromiumCookieDecryptor.extractDPAPIPayload(rawResult)
|
|
207
|
+
if (!b64) return null
|
|
208
|
+
return Buffer.from(b64, 'base64')
|
|
201
209
|
} catch {
|
|
202
210
|
return null
|
|
203
211
|
}
|
|
204
212
|
}
|
|
205
213
|
|
|
214
|
+
/**
|
|
215
|
+
* Extract the base64-encoded DPAPI payload from PowerShell stdout, stripping any
|
|
216
|
+
* CLIXML progress-stream contamination or other stray output. Returns null if
|
|
217
|
+
* no valid payload is found.
|
|
218
|
+
*/
|
|
219
|
+
static extractDPAPIPayload(stdout: string): string | null {
|
|
220
|
+
const match = stdout.match(/<<<B64>>>([A-Za-z0-9+/=\r\n]*)<<<END>>>/)
|
|
221
|
+
if (!match) return null
|
|
222
|
+
const b64 = match[1].replace(/\s+/g, '')
|
|
223
|
+
if (!b64) return null
|
|
224
|
+
return b64
|
|
225
|
+
}
|
|
226
|
+
|
|
206
227
|
static stripIntegrityHash(decrypted: Buffer): Buffer {
|
|
207
228
|
if (decrypted.length <= 32) return decrypted
|
|
208
229
|
const hasNonPrintablePrefix = decrypted.subarray(0, 32).some((b) => b < 0x20 || b > 0x7e)
|
|
@@ -4,8 +4,11 @@ export {
|
|
|
4
4
|
CHROMIUM_BROWSERS,
|
|
5
5
|
discoverBrowserProfileDirs,
|
|
6
6
|
findLocalStatePath,
|
|
7
|
+
getAgentBrowserProfileDirs,
|
|
7
8
|
getBrowserBasePath,
|
|
8
9
|
} from './browsers'
|
|
9
10
|
export { ChromiumCookieDecryptor } from './decryptor'
|
|
10
11
|
export type { ChromiumDecryptorOptions } from './decryptor'
|
|
11
12
|
export { ChromiumCookieReader } from './cookie-reader'
|
|
13
|
+
export { collectBrowserProfileOption } from './cli-options'
|
|
14
|
+
export type { BrowserProfileOption } from './cli-options'
|