agent-messenger 2.8.0 → 2.10.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/README.md +0 -11
- package/dist/package.json +1 -1
- package/dist/src/platforms/channeltalk/commands/snapshot.d.ts +4 -2
- package/dist/src/platforms/channeltalk/commands/snapshot.d.ts.map +1 -1
- package/dist/src/platforms/channeltalk/commands/snapshot.js +86 -31
- package/dist/src/platforms/channeltalk/commands/snapshot.js.map +1 -1
- package/dist/src/platforms/channeltalkbot/commands/snapshot.d.ts +3 -1
- package/dist/src/platforms/channeltalkbot/commands/snapshot.d.ts.map +1 -1
- package/dist/src/platforms/channeltalkbot/commands/snapshot.js +110 -60
- package/dist/src/platforms/channeltalkbot/commands/snapshot.js.map +1 -1
- package/dist/src/platforms/discord/commands/snapshot.d.ts +1 -0
- package/dist/src/platforms/discord/commands/snapshot.d.ts.map +1 -1
- package/dist/src/platforms/discord/commands/snapshot.js +48 -34
- package/dist/src/platforms/discord/commands/snapshot.js.map +1 -1
- package/dist/src/platforms/discordbot/commands/snapshot.d.ts +2 -0
- package/dist/src/platforms/discordbot/commands/snapshot.d.ts.map +1 -1
- package/dist/src/platforms/discordbot/commands/snapshot.js +46 -34
- package/dist/src/platforms/discordbot/commands/snapshot.js.map +1 -1
- package/dist/src/platforms/slack/commands/snapshot.d.ts.map +1 -1
- package/dist/src/platforms/slack/commands/snapshot.js +75 -55
- package/dist/src/platforms/slack/commands/snapshot.js.map +1 -1
- package/dist/src/platforms/teams/client.d.ts +9 -1
- package/dist/src/platforms/teams/client.d.ts.map +1 -1
- package/dist/src/platforms/teams/client.js +69 -18
- package/dist/src/platforms/teams/client.js.map +1 -1
- package/dist/src/platforms/teams/commands/auth.d.ts.map +1 -1
- package/dist/src/platforms/teams/commands/auth.js +7 -2
- package/dist/src/platforms/teams/commands/auth.js.map +1 -1
- package/dist/src/platforms/teams/commands/channel.d.ts.map +1 -1
- package/dist/src/platforms/teams/commands/channel.js +18 -3
- package/dist/src/platforms/teams/commands/channel.js.map +1 -1
- package/dist/src/platforms/teams/commands/file.d.ts.map +1 -1
- package/dist/src/platforms/teams/commands/file.js +18 -3
- package/dist/src/platforms/teams/commands/file.js.map +1 -1
- package/dist/src/platforms/teams/commands/message.d.ts.map +1 -1
- package/dist/src/platforms/teams/commands/message.js +24 -4
- package/dist/src/platforms/teams/commands/message.js.map +1 -1
- package/dist/src/platforms/teams/commands/reaction.d.ts.map +1 -1
- package/dist/src/platforms/teams/commands/reaction.js +12 -2
- package/dist/src/platforms/teams/commands/reaction.js.map +1 -1
- package/dist/src/platforms/teams/commands/snapshot.d.ts +1 -0
- package/dist/src/platforms/teams/commands/snapshot.d.ts.map +1 -1
- package/dist/src/platforms/teams/commands/snapshot.js +50 -32
- package/dist/src/platforms/teams/commands/snapshot.js.map +1 -1
- package/dist/src/platforms/teams/commands/team.d.ts.map +1 -1
- package/dist/src/platforms/teams/commands/team.js +6 -1
- package/dist/src/platforms/teams/commands/team.js.map +1 -1
- package/dist/src/platforms/teams/commands/user.d.ts.map +1 -1
- package/dist/src/platforms/teams/commands/user.js +18 -3
- package/dist/src/platforms/teams/commands/user.js.map +1 -1
- package/dist/src/platforms/teams/commands/whoami.d.ts.map +1 -1
- package/dist/src/platforms/teams/commands/whoami.js +6 -1
- package/dist/src/platforms/teams/commands/whoami.js.map +1 -1
- package/dist/src/platforms/teams/credential-manager.d.ts +3 -1
- package/dist/src/platforms/teams/credential-manager.d.ts.map +1 -1
- package/dist/src/platforms/teams/credential-manager.js +6 -1
- package/dist/src/platforms/teams/credential-manager.js.map +1 -1
- package/dist/src/platforms/teams/ensure-auth.d.ts.map +1 -1
- package/dist/src/platforms/teams/ensure-auth.js +7 -2
- package/dist/src/platforms/teams/ensure-auth.js.map +1 -1
- package/dist/src/platforms/teams/token-extractor.d.ts +3 -1
- package/dist/src/platforms/teams/token-extractor.d.ts.map +1 -1
- package/dist/src/platforms/teams/token-extractor.js +67 -10
- package/dist/src/platforms/teams/token-extractor.js.map +1 -1
- package/dist/src/platforms/teams/types.d.ts +17 -0
- package/dist/src/platforms/teams/types.d.ts.map +1 -1
- package/dist/src/platforms/teams/types.js +2 -0
- package/dist/src/platforms/teams/types.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 +58 -13
- package/dist/src/platforms/webex/client.js.map +1 -1
- package/dist/src/platforms/webex/commands/auth.d.ts.map +1 -1
- package/dist/src/platforms/webex/commands/auth.js +61 -10
- package/dist/src/platforms/webex/commands/auth.js.map +1 -1
- package/dist/src/platforms/webex/commands/snapshot.d.ts +1 -0
- package/dist/src/platforms/webex/commands/snapshot.d.ts.map +1 -1
- package/dist/src/platforms/webex/commands/snapshot.js +14 -7
- package/dist/src/platforms/webex/commands/snapshot.js.map +1 -1
- package/dist/src/platforms/webex/credential-manager.d.ts.map +1 -1
- package/dist/src/platforms/webex/credential-manager.js +18 -6
- package/dist/src/platforms/webex/credential-manager.js.map +1 -1
- package/dist/src/platforms/webex/encryption.d.ts.map +1 -1
- package/dist/src/platforms/webex/encryption.js +3 -1
- package/dist/src/platforms/webex/encryption.js.map +1 -1
- package/dist/src/platforms/webex/ensure-auth.d.ts.map +1 -1
- package/dist/src/platforms/webex/ensure-auth.js +10 -2
- package/dist/src/platforms/webex/ensure-auth.js.map +1 -1
- package/dist/src/platforms/webex/token-extractor.d.ts +1 -0
- package/dist/src/platforms/webex/token-extractor.d.ts.map +1 -1
- package/dist/src/platforms/webex/token-extractor.js +21 -4
- package/dist/src/platforms/webex/token-extractor.js.map +1 -1
- package/docs/content/docs/agent-skills.mdx +0 -10
- package/docs/content/docs/cli/channeltalk.mdx +18 -8
- package/docs/content/docs/cli/channeltalkbot.mdx +16 -6
- package/docs/content/docs/cli/discord.mdx +23 -7
- package/docs/content/docs/cli/discordbot.mdx +23 -7
- package/docs/content/docs/cli/slack.mdx +24 -7
- package/docs/content/docs/cli/teams.mdx +24 -8
- package/docs/content/docs/cli/webex.mdx +15 -2
- package/e2e/webex.e2e.test.ts +57 -0
- package/package.json +1 -1
- package/skills/agent-channeltalk/SKILL.md +19 -9
- package/skills/agent-channeltalk/references/common-patterns.md +10 -9
- package/skills/agent-channeltalkbot/SKILL.md +19 -9
- package/skills/agent-channeltalkbot/references/common-patterns.md +10 -9
- package/skills/agent-discord/SKILL.md +18 -9
- package/skills/agent-discord/references/common-patterns.md +8 -7
- package/skills/agent-discordbot/SKILL.md +18 -9
- 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 +19 -10
- package/skills/agent-slack/references/common-patterns.md +4 -7
- package/skills/agent-slackbot/SKILL.md +1 -1
- package/skills/agent-teams/SKILL.md +18 -9
- package/skills/agent-teams/references/common-patterns.md +9 -7
- package/skills/agent-telegram/SKILL.md +1 -1
- package/skills/agent-webex/SKILL.md +13 -4
- package/skills/agent-webex/references/common-patterns.md +8 -2
- 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/commands/snapshot.test.ts +58 -26
- package/src/platforms/channeltalk/commands/snapshot.ts +107 -33
- package/src/platforms/channeltalkbot/commands/snapshot.test.ts +26 -8
- package/src/platforms/channeltalkbot/commands/snapshot.ts +131 -64
- package/src/platforms/discord/commands/snapshot.test.ts +1 -1
- package/src/platforms/discord/commands/snapshot.ts +58 -42
- package/src/platforms/discordbot/commands/snapshot.test.ts +40 -18
- package/src/platforms/discordbot/commands/snapshot.ts +54 -37
- package/src/platforms/slack/commands/snapshot.test.ts +63 -8
- package/src/platforms/slack/commands/snapshot.ts +98 -66
- package/src/platforms/teams/client.test.ts +34 -30
- package/src/platforms/teams/client.ts +92 -20
- package/src/platforms/teams/commands/auth.test.ts +6 -2
- package/src/platforms/teams/commands/auth.ts +7 -2
- package/src/platforms/teams/commands/channel.test.ts +6 -6
- package/src/platforms/teams/commands/channel.ts +18 -3
- package/src/platforms/teams/commands/file.ts +18 -3
- package/src/platforms/teams/commands/message.ts +24 -4
- package/src/platforms/teams/commands/reaction.ts +12 -2
- package/src/platforms/teams/commands/snapshot.test.ts +1 -1
- package/src/platforms/teams/commands/snapshot.ts +59 -39
- package/src/platforms/teams/commands/team.test.ts +2 -2
- package/src/platforms/teams/commands/team.ts +6 -1
- package/src/platforms/teams/commands/user.ts +18 -3
- package/src/platforms/teams/commands/whoami.ts +6 -1
- package/src/platforms/teams/credential-manager.test.ts +25 -0
- package/src/platforms/teams/credential-manager.ts +13 -3
- package/src/platforms/teams/ensure-auth.test.ts +6 -1
- package/src/platforms/teams/ensure-auth.ts +7 -2
- package/src/platforms/teams/token-extractor.ts +77 -12
- package/src/platforms/teams/types.test.ts +17 -0
- package/src/platforms/teams/types.ts +6 -0
- package/src/platforms/webex/client.test.ts +157 -13
- package/src/platforms/webex/client.ts +64 -15
- package/src/platforms/webex/commands/auth.test.ts +122 -1
- package/src/platforms/webex/commands/auth.ts +72 -17
- package/src/platforms/webex/commands/snapshot.test.ts +14 -1
- package/src/platforms/webex/commands/snapshot.ts +17 -9
- package/src/platforms/webex/credential-manager.test.ts +63 -0
- package/src/platforms/webex/credential-manager.ts +22 -8
- package/src/platforms/webex/encryption.test.ts +54 -0
- package/src/platforms/webex/encryption.ts +3 -1
- package/src/platforms/webex/ensure-auth.ts +10 -2
- package/src/platforms/webex/token-extractor.test.ts +32 -3
- package/src/platforms/webex/token-extractor.ts +26 -5
|
@@ -8,7 +8,7 @@ test('snapshot: command is defined', () => {
|
|
|
8
8
|
})
|
|
9
9
|
|
|
10
10
|
test('snapshot: command has correct description', () => {
|
|
11
|
-
expect(snapshotCommand.description()).toContain('server
|
|
11
|
+
expect(snapshotCommand.description()).toContain('server overview')
|
|
12
12
|
})
|
|
13
13
|
|
|
14
14
|
test('snapshot: command has --channels-only option', () => {
|
|
@@ -11,6 +11,7 @@ import type { DiscordChannel } from '../types'
|
|
|
11
11
|
export async function snapshotAction(options: {
|
|
12
12
|
channelsOnly?: boolean
|
|
13
13
|
usersOnly?: boolean
|
|
14
|
+
full?: boolean
|
|
14
15
|
limit?: number
|
|
15
16
|
pretty?: boolean
|
|
16
17
|
}): Promise<void> {
|
|
@@ -25,7 +26,6 @@ export async function snapshotAction(options: {
|
|
|
25
26
|
|
|
26
27
|
const client = await new DiscordClient().login({ token: config.token as string })
|
|
27
28
|
const serverId = config.current_server as string
|
|
28
|
-
const messageLimit = options.limit || 20
|
|
29
29
|
|
|
30
30
|
const snapshot: Record<string, any> = {}
|
|
31
31
|
|
|
@@ -35,51 +35,65 @@ export async function snapshotAction(options: {
|
|
|
35
35
|
name: server.name,
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
const isFull = options.full || options.channelsOnly || options.usersOnly
|
|
39
|
+
if (isFull) {
|
|
40
|
+
const messageLimit = options.limit || 20
|
|
40
41
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
name: ch.name,
|
|
44
|
-
type: ch.type,
|
|
45
|
-
topic: ch.topic,
|
|
46
|
-
}))
|
|
42
|
+
if (!options.usersOnly) {
|
|
43
|
+
const channels = await client.listChannels(serverId)
|
|
47
44
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
textChannels,
|
|
54
|
-
async (channel: DiscordChannel) => {
|
|
55
|
-
const messages = await client.getMessages(channel.id, messageLimit)
|
|
56
|
-
return messages.map((msg) => ({
|
|
57
|
-
...msg,
|
|
58
|
-
channel_name: channel.name,
|
|
59
|
-
}))
|
|
60
|
-
},
|
|
61
|
-
5,
|
|
62
|
-
)
|
|
63
|
-
|
|
64
|
-
snapshot.recent_messages = channelMessages.flat().map((msg) => ({
|
|
65
|
-
channel_id: msg.channel_id,
|
|
66
|
-
channel_name: msg.channel_name,
|
|
67
|
-
id: msg.id,
|
|
68
|
-
author: msg.author.username,
|
|
69
|
-
content: msg.content,
|
|
70
|
-
timestamp: msg.timestamp,
|
|
45
|
+
snapshot.channels = channels.map((ch) => ({
|
|
46
|
+
id: ch.id,
|
|
47
|
+
name: ch.name,
|
|
48
|
+
type: ch.type,
|
|
49
|
+
topic: ch.topic,
|
|
71
50
|
}))
|
|
51
|
+
|
|
52
|
+
if (!options.channelsOnly) {
|
|
53
|
+
const isTextChannel = (ch: DiscordChannel) => ch.type === 0 || ch.type === 5
|
|
54
|
+
const textChannels = channels.filter(isTextChannel)
|
|
55
|
+
|
|
56
|
+
const channelMessages = await parallelMap(
|
|
57
|
+
textChannels,
|
|
58
|
+
async (channel: DiscordChannel) => {
|
|
59
|
+
const messages = await client.getMessages(channel.id, messageLimit)
|
|
60
|
+
return messages.map((msg) => ({
|
|
61
|
+
...msg,
|
|
62
|
+
channel_name: channel.name,
|
|
63
|
+
}))
|
|
64
|
+
},
|
|
65
|
+
5,
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
snapshot.recent_messages = channelMessages.flat().map((msg) => ({
|
|
69
|
+
channel_id: msg.channel_id,
|
|
70
|
+
channel_name: msg.channel_name,
|
|
71
|
+
id: msg.id,
|
|
72
|
+
author: msg.author.username,
|
|
73
|
+
content: msg.content,
|
|
74
|
+
timestamp: msg.timestamp,
|
|
75
|
+
}))
|
|
76
|
+
}
|
|
72
77
|
}
|
|
73
|
-
}
|
|
74
78
|
|
|
75
|
-
|
|
76
|
-
|
|
79
|
+
if (!options.channelsOnly) {
|
|
80
|
+
const users = await client.listUsers(serverId)
|
|
81
|
+
|
|
82
|
+
snapshot.members = users.map((u) => ({
|
|
83
|
+
id: u.id,
|
|
84
|
+
username: u.username,
|
|
85
|
+
global_name: u.global_name || null,
|
|
86
|
+
}))
|
|
87
|
+
}
|
|
88
|
+
} else {
|
|
89
|
+
if (!options.usersOnly) {
|
|
90
|
+
const channels = await client.listChannels(serverId)
|
|
91
|
+
const textChannels = channels.filter((ch: DiscordChannel) => ch.type === 0 || ch.type === 5)
|
|
92
|
+
snapshot.channels = textChannels.map((ch) => ({ id: ch.id, name: ch.name }))
|
|
93
|
+
}
|
|
77
94
|
|
|
78
|
-
snapshot.
|
|
79
|
-
|
|
80
|
-
username: u.username,
|
|
81
|
-
global_name: u.global_name || null,
|
|
82
|
-
}))
|
|
95
|
+
snapshot.hint =
|
|
96
|
+
"Use 'message list <channel>' for messages, 'channel info <channel>' for channel details, 'user list' for members."
|
|
83
97
|
}
|
|
84
98
|
|
|
85
99
|
console.log(formatOutput(snapshot, options.pretty))
|
|
@@ -89,14 +103,16 @@ export async function snapshotAction(options: {
|
|
|
89
103
|
}
|
|
90
104
|
|
|
91
105
|
export const snapshotCommand = new Command('snapshot')
|
|
92
|
-
.description('Get
|
|
106
|
+
.description('Get server overview for AI agents (brief by default, use --full for comprehensive data)')
|
|
107
|
+
.option('--full', 'Include messages and members (verbose)')
|
|
93
108
|
.option('--channels-only', 'Include only channels (exclude messages and members)')
|
|
94
109
|
.option('--users-only', 'Include only members (exclude channels and messages)')
|
|
95
|
-
.option('--limit <n>', 'Number of recent messages per channel (default: 20)', '20')
|
|
110
|
+
.option('--limit <n>', 'Number of recent messages per channel with --full (default: 20)', '20')
|
|
96
111
|
.action(async (options) => {
|
|
97
112
|
await snapshotAction({
|
|
98
113
|
channelsOnly: options.channelsOnly,
|
|
99
114
|
usersOnly: options.usersOnly,
|
|
115
|
+
full: options.full,
|
|
100
116
|
limit: parseInt(options.limit, 10),
|
|
101
117
|
pretty: options.pretty,
|
|
102
118
|
})
|
|
@@ -86,23 +86,17 @@ describe('snapshot command', () => {
|
|
|
86
86
|
process.env = originalEnv
|
|
87
87
|
})
|
|
88
88
|
|
|
89
|
-
describe('default (
|
|
90
|
-
test('returns channels with
|
|
89
|
+
describe('default (brief)', () => {
|
|
90
|
+
test('returns channels with id and name only', async () => {
|
|
91
91
|
const manager = await setupManager(tempDir)
|
|
92
92
|
|
|
93
93
|
const result = await snapshotAction({ _credManager: manager })
|
|
94
94
|
|
|
95
95
|
expect(result.server_id).toBe('guild1')
|
|
96
96
|
expect(result.channels).toHaveLength(2)
|
|
97
|
-
expect(result.channels?.[0]
|
|
98
|
-
expect(result.channels?.[
|
|
99
|
-
expect(result.
|
|
100
|
-
expect(result.channels?.[0].messages?.[0]).toEqual({
|
|
101
|
-
id: 'msg1-ch1',
|
|
102
|
-
author: 'alice',
|
|
103
|
-
content: 'Hello from ch1',
|
|
104
|
-
timestamp: '2025-01-01T00:00:00Z',
|
|
105
|
-
})
|
|
97
|
+
expect(result.channels?.[0]).toEqual({ id: 'ch1', name: 'general' })
|
|
98
|
+
expect(result.channels?.[1]).toEqual({ id: 'ch2', name: 'random' })
|
|
99
|
+
expect(result.hint).toBeDefined()
|
|
106
100
|
})
|
|
107
101
|
|
|
108
102
|
test('filters out non-text channels', async () => {
|
|
@@ -114,11 +108,39 @@ describe('snapshot command', () => {
|
|
|
114
108
|
expect(channelNames).not.toContain('voice')
|
|
115
109
|
})
|
|
116
110
|
|
|
117
|
-
test('
|
|
111
|
+
test('does not fetch messages', async () => {
|
|
118
112
|
const manager = await setupManager(tempDir)
|
|
119
113
|
|
|
120
114
|
await snapshotAction({ _credManager: manager })
|
|
121
115
|
|
|
116
|
+
expect(mockGetMessages).not.toHaveBeenCalled()
|
|
117
|
+
})
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
describe('--full (channels + messages)', () => {
|
|
121
|
+
test('returns channels with recent messages', async () => {
|
|
122
|
+
const manager = await setupManager(tempDir)
|
|
123
|
+
|
|
124
|
+
const result = await snapshotAction({ _credManager: manager, full: true })
|
|
125
|
+
|
|
126
|
+
expect(result.server_id).toBe('guild1')
|
|
127
|
+
expect(result.channels).toHaveLength(2)
|
|
128
|
+
expect(result.channels?.[0].id).toBe('ch1')
|
|
129
|
+
expect(result.channels?.[0].name).toBe('general')
|
|
130
|
+
expect(result.channels?.[0].messages).toHaveLength(2)
|
|
131
|
+
expect(result.channels?.[0].messages?.[0]).toEqual({
|
|
132
|
+
id: 'msg1-ch1',
|
|
133
|
+
author: 'alice',
|
|
134
|
+
content: 'Hello from ch1',
|
|
135
|
+
timestamp: '2025-01-01T00:00:00Z',
|
|
136
|
+
})
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
test('fetches messages in parallel for all text channels', async () => {
|
|
140
|
+
const manager = await setupManager(tempDir)
|
|
141
|
+
|
|
142
|
+
await snapshotAction({ _credManager: manager, full: true })
|
|
143
|
+
|
|
122
144
|
expect(mockGetMessages).toHaveBeenCalledTimes(2)
|
|
123
145
|
expect(mockGetMessages).toHaveBeenCalledWith('ch1', 5)
|
|
124
146
|
expect(mockGetMessages).toHaveBeenCalledWith('ch2', 5)
|
|
@@ -127,7 +149,7 @@ describe('snapshot command', () => {
|
|
|
127
149
|
test('respects --limit option', async () => {
|
|
128
150
|
const manager = await setupManager(tempDir)
|
|
129
151
|
|
|
130
|
-
await snapshotAction({ _credManager: manager, limit: 10 })
|
|
152
|
+
await snapshotAction({ _credManager: manager, full: true, limit: 10 })
|
|
131
153
|
|
|
132
154
|
expect(mockGetMessages).toHaveBeenCalledWith('ch1', 10)
|
|
133
155
|
expect(mockGetMessages).toHaveBeenCalledWith('ch2', 10)
|
|
@@ -136,17 +158,17 @@ describe('snapshot command', () => {
|
|
|
136
158
|
test('defaults limit to 5', async () => {
|
|
137
159
|
const manager = await setupManager(tempDir)
|
|
138
160
|
|
|
139
|
-
await snapshotAction({ _credManager: manager })
|
|
161
|
+
await snapshotAction({ _credManager: manager, full: true })
|
|
140
162
|
|
|
141
163
|
expect(mockGetMessages).toHaveBeenCalledWith('ch1', 5)
|
|
142
164
|
})
|
|
143
165
|
})
|
|
144
166
|
|
|
145
|
-
describe('--channels-only', () => {
|
|
167
|
+
describe('--full --channels-only', () => {
|
|
146
168
|
test('returns only channel list without messages', async () => {
|
|
147
169
|
const manager = await setupManager(tempDir)
|
|
148
170
|
|
|
149
|
-
const result = await snapshotAction({ _credManager: manager, channelsOnly: true })
|
|
171
|
+
const result = await snapshotAction({ _credManager: manager, full: true, channelsOnly: true })
|
|
150
172
|
|
|
151
173
|
expect(result.server_id).toBe('guild1')
|
|
152
174
|
expect(result.channels).toHaveLength(2)
|
|
@@ -156,11 +178,11 @@ describe('snapshot command', () => {
|
|
|
156
178
|
})
|
|
157
179
|
})
|
|
158
180
|
|
|
159
|
-
describe('--users-only', () => {
|
|
181
|
+
describe('--full --users-only', () => {
|
|
160
182
|
test('returns only user list', async () => {
|
|
161
183
|
const manager = await setupManager(tempDir)
|
|
162
184
|
|
|
163
|
-
const result = await snapshotAction({ _credManager: manager, usersOnly: true })
|
|
185
|
+
const result = await snapshotAction({ _credManager: manager, full: true, usersOnly: true })
|
|
164
186
|
|
|
165
187
|
expect(result.server_id).toBe('guild1')
|
|
166
188
|
expect(result.users).toHaveLength(3)
|
|
@@ -10,6 +10,7 @@ import { getClient } from './shared'
|
|
|
10
10
|
interface SnapshotOption extends BotOption {
|
|
11
11
|
channelsOnly?: boolean
|
|
12
12
|
usersOnly?: boolean
|
|
13
|
+
full?: boolean
|
|
13
14
|
limit?: number
|
|
14
15
|
}
|
|
15
16
|
|
|
@@ -31,6 +32,7 @@ interface SnapshotResult {
|
|
|
31
32
|
username: string
|
|
32
33
|
global_name: string | null
|
|
33
34
|
}>
|
|
35
|
+
hint?: string
|
|
34
36
|
error?: string
|
|
35
37
|
}
|
|
36
38
|
|
|
@@ -43,53 +45,66 @@ export async function snapshotAction(options: SnapshotOption): Promise<SnapshotR
|
|
|
43
45
|
}
|
|
44
46
|
|
|
45
47
|
const client = await getClient(options)
|
|
46
|
-
const limit = options.limit ?? 5
|
|
47
48
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
49
|
+
const isFull = options.full || options.channelsOnly || options.usersOnly
|
|
50
|
+
if (isFull) {
|
|
51
|
+
const limit = options.limit ?? 5
|
|
52
|
+
|
|
53
|
+
if (options.usersOnly) {
|
|
54
|
+
const users = await client.listUsers(serverId)
|
|
55
|
+
return {
|
|
56
|
+
server_id: serverId,
|
|
57
|
+
users: users.map((u) => ({
|
|
58
|
+
id: u.id,
|
|
59
|
+
username: u.username,
|
|
60
|
+
global_name: u.global_name ?? null,
|
|
61
|
+
})),
|
|
62
|
+
}
|
|
57
63
|
}
|
|
58
|
-
}
|
|
59
64
|
|
|
60
|
-
|
|
61
|
-
|
|
65
|
+
const allChannels = await client.listChannels(serverId)
|
|
66
|
+
const textChannels = allChannels.filter((ch) => ch.type === 0)
|
|
67
|
+
|
|
68
|
+
if (options.channelsOnly) {
|
|
69
|
+
return {
|
|
70
|
+
server_id: serverId,
|
|
71
|
+
channels: textChannels.map((ch) => ({
|
|
72
|
+
id: ch.id,
|
|
73
|
+
name: ch.name,
|
|
74
|
+
type: ch.type,
|
|
75
|
+
})),
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const channelsWithMessages = await Promise.all(
|
|
80
|
+
textChannels.map(async (ch) => {
|
|
81
|
+
const messages = await client.getMessages(ch.id, limit)
|
|
82
|
+
return {
|
|
83
|
+
id: ch.id,
|
|
84
|
+
name: ch.name,
|
|
85
|
+
messages: messages.map((msg) => ({
|
|
86
|
+
id: msg.id,
|
|
87
|
+
author: msg.author.username,
|
|
88
|
+
content: msg.content,
|
|
89
|
+
timestamp: msg.timestamp,
|
|
90
|
+
})),
|
|
91
|
+
}
|
|
92
|
+
}),
|
|
93
|
+
)
|
|
62
94
|
|
|
63
|
-
if (options.channelsOnly) {
|
|
64
95
|
return {
|
|
65
96
|
server_id: serverId,
|
|
66
|
-
channels:
|
|
67
|
-
id: ch.id,
|
|
68
|
-
name: ch.name,
|
|
69
|
-
type: ch.type,
|
|
70
|
-
})),
|
|
97
|
+
channels: channelsWithMessages,
|
|
71
98
|
}
|
|
72
99
|
}
|
|
73
100
|
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
const messages = await client.getMessages(ch.id, limit)
|
|
77
|
-
return {
|
|
78
|
-
id: ch.id,
|
|
79
|
-
name: ch.name,
|
|
80
|
-
messages: messages.map((msg) => ({
|
|
81
|
-
id: msg.id,
|
|
82
|
-
author: msg.author.username,
|
|
83
|
-
content: msg.content,
|
|
84
|
-
timestamp: msg.timestamp,
|
|
85
|
-
})),
|
|
86
|
-
}
|
|
87
|
-
}),
|
|
88
|
-
)
|
|
101
|
+
const allChannels = await client.listChannels(serverId)
|
|
102
|
+
const textChannels = allChannels.filter((ch) => ch.type === 0)
|
|
89
103
|
|
|
90
104
|
return {
|
|
91
105
|
server_id: serverId,
|
|
92
|
-
channels:
|
|
106
|
+
channels: textChannels.map((ch) => ({ id: ch.id, name: ch.name })),
|
|
107
|
+
hint: "Use 'message list <channel>' for messages, 'channel info <channel>' for channel details, 'user list' for members.",
|
|
93
108
|
}
|
|
94
109
|
} catch (error) {
|
|
95
110
|
return { error: (error as Error).message }
|
|
@@ -97,10 +112,11 @@ export async function snapshotAction(options: SnapshotOption): Promise<SnapshotR
|
|
|
97
112
|
}
|
|
98
113
|
|
|
99
114
|
export const snapshotCommand = new Command('snapshot')
|
|
100
|
-
.description('Server overview for AI
|
|
115
|
+
.description('Server overview for AI agents (brief by default, use --full for comprehensive data)')
|
|
116
|
+
.option('--full', 'Include messages and members (verbose)')
|
|
101
117
|
.option('--channels-only', 'List channels only, skip messages')
|
|
102
118
|
.option('--users-only', 'List users only')
|
|
103
|
-
.option('--limit <n>', 'Messages per channel (default: 5)', '5')
|
|
119
|
+
.option('--limit <n>', 'Messages per channel with --full (default: 5)', '5')
|
|
104
120
|
.option('--server <id>', 'Use specific server')
|
|
105
121
|
.option('--bot <id>', 'Use specific bot')
|
|
106
122
|
.option('--pretty', 'Pretty print JSON output')
|
|
@@ -108,6 +124,7 @@ export const snapshotCommand = new Command('snapshot')
|
|
|
108
124
|
try {
|
|
109
125
|
const result = await snapshotAction({
|
|
110
126
|
...options,
|
|
127
|
+
full: options.full,
|
|
111
128
|
limit: parseInt(options.limit, 10),
|
|
112
129
|
})
|
|
113
130
|
console.log(formatOutput(result, options.pretty))
|
|
@@ -34,6 +34,12 @@ test('snapshot command has --limit option', () => {
|
|
|
34
34
|
expect(hasLimit).toBe(true)
|
|
35
35
|
})
|
|
36
36
|
|
|
37
|
+
test('snapshot command has --full option', () => {
|
|
38
|
+
const options = snapshotCommand.options
|
|
39
|
+
const hasFull = options.some((opt: any) => opt.long === '--full')
|
|
40
|
+
expect(hasFull).toBe(true)
|
|
41
|
+
})
|
|
42
|
+
|
|
37
43
|
// Test snapshot logic using spyOn (no global mock pollution)
|
|
38
44
|
let credManagerSpy: ReturnType<typeof spyOn>
|
|
39
45
|
let clientTestAuthSpy: ReturnType<typeof spyOn>
|
|
@@ -147,11 +153,66 @@ afterEach(() => {
|
|
|
147
153
|
clientGetMessagesSpy?.mockRestore()
|
|
148
154
|
})
|
|
149
155
|
|
|
156
|
+
test('brief snapshot (default) returns workspace, channels as {id, name}, and hint', async () => {
|
|
157
|
+
const client = await new SlackClient().login({ token: 'xoxc-test', cookie: 'test-cookie' })
|
|
158
|
+
|
|
159
|
+
const auth = await client.testAuth()
|
|
160
|
+
const channels = await client.listChannels()
|
|
161
|
+
const active = channels.filter((ch) => !ch.is_archived)
|
|
162
|
+
|
|
163
|
+
const snapshot = {
|
|
164
|
+
workspace: {
|
|
165
|
+
id: auth.team_id,
|
|
166
|
+
name: auth.team,
|
|
167
|
+
},
|
|
168
|
+
channels: active.map((ch) => ({ id: ch.id, name: ch.name })),
|
|
169
|
+
hint: "Use 'message list <channel>' for messages, 'channel info <channel>' for channel details, 'user list' for users, 'usergroup list' for groups.",
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
expect(snapshot.workspace).toBeDefined()
|
|
173
|
+
expect(snapshot.workspace.id).toBe('T123')
|
|
174
|
+
expect(snapshot.workspace.name).toBe('Test Workspace')
|
|
175
|
+
|
|
176
|
+
expect(snapshot.channels).toBeDefined()
|
|
177
|
+
expect(snapshot.channels.length).toBe(2)
|
|
178
|
+
expect(snapshot.channels[0]).toEqual({ id: 'C123', name: 'general' })
|
|
179
|
+
expect(snapshot.channels[1]).toEqual({ id: 'C456', name: 'random' })
|
|
180
|
+
|
|
181
|
+
expect((snapshot as any).recent_messages).toBeUndefined()
|
|
182
|
+
expect((snapshot as any).users).toBeUndefined()
|
|
183
|
+
expect((snapshot as any).usergroups).toBeUndefined()
|
|
184
|
+
|
|
185
|
+
expect(snapshot.hint).toContain('message list')
|
|
186
|
+
})
|
|
187
|
+
|
|
188
|
+
test('brief snapshot excludes archived channels', async () => {
|
|
189
|
+
const channelsWithArchived: SlackChannel[] = [
|
|
190
|
+
...mockChannels,
|
|
191
|
+
{
|
|
192
|
+
id: 'C789',
|
|
193
|
+
name: 'old-channel',
|
|
194
|
+
is_private: false,
|
|
195
|
+
is_archived: true,
|
|
196
|
+
created: 1234567800,
|
|
197
|
+
creator: 'U123',
|
|
198
|
+
topic: { value: 'Archived', creator: 'U123', last_set: 1234567800 },
|
|
199
|
+
purpose: { value: 'Old channel', creator: 'U123', last_set: 1234567800 },
|
|
200
|
+
},
|
|
201
|
+
]
|
|
202
|
+
|
|
203
|
+
clientListChannelsSpy.mockResolvedValue(channelsWithArchived)
|
|
204
|
+
|
|
205
|
+
const client = await new SlackClient().login({ token: 'xoxc-test', cookie: 'test-cookie' })
|
|
206
|
+
const channels = await client.listChannels()
|
|
207
|
+
const active = channels.filter((ch) => !ch.is_archived)
|
|
208
|
+
|
|
209
|
+
expect(active.length).toBe(2)
|
|
210
|
+
expect(active.every((ch) => !ch.is_archived)).toBe(true)
|
|
211
|
+
})
|
|
212
|
+
|
|
150
213
|
test('full snapshot returns workspace, channels, messages, and users', async () => {
|
|
151
|
-
const credManager = new CredentialManager()
|
|
152
214
|
const client = await new SlackClient().login({ token: 'xoxc-test', cookie: 'test-cookie' })
|
|
153
215
|
|
|
154
|
-
const _workspace = await credManager.getWorkspace()
|
|
155
216
|
const auth = await client.testAuth()
|
|
156
217
|
const channels = await client.listChannels()
|
|
157
218
|
const users = await client.listUsers()
|
|
@@ -218,10 +279,8 @@ test('full snapshot returns workspace, channels, messages, and users', async ()
|
|
|
218
279
|
})
|
|
219
280
|
|
|
220
281
|
test('snapshot with --channels-only excludes messages and users', async () => {
|
|
221
|
-
const credManager = new CredentialManager()
|
|
222
282
|
const client = await new SlackClient().login({ token: 'xoxc-test', cookie: 'test-cookie' })
|
|
223
283
|
|
|
224
|
-
const _workspace = await credManager.getWorkspace()
|
|
225
284
|
const auth = await client.testAuth()
|
|
226
285
|
const channels = await client.listChannels()
|
|
227
286
|
|
|
@@ -249,10 +308,8 @@ test('snapshot with --channels-only excludes messages and users', async () => {
|
|
|
249
308
|
})
|
|
250
309
|
|
|
251
310
|
test('snapshot with --users-only excludes channels and messages', async () => {
|
|
252
|
-
const credManager = new CredentialManager()
|
|
253
311
|
const client = await new SlackClient().login({ token: 'xoxc-test', cookie: 'test-cookie' })
|
|
254
312
|
|
|
255
|
-
const _workspace = await credManager.getWorkspace()
|
|
256
313
|
const auth = await client.testAuth()
|
|
257
314
|
const users = await client.listUsers()
|
|
258
315
|
|
|
@@ -279,10 +336,8 @@ test('snapshot with --users-only excludes channels and messages', async () => {
|
|
|
279
336
|
})
|
|
280
337
|
|
|
281
338
|
test('snapshot respects --limit option for messages', async () => {
|
|
282
|
-
const credManager = new CredentialManager()
|
|
283
339
|
const client = await new SlackClient().login({ token: 'xoxc-test', cookie: 'test-cookie' })
|
|
284
340
|
|
|
285
|
-
const _workspace = await credManager.getWorkspace()
|
|
286
341
|
const auth = await client.testAuth()
|
|
287
342
|
const channels = await client.listChannels()
|
|
288
343
|
|