agent-messenger 2.32.0 → 2.32.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/bun.lock +7 -0
- package/dist/package.json +2 -1
- package/dist/src/platforms/channeltalk/token-extractor.d.ts.map +1 -1
- package/dist/src/platforms/channeltalk/token-extractor.js +67 -18
- package/dist/src/platforms/channeltalk/token-extractor.js.map +1 -1
- package/dist/src/platforms/discord/commands/channel.d.ts.map +1 -1
- package/dist/src/platforms/discord/commands/channel.js +3 -2
- package/dist/src/platforms/discord/commands/channel.js.map +1 -1
- package/dist/src/platforms/discord/commands/snapshot.d.ts.map +1 -1
- package/dist/src/platforms/discord/commands/snapshot.js +7 -6
- package/dist/src/platforms/discord/commands/snapshot.js.map +1 -1
- package/dist/src/platforms/discord/types.d.ts +17 -0
- package/dist/src/platforms/discord/types.d.ts.map +1 -1
- package/dist/src/platforms/discord/types.js +36 -0
- package/dist/src/platforms/discord/types.js.map +1 -1
- package/dist/src/platforms/slack/index.d.ts +1 -0
- package/dist/src/platforms/slack/index.d.ts.map +1 -1
- package/dist/src/platforms/slack/index.js.map +1 -1
- package/dist/src/platforms/slack/qr-confirmation.d.ts +19 -0
- package/dist/src/platforms/slack/qr-confirmation.d.ts.map +1 -0
- package/dist/src/platforms/slack/qr-confirmation.js +68 -0
- package/dist/src/platforms/slack/qr-confirmation.js.map +1 -0
- package/dist/src/platforms/slack/qr-cookie-jar.d.ts +7 -0
- package/dist/src/platforms/slack/qr-cookie-jar.d.ts.map +1 -0
- package/dist/src/platforms/slack/qr-cookie-jar.js +48 -0
- package/dist/src/platforms/slack/qr-cookie-jar.js.map +1 -0
- package/dist/src/platforms/slack/qr-http-login.d.ts +2 -1
- package/dist/src/platforms/slack/qr-http-login.d.ts.map +1 -1
- package/dist/src/platforms/slack/qr-http-login.js +88 -53
- package/dist/src/platforms/slack/qr-http-login.js.map +1 -1
- package/docs/content/docs/cli/channeltalk.mdx +4 -4
- package/package.json +2 -1
- package/skills/agent-channeltalk/SKILL.md +5 -5
- package/skills/agent-channeltalk/references/authentication.md +9 -5
- package/skills/agent-channeltalkbot/SKILL.md +1 -1
- package/skills/agent-discord/SKILL.md +8 -4
- package/skills/agent-discord/references/common-patterns.md +7 -3
- package/skills/agent-discordbot/SKILL.md +1 -1
- package/skills/agent-imessage/SKILL.md +1 -1
- package/skills/agent-instagram/SKILL.md +1 -1
- package/skills/agent-kakaotalk/SKILL.md +1 -1
- package/skills/agent-line/SKILL.md +1 -1
- package/skills/agent-slack/SKILL.md +25 -2
- package/skills/agent-slackbot/SKILL.md +1 -1
- package/skills/agent-teams/SKILL.md +1 -1
- package/skills/agent-telegram/SKILL.md +1 -1
- package/skills/agent-telegrambot/SKILL.md +1 -1
- package/skills/agent-webex/SKILL.md +1 -1
- package/skills/agent-webexbot/SKILL.md +1 -1
- package/skills/agent-wechatbot/SKILL.md +1 -1
- package/skills/agent-whatsapp/SKILL.md +1 -1
- package/skills/agent-whatsappbot/SKILL.md +1 -1
- package/src/platforms/channeltalk/token-extractor.test.ts +235 -0
- package/src/platforms/channeltalk/token-extractor.ts +81 -22
- package/src/platforms/discord/commands/channel.test.ts +33 -23
- package/src/platforms/discord/commands/channel.ts +3 -2
- package/src/platforms/discord/commands/snapshot.test.ts +80 -2
- package/src/platforms/discord/commands/snapshot.ts +7 -6
- package/src/platforms/discord/types.test.ts +45 -0
- package/src/platforms/discord/types.ts +41 -0
- package/src/platforms/slack/index.ts +1 -0
- package/src/platforms/slack/qr-confirmation.ts +86 -0
- package/src/platforms/slack/qr-cookie-jar.ts +54 -0
- package/src/platforms/slack/qr-http-login-2fa.test.ts +398 -0
- package/src/platforms/slack/qr-http-login.test.ts +10 -18
- package/src/platforms/slack/qr-http-login.ts +109 -52
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qr-confirmation.js","sourceRoot":"","sources":["../../../../src/platforms/slack/qr-confirmation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare class SlackCookieJar {
|
|
2
|
+
#private;
|
|
3
|
+
fetch(doFetch: typeof fetch, url: string, init?: RequestInit): Promise<Response>;
|
|
4
|
+
sessionCookie(url: string): Promise<string | null>;
|
|
5
|
+
}
|
|
6
|
+
export declare function setCookieNames(response: Response): readonly string[];
|
|
7
|
+
//# sourceMappingURL=qr-cookie-jar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qr-cookie-jar.d.ts","sourceRoot":"","sources":["../../../../src/platforms/slack/qr-cookie-jar.ts"],"names":[],"mappings":"AAQA,qBAAa,cAAc;;IAGnB,KAAK,CAAC,OAAO,EAAE,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,GAAE,WAAgB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAiBzF;IAEK,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAQvD;CACF;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,QAAQ,GAAG,SAAS,MAAM,EAAE,CAKpE"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { CookieJar } from 'tough-cookie';
|
|
2
|
+
const BROWSER_USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36';
|
|
3
|
+
const SESSION_COOKIE_NAME = 'd';
|
|
4
|
+
const SESSION_COOKIE_PREFIX = 'xoxd-';
|
|
5
|
+
export class SlackCookieJar {
|
|
6
|
+
#jar = new CookieJar();
|
|
7
|
+
async fetch(doFetch, url, init = {}) {
|
|
8
|
+
const cookie = await this.#jar.getCookieString(url);
|
|
9
|
+
const response = await doFetch(url, {
|
|
10
|
+
...init,
|
|
11
|
+
redirect: 'manual',
|
|
12
|
+
headers: {
|
|
13
|
+
'User-Agent': BROWSER_USER_AGENT,
|
|
14
|
+
Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
|
|
15
|
+
'Accept-Language': 'en-US,en;q=0.9',
|
|
16
|
+
...init.headers,
|
|
17
|
+
...(cookie ? { Cookie: cookie } : {}),
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
for (const setCookie of getSetCookies(response)) {
|
|
21
|
+
await this.#jar.setCookie(setCookie, url, { ignoreError: true });
|
|
22
|
+
}
|
|
23
|
+
return response;
|
|
24
|
+
}
|
|
25
|
+
async sessionCookie(url) {
|
|
26
|
+
const cookies = await this.#jar.getCookies(url);
|
|
27
|
+
for (const cookie of cookies) {
|
|
28
|
+
if (cookie.key === SESSION_COOKIE_NAME && cookie.value.startsWith(SESSION_COOKIE_PREFIX)) {
|
|
29
|
+
return cookie.value;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
export function setCookieNames(response) {
|
|
36
|
+
return getSetCookies(response).flatMap((setCookie) => {
|
|
37
|
+
const name = setCookie.split('=')[0]?.trim();
|
|
38
|
+
return name ? [name] : [];
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
function getSetCookies(response) {
|
|
42
|
+
const withGetter = response.headers;
|
|
43
|
+
if (typeof withGetter.getSetCookie === 'function')
|
|
44
|
+
return withGetter.getSetCookie();
|
|
45
|
+
const single = response.headers.get('set-cookie');
|
|
46
|
+
return single ? [single] : [];
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=qr-cookie-jar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qr-cookie-jar.js","sourceRoot":"","sources":["../../../../src/platforms/slack/qr-cookie-jar.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAExC,MAAM,kBAAkB,GACtB,uHAAuH,CAAA;AAEzH,MAAM,mBAAmB,GAAG,GAAG,CAAA;AAC/B,MAAM,qBAAqB,GAAG,OAAO,CAAA;AAErC,MAAM,OAAO,cAAc;IAChB,IAAI,GAAG,IAAI,SAAS,EAAE,CAAA;IAE/B,KAAK,CAAC,KAAK,CAAC,OAAqB,EAAE,GAAW,EAAE,IAAI,GAAgB,EAAE;QACpE,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,CAAA;QACnD,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE;YAClC,GAAG,IAAI;YACP,QAAQ,EAAE,QAAQ;YAClB,OAAO,EAAE;gBACP,YAAY,EAAE,kBAAkB;gBAChC,MAAM,EAAE,iEAAiE;gBACzE,iBAAiB,EAAE,gBAAgB;gBACnC,GAAG,IAAI,CAAC,OAAO;gBACf,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACtC;SACF,CAAC,CAAA;QACF,KAAK,MAAM,SAAS,IAAI,aAAa,CAAC,QAAQ,CAAC,EAAE,CAAC;YAChD,MAAM,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,GAAG,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAA;QAClE,CAAC;QACD,OAAO,QAAQ,CAAA;IACjB,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,GAAW;QAC7B,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAA;QAC/C,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,IAAI,MAAM,CAAC,GAAG,KAAK,mBAAmB,IAAI,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,qBAAqB,CAAC,EAAE,CAAC;gBACzF,OAAO,MAAM,CAAC,KAAK,CAAA;YACrB,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;CACF;AAED,MAAM,UAAU,cAAc,CAAC,QAAkB;IAC/C,OAAO,aAAa,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,EAAE;QACnD,MAAM,IAAI,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAA;QAC5C,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;IAC3B,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,QAAkB;IACvC,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAsD,CAAA;IAClF,IAAI,OAAO,UAAU,CAAC,YAAY,KAAK,UAAU;QAAE,OAAO,UAAU,CAAC,YAAY,EAAE,CAAA;IACnF,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAA;IACjD,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;AAC/B,CAAC"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type SlackConfirmationCodeRequest } from './qr-confirmation.js';
|
|
1
2
|
export interface QrSession {
|
|
2
3
|
token: string;
|
|
3
4
|
cookie: string;
|
|
@@ -7,8 +8,8 @@ export interface QrLoginOptions {
|
|
|
7
8
|
fetchImpl?: typeof fetch;
|
|
8
9
|
maxRedirects?: number;
|
|
9
10
|
debug?: (message: string) => void;
|
|
11
|
+
requestConfirmationCode?: SlackConfirmationCodeRequest;
|
|
10
12
|
}
|
|
11
13
|
export declare function loginWithQr(dataUrl: string, options?: QrLoginOptions): Promise<QrSession>;
|
|
12
14
|
export declare function isSlackHost(rawUrl: string): boolean;
|
|
13
|
-
export declare function parseDCookie(setCookieHeader: string): string | null;
|
|
14
15
|
//# sourceMappingURL=qr-http-login.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"qr-http-login.d.ts","sourceRoot":"","sources":["../../../../src/platforms/slack/qr-http-login.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"qr-http-login.d.ts","sourceRoot":"","sources":["../../../../src/platforms/slack/qr-http-login.ts"],"names":[],"mappings":"AAEA,OAAO,EAIL,KAAK,4BAA4B,EAClC,MAAM,mBAAmB,CAAA;AAI1B,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;IACxB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;IACjC,uBAAuB,CAAC,EAAE,4BAA4B,CAAA;CACvD;AAID,wBAAsB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,SAAS,CAAC,CAwBnG;AA+ND,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAQnD"}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { SlackError } from './client.js';
|
|
2
2
|
import { refreshTokenFromWeb } from './ensure-auth.js';
|
|
3
|
+
import { buildConfirmationRequest, expectedConfirmationPath, parseConfirmationPage, } from './qr-confirmation.js';
|
|
4
|
+
import { setCookieNames, SlackCookieJar } from './qr-cookie-jar.js';
|
|
3
5
|
import { decodeSlackQr } from './qr-login.js';
|
|
4
|
-
const BROWSER_USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36';
|
|
5
6
|
const DEFAULT_MAX_REDIRECTS = 10;
|
|
6
7
|
export async function loginWithQr(dataUrl, options = {}) {
|
|
7
8
|
const login = decodeSlackQr(dataUrl.trim());
|
|
8
9
|
const debug = options.debug;
|
|
9
10
|
debug?.(`Decoded QR for workspace ${login.workspace}`);
|
|
10
|
-
const { cookie, denialReason, ssoProvider } = await captureDCookie(login
|
|
11
|
+
const { cookie, denialReason, ssoProvider } = await captureDCookie(login, options);
|
|
11
12
|
if (!cookie) {
|
|
12
13
|
throw new SlackError(qrSessionFailureMessage(denialReason, { workspace: login.workspace, ssoProvider }), 'qr_session_failed');
|
|
13
14
|
}
|
|
@@ -65,15 +66,16 @@ function qrSessionFailureMessage(denialReason, context = {}) {
|
|
|
65
66
|
'to Slack.',
|
|
66
67
|
].join('\n');
|
|
67
68
|
}
|
|
68
|
-
async function captureDCookie(
|
|
69
|
+
async function captureDCookie(login, options) {
|
|
69
70
|
const doFetch = options.fetchImpl ?? fetch;
|
|
70
71
|
const maxRedirects = options.maxRedirects ?? DEFAULT_MAX_REDIRECTS;
|
|
71
72
|
const debug = options.debug;
|
|
72
|
-
let url =
|
|
73
|
+
let url = login.url;
|
|
73
74
|
let dCookie = null;
|
|
74
75
|
let sessionDenialReason = null;
|
|
75
76
|
let ssoProvider = null;
|
|
76
|
-
const cookieJar =
|
|
77
|
+
const cookieJar = new SlackCookieJar();
|
|
78
|
+
const sessionCookieUrl = tokenUrl(login.workspace);
|
|
77
79
|
for (let hop = 0; hop < maxRedirects; hop++) {
|
|
78
80
|
// Only ever send captured cookies (including the d session cookie) to Slack
|
|
79
81
|
// hosts. A redirect to an off-domain host (e.g. an SSO IdP) must never
|
|
@@ -82,32 +84,48 @@ async function captureDCookie(startUrl, options) {
|
|
|
82
84
|
debug?.(`hop ${hop}: refusing non-Slack host`);
|
|
83
85
|
break;
|
|
84
86
|
}
|
|
85
|
-
const response = await doFetch
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
'User-Agent': BROWSER_USER_AGENT,
|
|
89
|
-
Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
|
|
90
|
-
'Accept-Language': 'en-US,en;q=0.9',
|
|
91
|
-
...(cookieJar.length ? { Cookie: cookieJar.join('; ') } : {}),
|
|
92
|
-
},
|
|
93
|
-
});
|
|
94
|
-
const cookieNames = [];
|
|
95
|
-
for (const setCookie of getSetCookies(response)) {
|
|
96
|
-
const value = parseDCookie(setCookie);
|
|
97
|
-
if (value)
|
|
98
|
-
dCookie = value;
|
|
99
|
-
const name = setCookie.split('=')[0]?.trim();
|
|
100
|
-
if (name)
|
|
101
|
-
cookieNames.push(name);
|
|
102
|
-
const pair = setCookie.split(';')[0]?.trim();
|
|
103
|
-
if (pair)
|
|
104
|
-
cookieJar.push(pair);
|
|
105
|
-
}
|
|
87
|
+
const response = await cookieJar.fetch(doFetch, url);
|
|
88
|
+
dCookie = await cookieJar.sessionCookie(sessionCookieUrl);
|
|
89
|
+
const cookieNames = setCookieNames(response);
|
|
106
90
|
debug?.(`hop ${hop}: ${response.status} set-cookie=[${cookieNames.join(',') || 'none'}]`);
|
|
107
91
|
const location = response.status >= 300 && response.status < 400 ? response.headers.get('location') : null;
|
|
108
92
|
if (!location) {
|
|
109
|
-
if (!dCookie)
|
|
110
|
-
|
|
93
|
+
if (!dCookie) {
|
|
94
|
+
const body = await response.text();
|
|
95
|
+
const props = parseConfirmationPage(body);
|
|
96
|
+
if (props && options.requestConfirmationCode) {
|
|
97
|
+
const request = buildConfirmationRequest(login, url, props, '');
|
|
98
|
+
if (!request) {
|
|
99
|
+
sessionDenialReason = 'invalid_confirmation_origin';
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
const code = await options.requestConfirmationCode({
|
|
103
|
+
email: props.emailAddress,
|
|
104
|
+
type: props.twoFactorType,
|
|
105
|
+
});
|
|
106
|
+
if (code.trim() === '') {
|
|
107
|
+
sessionDenialReason = 'confirmation_failed';
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
const confirmedRequest = buildConfirmationRequest(login, url, props, code);
|
|
111
|
+
if (!confirmedRequest) {
|
|
112
|
+
sessionDenialReason = 'invalid_confirmation_origin';
|
|
113
|
+
break;
|
|
114
|
+
}
|
|
115
|
+
const confirmed = await cookieJar.fetch(doFetch, confirmedRequest.url, {
|
|
116
|
+
method: 'POST',
|
|
117
|
+
body: confirmedRequest.body,
|
|
118
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
119
|
+
});
|
|
120
|
+
debug?.(`confirmation submit: ${confirmed.status}`);
|
|
121
|
+
dCookie = await followConfirmationRedirects(confirmed, confirmedRequest.url, sessionCookieUrl, cookieJar, doFetch, maxRedirects, debug);
|
|
122
|
+
if (!dCookie)
|
|
123
|
+
sessionDenialReason = 'confirmation_failed';
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
sessionDenialReason = classifySessionDenialBody(body);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
111
129
|
break;
|
|
112
130
|
}
|
|
113
131
|
const next = new URL(location, url).toString();
|
|
@@ -122,10 +140,46 @@ async function captureDCookie(startUrl, options) {
|
|
|
122
140
|
debug?.(`hop ${hop}: redirect target is not a Slack host (${new URL(next).hostname}), stopping`);
|
|
123
141
|
break;
|
|
124
142
|
}
|
|
143
|
+
if (!dCookie && options.requestConfirmationCode && isWorkspaceConfirmationUrl(next, login) === false) {
|
|
144
|
+
sessionDenialReason = 'invalid_confirmation_origin';
|
|
145
|
+
break;
|
|
146
|
+
}
|
|
125
147
|
url = next;
|
|
126
148
|
}
|
|
127
149
|
return { cookie: dCookie, denialReason: sessionDenialReason, ssoProvider };
|
|
128
150
|
}
|
|
151
|
+
function isWorkspaceConfirmationUrl(rawUrl, login) {
|
|
152
|
+
const expected = expectedConfirmationPath(login);
|
|
153
|
+
if (!expected)
|
|
154
|
+
return null;
|
|
155
|
+
const url = new URL(rawUrl);
|
|
156
|
+
if (url.pathname !== expected)
|
|
157
|
+
return null;
|
|
158
|
+
return url.hostname === `${login.workspace}.slack.com`;
|
|
159
|
+
}
|
|
160
|
+
async function followConfirmationRedirects(response, responseUrl, sessionCookieUrl, cookieJar, doFetch, maxRedirects, debug) {
|
|
161
|
+
let currentResponse = response;
|
|
162
|
+
let currentUrl = responseUrl;
|
|
163
|
+
let currentSessionCookie = await cookieJar.sessionCookie(sessionCookieUrl);
|
|
164
|
+
for (let hop = 0; hop < maxRedirects; hop++) {
|
|
165
|
+
if (currentSessionCookie)
|
|
166
|
+
return currentSessionCookie;
|
|
167
|
+
const location = currentResponse.status >= 300 && currentResponse.status < 400 ? currentResponse.headers.get('location') : null;
|
|
168
|
+
if (!location)
|
|
169
|
+
return null;
|
|
170
|
+
const next = new URL(location, currentUrl).toString();
|
|
171
|
+
if (!isSlackHost(next))
|
|
172
|
+
return null;
|
|
173
|
+
currentUrl = next;
|
|
174
|
+
currentResponse = await cookieJar.fetch(doFetch, currentUrl);
|
|
175
|
+
currentSessionCookie = await cookieJar.sessionCookie(sessionCookieUrl);
|
|
176
|
+
debug?.(`confirmation hop ${hop}: ${currentResponse.status}`);
|
|
177
|
+
}
|
|
178
|
+
return currentSessionCookie;
|
|
179
|
+
}
|
|
180
|
+
function tokenUrl(workspace) {
|
|
181
|
+
return `https://${workspace}.slack.com/ssb/redirect`;
|
|
182
|
+
}
|
|
129
183
|
function ssoProviderFromUrl(rawUrl) {
|
|
130
184
|
let hostname;
|
|
131
185
|
try {
|
|
@@ -148,20 +202,13 @@ function ssoProviderFromUrl(rawUrl) {
|
|
|
148
202
|
return 'Auth0';
|
|
149
203
|
return null;
|
|
150
204
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
}
|
|
157
|
-
if (/sign in on your other device/i.test(body) || /open Slack/i.test(body) || /confirm/i.test(body)) {
|
|
158
|
-
return 'awaiting_device_confirmation';
|
|
159
|
-
}
|
|
160
|
-
return null;
|
|
161
|
-
}
|
|
162
|
-
catch {
|
|
163
|
-
return null;
|
|
205
|
+
function classifySessionDenialBody(body) {
|
|
206
|
+
if (/Link Expired/i.test(body) || /trouble signing you in/i.test(body))
|
|
207
|
+
return 'link_expired';
|
|
208
|
+
if (/sign in on your other device/i.test(body) || /open Slack/i.test(body) || /confirm/i.test(body)) {
|
|
209
|
+
return 'awaiting_device_confirmation';
|
|
164
210
|
}
|
|
211
|
+
return null;
|
|
165
212
|
}
|
|
166
213
|
export function isSlackHost(rawUrl) {
|
|
167
214
|
try {
|
|
@@ -174,16 +221,4 @@ export function isSlackHost(rawUrl) {
|
|
|
174
221
|
return false;
|
|
175
222
|
}
|
|
176
223
|
}
|
|
177
|
-
export function parseDCookie(setCookieHeader) {
|
|
178
|
-
const match = setCookieHeader.match(/(?:^|,\s*)d=(xoxd-[^;]+)/);
|
|
179
|
-
return match ? match[1] : null;
|
|
180
|
-
}
|
|
181
|
-
function getSetCookies(response) {
|
|
182
|
-
const withGetter = response.headers;
|
|
183
|
-
if (typeof withGetter.getSetCookie === 'function') {
|
|
184
|
-
return withGetter.getSetCookie();
|
|
185
|
-
}
|
|
186
|
-
const single = response.headers.get('set-cookie');
|
|
187
|
-
return single ? [single] : [];
|
|
188
|
-
}
|
|
189
224
|
//# sourceMappingURL=qr-http-login.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"qr-http-login.js","sourceRoot":"","sources":["../../../../src/platforms/slack/qr-http-login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AACrC,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAA;AACnD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"qr-http-login.js","sourceRoot":"","sources":["../../../../src/platforms/slack/qr-http-login.ts"],"names":[],"mappings":"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"}
|
|
@@ -238,16 +238,16 @@ Use **agent-channeltalk** when you want zero-config access acting as yourself. U
|
|
|
238
238
|
|
|
239
239
|
### Channel Talk desktop app not found
|
|
240
240
|
|
|
241
|
-
The CLI looks for the
|
|
241
|
+
The CLI looks for the desktop app's cookie database in the locations below. The app was rebranded from Channel Talk to Channel Works, so both names are probed, `Channel Works` first.
|
|
242
242
|
|
|
243
243
|
**macOS:**
|
|
244
244
|
|
|
245
|
-
1. `~/Library/Containers/com.zoyi.channel.desk.osx/Data/Library/Application Support/Channel Talk/Cookies` (Mac App Store)
|
|
246
|
-
2. `~/Library/Application Support/Channel Talk/Cookies` (Electron version)
|
|
245
|
+
1. `~/Library/Containers/com.zoyi.channel.desk.osx/Data/Library/Application Support/{Channel Works,Channel Talk}/Cookies` (Mac App Store)
|
|
246
|
+
2. `~/Library/Application Support/{Channel Works,Channel Talk}/Cookies` (Electron version)
|
|
247
247
|
|
|
248
248
|
**Windows:**
|
|
249
249
|
|
|
250
|
-
1. `%APPDATA%\Channel Talk\Network\Cookies`
|
|
250
|
+
1. `%APPDATA%\{Channel Works,Channel Talk}\Network\Cookies`
|
|
251
251
|
|
|
252
252
|
If none exist, either install the Channel Talk desktop app and log in, or log in via a Chromium browser (Chrome, Edge, Arc, Brave, etc.) — the CLI will fall back to browser extraction automatically.
|
|
253
253
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-messenger",
|
|
3
|
-
"version": "2.32.
|
|
3
|
+
"version": "2.32.1",
|
|
4
4
|
"description": "Multi-platform messaging CLI for AI agents (Slack, Discord, Teams, Webex, Telegram, Telegram Bot, WhatsApp, LINE, iMessage, Instagram, KakaoTalk, Channel Talk)",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -193,6 +193,7 @@
|
|
|
193
193
|
"pngjs": "^7.0.0",
|
|
194
194
|
"qrcode": "^1.5.4",
|
|
195
195
|
"thrift": "^0.20.0",
|
|
196
|
+
"tough-cookie": "^6.0.2",
|
|
196
197
|
"tweetnacl": "^1.0.3",
|
|
197
198
|
"webex-message-handler": "^0.6.10",
|
|
198
199
|
"ws": "^8.19.0",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: agent-channeltalk
|
|
3
3
|
description: Interact with Channel Talk using extracted desktop app or browser credentials - read chats, send messages, search messages, manage groups
|
|
4
|
-
version: 2.32.
|
|
4
|
+
version: 2.32.1
|
|
5
5
|
allowed-tools: Bash(agent-channeltalk:*)
|
|
6
6
|
metadata:
|
|
7
7
|
openclaw:
|
|
@@ -438,14 +438,14 @@ npx -y agent-messenger channeltalk snapshot --pretty
|
|
|
438
438
|
|
|
439
439
|
### Channel Talk desktop app not found
|
|
440
440
|
|
|
441
|
-
The CLI looks for the
|
|
441
|
+
The CLI looks for the desktop app's cookie database in these locations. The app was rebranded from Channel Talk to Channel Works, so both names are probed, `Channel Works` first.
|
|
442
442
|
|
|
443
443
|
**macOS:**
|
|
444
|
-
1. `~/Library/Containers/com.zoyi.channel.desk.osx/Data/Library/Application Support/Channel Talk/Cookies` (Mac App Store version)
|
|
445
|
-
2. `~/Library/Application Support/Channel Talk/Cookies` (direct download / Electron version)
|
|
444
|
+
1. `~/Library/Containers/com.zoyi.channel.desk.osx/Data/Library/Application Support/{Channel Works,Channel Talk}/Cookies` (Mac App Store version)
|
|
445
|
+
2. `~/Library/Application Support/{Channel Works,Channel Talk}/Cookies` (direct download / Electron version)
|
|
446
446
|
|
|
447
447
|
**Windows:**
|
|
448
|
-
1. `%APPDATA%\Channel Talk\Network\Cookies`
|
|
448
|
+
1. `%APPDATA%\{Channel Works,Channel Talk}\Network\Cookies`
|
|
449
449
|
|
|
450
450
|
If none exist, log in to Channel Talk in a supported Chromium browser (Chrome, Edge, Arc, Brave) or install the desktop app and log in.
|
|
451
451
|
|
|
@@ -29,7 +29,7 @@ Use `--browser-profile <path>` for agent-browser profiles, custom Chrome user da
|
|
|
29
29
|
1. Locates the Channel Talk desktop app's SQLite cookie database
|
|
30
30
|
2. Scans Chromium browser profiles for Channel Talk cookies when the desktop app isn't found, or when custom `--browser-profile` paths are provided
|
|
31
31
|
3. Copies the database to a temp file (avoids locking the original)
|
|
32
|
-
4. Reads `x-account` and `ch-session-1` cookies for `*.channel.io`
|
|
32
|
+
4. Reads `x-account` and `ch-session-1` cookies for `*.channel.io` and `*.channel.works`
|
|
33
33
|
5. Decrypts encrypted cookies if needed (macOS Keychain, Linux peanuts, Windows DPAPI)
|
|
34
34
|
6. Validates cookies against the Channel Talk API
|
|
35
35
|
7. Discovers ALL workspaces you belong to
|
|
@@ -48,15 +48,19 @@ When extracting from the desktop app, no Keychain prompt is needed (cookies are
|
|
|
48
48
|
|
|
49
49
|
### Platform-Specific Paths
|
|
50
50
|
|
|
51
|
+
The desktop app was rebranded from Channel Talk to Channel Works. Both directory names are probed, `Channel Works` first, so upgraded and legacy installs both work.
|
|
52
|
+
|
|
51
53
|
**macOS (Mac App Store / sandboxed):**
|
|
52
54
|
|
|
53
55
|
```
|
|
56
|
+
~/Library/Containers/com.zoyi.channel.desk.osx/Data/Library/Application Support/Channel Works/Cookies
|
|
54
57
|
~/Library/Containers/com.zoyi.channel.desk.osx/Data/Library/Application Support/Channel Talk/Cookies
|
|
55
58
|
```
|
|
56
59
|
|
|
57
60
|
**macOS (Electron / direct download):**
|
|
58
61
|
|
|
59
62
|
```
|
|
63
|
+
~/Library/Application Support/Channel Works/Cookies
|
|
60
64
|
~/Library/Application Support/Channel Talk/Cookies
|
|
61
65
|
```
|
|
62
66
|
|
|
@@ -253,10 +257,10 @@ No credentials are configured and auto-extraction failed:
|
|
|
253
257
|
|
|
254
258
|
The CLI first checks for the desktop app, then falls back to Chromium browsers.
|
|
255
259
|
|
|
256
|
-
Desktop app paths:
|
|
257
|
-
1. **macOS (Mac App Store)**: `~/Library/Containers/com.zoyi.channel.desk.osx/Data/Library/Application Support/Channel Talk/Cookies`
|
|
258
|
-
2. **macOS (Electron)**: `~/Library/Application Support/Channel Talk/Cookies`
|
|
259
|
-
3. **Windows**: `%APPDATA%/Channel Talk/Network/Cookies`
|
|
260
|
+
Desktop app paths (`Channel Works` is the current name, `Channel Talk` the legacy one; both are probed):
|
|
261
|
+
1. **macOS (Mac App Store)**: `~/Library/Containers/com.zoyi.channel.desk.osx/Data/Library/Application Support/{Channel Works,Channel Talk}/Cookies`
|
|
262
|
+
2. **macOS (Electron)**: `~/Library/Application Support/{Channel Works,Channel Talk}/Cookies`
|
|
263
|
+
3. **Windows**: `%APPDATA%/{Channel Works,Channel Talk}/Network/Cookies`
|
|
260
264
|
|
|
261
265
|
If neither the desktop app nor browser cookies are found:
|
|
262
266
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: agent-discord
|
|
3
3
|
description: Interact with Discord servers - send messages, read channels, manage reactions
|
|
4
|
-
version: 2.32.
|
|
4
|
+
version: 2.32.1
|
|
5
5
|
allowed-tools: Bash(agent-discord:*)
|
|
6
6
|
metadata:
|
|
7
7
|
openclaw:
|
|
@@ -212,7 +212,9 @@ agent-discord message search "hello" --channel <channel-id> --author <user-id>
|
|
|
212
212
|
### Channel Commands
|
|
213
213
|
|
|
214
214
|
```bash
|
|
215
|
-
# List channels in current server
|
|
215
|
+
# List channels in current server
|
|
216
|
+
# Includes text, announcement, voice/stage (voice channels carry text chat),
|
|
217
|
+
# forum, media, and directory channels. Categories and threads are excluded.
|
|
216
218
|
agent-discord channel list
|
|
217
219
|
|
|
218
220
|
# Get channel info
|
|
@@ -377,9 +379,11 @@ agent-discord snapshot --full --limit 10
|
|
|
377
379
|
Default returns brief JSON with:
|
|
378
380
|
|
|
379
381
|
- Server metadata (id, name)
|
|
380
|
-
- Channels (id, name) —
|
|
382
|
+
- Channels (id, name) — all listable channels (text, announcement, voice/stage, forum, media, directory; excludes categories and threads)
|
|
381
383
|
- Hint for next commands
|
|
382
384
|
|
|
385
|
+
> Not every listed channel accepts a direct `message list`. Forum, media, and directory channels are containers or hub views with no direct message timeline — their messages live in child posts/threads. Use text, announcement, voice, or stage channels for `message list`.
|
|
386
|
+
|
|
383
387
|
With `--full`, returns comprehensive JSON with:
|
|
384
388
|
|
|
385
389
|
- Server metadata (id, name)
|
|
@@ -556,7 +560,7 @@ See the [Discord SDK documentation](https://agent-messenger.dev/docs/sdk/discord
|
|
|
556
560
|
|
|
557
561
|
## Limitations
|
|
558
562
|
|
|
559
|
-
- No voice
|
|
563
|
+
- No voice audio support (voice/stage channels are listed and their embedded text chat is readable, but joining voice or streaming audio is unsupported)
|
|
560
564
|
- No server management (create/delete channels, roles)
|
|
561
565
|
- No slash commands
|
|
562
566
|
- No webhook support
|
|
@@ -87,12 +87,16 @@ CHANNEL_COUNT=$(echo "$SNAPSHOT" | jq -r '.channels | length')
|
|
|
87
87
|
echo "Server: $SERVER_NAME"
|
|
88
88
|
echo "Channels: $CHANNEL_COUNT"
|
|
89
89
|
|
|
90
|
-
# List all
|
|
90
|
+
# List all channels
|
|
91
91
|
echo -e "\nChannels:"
|
|
92
92
|
echo "$SNAPSHOT" | jq -r '.channels[] | " #\(.name) (\(.id))"'
|
|
93
93
|
|
|
94
|
-
# Then drill into a specific channel for recent activity
|
|
95
|
-
|
|
94
|
+
# Then drill into a specific channel for recent activity.
|
|
95
|
+
# Only text (0), announcement (5), voice (2), and stage (13) channels accept
|
|
96
|
+
# `message list`; forum (15), media (16), and directory (14) channels do not.
|
|
97
|
+
# A full snapshot includes `type`, so pick the first message-readable channel.
|
|
98
|
+
FULL=$(agent-discord snapshot --full)
|
|
99
|
+
CHANNEL_ID=$(echo "$FULL" | jq -r '[.channels[] | select(.type == 0 or .type == 5 or .type == 2 or .type == 13)][0].id // empty')
|
|
96
100
|
if [ -n "$CHANNEL_ID" ]; then
|
|
97
101
|
echo -e "\nRecent messages:"
|
|
98
102
|
agent-discord message list "$CHANNEL_ID" --limit 10
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: agent-slack
|
|
3
3
|
description: Interact with Slack workspaces - send messages, read channels, manage reactions
|
|
4
|
-
version: 2.32.
|
|
4
|
+
version: 2.32.1
|
|
5
5
|
allowed-tools: Bash(agent-slack:*)
|
|
6
6
|
metadata:
|
|
7
7
|
openclaw:
|
|
@@ -607,7 +607,30 @@ await new SlackCredentialManager().setWorkspace({
|
|
|
607
607
|
})
|
|
608
608
|
```
|
|
609
609
|
|
|
610
|
-
`loginWithQr(dataUrl, options)` accepts an optional `{ debug, fetchImpl, maxRedirects }`. It throws `SlackError` with codes `qr_session_failed` (link expired / no session) or `qr_token_failed` (token could not be retrieved). To decode the QR without logging in, use `decodeSlackQr(dataUrl)` which returns `{ url, workspace, teamId, userId }`.
|
|
610
|
+
`loginWithQr(dataUrl, options)` accepts an optional `{ debug, fetchImpl, maxRedirects, requestConfirmationCode }`. It throws `SlackError` with codes `qr_session_failed` (link expired / no session) or `qr_token_failed` (token could not be retrieved). To decode the QR without logging in, use `decodeSlackQr(dataUrl)` which returns `{ url, workspace, teamId, userId }`.
|
|
611
|
+
|
|
612
|
+
### Handling Slack confirmation codes (workspace 2FA)
|
|
613
|
+
|
|
614
|
+
Some workspaces make a QR sign-in surface a confirmation-code page (email code, SMS, TOTP, etc.) before issuing the session cookie. Pass `requestConfirmationCode` to complete that step. The callback is only invoked when Slack actually shows a confirmation page — ordinary QR logins that receive the session cookie directly stay prompt-free.
|
|
615
|
+
|
|
616
|
+
```typescript
|
|
617
|
+
import { loginWithQr, type SlackConfirmationChallenge } from 'agent-messenger/slack'
|
|
618
|
+
|
|
619
|
+
const session = await loginWithQr(dataUrl, {
|
|
620
|
+
requestConfirmationCode: async (challenge: SlackConfirmationChallenge) => {
|
|
621
|
+
// challenge.email is the address Slack sent the code to.
|
|
622
|
+
// challenge.type is the mechanism ("email", "sms", "totp", ...) or null if unknown.
|
|
623
|
+
return await promptUserForCode(challenge)
|
|
624
|
+
},
|
|
625
|
+
})
|
|
626
|
+
```
|
|
627
|
+
|
|
628
|
+
Contract:
|
|
629
|
+
|
|
630
|
+
- Return the raw code as a `string`. Whitespace is trimmed before submission.
|
|
631
|
+
- Return an empty string (or all whitespace) to abort — `loginWithQr` throws `qr_session_failed` and no code is posted.
|
|
632
|
+
- The code is submitted to the exact `https://<workspace>.slack.com/login/<qrSecret>` endpoint bound to the QR payload. Redirects to a different workspace host or an unexpected pathname reject the flow before the callback is invoked.
|
|
633
|
+
- The callback and `email`/`type` fields never appear in `debug` output.
|
|
611
634
|
|
|
612
635
|
## SDK: Real-Time Events
|
|
613
636
|
|