agent-messenger 2.6.1 → 2.6.3
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/dist/package.json +1 -1
- package/dist/src/platforms/channeltalk/cli.js +1 -1
- package/dist/src/platforms/channeltalk/cli.js.map +1 -1
- package/dist/src/platforms/channeltalk/client.js +1 -1
- package/dist/src/platforms/channeltalk/client.js.map +1 -1
- package/dist/src/platforms/channeltalk/commands/auth.d.ts +2 -0
- package/dist/src/platforms/channeltalk/commands/auth.d.ts.map +1 -1
- package/dist/src/platforms/channeltalk/commands/auth.js +9 -3
- package/dist/src/platforms/channeltalk/commands/auth.js.map +1 -1
- package/dist/src/platforms/discord/client.js +1 -1
- package/dist/src/platforms/discord/client.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 +6 -3
- package/dist/src/platforms/discord/commands/auth.js.map +1 -1
- package/dist/src/platforms/slack/cli.js +1 -1
- package/dist/src/platforms/slack/cli.js.map +1 -1
- package/dist/src/platforms/slack/client.js +1 -1
- package/dist/src/platforms/slack/client.js.map +1 -1
- package/dist/src/platforms/slack/commands/auth.d.ts +1 -0
- package/dist/src/platforms/slack/commands/auth.d.ts.map +1 -1
- package/dist/src/platforms/slack/commands/auth.js +8 -5
- package/dist/src/platforms/slack/commands/auth.js.map +1 -1
- package/dist/src/platforms/teams/client.js +1 -1
- package/dist/src/platforms/teams/client.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 +12 -7
- package/dist/src/platforms/teams/commands/auth.js.map +1 -1
- package/dist/src/platforms/webex/client.d.ts +3 -0
- package/dist/src/platforms/webex/client.d.ts.map +1 -1
- package/dist/src/platforms/webex/client.js +6 -0
- package/dist/src/platforms/webex/client.js.map +1 -1
- package/dist/src/platforms/webex/commands/snapshot.d.ts +0 -3
- package/dist/src/platforms/webex/commands/snapshot.d.ts.map +1 -1
- package/dist/src/platforms/webex/commands/snapshot.js +9 -47
- package/dist/src/platforms/webex/commands/snapshot.js.map +1 -1
- package/docs/content/docs/cli/webex.mdx +3 -11
- package/package.json +1 -1
- package/skills/agent-channeltalk/SKILL.md +3 -3
- package/skills/agent-channeltalk/references/authentication.md +3 -3
- package/skills/agent-channeltalk/templates/monitor-chat.sh +1 -1
- package/skills/agent-channeltalk/templates/post-message.sh +2 -2
- package/skills/agent-channeltalk/templates/workspace-summary.sh +1 -1
- package/skills/agent-channeltalkbot/SKILL.md +1 -1
- package/skills/agent-discord/SKILL.md +1 -1
- package/skills/agent-discordbot/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 +1 -1
- package/skills/agent-slack/references/authentication.md +3 -3
- 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-webex/SKILL.md +6 -14
- package/skills/agent-webex/references/common-patterns.md +3 -32
- 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/cli.ts +1 -1
- package/src/platforms/channeltalk/client.ts +1 -1
- package/src/platforms/channeltalk/commands/auth.test.ts +4 -2
- package/src/platforms/channeltalk/commands/auth.ts +11 -3
- package/src/platforms/discord/client.ts +1 -1
- package/src/platforms/discord/commands/auth.test.ts +5 -0
- package/src/platforms/discord/commands/auth.ts +7 -3
- package/src/platforms/slack/cli.ts +1 -1
- package/src/platforms/slack/client.ts +1 -1
- package/src/platforms/slack/commands/auth.test.ts +31 -6
- package/src/platforms/slack/commands/auth.ts +9 -5
- package/src/platforms/teams/client.ts +1 -1
- package/src/platforms/teams/commands/auth.test.ts +5 -0
- package/src/platforms/teams/commands/auth.ts +14 -7
- package/src/platforms/webex/client.ts +10 -0
- package/src/platforms/webex/commands/snapshot.test.ts +13 -41
- package/src/platforms/webex/commands/snapshot.ts +10 -61
|
@@ -44,7 +44,7 @@ VALID=$(echo "$AUTH_STATUS" | jq -r '.valid // false')
|
|
|
44
44
|
|
|
45
45
|
if [ "$VALID" != "true" ]; then
|
|
46
46
|
echo -e "${RED}Not authenticated!${NC}" >&2
|
|
47
|
-
echo "Make sure Channel Talk desktop app
|
|
47
|
+
echo "Make sure Channel Talk is logged in via the desktop app or a supported Chromium browser." >&2
|
|
48
48
|
echo "Then run: agent-channeltalk auth extract" >&2
|
|
49
49
|
exit 1
|
|
50
50
|
fi
|
|
@@ -243,11 +243,11 @@ This shows:
|
|
|
243
243
|
|
|
244
244
|
### "No workspaces found"
|
|
245
245
|
|
|
246
|
-
**Cause**: Not logged into any workspaces in Slack desktop app
|
|
246
|
+
**Cause**: Not logged into any workspaces in the Slack desktop app or a supported Chromium browser
|
|
247
247
|
|
|
248
248
|
**Solution**:
|
|
249
249
|
|
|
250
|
-
1. Open Slack desktop app
|
|
250
|
+
1. Open Slack desktop app or sign in at app.slack.com in a supported Chromium browser (Chrome, Edge, Arc, Brave)
|
|
251
251
|
2. Sign in to at least one workspace
|
|
252
252
|
3. Run `agent-slack auth extract` again
|
|
253
253
|
|
|
@@ -281,7 +281,7 @@ agent-slack auth status
|
|
|
281
281
|
|
|
282
282
|
**Solution**:
|
|
283
283
|
|
|
284
|
-
1. Open Slack desktop app
|
|
284
|
+
1. Open Slack desktop app or app.slack.com in a supported Chromium browser
|
|
285
285
|
2. Make sure you're logged in (send a message to verify)
|
|
286
286
|
3. Run `agent-slack auth extract --debug` to see details
|
|
287
287
|
4. If issues persist, try logging out and back into Slack
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: agent-webex
|
|
3
3
|
description: Interact with Cisco Webex - send messages, read spaces, manage memberships
|
|
4
|
-
version: 2.6.
|
|
4
|
+
version: 2.6.3
|
|
5
5
|
allowed-tools: Bash(agent-webex:*)
|
|
6
6
|
metadata:
|
|
7
7
|
openclaw:
|
|
@@ -116,7 +116,7 @@ At the **start of every task**, read `~/.config/agent-messenger/MEMORY.md` using
|
|
|
116
116
|
After discovering useful information, update `~/.config/agent-messenger/MEMORY.md` using the `Write` tool. Write triggers include:
|
|
117
117
|
|
|
118
118
|
- After discovering space IDs and titles (from `space list`, `snapshot`, etc.)
|
|
119
|
-
- After discovering member IDs and names (from `member list`,
|
|
119
|
+
- After discovering member IDs and names (from `member list`, etc.)
|
|
120
120
|
- After the user gives you an alias or preference ("call this the standup space", "my main space is X")
|
|
121
121
|
- After discovering space structure (group vs direct spaces)
|
|
122
122
|
|
|
@@ -247,25 +247,17 @@ agent-webex member list <space-id> --limit 100
|
|
|
247
247
|
|
|
248
248
|
### Snapshot Command
|
|
249
249
|
|
|
250
|
-
Get
|
|
250
|
+
Get workspace spaces overview for AI agents:
|
|
251
251
|
|
|
252
252
|
```bash
|
|
253
|
-
# Full snapshot
|
|
254
253
|
agent-webex snapshot
|
|
255
|
-
|
|
256
|
-
# Filtered snapshots
|
|
257
|
-
agent-webex snapshot --spaces-only
|
|
258
|
-
agent-webex snapshot --members-only
|
|
259
|
-
|
|
260
|
-
# Limit messages per space
|
|
261
|
-
agent-webex snapshot --limit 10
|
|
262
254
|
```
|
|
263
255
|
|
|
264
256
|
Returns JSON with:
|
|
265
257
|
|
|
266
|
-
- Spaces (id, title, type,
|
|
267
|
-
|
|
268
|
-
|
|
258
|
+
- Spaces (id, title, type, lastActivity) — only spaces you're a member of
|
|
259
|
+
|
|
260
|
+
For messages or members, use `message list <space-id>` or `member list <space-id>`.
|
|
269
261
|
|
|
270
262
|
## Output Format
|
|
271
263
|
|
|
@@ -323,9 +323,9 @@ echo "Found: $(echo "$MATCH" | jq -r '.personDisplayName') ($(echo "$MATCH" | jq
|
|
|
323
323
|
|
|
324
324
|
## Snapshot Patterns
|
|
325
325
|
|
|
326
|
-
### Pattern 19:
|
|
326
|
+
### Pattern 19: Workspace Snapshot
|
|
327
327
|
|
|
328
|
-
**Use case**: Get
|
|
328
|
+
**Use case**: Get spaces overview for AI context
|
|
329
329
|
|
|
330
330
|
```bash
|
|
331
331
|
#!/bin/bash
|
|
@@ -339,36 +339,7 @@ echo "Total spaces: $SPACE_COUNT"
|
|
|
339
339
|
echo "$SNAPSHOT" | jq -r '.spaces[] | " \(.title) (\(.type))"'
|
|
340
340
|
```
|
|
341
341
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
**Use case**: Quick overview without messages or members
|
|
345
|
-
|
|
346
|
-
```bash
|
|
347
|
-
#!/bin/bash
|
|
348
|
-
|
|
349
|
-
agent-webex snapshot --spaces-only
|
|
350
|
-
```
|
|
351
|
-
|
|
352
|
-
### Pattern 21: Members-Only Snapshot
|
|
353
|
-
|
|
354
|
-
**Use case**: Get member lists across all spaces
|
|
355
|
-
|
|
356
|
-
```bash
|
|
357
|
-
#!/bin/bash
|
|
358
|
-
|
|
359
|
-
agent-webex snapshot --members-only
|
|
360
|
-
```
|
|
361
|
-
|
|
362
|
-
### Pattern 22: Snapshot with Message Limit
|
|
363
|
-
|
|
364
|
-
**Use case**: Control how many messages per space
|
|
365
|
-
|
|
366
|
-
```bash
|
|
367
|
-
#!/bin/bash
|
|
368
|
-
|
|
369
|
-
# Get snapshot with last 5 messages per space
|
|
370
|
-
agent-webex snapshot --limit 5
|
|
371
|
-
```
|
|
342
|
+
**When to use**: Quick workspace overview to discover space IDs and titles. Use `message list <space-id>` or `member list <space-id>` for details.
|
|
372
343
|
|
|
373
344
|
## Pipeline Patterns
|
|
374
345
|
|
|
@@ -29,7 +29,7 @@ const program = new Command()
|
|
|
29
29
|
|
|
30
30
|
program
|
|
31
31
|
.name('agent-channeltalk')
|
|
32
|
-
.description('CLI tool for Channel Talk using extracted desktop app credentials')
|
|
32
|
+
.description('CLI tool for Channel Talk using extracted desktop app or supported Chromium browser credentials')
|
|
33
33
|
.version(pkg.version)
|
|
34
34
|
.option('--pretty', 'Pretty-print JSON output')
|
|
35
35
|
.option('--workspace <id>', 'Workspace ID to use')
|
|
@@ -44,7 +44,7 @@ export class ChannelClient {
|
|
|
44
44
|
const creds = await new ChannelCredentialManager().getCredentials()
|
|
45
45
|
if (!creds) {
|
|
46
46
|
throw new ChannelError(
|
|
47
|
-
'No Channel Talk credentials found. Make sure Channel Talk desktop app
|
|
47
|
+
'No Channel Talk credentials found. Make sure Channel Talk is logged in to the desktop app or a supported Chromium browser.',
|
|
48
48
|
'no_credentials',
|
|
49
49
|
)
|
|
50
50
|
}
|
|
@@ -26,6 +26,8 @@ const mockExtract = mock(() =>
|
|
|
26
26
|
import {
|
|
27
27
|
clearAction,
|
|
28
28
|
extractAction,
|
|
29
|
+
getNoChannelTalkCredentialsMessage,
|
|
30
|
+
getNoValidChannelTalkCredentialsMessage,
|
|
29
31
|
listAction,
|
|
30
32
|
removeAction,
|
|
31
33
|
resetChannelAuthCommandDependenciesForTesting,
|
|
@@ -182,7 +184,7 @@ describe('channel auth commands', () => {
|
|
|
182
184
|
const result = await extractAction()
|
|
183
185
|
|
|
184
186
|
expect(result).toEqual({
|
|
185
|
-
error:
|
|
187
|
+
error: getNoChannelTalkCredentialsMessage(),
|
|
186
188
|
})
|
|
187
189
|
})
|
|
188
190
|
|
|
@@ -192,7 +194,7 @@ describe('channel auth commands', () => {
|
|
|
192
194
|
const result = await extractAction()
|
|
193
195
|
|
|
194
196
|
expect(result).toEqual({
|
|
195
|
-
error:
|
|
197
|
+
error: getNoValidChannelTalkCredentialsMessage(),
|
|
196
198
|
})
|
|
197
199
|
})
|
|
198
200
|
})
|
|
@@ -84,7 +84,7 @@ export async function extractAction(options: ActionOptions = {}): Promise<Extrac
|
|
|
84
84
|
|
|
85
85
|
if (extracted.length === 0) {
|
|
86
86
|
return {
|
|
87
|
-
error:
|
|
87
|
+
error: getNoChannelTalkCredentialsMessage(),
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
90
|
|
|
@@ -126,12 +126,20 @@ export async function extractAction(options: ActionOptions = {}): Promise<Extrac
|
|
|
126
126
|
}
|
|
127
127
|
}
|
|
128
128
|
|
|
129
|
-
return { error:
|
|
129
|
+
return { error: getNoValidChannelTalkCredentialsMessage() }
|
|
130
130
|
} catch (error: unknown) {
|
|
131
131
|
return { error: (error as Error).message }
|
|
132
132
|
}
|
|
133
133
|
}
|
|
134
134
|
|
|
135
|
+
export function getNoChannelTalkCredentialsMessage(): string {
|
|
136
|
+
return 'No credentials. Make sure Channel Talk is logged in to the desktop app or a supported Chromium browser.'
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export function getNoValidChannelTalkCredentialsMessage(): string {
|
|
140
|
+
return 'No valid credentials found. Make sure Channel Talk is logged in to the desktop app or a supported Chromium browser.'
|
|
141
|
+
}
|
|
142
|
+
|
|
135
143
|
export async function statusAction(options: ActionOptions = {}): Promise<StatusResult> {
|
|
136
144
|
try {
|
|
137
145
|
const credManager = options._credManager ?? createCredentialManager()
|
|
@@ -246,7 +254,7 @@ export function createAuthCommand(): Command {
|
|
|
246
254
|
.description('Authentication commands')
|
|
247
255
|
.addCommand(
|
|
248
256
|
new Command('extract')
|
|
249
|
-
.description('Extract cookies from Channel Talk desktop app')
|
|
257
|
+
.description('Extract cookies from Channel Talk desktop app or a supported Chromium browser')
|
|
250
258
|
.option('--pretty', 'Pretty print JSON output')
|
|
251
259
|
.action(async (opts: { pretty?: boolean }) => {
|
|
252
260
|
cliOutput(await extractAction(opts), opts.pretty)
|
|
@@ -59,7 +59,7 @@ export class DiscordClient {
|
|
|
59
59
|
const token = await credManager.getToken()
|
|
60
60
|
if (!token) {
|
|
61
61
|
throw new DiscordError(
|
|
62
|
-
'No Discord credentials found. Make sure Discord desktop app
|
|
62
|
+
'No Discord credentials found. Make sure Discord is logged in to the desktop app or a supported Chromium browser.',
|
|
63
63
|
'no_credentials',
|
|
64
64
|
)
|
|
65
65
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { afterEach, beforeEach, expect, spyOn, test } from 'bun:test'
|
|
2
2
|
|
|
3
|
+
import { getNoDiscordTokenFoundMessage } from './auth'
|
|
3
4
|
import { DiscordClient } from '../client'
|
|
4
5
|
import { DiscordCredentialManager } from '../credential-manager'
|
|
5
6
|
import { DiscordTokenExtractor } from '../token-extractor'
|
|
@@ -82,3 +83,7 @@ test('status: returns auth state', async () => {
|
|
|
82
83
|
expect(config.token).toBeNull()
|
|
83
84
|
expect(config.current_server).toBeNull()
|
|
84
85
|
})
|
|
86
|
+
|
|
87
|
+
test('no-token message mentions desktop app and browser fallback', () => {
|
|
88
|
+
expect(getNoDiscordTokenFoundMessage()).toContain('desktop app or a supported Chromium browser')
|
|
89
|
+
})
|
|
@@ -39,7 +39,7 @@ export async function extractAction(options: { pretty?: boolean; debug?: boolean
|
|
|
39
39
|
console.log(
|
|
40
40
|
formatOutput(
|
|
41
41
|
{
|
|
42
|
-
error:
|
|
42
|
+
error: getNoDiscordTokenFoundMessage(),
|
|
43
43
|
hint: options.debug ? undefined : 'Run with --debug for more info.',
|
|
44
44
|
},
|
|
45
45
|
options.pretty,
|
|
@@ -121,7 +121,7 @@ export async function extractAction(options: { pretty?: boolean; debug?: boolean
|
|
|
121
121
|
formatOutput(
|
|
122
122
|
{
|
|
123
123
|
error: 'No usable Discord token found. Tokens may be expired or have no servers.',
|
|
124
|
-
hint: 'Make sure Discord is logged in and you are a member of at least one server.',
|
|
124
|
+
hint: 'Make sure Discord is logged in to the desktop app or a supported Chromium browser, and that you are a member of at least one server.',
|
|
125
125
|
},
|
|
126
126
|
options.pretty,
|
|
127
127
|
),
|
|
@@ -184,11 +184,15 @@ export async function statusAction(options: { pretty?: boolean }): Promise<void>
|
|
|
184
184
|
}
|
|
185
185
|
}
|
|
186
186
|
|
|
187
|
+
export function getNoDiscordTokenFoundMessage(): string {
|
|
188
|
+
return 'No Discord token found. Make sure Discord is logged in to the desktop app or a supported Chromium browser.'
|
|
189
|
+
}
|
|
190
|
+
|
|
187
191
|
export const authCommand = new Command('auth')
|
|
188
192
|
.description('Authentication commands')
|
|
189
193
|
.addCommand(
|
|
190
194
|
new Command('extract')
|
|
191
|
-
.description('Extract token from Discord desktop app')
|
|
195
|
+
.description('Extract token from Discord desktop app or a supported Chromium browser')
|
|
192
196
|
.option('--pretty', 'Pretty print JSON output')
|
|
193
197
|
.option('--debug', 'Show debug output for troubleshooting')
|
|
194
198
|
.action(extractAction),
|
|
@@ -40,7 +40,7 @@ const program = new Command()
|
|
|
40
40
|
|
|
41
41
|
program
|
|
42
42
|
.name('agent-slack')
|
|
43
|
-
.description('CLI tool for Slack communication with token extraction from
|
|
43
|
+
.description('CLI tool for Slack communication with token extraction from the desktop app or a supported Chromium browser')
|
|
44
44
|
.version(pkg.version)
|
|
45
45
|
.option('--workspace <id>', 'Use specific workspace')
|
|
46
46
|
|
|
@@ -62,7 +62,7 @@ export class SlackClient {
|
|
|
62
62
|
const workspace = await credManager.getWorkspace()
|
|
63
63
|
if (!workspace) {
|
|
64
64
|
throw new SlackError(
|
|
65
|
-
'No workspace credentials found. Make sure Slack desktop app
|
|
65
|
+
'No workspace credentials found. Make sure Slack is logged in in the desktop app or a supported Chromium browser.',
|
|
66
66
|
'no_credentials',
|
|
67
67
|
)
|
|
68
68
|
}
|
|
@@ -3,7 +3,11 @@ import { mkdirSync, rmSync } from 'node:fs'
|
|
|
3
3
|
import { homedir } from 'node:os'
|
|
4
4
|
import { join } from 'node:path'
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
formatCredentialDebug,
|
|
8
|
+
getExtractionErrorMessage,
|
|
9
|
+
getNoWorkspacesFoundMessage,
|
|
10
|
+
} from '@/platforms/slack/commands/auth'
|
|
7
11
|
import { CredentialManager } from '@/platforms/slack/credential-manager'
|
|
8
12
|
import { type ExtractedWorkspace, TokenExtractor } from '@/platforms/slack/token-extractor'
|
|
9
13
|
|
|
@@ -402,23 +406,44 @@ describe('formatCredentialDebug', () => {
|
|
|
402
406
|
|
|
403
407
|
describe('getExtractionErrorMessage', () => {
|
|
404
408
|
test('returns cookie failure message for missing_cookie', () => {
|
|
405
|
-
|
|
409
|
+
const message = getExtractionErrorMessage(['missing_cookie'])
|
|
410
|
+
|
|
411
|
+
expect(message).toContain('Cookie extraction failed')
|
|
412
|
+
expect(message).toContain('desktop app or a supported Chromium browser')
|
|
406
413
|
})
|
|
407
414
|
|
|
408
415
|
test('returns session expired message for invalid_auth', () => {
|
|
409
|
-
|
|
416
|
+
const message = getExtractionErrorMessage(['invalid_auth'])
|
|
417
|
+
|
|
418
|
+
expect(message).toContain('session has expired')
|
|
419
|
+
expect(message).toContain('desktop app or a supported Chromium browser')
|
|
410
420
|
})
|
|
411
421
|
|
|
412
422
|
test('prioritizes missing_cookie over invalid_auth', () => {
|
|
413
|
-
|
|
423
|
+
const message = getExtractionErrorMessage(['invalid_auth', 'missing_cookie'])
|
|
424
|
+
|
|
425
|
+
expect(message).toContain('Cookie extraction failed')
|
|
426
|
+
expect(message).toContain('desktop app or a supported Chromium browser')
|
|
414
427
|
})
|
|
415
428
|
|
|
416
429
|
test('returns generic message for unknown error codes', () => {
|
|
417
|
-
|
|
430
|
+
const message = getExtractionErrorMessage(['unknown_error'])
|
|
431
|
+
|
|
432
|
+
expect(message).toContain('Extracted tokens are invalid')
|
|
433
|
+
expect(message).toContain('desktop app or a supported Chromium browser')
|
|
418
434
|
})
|
|
419
435
|
|
|
420
436
|
test('returns generic message for empty failure list', () => {
|
|
421
|
-
|
|
437
|
+
const message = getExtractionErrorMessage([])
|
|
438
|
+
|
|
439
|
+
expect(message).toContain('Extracted tokens are invalid')
|
|
440
|
+
expect(message).toContain('desktop app or a supported Chromium browser')
|
|
441
|
+
})
|
|
442
|
+
})
|
|
443
|
+
|
|
444
|
+
describe('getNoWorkspacesFoundMessage', () => {
|
|
445
|
+
test('mentions desktop app and browser fallback', () => {
|
|
446
|
+
expect(getNoWorkspacesFoundMessage()).toContain('desktop app or a supported Chromium browser')
|
|
422
447
|
})
|
|
423
448
|
})
|
|
424
449
|
|
|
@@ -61,7 +61,7 @@ async function extractAction(options: {
|
|
|
61
61
|
console.log(
|
|
62
62
|
formatOutput(
|
|
63
63
|
{
|
|
64
|
-
error:
|
|
64
|
+
error: getNoWorkspacesFoundMessage(),
|
|
65
65
|
hint: options.debug ? undefined : 'Run with --debug for more info.',
|
|
66
66
|
},
|
|
67
67
|
options.pretty,
|
|
@@ -227,19 +227,23 @@ async function statusAction(options: { pretty?: boolean }): Promise<void> {
|
|
|
227
227
|
|
|
228
228
|
export function getExtractionErrorMessage(failureReasons: string[]): string {
|
|
229
229
|
if (failureReasons.includes('missing_cookie')) {
|
|
230
|
-
return 'Cookie extraction failed.
|
|
230
|
+
return 'Cookie extraction failed. Grant Keychain access when prompted, and make sure you are signed into Slack in the desktop app or a supported Chromium browser.'
|
|
231
231
|
}
|
|
232
232
|
if (failureReasons.includes('invalid_auth')) {
|
|
233
|
-
return 'Slack session has expired. Sign into the
|
|
233
|
+
return 'Slack session has expired. Sign into Slack in the desktop app or a supported Chromium browser, wait a few seconds, then re-run this command.'
|
|
234
234
|
}
|
|
235
|
-
return 'Extracted tokens are invalid. Make sure you are logged into the
|
|
235
|
+
return 'Extracted tokens are invalid. Make sure you are logged into Slack in the desktop app or a supported Chromium browser.'
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
export function getNoWorkspacesFoundMessage(): string {
|
|
239
|
+
return 'No workspaces found. Make sure you are logged into Slack in the desktop app or a supported Chromium browser.'
|
|
236
240
|
}
|
|
237
241
|
|
|
238
242
|
export const authCommand = new Command('auth')
|
|
239
243
|
.description('Authentication commands')
|
|
240
244
|
.addCommand(
|
|
241
245
|
new Command('extract')
|
|
242
|
-
.description('Extract tokens from Slack desktop app')
|
|
246
|
+
.description('Extract tokens from Slack desktop app or a supported Chromium browser')
|
|
243
247
|
.option('--pretty', 'Pretty print JSON output')
|
|
244
248
|
.option('--debug', 'Show debug output for troubleshooting')
|
|
245
249
|
.option('--unsafely-show-secrets', 'Show full token and cookie values in debug output')
|
|
@@ -39,7 +39,7 @@ export class TeamsClient {
|
|
|
39
39
|
const creds = await credManager.getTokenWithExpiry()
|
|
40
40
|
if (!creds) {
|
|
41
41
|
throw new TeamsError(
|
|
42
|
-
'No Teams credentials found. Make sure Microsoft Teams desktop app
|
|
42
|
+
'No Teams credentials found. Make sure Microsoft Teams is logged in via the desktop app or a supported Chromium browser.',
|
|
43
43
|
'no_credentials',
|
|
44
44
|
)
|
|
45
45
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { afterEach, beforeEach, expect, spyOn, test } from 'bun:test'
|
|
2
2
|
|
|
3
|
+
import { getNoTeamsTokenFoundMessage } from './auth'
|
|
3
4
|
import { TeamsClient } from '../client'
|
|
4
5
|
import { TeamsCredentialManager } from '../credential-manager'
|
|
5
6
|
import { TeamsTokenExtractor } from '../token-extractor'
|
|
@@ -89,3 +90,7 @@ test('status: checks token expiry', async () => {
|
|
|
89
90
|
const isExpired = await credManager.isTokenExpired()
|
|
90
91
|
expect(isExpired).toBe(false)
|
|
91
92
|
})
|
|
93
|
+
|
|
94
|
+
test('no-token message mentions desktop app and browser fallback', () => {
|
|
95
|
+
expect(getNoTeamsTokenFoundMessage()).toContain('desktop app or a supported Chromium browser')
|
|
96
|
+
})
|
|
@@ -45,7 +45,7 @@ export async function extractAction(options: { pretty?: boolean; debug?: boolean
|
|
|
45
45
|
console.log(
|
|
46
46
|
formatOutput(
|
|
47
47
|
{
|
|
48
|
-
error:
|
|
48
|
+
error: getNoTeamsTokenFoundMessage(),
|
|
49
49
|
hint: 'Run with --token <token> to manually provide a token, or --debug for more info.',
|
|
50
50
|
},
|
|
51
51
|
options.pretty,
|
|
@@ -116,8 +116,8 @@ export async function extractAction(options: { pretty?: boolean; debug?: boolean
|
|
|
116
116
|
{
|
|
117
117
|
error: `Token validation failed: ${errorMessage}`,
|
|
118
118
|
hint: is401
|
|
119
|
-
? 'Token expired. Open Microsoft Teams, send a message to refresh your session, then run "auth extract" again.'
|
|
120
|
-
: 'Make sure Microsoft Teams
|
|
119
|
+
? 'Token expired. Open Microsoft Teams in the desktop app or a supported Chromium browser, send a message to refresh your session, then run "auth extract" again.'
|
|
120
|
+
: 'Make sure Microsoft Teams is running and you are logged in via the desktop app or a supported Chromium browser.',
|
|
121
121
|
},
|
|
122
122
|
options.pretty,
|
|
123
123
|
),
|
|
@@ -130,7 +130,10 @@ export async function extractAction(options: { pretty?: boolean; debug?: boolean
|
|
|
130
130
|
if (Object.keys(config.accounts).length === 0) {
|
|
131
131
|
console.log(
|
|
132
132
|
formatOutput(
|
|
133
|
-
{
|
|
133
|
+
{
|
|
134
|
+
error:
|
|
135
|
+
'All extracted tokens failed validation. Make sure Microsoft Teams is running and you are logged in via the desktop app or a supported Chromium browser.',
|
|
136
|
+
},
|
|
134
137
|
options.pretty,
|
|
135
138
|
),
|
|
136
139
|
)
|
|
@@ -229,8 +232,8 @@ async function extractManualToken(token: string, options: { pretty?: boolean; de
|
|
|
229
232
|
{
|
|
230
233
|
error: `Token validation failed: ${errorMessage}`,
|
|
231
234
|
hint: is401
|
|
232
|
-
? 'Token expired. Open Microsoft Teams, send a message to refresh your session, then run "auth extract" again.'
|
|
233
|
-
: 'Make sure Microsoft Teams
|
|
235
|
+
? 'Token expired. Open Microsoft Teams in the desktop app or a supported Chromium browser, send a message to refresh your session, then run "auth extract" again.'
|
|
236
|
+
: 'Make sure Microsoft Teams is running and you are logged in via the desktop app or a supported Chromium browser.',
|
|
234
237
|
},
|
|
235
238
|
options.pretty,
|
|
236
239
|
),
|
|
@@ -239,6 +242,10 @@ async function extractManualToken(token: string, options: { pretty?: boolean; de
|
|
|
239
242
|
}
|
|
240
243
|
}
|
|
241
244
|
|
|
245
|
+
export function getNoTeamsTokenFoundMessage(): string {
|
|
246
|
+
return 'No Teams token found. Make sure you are logged in to Microsoft Teams via the desktop app or a supported Chromium browser.'
|
|
247
|
+
}
|
|
248
|
+
|
|
242
249
|
export async function logoutAction(options: { pretty?: boolean }): Promise<void> {
|
|
243
250
|
try {
|
|
244
251
|
const credManager = new TeamsCredentialManager()
|
|
@@ -361,7 +368,7 @@ export const authCommand = new Command('auth')
|
|
|
361
368
|
.description('Authentication commands')
|
|
362
369
|
.addCommand(
|
|
363
370
|
new Command('extract')
|
|
364
|
-
.description('Extract token from Microsoft Teams desktop app')
|
|
371
|
+
.description('Extract token from Microsoft Teams desktop app or a supported Chromium browser')
|
|
365
372
|
.option('--pretty', 'Pretty print JSON output')
|
|
366
373
|
.option('--debug', 'Show debug output for troubleshooting')
|
|
367
374
|
.option('--token <token>', 'Manually provide a token (bypasses auto-extraction)')
|
|
@@ -438,6 +438,16 @@ export class WebexClient {
|
|
|
438
438
|
return data.items
|
|
439
439
|
}
|
|
440
440
|
|
|
441
|
+
async listMyMemberships(options?: { max?: number }): Promise<WebexMembership[]> {
|
|
442
|
+
const params = new URLSearchParams()
|
|
443
|
+
params.set('max', String(options?.max ?? 100))
|
|
444
|
+
const data = await this.request<{ items: WebexMembership[] }>(
|
|
445
|
+
'GET',
|
|
446
|
+
`/memberships?${params}`,
|
|
447
|
+
)
|
|
448
|
+
return data.items
|
|
449
|
+
}
|
|
450
|
+
|
|
441
451
|
async listMemberships(
|
|
442
452
|
roomId: string,
|
|
443
453
|
options?: { max?: number },
|