agent-messenger 2.8.0 → 2.9.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/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 +44 -31
- package/dist/src/platforms/teams/commands/snapshot.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/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/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/commands/snapshot.test.ts +1 -1
- package/src/platforms/teams/commands/snapshot.ts +53 -38
- package/src/platforms/webex/commands/snapshot.test.ts +14 -1
- package/src/platforms/webex/commands/snapshot.ts +17 -9
|
@@ -67,10 +67,28 @@ describe('snapshot command', () => {
|
|
|
67
67
|
})
|
|
68
68
|
|
|
69
69
|
describe('snapshotAction', () => {
|
|
70
|
-
test('returns workspace, groups
|
|
70
|
+
test('brief snapshot returns workspace, groups (names), chat counts, and hint', async () => {
|
|
71
71
|
const manager = new ChannelBotCredentialManager(tempDir)
|
|
72
72
|
const result = await snapshotAction({ _credManager: manager })
|
|
73
73
|
|
|
74
|
+
expect(result.error).toBeUndefined()
|
|
75
|
+
expect(result.workspace).toBeDefined()
|
|
76
|
+
expect(result.workspace?.id).toBe('ch1')
|
|
77
|
+
expect(result.workspace?.name).toBe('Test Workspace')
|
|
78
|
+
expect(result.groups).toBeDefined()
|
|
79
|
+
expect(result.groups?.[0]).toEqual({ id: 'grp1', name: 'Team Alpha' })
|
|
80
|
+
expect(result.user_chats).toBeDefined()
|
|
81
|
+
expect(result.user_chats?.opened_count).toBe(1)
|
|
82
|
+
expect(result.hint).toBeDefined()
|
|
83
|
+
expect(result.managers).toBeUndefined()
|
|
84
|
+
expect(result.bots).toBeUndefined()
|
|
85
|
+
expect(mockGetGroupMessages).not.toHaveBeenCalled()
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
test('full snapshot returns workspace, groups, user_chats, managers, bots', async () => {
|
|
89
|
+
const manager = new ChannelBotCredentialManager(tempDir)
|
|
90
|
+
const result = await snapshotAction({ full: true, _credManager: manager })
|
|
91
|
+
|
|
74
92
|
expect(result.error).toBeUndefined()
|
|
75
93
|
expect(result.workspace).toBeDefined()
|
|
76
94
|
expect(result.workspace?.id).toBe('ch1')
|
|
@@ -83,7 +101,7 @@ describe('snapshot command', () => {
|
|
|
83
101
|
|
|
84
102
|
test('groups-only flag skips user_chats, managers, bots', async () => {
|
|
85
103
|
const manager = new ChannelBotCredentialManager(tempDir)
|
|
86
|
-
const result = await snapshotAction({ groupsOnly: true, _credManager: manager })
|
|
104
|
+
const result = await snapshotAction({ full: true, groupsOnly: true, _credManager: manager })
|
|
87
105
|
|
|
88
106
|
expect(result.error).toBeUndefined()
|
|
89
107
|
expect(result.workspace).toBeDefined()
|
|
@@ -95,7 +113,7 @@ describe('snapshot command', () => {
|
|
|
95
113
|
|
|
96
114
|
test('chats-only flag skips groups, managers, bots', async () => {
|
|
97
115
|
const manager = new ChannelBotCredentialManager(tempDir)
|
|
98
|
-
const result = await snapshotAction({ chatsOnly: true, _credManager: manager })
|
|
116
|
+
const result = await snapshotAction({ full: true, chatsOnly: true, _credManager: manager })
|
|
99
117
|
|
|
100
118
|
expect(result.error).toBeUndefined()
|
|
101
119
|
expect(result.workspace).toBeDefined()
|
|
@@ -105,21 +123,21 @@ describe('snapshot command', () => {
|
|
|
105
123
|
expect(result.bots).toBeUndefined()
|
|
106
124
|
})
|
|
107
125
|
|
|
108
|
-
test('groups include recent messages', async () => {
|
|
126
|
+
test('full groups include recent messages', async () => {
|
|
109
127
|
const manager = new ChannelBotCredentialManager(tempDir)
|
|
110
|
-
const result = await snapshotAction({ groupsOnly: true, limit: 3, _credManager: manager })
|
|
128
|
+
const result = await snapshotAction({ full: true, groupsOnly: true, limit: 3, _credManager: manager })
|
|
111
129
|
|
|
112
130
|
expect(result.groups?.[0].messages).toBeDefined()
|
|
113
131
|
expect(result.groups?.[0].messages?.[0].id).toBe('msg1')
|
|
114
132
|
})
|
|
115
133
|
|
|
116
|
-
test('user_chats includes counts and recent opened', async () => {
|
|
134
|
+
test('full user_chats includes counts and recent opened', async () => {
|
|
117
135
|
const manager = new ChannelBotCredentialManager(tempDir)
|
|
118
|
-
const result = await snapshotAction({ chatsOnly: true, _credManager: manager })
|
|
136
|
+
const result = await snapshotAction({ full: true, chatsOnly: true, _credManager: manager })
|
|
119
137
|
|
|
120
138
|
expect(result.user_chats?.opened_count).toBe(1)
|
|
121
139
|
expect(result.user_chats?.recent_opened).toHaveLength(1)
|
|
122
|
-
expect(result.user_chats?.recent_opened[0].id).toBe('chat1')
|
|
140
|
+
expect(result.user_chats?.recent_opened?.[0].id).toBe('chat1')
|
|
123
141
|
})
|
|
124
142
|
})
|
|
125
143
|
})
|
|
@@ -9,6 +9,7 @@ import { getClient } from './shared'
|
|
|
9
9
|
interface SnapshotOption extends WorkspaceOption {
|
|
10
10
|
groupsOnly?: boolean
|
|
11
11
|
chatsOnly?: boolean
|
|
12
|
+
full?: boolean
|
|
12
13
|
limit?: number
|
|
13
14
|
}
|
|
14
15
|
|
|
@@ -33,7 +34,7 @@ interface SnapshotResult {
|
|
|
33
34
|
opened_count: number
|
|
34
35
|
snoozed_count: number
|
|
35
36
|
closed_count: number
|
|
36
|
-
recent_opened
|
|
37
|
+
recent_opened?: Array<{
|
|
37
38
|
id: string
|
|
38
39
|
name?: string
|
|
39
40
|
user_id?: string
|
|
@@ -46,13 +47,13 @@ interface SnapshotResult {
|
|
|
46
47
|
}
|
|
47
48
|
managers?: Array<{ id: string; name: string; description?: string }>
|
|
48
49
|
bots?: Array<{ id: string; name: string }>
|
|
50
|
+
hint?: string
|
|
49
51
|
error?: string
|
|
50
52
|
}
|
|
51
53
|
|
|
52
54
|
export async function snapshotAction(options: SnapshotOption): Promise<SnapshotResult> {
|
|
53
55
|
try {
|
|
54
56
|
const client = await getClient(options)
|
|
55
|
-
const limit = options.limit ?? 5
|
|
56
57
|
|
|
57
58
|
const channel = await client.getChannel()
|
|
58
59
|
const workspace = {
|
|
@@ -62,71 +63,75 @@ export async function snapshotAction(options: SnapshotOption): Promise<SnapshotR
|
|
|
62
63
|
description: channel.description,
|
|
63
64
|
}
|
|
64
65
|
|
|
65
|
-
if (options.
|
|
66
|
-
|
|
67
|
-
const groupsWithMessages = await Promise.all(
|
|
68
|
-
groups.map(async (g) => {
|
|
69
|
-
const messages = await client.getGroupMessages(g.id, { limit, sortOrder: 'desc' })
|
|
70
|
-
return {
|
|
71
|
-
id: g.id,
|
|
72
|
-
name: g.name,
|
|
73
|
-
messages: messages.map((m) => ({
|
|
74
|
-
id: m.id,
|
|
75
|
-
person_type: m.personType,
|
|
76
|
-
plain_text: m.plainText,
|
|
77
|
-
created_at: m.createdAt,
|
|
78
|
-
})),
|
|
79
|
-
}
|
|
80
|
-
}),
|
|
81
|
-
)
|
|
82
|
-
return { workspace, groups: groupsWithMessages }
|
|
66
|
+
if (options.full) {
|
|
67
|
+
return buildFullSnapshot(client, workspace, options)
|
|
83
68
|
}
|
|
84
69
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
])
|
|
91
|
-
|
|
92
|
-
const recentOpened = await Promise.all(
|
|
93
|
-
openedChats.slice(0, 5).map(async (chat) => {
|
|
94
|
-
const messages = await client.getUserChatMessages(chat.id, { limit: 1, sortOrder: 'desc' })
|
|
95
|
-
return {
|
|
96
|
-
id: chat.id,
|
|
97
|
-
name: chat.name,
|
|
98
|
-
user_id: chat.userId,
|
|
99
|
-
last_message: messages[0]
|
|
100
|
-
? {
|
|
101
|
-
id: messages[0].id,
|
|
102
|
-
plain_text: messages[0].plainText,
|
|
103
|
-
created_at: messages[0].createdAt,
|
|
104
|
-
}
|
|
105
|
-
: undefined,
|
|
106
|
-
}
|
|
107
|
-
}),
|
|
108
|
-
)
|
|
70
|
+
return buildBriefSnapshot(client, workspace, options)
|
|
71
|
+
} catch (error) {
|
|
72
|
+
return { error: (error as Error).message }
|
|
73
|
+
}
|
|
74
|
+
}
|
|
109
75
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
76
|
+
async function buildBriefSnapshot(
|
|
77
|
+
client: Awaited<ReturnType<typeof getClient>>,
|
|
78
|
+
workspace: SnapshotResult['workspace'],
|
|
79
|
+
options: SnapshotOption,
|
|
80
|
+
): Promise<SnapshotResult> {
|
|
81
|
+
if (options.groupsOnly) {
|
|
82
|
+
const groups = await client.listGroups({ limit: 20 })
|
|
83
|
+
return {
|
|
84
|
+
workspace,
|
|
85
|
+
groups: groups.map((g) => ({ id: g.id, name: g.name })),
|
|
86
|
+
hint: "Use 'group messages <group>' for messages.",
|
|
119
87
|
}
|
|
88
|
+
}
|
|
120
89
|
|
|
121
|
-
|
|
122
|
-
|
|
90
|
+
if (options.chatsOnly) {
|
|
91
|
+
const [openedChats, snoozedChats, closedChats] = await Promise.all([
|
|
123
92
|
client.listUserChats({ state: 'opened', limit: 10, sortOrder: 'desc' }),
|
|
124
93
|
client.listUserChats({ state: 'snoozed', limit: 1 }),
|
|
125
94
|
client.listUserChats({ state: 'closed', limit: 1 }),
|
|
126
|
-
client.listManagers({ limit: 50 }),
|
|
127
|
-
client.listBots({ limit: 50 }),
|
|
128
95
|
])
|
|
96
|
+
return {
|
|
97
|
+
workspace,
|
|
98
|
+
user_chats: {
|
|
99
|
+
opened_count: openedChats.length,
|
|
100
|
+
snoozed_count: snoozedChats.length,
|
|
101
|
+
closed_count: closedChats.length,
|
|
102
|
+
},
|
|
103
|
+
hint: "Use 'chat list --state opened' for chat details, 'chat messages <chat>' for messages.",
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const [groups, openedChats, snoozedChats, closedChats] = await Promise.all([
|
|
108
|
+
client.listGroups({ limit: 20 }),
|
|
109
|
+
client.listUserChats({ state: 'opened', limit: 10, sortOrder: 'desc' }),
|
|
110
|
+
client.listUserChats({ state: 'snoozed', limit: 1 }),
|
|
111
|
+
client.listUserChats({ state: 'closed', limit: 1 }),
|
|
112
|
+
])
|
|
113
|
+
|
|
114
|
+
return {
|
|
115
|
+
workspace,
|
|
116
|
+
groups: groups.map((g) => ({ id: g.id, name: g.name })),
|
|
117
|
+
user_chats: {
|
|
118
|
+
opened_count: openedChats.length,
|
|
119
|
+
snoozed_count: snoozedChats.length,
|
|
120
|
+
closed_count: closedChats.length,
|
|
121
|
+
},
|
|
122
|
+
hint: "Use 'group messages <group>' for group messages, 'chat list --state opened' for chats, 'manager list' for managers.",
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
async function buildFullSnapshot(
|
|
127
|
+
client: Awaited<ReturnType<typeof getClient>>,
|
|
128
|
+
workspace: SnapshotResult['workspace'],
|
|
129
|
+
options: SnapshotOption,
|
|
130
|
+
): Promise<SnapshotResult> {
|
|
131
|
+
const limit = options.limit ?? 5
|
|
129
132
|
|
|
133
|
+
if (options.groupsOnly) {
|
|
134
|
+
const groups = await client.listGroups({ limit: 20 })
|
|
130
135
|
const groupsWithMessages = await Promise.all(
|
|
131
136
|
groups.map(async (g) => {
|
|
132
137
|
const messages = await client.getGroupMessages(g.id, { limit, sortOrder: 'desc' })
|
|
@@ -142,6 +147,15 @@ export async function snapshotAction(options: SnapshotOption): Promise<SnapshotR
|
|
|
142
147
|
}
|
|
143
148
|
}),
|
|
144
149
|
)
|
|
150
|
+
return { workspace, groups: groupsWithMessages }
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (options.chatsOnly) {
|
|
154
|
+
const [openedChats, snoozedChats, closedChats] = await Promise.all([
|
|
155
|
+
client.listUserChats({ state: 'opened', limit: 10, sortOrder: 'desc' }),
|
|
156
|
+
client.listUserChats({ state: 'snoozed', limit: 1 }),
|
|
157
|
+
client.listUserChats({ state: 'closed', limit: 1 }),
|
|
158
|
+
])
|
|
145
159
|
|
|
146
160
|
const recentOpened = await Promise.all(
|
|
147
161
|
openedChats.slice(0, 5).map(async (chat) => {
|
|
@@ -163,26 +177,78 @@ export async function snapshotAction(options: SnapshotOption): Promise<SnapshotR
|
|
|
163
177
|
|
|
164
178
|
return {
|
|
165
179
|
workspace,
|
|
166
|
-
groups: groupsWithMessages,
|
|
167
180
|
user_chats: {
|
|
168
181
|
opened_count: openedChats.length,
|
|
169
182
|
snoozed_count: snoozedChats.length,
|
|
170
183
|
closed_count: closedChats.length,
|
|
171
184
|
recent_opened: recentOpened,
|
|
172
185
|
},
|
|
173
|
-
managers: managers.map((m) => ({ id: m.id, name: m.name, description: m.description })),
|
|
174
|
-
bots: bots.map((b) => ({ id: b.id, name: b.name })),
|
|
175
186
|
}
|
|
176
|
-
}
|
|
177
|
-
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const [groups, openedChats, snoozedChats, closedChats, managers, bots] = await Promise.all([
|
|
190
|
+
client.listGroups({ limit: 20 }),
|
|
191
|
+
client.listUserChats({ state: 'opened', limit: 10, sortOrder: 'desc' }),
|
|
192
|
+
client.listUserChats({ state: 'snoozed', limit: 1 }),
|
|
193
|
+
client.listUserChats({ state: 'closed', limit: 1 }),
|
|
194
|
+
client.listManagers({ limit: 50 }),
|
|
195
|
+
client.listBots({ limit: 50 }),
|
|
196
|
+
])
|
|
197
|
+
|
|
198
|
+
const groupsWithMessages = await Promise.all(
|
|
199
|
+
groups.map(async (g) => {
|
|
200
|
+
const messages = await client.getGroupMessages(g.id, { limit, sortOrder: 'desc' })
|
|
201
|
+
return {
|
|
202
|
+
id: g.id,
|
|
203
|
+
name: g.name,
|
|
204
|
+
messages: messages.map((m) => ({
|
|
205
|
+
id: m.id,
|
|
206
|
+
person_type: m.personType,
|
|
207
|
+
plain_text: m.plainText,
|
|
208
|
+
created_at: m.createdAt,
|
|
209
|
+
})),
|
|
210
|
+
}
|
|
211
|
+
}),
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
const recentOpened = await Promise.all(
|
|
215
|
+
openedChats.slice(0, 5).map(async (chat) => {
|
|
216
|
+
const messages = await client.getUserChatMessages(chat.id, { limit: 1, sortOrder: 'desc' })
|
|
217
|
+
return {
|
|
218
|
+
id: chat.id,
|
|
219
|
+
name: chat.name,
|
|
220
|
+
user_id: chat.userId,
|
|
221
|
+
last_message: messages[0]
|
|
222
|
+
? {
|
|
223
|
+
id: messages[0].id,
|
|
224
|
+
plain_text: messages[0].plainText,
|
|
225
|
+
created_at: messages[0].createdAt,
|
|
226
|
+
}
|
|
227
|
+
: undefined,
|
|
228
|
+
}
|
|
229
|
+
}),
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
return {
|
|
233
|
+
workspace,
|
|
234
|
+
groups: groupsWithMessages,
|
|
235
|
+
user_chats: {
|
|
236
|
+
opened_count: openedChats.length,
|
|
237
|
+
snoozed_count: snoozedChats.length,
|
|
238
|
+
closed_count: closedChats.length,
|
|
239
|
+
recent_opened: recentOpened,
|
|
240
|
+
},
|
|
241
|
+
managers: managers.map((m) => ({ id: m.id, name: m.name, description: m.description })),
|
|
242
|
+
bots: bots.map((b) => ({ id: b.id, name: b.name })),
|
|
178
243
|
}
|
|
179
244
|
}
|
|
180
245
|
|
|
181
246
|
export const snapshotCommand = new Command('snapshot')
|
|
182
|
-
.description('Workspace overview for AI
|
|
247
|
+
.description('Workspace overview for AI agents (brief by default, use --full for comprehensive data)')
|
|
248
|
+
.option('--full', 'Include messages, managers, and bots (verbose)')
|
|
183
249
|
.option('--groups-only', 'List groups only, skip user chats')
|
|
184
250
|
.option('--chats-only', 'List user chats only, skip groups')
|
|
185
|
-
.option('--limit <n>', 'Messages per group/chat (default: 5)', '5')
|
|
251
|
+
.option('--limit <n>', 'Messages per group/chat with --full (default: 5)', '5')
|
|
186
252
|
.option('--workspace <id>', 'Workspace ID')
|
|
187
253
|
.option('--bot <name>', 'Bot name')
|
|
188
254
|
.option('--pretty', 'Pretty print JSON output')
|
|
@@ -190,6 +256,7 @@ export const snapshotCommand = new Command('snapshot')
|
|
|
190
256
|
try {
|
|
191
257
|
const result = await snapshotAction({
|
|
192
258
|
...options,
|
|
259
|
+
full: options.full,
|
|
193
260
|
limit: parseInt(options.limit, 10),
|
|
194
261
|
})
|
|
195
262
|
console.log(formatOutput(result, options.pretty))
|
|
@@ -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)
|