agent-messenger 1.3.0 → 1.3.2

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.
Files changed (236) hide show
  1. package/.claude-plugin/marketplace.json +27 -1
  2. package/.claude-plugin/plugin.json +17 -4
  3. package/.env.template +3 -0
  4. package/.github/workflows/release.yml +80 -0
  5. package/AGENTS.md +48 -0
  6. package/README.md +25 -20
  7. package/biome.json +15 -39
  8. package/bun.lock +69 -0
  9. package/dist/package.json +10 -3
  10. package/dist/src/cli.d.ts.map +1 -1
  11. package/dist/src/cli.js +1 -4
  12. package/dist/src/cli.js.map +1 -1
  13. package/dist/src/platforms/discord/client.d.ts.map +1 -1
  14. package/dist/src/platforms/discord/client.js.map +1 -1
  15. package/dist/src/platforms/discord/commands/auth.d.ts.map +1 -1
  16. package/dist/src/platforms/discord/commands/auth.js.map +1 -1
  17. package/dist/src/platforms/discord/commands/channel.d.ts.map +1 -1
  18. package/dist/src/platforms/discord/commands/channel.js.map +1 -1
  19. package/dist/src/platforms/discord/commands/dm.d.ts.map +1 -1
  20. package/dist/src/platforms/discord/commands/dm.js.map +1 -1
  21. package/dist/src/platforms/discord/commands/file.d.ts.map +1 -1
  22. package/dist/src/platforms/discord/commands/file.js +1 -4
  23. package/dist/src/platforms/discord/commands/file.js.map +1 -1
  24. package/dist/src/platforms/discord/commands/friend.d.ts.map +1 -1
  25. package/dist/src/platforms/discord/commands/friend.js +1 -3
  26. package/dist/src/platforms/discord/commands/friend.js.map +1 -1
  27. package/dist/src/platforms/discord/commands/member.d.ts.map +1 -1
  28. package/dist/src/platforms/discord/commands/member.js.map +1 -1
  29. package/dist/src/platforms/discord/commands/mention.d.ts.map +1 -1
  30. package/dist/src/platforms/discord/commands/mention.js.map +1 -1
  31. package/dist/src/platforms/discord/commands/message.d.ts.map +1 -1
  32. package/dist/src/platforms/discord/commands/message.js.map +1 -1
  33. package/dist/src/platforms/discord/commands/note.d.ts.map +1 -1
  34. package/dist/src/platforms/discord/commands/note.js.map +1 -1
  35. package/dist/src/platforms/discord/commands/profile.d.ts.map +1 -1
  36. package/dist/src/platforms/discord/commands/profile.js.map +1 -1
  37. package/dist/src/platforms/discord/commands/reaction.d.ts.map +1 -1
  38. package/dist/src/platforms/discord/commands/reaction.js.map +1 -1
  39. package/dist/src/platforms/discord/commands/server.d.ts.map +1 -1
  40. package/dist/src/platforms/discord/commands/server.js.map +1 -1
  41. package/dist/src/platforms/discord/commands/snapshot.d.ts.map +1 -1
  42. package/dist/src/platforms/discord/commands/snapshot.js.map +1 -1
  43. package/dist/src/platforms/discord/commands/thread.d.ts.map +1 -1
  44. package/dist/src/platforms/discord/commands/thread.js.map +1 -1
  45. package/dist/src/platforms/discord/commands/user.d.ts.map +1 -1
  46. package/dist/src/platforms/discord/commands/user.js.map +1 -1
  47. package/dist/src/platforms/discord/credential-manager.d.ts.map +1 -1
  48. package/dist/src/platforms/discord/credential-manager.js.map +1 -1
  49. package/dist/src/platforms/discord/token-extractor.d.ts.map +1 -1
  50. package/dist/src/platforms/discord/token-extractor.js +2 -7
  51. package/dist/src/platforms/discord/token-extractor.js.map +1 -1
  52. package/dist/src/platforms/slack/client.d.ts.map +1 -1
  53. package/dist/src/platforms/slack/client.js +2 -0
  54. package/dist/src/platforms/slack/client.js.map +1 -1
  55. package/dist/src/platforms/slack/commands/activity.d.ts.map +1 -1
  56. package/dist/src/platforms/slack/commands/activity.js.map +1 -1
  57. package/dist/src/platforms/slack/commands/auth.d.ts.map +1 -1
  58. package/dist/src/platforms/slack/commands/auth.js.map +1 -1
  59. package/dist/src/platforms/slack/commands/channel.d.ts.map +1 -1
  60. package/dist/src/platforms/slack/commands/channel.js.map +1 -1
  61. package/dist/src/platforms/slack/commands/drafts.d.ts.map +1 -1
  62. package/dist/src/platforms/slack/commands/drafts.js.map +1 -1
  63. package/dist/src/platforms/slack/commands/file.d.ts.map +1 -1
  64. package/dist/src/platforms/slack/commands/file.js +1 -4
  65. package/dist/src/platforms/slack/commands/file.js.map +1 -1
  66. package/dist/src/platforms/slack/commands/message.d.ts.map +1 -1
  67. package/dist/src/platforms/slack/commands/message.js.map +1 -1
  68. package/dist/src/platforms/slack/commands/reaction.d.ts.map +1 -1
  69. package/dist/src/platforms/slack/commands/reaction.js +1 -2
  70. package/dist/src/platforms/slack/commands/reaction.js.map +1 -1
  71. package/dist/src/platforms/slack/commands/saved.d.ts.map +1 -1
  72. package/dist/src/platforms/slack/commands/saved.js.map +1 -1
  73. package/dist/src/platforms/slack/commands/sections.d.ts.map +1 -1
  74. package/dist/src/platforms/slack/commands/sections.js.map +1 -1
  75. package/dist/src/platforms/slack/commands/snapshot.d.ts.map +1 -1
  76. package/dist/src/platforms/slack/commands/snapshot.js.map +1 -1
  77. package/dist/src/platforms/slack/commands/unread.d.ts.map +1 -1
  78. package/dist/src/platforms/slack/commands/unread.js.map +1 -1
  79. package/dist/src/platforms/slack/commands/user.d.ts.map +1 -1
  80. package/dist/src/platforms/slack/commands/user.js.map +1 -1
  81. package/dist/src/platforms/slack/commands/workspace.d.ts.map +1 -1
  82. package/dist/src/platforms/slack/commands/workspace.js.map +1 -1
  83. package/dist/src/platforms/slack/token-extractor.d.ts.map +1 -1
  84. package/dist/src/platforms/slack/token-extractor.js +4 -5
  85. package/dist/src/platforms/slack/token-extractor.js.map +1 -1
  86. package/dist/src/platforms/slack/types.d.ts +24 -0
  87. package/dist/src/platforms/slack/types.d.ts.map +1 -1
  88. package/dist/src/platforms/slack/types.js +7 -0
  89. package/dist/src/platforms/slack/types.js.map +1 -1
  90. package/dist/src/platforms/slackbot/cli.d.ts.map +1 -1
  91. package/dist/src/platforms/slackbot/cli.js +1 -1
  92. package/dist/src/platforms/slackbot/cli.js.map +1 -1
  93. package/dist/src/platforms/slackbot/client.d.ts.map +1 -1
  94. package/dist/src/platforms/slackbot/client.js.map +1 -1
  95. package/dist/src/platforms/slackbot/commands/auth.js.map +1 -1
  96. package/dist/src/platforms/slackbot/commands/channel.js.map +1 -1
  97. package/dist/src/platforms/slackbot/commands/message.d.ts.map +1 -1
  98. package/dist/src/platforms/slackbot/commands/message.js.map +1 -1
  99. package/dist/src/platforms/slackbot/commands/reaction.d.ts.map +1 -1
  100. package/dist/src/platforms/slackbot/commands/reaction.js.map +1 -1
  101. package/dist/src/platforms/slackbot/commands/shared.d.ts.map +1 -1
  102. package/dist/src/platforms/slackbot/commands/shared.js.map +1 -1
  103. package/dist/src/platforms/slackbot/commands/user.js.map +1 -1
  104. package/dist/src/platforms/slackbot/credential-manager.d.ts.map +1 -1
  105. package/dist/src/platforms/slackbot/credential-manager.js +2 -4
  106. package/dist/src/platforms/slackbot/credential-manager.js.map +1 -1
  107. package/dist/src/platforms/teams/client.d.ts.map +1 -1
  108. package/dist/src/platforms/teams/client.js.map +1 -1
  109. package/dist/src/platforms/teams/commands/auth.d.ts.map +1 -1
  110. package/dist/src/platforms/teams/commands/auth.js.map +1 -1
  111. package/dist/src/platforms/teams/commands/channel.d.ts.map +1 -1
  112. package/dist/src/platforms/teams/commands/channel.js.map +1 -1
  113. package/dist/src/platforms/teams/commands/file.d.ts.map +1 -1
  114. package/dist/src/platforms/teams/commands/file.js.map +1 -1
  115. package/dist/src/platforms/teams/commands/message.d.ts.map +1 -1
  116. package/dist/src/platforms/teams/commands/message.js.map +1 -1
  117. package/dist/src/platforms/teams/commands/reaction.d.ts.map +1 -1
  118. package/dist/src/platforms/teams/commands/reaction.js.map +1 -1
  119. package/dist/src/platforms/teams/commands/snapshot.d.ts.map +1 -1
  120. package/dist/src/platforms/teams/commands/snapshot.js.map +1 -1
  121. package/dist/src/platforms/teams/commands/team.d.ts.map +1 -1
  122. package/dist/src/platforms/teams/commands/team.js +1 -4
  123. package/dist/src/platforms/teams/commands/team.js.map +1 -1
  124. package/dist/src/platforms/teams/commands/user.d.ts.map +1 -1
  125. package/dist/src/platforms/teams/commands/user.js.map +1 -1
  126. package/dist/src/platforms/teams/token-extractor.d.ts.map +1 -1
  127. package/dist/src/platforms/teams/token-extractor.js +3 -1
  128. package/dist/src/platforms/teams/token-extractor.js.map +1 -1
  129. package/docs/content/docs/agent-skills.mdx +4 -4
  130. package/docs/content/docs/index.mdx +11 -18
  131. package/docs/content/docs/integrations/discord.mdx +65 -1
  132. package/docs/content/docs/integrations/slack.mdx +51 -1
  133. package/docs/content/docs/integrations/slackbot.mdx +11 -1
  134. package/docs/content/docs/integrations/teams.mdx +4 -1
  135. package/docs/content/docs/quick-start.mdx +3 -2
  136. package/docs/src/app/icon.png +0 -0
  137. package/docs/src/app/layout.config.tsx +8 -1
  138. package/package.json +16 -9
  139. package/scripts/prepublish.ts +11 -0
  140. package/skills/agent-discord/SKILL.md +14 -0
  141. package/skills/agent-slack/SKILL.md +14 -0
  142. package/skills/agent-slackbot/SKILL.md +14 -0
  143. package/skills/agent-teams/SKILL.md +14 -0
  144. package/src/cli.ts +1 -4
  145. package/src/platforms/discord/client.test.ts +6 -14
  146. package/src/platforms/discord/client.ts +12 -34
  147. package/src/platforms/discord/commands/auth.test.ts +2 -7
  148. package/src/platforms/discord/commands/auth.ts +14 -19
  149. package/src/platforms/discord/commands/channel.test.ts +18 -20
  150. package/src/platforms/discord/commands/channel.ts +9 -18
  151. package/src/platforms/discord/commands/dm.test.ts +1 -3
  152. package/src/platforms/discord/commands/dm.ts +6 -10
  153. package/src/platforms/discord/commands/file.ts +10 -23
  154. package/src/platforms/discord/commands/friend.ts +33 -35
  155. package/src/platforms/discord/commands/member.ts +5 -7
  156. package/src/platforms/discord/commands/mention.ts +5 -11
  157. package/src/platforms/discord/commands/message.test.ts +1 -3
  158. package/src/platforms/discord/commands/message.ts +23 -61
  159. package/src/platforms/discord/commands/note.ts +7 -15
  160. package/src/platforms/discord/commands/profile.ts +4 -6
  161. package/src/platforms/discord/commands/reaction.test.ts +1 -3
  162. package/src/platforms/discord/commands/reaction.ts +19 -29
  163. package/src/platforms/discord/commands/server.test.ts +14 -18
  164. package/src/platforms/discord/commands/server.ts +9 -15
  165. package/src/platforms/discord/commands/snapshot.ts +5 -7
  166. package/src/platforms/discord/commands/thread.ts +8 -15
  167. package/src/platforms/discord/commands/user.ts +9 -20
  168. package/src/platforms/discord/credential-manager.test.ts +2 -2
  169. package/src/platforms/discord/credential-manager.ts +1 -3
  170. package/src/platforms/discord/token-extractor.test.ts +28 -57
  171. package/src/platforms/discord/token-extractor.ts +10 -30
  172. package/src/platforms/discord/types.ts +1 -1
  173. package/src/platforms/slack/client.test.ts +14 -20
  174. package/src/platforms/slack/client.ts +6 -11
  175. package/src/platforms/slack/commands/activity.test.ts +3 -9
  176. package/src/platforms/slack/commands/activity.ts +7 -12
  177. package/src/platforms/slack/commands/auth.test.ts +2 -2
  178. package/src/platforms/slack/commands/auth.ts +15 -31
  179. package/src/platforms/slack/commands/channel.ts +10 -32
  180. package/src/platforms/slack/commands/drafts.ts +5 -14
  181. package/src/platforms/slack/commands/file.ts +9 -29
  182. package/src/platforms/slack/commands/message.ts +23 -67
  183. package/src/platforms/slack/commands/reaction.test.ts +37 -33
  184. package/src/platforms/slack/commands/reaction.ts +21 -51
  185. package/src/platforms/slack/commands/saved.ts +5 -14
  186. package/src/platforms/slack/commands/sections.ts +4 -11
  187. package/src/platforms/slack/commands/snapshot.test.ts +1 -3
  188. package/src/platforms/slack/commands/snapshot.ts +5 -10
  189. package/src/platforms/slack/commands/unread.test.ts +6 -8
  190. package/src/platforms/slack/commands/unread.ts +10 -33
  191. package/src/platforms/slack/commands/user.test.ts +1 -4
  192. package/src/platforms/slack/commands/user.ts +6 -8
  193. package/src/platforms/slack/commands/workspace.test.ts +1 -1
  194. package/src/platforms/slack/commands/workspace.ts +7 -12
  195. package/src/platforms/slack/token-extractor-node-test.ts +1 -1
  196. package/src/platforms/slack/token-extractor.ts +8 -17
  197. package/src/platforms/slack/types.ts +11 -1
  198. package/src/platforms/slackbot/cli.ts +1 -7
  199. package/src/platforms/slackbot/client.test.ts +7 -7
  200. package/src/platforms/slackbot/client.ts +4 -11
  201. package/src/platforms/slackbot/commands/auth.test.ts +1 -1
  202. package/src/platforms/slackbot/commands/auth.ts +7 -7
  203. package/src/platforms/slackbot/commands/channel.ts +4 -4
  204. package/src/platforms/slackbot/commands/message.ts +16 -29
  205. package/src/platforms/slackbot/commands/reaction.ts +6 -16
  206. package/src/platforms/slackbot/commands/shared.ts +2 -4
  207. package/src/platforms/slackbot/commands/user.ts +4 -4
  208. package/src/platforms/slackbot/credential-manager.ts +2 -7
  209. package/src/platforms/slackbot/types.ts +1 -1
  210. package/src/platforms/teams/client.test.ts +15 -32
  211. package/src/platforms/teams/client.ts +18 -51
  212. package/src/platforms/teams/commands/auth.test.ts +6 -16
  213. package/src/platforms/teams/commands/auth.ts +16 -26
  214. package/src/platforms/teams/commands/channel.test.ts +2 -5
  215. package/src/platforms/teams/commands/channel.ts +10 -20
  216. package/src/platforms/teams/commands/file.test.ts +1 -4
  217. package/src/platforms/teams/commands/file.ts +11 -21
  218. package/src/platforms/teams/commands/message.test.ts +1 -3
  219. package/src/platforms/teams/commands/message.ts +15 -25
  220. package/src/platforms/teams/commands/reaction.test.ts +2 -7
  221. package/src/platforms/teams/commands/reaction.ts +12 -16
  222. package/src/platforms/teams/commands/snapshot.ts +6 -11
  223. package/src/platforms/teams/commands/team.test.ts +15 -26
  224. package/src/platforms/teams/commands/team.ts +10 -19
  225. package/src/platforms/teams/commands/user.ts +8 -14
  226. package/src/platforms/teams/credential-manager.test.ts +2 -5
  227. package/src/platforms/teams/token-extractor.test.ts +21 -50
  228. package/src/platforms/teams/token-extractor.ts +12 -20
  229. package/src/platforms/teams/types.ts +1 -1
  230. package/src/shared/utils/concurrency.test.ts +2 -2
  231. package/src/shared/utils/concurrency.ts +1 -1
  232. package/.claude/commands/release.md +0 -92
  233. package/dist/src/platforms/discord/commands/guild.d.ts +0 -15
  234. package/dist/src/platforms/discord/commands/guild.d.ts.map +0 -1
  235. package/dist/src/platforms/discord/commands/guild.js +0 -102
  236. package/dist/src/platforms/discord/commands/guild.js.map +0 -1
@@ -3,7 +3,7 @@ import { createDecipheriv, pbkdf2Sync } from 'node:crypto'
3
3
  import { existsSync, readdirSync, readFileSync } from 'node:fs'
4
4
  import { homedir } from 'node:os'
5
5
  import { join } from 'node:path'
6
- import { DerivedKeyCache } from '../../shared/utils/derived-key-cache'
6
+ import { DerivedKeyCache } from '@/shared/utils/derived-key-cache'
7
7
 
8
8
  export interface ExtractedDiscordToken {
9
9
  token: string
@@ -41,10 +41,7 @@ export const CDP_TIMEOUT = 5000
41
41
  export const DISCORD_STARTUP_WAIT = 4000
42
42
  export const TOKEN_EXTRACTION_JS = `(webpackChunkdiscord_app.push([[''], {}, e => { m = []; for (let c in e.c) m.push(e.c[c]); }]), m).find(m => m?.exports?.default?.getToken !== void 0).exports.default.getToken()`
43
43
 
44
- const DISCORD_PROCESS_NAMES: Record<
45
- DiscordVariant,
46
- { darwin: string; win32: string; linux: string }
47
- > = {
44
+ const DISCORD_PROCESS_NAMES: Record<DiscordVariant, { darwin: string; win32: string; linux: string }> = {
48
45
  stable: { darwin: 'Discord', win32: 'Discord.exe', linux: 'discord' },
49
46
  canary: { darwin: 'Discord Canary', win32: 'DiscordCanary.exe', linux: 'discordcanary' },
50
47
  ptb: { darwin: 'Discord PTB', win32: 'DiscordPTB.exe', linux: 'discordptb' },
@@ -63,12 +60,7 @@ export class DiscordTokenExtractor {
63
60
  private keyCache: DerivedKeyCache
64
61
  private cachedKey: Buffer | null = null
65
62
 
66
- constructor(
67
- platform?: NodeJS.Platform,
68
- startupWait?: number,
69
- killWait?: number,
70
- keyCache?: DerivedKeyCache
71
- ) {
63
+ constructor(platform?: NodeJS.Platform, startupWait?: number, killWait?: number, keyCache?: DerivedKeyCache) {
72
64
  this.platform = platform ?? process.platform
73
65
  this.startupWait = startupWait ?? DISCORD_STARTUP_WAIT
74
66
  this.killWait = killWait ?? 1000
@@ -91,11 +83,7 @@ export class DiscordTokenExtractor {
91
83
  ]
92
84
  case 'win32': {
93
85
  const appdata = process.env.APPDATA || join(homedir(), 'AppData', 'Roaming')
94
- return [
95
- join(appdata, 'Discord'),
96
- join(appdata, 'discordcanary'),
97
- join(appdata, 'discordptb'),
98
- ]
86
+ return [join(appdata, 'Discord'), join(appdata, 'discordcanary'), join(appdata, 'discordptb')]
99
87
  }
100
88
  default:
101
89
  return []
@@ -322,10 +310,8 @@ export class DiscordTokenExtractor {
322
310
  const keychainVariants = this.getKeychainVariants().filter((v) => {
323
311
  const lowerAccount = v.account.toLowerCase()
324
312
  if (variant === 'stable') return lowerAccount === 'discord' || lowerAccount === 'discord key'
325
- if (variant === 'canary')
326
- return lowerAccount === 'discord canary' || lowerAccount === 'discordcanary key'
327
- if (variant === 'ptb')
328
- return lowerAccount === 'discord ptb' || lowerAccount === 'discordptb key'
313
+ if (variant === 'canary') return lowerAccount === 'discord canary' || lowerAccount === 'discordcanary key'
314
+ if (variant === 'ptb') return lowerAccount === 'discord ptb' || lowerAccount === 'discordptb key'
329
315
  return false
330
316
  })
331
317
 
@@ -333,7 +319,7 @@ export class DiscordTokenExtractor {
333
319
  try {
334
320
  const password = execSync(
335
321
  `security find-generic-password -s "${keychainVariant.service}" -a "${keychainVariant.account}" -w 2>/dev/null`,
336
- { encoding: 'utf8' }
322
+ { encoding: 'utf8' },
337
323
  ).trim()
338
324
 
339
325
  const key = pbkdf2Sync(password, 'saltysalt', 1003, 16, 'sha1')
@@ -473,8 +459,7 @@ export class DiscordTokenExtractor {
473
459
  return DISCORD_APP_PATHS[variant].darwin
474
460
  } else if (this.platform === 'win32') {
475
461
  const localAppData = process.env.LOCALAPPDATA || join(homedir(), 'AppData', 'Local')
476
- const appName =
477
- variant === 'stable' ? 'Discord' : variant === 'canary' ? 'DiscordCanary' : 'DiscordPTB'
462
+ const appName = variant === 'stable' ? 'Discord' : variant === 'canary' ? 'DiscordCanary' : 'DiscordPTB'
478
463
  return join(localAppData, appName, 'Update.exe')
479
464
  } else {
480
465
  return variant === 'stable' ? 'discord' : `discord${variant}`
@@ -497,9 +482,7 @@ export class DiscordTokenExtractor {
497
482
 
498
483
  findDiscordPageTarget(targets: CDPTarget[]): CDPTarget | null {
499
484
  const discordTarget = targets.find(
500
- (t) =>
501
- t.type === 'page' &&
502
- (t.url.includes('discord.com') || t.title.toLowerCase().includes('discord'))
485
+ (t) => t.type === 'page' && (t.url.includes('discord.com') || t.title.toLowerCase().includes('discord')),
503
486
  )
504
487
  return discordTarget ?? null
505
488
  }
@@ -568,10 +551,7 @@ export class DiscordTokenExtractor {
568
551
  }
569
552
 
570
553
  try {
571
- const result = await this.executeJSViaCDP(
572
- discordTarget.webSocketDebuggerUrl,
573
- TOKEN_EXTRACTION_JS
574
- )
554
+ const result = await this.executeJSViaCDP(discordTarget.webSocketDebuggerUrl, TOKEN_EXTRACTION_JS)
575
555
  if (typeof result === 'string' && this.isValidToken(result)) {
576
556
  return result
577
557
  }
@@ -279,7 +279,7 @@ export const DiscordConfigSchema = z.object({
279
279
  z.object({
280
280
  server_id: z.string(),
281
281
  server_name: z.string(),
282
- })
282
+ }),
283
283
  ),
284
284
  })
285
285
 
@@ -10,9 +10,7 @@ const mockWebClient: any = {
10
10
  replies: mock((): Promise<any> => Promise.resolve({ ok: true, messages: [], has_more: false })),
11
11
  },
12
12
  chat: {
13
- postMessage: mock(
14
- (): Promise<any> => Promise.resolve({ ok: true, ts: '123.456', message: {} })
15
- ),
13
+ postMessage: mock((): Promise<any> => Promise.resolve({ ok: true, ts: '123.456', message: {} })),
16
14
  update: mock((): Promise<any> => Promise.resolve({ ok: true, ts: '123.456', message: {} })),
17
15
  delete: mock((): Promise<any> => Promise.resolve({ ok: true })),
18
16
  },
@@ -249,7 +247,7 @@ describe('SlackClient', () => {
249
247
  const result = await client.getMessages('C123')
250
248
  expect(result).toHaveLength(20)
251
249
  expect(mockWebClient.conversations.history).toHaveBeenCalledWith(
252
- expect.objectContaining({ channel: 'C123', limit: 20 })
250
+ expect.objectContaining({ channel: 'C123', limit: 20 }),
253
251
  )
254
252
  })
255
253
 
@@ -265,7 +263,7 @@ describe('SlackClient', () => {
265
263
 
266
264
  await client.getMessages('C123', 50)
267
265
  expect(mockWebClient.conversations.history).toHaveBeenCalledWith(
268
- expect.objectContaining({ channel: 'C123', limit: 50 })
266
+ expect.objectContaining({ channel: 'C123', limit: 50 }),
269
267
  )
270
268
  })
271
269
 
@@ -300,7 +298,7 @@ describe('SlackClient', () => {
300
298
  const message = await client.sendMessage('C123', 'Hello')
301
299
  expect(message.ts).toBe('123.456')
302
300
  expect(mockWebClient.chat.postMessage).toHaveBeenCalledWith(
303
- expect.objectContaining({ channel: 'C123', text: 'Hello' })
301
+ expect.objectContaining({ channel: 'C123', text: 'Hello' }),
304
302
  )
305
303
  })
306
304
 
@@ -318,7 +316,7 @@ describe('SlackClient', () => {
318
316
  const message = await client.sendMessage('C123', 'Reply', '123.456')
319
317
  expect(message.thread_ts).toBe('123.456')
320
318
  expect(mockWebClient.chat.postMessage).toHaveBeenCalledWith(
321
- expect.objectContaining({ channel: 'C123', text: 'Reply', thread_ts: '123.456' })
319
+ expect.objectContaining({ channel: 'C123', text: 'Reply', thread_ts: '123.456' }),
322
320
  )
323
321
  })
324
322
 
@@ -353,7 +351,7 @@ describe('SlackClient', () => {
353
351
  const message = await client.updateMessage('C123', '123.456', 'Updated')
354
352
  expect(message.text).toBe('Updated')
355
353
  expect(mockWebClient.chat.update).toHaveBeenCalledWith(
356
- expect.objectContaining({ channel: 'C123', ts: '123.456', text: 'Updated' })
354
+ expect.objectContaining({ channel: 'C123', ts: '123.456', text: 'Updated' }),
357
355
  )
358
356
  })
359
357
 
@@ -383,7 +381,7 @@ describe('SlackClient', () => {
383
381
 
384
382
  await expect(client.deleteMessage('C123', '123.456')).resolves.toBeUndefined()
385
383
  expect(mockWebClient.chat.delete).toHaveBeenCalledWith(
386
- expect.objectContaining({ channel: 'C123', ts: '123.456' })
384
+ expect.objectContaining({ channel: 'C123', ts: '123.456' }),
387
385
  )
388
386
  })
389
387
 
@@ -413,7 +411,7 @@ describe('SlackClient', () => {
413
411
 
414
412
  await expect(client.addReaction('C123', '123.456', 'thumbsup')).resolves.toBeUndefined()
415
413
  expect(mockWebClient.reactions.add).toHaveBeenCalledWith(
416
- expect.objectContaining({ channel: 'C123', timestamp: '123.456', name: 'thumbsup' })
414
+ expect.objectContaining({ channel: 'C123', timestamp: '123.456', name: 'thumbsup' }),
417
415
  )
418
416
  })
419
417
 
@@ -443,7 +441,7 @@ describe('SlackClient', () => {
443
441
 
444
442
  await expect(client.removeReaction('C123', '123.456', 'thumbsup')).resolves.toBeUndefined()
445
443
  expect(mockWebClient.reactions.remove).toHaveBeenCalledWith(
446
- expect.objectContaining({ channel: 'C123', timestamp: '123.456', name: 'thumbsup' })
444
+ expect.objectContaining({ channel: 'C123', timestamp: '123.456', name: 'thumbsup' }),
447
445
  )
448
446
  })
449
447
 
@@ -619,7 +617,7 @@ describe('SlackClient', () => {
619
617
  const file = await client.uploadFile(['C123'], Buffer.from('test'), 'test.txt')
620
618
  expect(file.id).toBe('F123')
621
619
  expect(mockWebClient.files.uploadV2).toHaveBeenCalledWith(
622
- expect.objectContaining({ channel_id: 'C123', filename: 'test.txt' })
620
+ expect.objectContaining({ channel_id: 'C123', filename: 'test.txt' }),
623
621
  )
624
622
  })
625
623
 
@@ -633,9 +631,7 @@ describe('SlackClient', () => {
633
631
  // @ts-expect-error - accessing private property for testing
634
632
  client.client = mockWebClient as unknown as WebClient
635
633
 
636
- await expect(client.uploadFile(['C123'], Buffer.from('test'), 'test.txt')).rejects.toThrow(
637
- SlackError
638
- )
634
+ await expect(client.uploadFile(['C123'], Buffer.from('test'), 'test.txt')).rejects.toThrow(SlackError)
639
635
  })
640
636
  })
641
637
 
@@ -679,9 +675,7 @@ describe('SlackClient', () => {
679
675
  client.client = mockWebClient as unknown as WebClient
680
676
 
681
677
  await client.listFiles('C123')
682
- expect(mockWebClient.files.list).toHaveBeenCalledWith(
683
- expect.objectContaining({ channel: 'C123' })
684
- )
678
+ expect(mockWebClient.files.list).toHaveBeenCalledWith(expect.objectContaining({ channel: 'C123' }))
685
679
  })
686
680
 
687
681
  test('throws SlackError on API failure', async () => {
@@ -757,7 +751,7 @@ describe('SlackClient', () => {
757
751
 
758
752
  await client.getThreadReplies('C123', '123.456', { limit: 50 })
759
753
  expect(mockWebClient.conversations.replies).toHaveBeenCalledWith(
760
- expect.objectContaining({ channel: 'C123', ts: '123.456', limit: 50 })
754
+ expect.objectContaining({ channel: 'C123', ts: '123.456', limit: 50 }),
761
755
  )
762
756
  })
763
757
 
@@ -782,7 +776,7 @@ describe('SlackClient', () => {
782
776
  ts: '123.456',
783
777
  oldest: '123.400',
784
778
  latest: '123.500',
785
- })
779
+ }),
786
780
  )
787
781
  })
788
782
 
@@ -57,10 +57,7 @@ export class SlackClient {
57
57
  break
58
58
  }
59
59
  }
60
- throw new SlackError(
61
- lastError?.message || 'Unknown error',
62
- (lastError as any)?.code || 'unknown_error'
63
- )
60
+ throw new SlackError(lastError?.message || 'Unknown error', (lastError as any)?.code || 'unknown_error')
64
61
  }
65
62
 
66
63
  private sleep(ms: number): Promise<void> {
@@ -201,6 +198,7 @@ export class SlackClient {
201
198
  thread_ts: msg.thread_ts,
202
199
  reply_count: msg.reply_count,
203
200
  replies: (msg as any).replies,
201
+ reactions: (msg as any).reactions,
204
202
  edited: msg.edited
205
203
  ? {
206
204
  user: msg.edited.user || '',
@@ -235,6 +233,7 @@ export class SlackClient {
235
233
  thread_ts: msg.thread_ts,
236
234
  reply_count: msg.reply_count,
237
235
  replies: (msg as any).replies,
236
+ reactions: (msg as any).reactions,
238
237
  edited: msg.edited
239
238
  ? {
240
239
  user: msg.edited.user || '',
@@ -410,7 +409,7 @@ export class SlackClient {
410
409
 
411
410
  async searchMessages(
412
411
  query: string,
413
- options: { sort?: 'score' | 'timestamp'; sortDir?: 'asc' | 'desc'; count?: number } = {}
412
+ options: { sort?: 'score' | 'timestamp'; sortDir?: 'asc' | 'desc'; count?: number } = {},
414
413
  ): Promise<SlackSearchResult[]> {
415
414
  return this.withRetry(async () => {
416
415
  const response = await this.client.search.messages({
@@ -439,7 +438,7 @@ export class SlackClient {
439
438
  async getThreadReplies(
440
439
  channel: string,
441
440
  threadTs: string,
442
- options: { limit?: number; oldest?: string; latest?: string; cursor?: string } = {}
441
+ options: { limit?: number; oldest?: string; latest?: string; cursor?: string } = {},
443
442
  ): Promise<{ messages: SlackMessage[]; has_more: boolean; next_cursor?: string }> {
444
443
  return this.withRetry(async () => {
445
444
  const response = await this.client.conversations.replies({
@@ -525,11 +524,7 @@ export class SlackClient {
525
524
  })
526
525
  }
527
526
 
528
- async getActivityFeed(options?: {
529
- types?: string
530
- mode?: string
531
- limit?: number
532
- }): Promise<SlackActivityItem[]> {
527
+ async getActivityFeed(options?: { types?: string; mode?: string; limit?: number }): Promise<SlackActivityItem[]> {
533
528
  return this.withRetry(async () => {
534
529
  const response = await (this.client as any).activity.feed({
535
530
  types: options?.types,
@@ -47,9 +47,7 @@ describe('activity command', () => {
47
47
  },
48
48
  ]
49
49
 
50
- const mockGetActivityFeed = mock((_options?: { limit?: number }) =>
51
- Promise.resolve(mockActivityItems)
52
- )
50
+ const mockGetActivityFeed = mock((_options?: { limit?: number }) => Promise.resolve(mockActivityItems))
53
51
  const result = await mockGetActivityFeed({ limit: 10 })
54
52
 
55
53
  expect(mockGetActivityFeed).toHaveBeenCalledWith({ limit: 10 })
@@ -69,9 +67,7 @@ describe('activity command', () => {
69
67
  },
70
68
  ]
71
69
 
72
- const mockGetActivityFeed = mock((_options?: { mode?: string }) =>
73
- Promise.resolve(mockActivityItems)
74
- )
70
+ const mockGetActivityFeed = mock((_options?: { mode?: string }) => Promise.resolve(mockActivityItems))
75
71
  const result = await mockGetActivityFeed({ mode: 'priority_unreads_v1' })
76
72
 
77
73
  expect(mockGetActivityFeed).toHaveBeenCalledWith({ mode: 'priority_unreads_v1' })
@@ -91,9 +87,7 @@ describe('activity command', () => {
91
87
  },
92
88
  ]
93
89
 
94
- const mockGetActivityFeed = mock((_options?: { types?: string }) =>
95
- Promise.resolve(mockActivityItems)
96
- )
90
+ const mockGetActivityFeed = mock((_options?: { types?: string }) => Promise.resolve(mockActivityItems))
97
91
  const result = await mockGetActivityFeed({ types: 'thread_reply,at_user' })
98
92
 
99
93
  expect(mockGetActivityFeed).toHaveBeenCalledWith({ types: 'thread_reply,at_user' })
@@ -1,6 +1,6 @@
1
1
  import { Command } from 'commander'
2
- import { handleError } from '../../../shared/utils/error-handler'
3
- import { formatOutput } from '../../../shared/utils/output'
2
+ import { handleError } from '@/shared/utils/error-handler'
3
+ import { formatOutput } from '@/shared/utils/output'
4
4
  import { SlackClient } from '../client'
5
5
  import { CredentialManager } from '../credential-manager'
6
6
 
@@ -15,12 +15,7 @@ async function listAction(options: {
15
15
  const ws = await credManager.getWorkspace()
16
16
 
17
17
  if (!ws) {
18
- console.log(
19
- formatOutput(
20
- { error: 'No workspace configured. Run "auth extract" first.' },
21
- options.pretty
22
- )
23
- )
18
+ console.log(formatOutput({ error: 'No workspace configured. Run "auth extract" first.' }, options.pretty))
24
19
  process.exit(1)
25
20
  }
26
21
 
@@ -41,8 +36,8 @@ async function listAction(options: {
41
36
  items,
42
37
  count: items.length,
43
38
  },
44
- options.pretty
45
- )
39
+ options.pretty,
40
+ ),
46
41
  )
47
42
  } catch (error) {
48
43
  handleError(error as Error)
@@ -59,7 +54,7 @@ export const activityCommand = new Command('activity')
59
54
  .option('--limit <number>', 'Number of items to return (default: 20)')
60
55
  .option(
61
56
  '--types <types>',
62
- 'Filter by activity types (comma-separated: thread_reply,message_reaction,at_user,at_channel,keyword)'
57
+ 'Filter by activity types (comma-separated: thread_reply,message_reaction,at_user,at_channel,keyword)',
63
58
  )
64
- .action(listAction)
59
+ .action(listAction),
65
60
  )
@@ -38,7 +38,7 @@ describe('TokenExtractor', () => {
38
38
  'Data',
39
39
  'Library',
40
40
  'Application Support',
41
- 'Slack'
41
+ 'Slack',
42
42
  )
43
43
  expect([directPath, sandboxedPath]).toContain(dir)
44
44
  })
@@ -274,7 +274,7 @@ describe('Auth Commands Integration', () => {
274
274
  team_id: 'T123',
275
275
  user: 'testuser',
276
276
  team: 'Test Team',
277
- })
277
+ }),
278
278
  )
279
279
 
280
280
  // When: testAuth is called
@@ -1,6 +1,6 @@
1
1
  import { Command } from 'commander'
2
- import { handleError } from '../../../shared/utils/error-handler'
3
- import { formatOutput } from '../../../shared/utils/output'
2
+ import { handleError } from '@/shared/utils/error-handler'
3
+ import { formatOutput } from '@/shared/utils/output'
4
4
  import { SlackClient } from '../client'
5
5
  import { CredentialManager } from '../credential-manager'
6
6
  import { TokenExtractor } from '../token-extractor'
@@ -36,7 +36,7 @@ async function extractAction(options: { pretty?: boolean; debug?: boolean }): Pr
36
36
  console.error(`[debug] Found ${workspaces.length} workspace(s)`)
37
37
  for (const ws of workspaces) {
38
38
  console.error(
39
- `[debug] - ${ws.workspace_id}: token=${ws.token.substring(0, 20)}..., cookie=${ws.cookie ? 'present' : 'missing'}`
39
+ `[debug] - ${ws.workspace_id}: token=${ws.token.substring(0, 20)}..., cookie=${ws.cookie ? 'present' : 'missing'}`,
40
40
  )
41
41
  }
42
42
  }
@@ -48,8 +48,8 @@ async function extractAction(options: { pretty?: boolean; debug?: boolean }): Pr
48
48
  error: 'No workspaces found. Make sure Slack desktop app is installed and logged in.',
49
49
  hint: options.debug ? undefined : 'Run with --debug for more info.',
50
50
  },
51
- options.pretty
52
- )
51
+ options.pretty,
52
+ ),
53
53
  )
54
54
  process.exit(1)
55
55
  }
@@ -84,12 +84,11 @@ async function extractAction(options: { pretty?: boolean; debug?: boolean }): Pr
84
84
  console.log(
85
85
  formatOutput(
86
86
  {
87
- error:
88
- 'Extracted tokens are invalid. Make sure you are logged into the Slack desktop app.',
87
+ error: 'Extracted tokens are invalid. Make sure you are logged into the Slack desktop app.',
89
88
  extracted_count: workspaces.length,
90
89
  },
91
- options.pretty
92
- )
90
+ options.pretty,
91
+ ),
93
92
  )
94
93
  process.exit(1)
95
94
  }
@@ -109,10 +108,7 @@ async function extractAction(options: { pretty?: boolean; debug?: boolean }): Pr
109
108
  }
110
109
  }
111
110
 
112
- async function logoutAction(
113
- workspace: string | undefined,
114
- options: { pretty?: boolean }
115
- ): Promise<void> {
111
+ async function logoutAction(workspace: string | undefined, options: { pretty?: boolean }): Promise<void> {
116
112
  try {
117
113
  const credManager = new CredentialManager()
118
114
  const config = await credManager.load()
@@ -121,21 +117,14 @@ async function logoutAction(
121
117
 
122
118
  if (!targetWorkspace) {
123
119
  if (!config.current_workspace) {
124
- console.log(
125
- formatOutput(
126
- { error: 'No current workspace set. Specify a workspace ID.' },
127
- options.pretty
128
- )
129
- )
120
+ console.log(formatOutput({ error: 'No current workspace set. Specify a workspace ID.' }, options.pretty))
130
121
  process.exit(1)
131
122
  }
132
123
  targetWorkspace = config.current_workspace
133
124
  }
134
125
 
135
126
  if (!config.workspaces[targetWorkspace]) {
136
- console.log(
137
- formatOutput({ error: `Workspace not found: ${targetWorkspace}` }, options.pretty)
138
- )
127
+ console.log(formatOutput({ error: `Workspace not found: ${targetWorkspace}` }, options.pretty))
139
128
  process.exit(1)
140
129
  }
141
130
 
@@ -153,12 +142,7 @@ async function statusAction(options: { pretty?: boolean }): Promise<void> {
153
142
  const ws = await credManager.getWorkspace()
154
143
 
155
144
  if (!ws) {
156
- console.log(
157
- formatOutput(
158
- { error: 'No workspace configured. Run "auth extract" first.' },
159
- options.pretty
160
- )
161
- )
145
+ console.log(formatOutput({ error: 'No workspace configured. Run "auth extract" first.' }, options.pretty))
162
146
  process.exit(1)
163
147
  }
164
148
 
@@ -194,18 +178,18 @@ export const authCommand = new Command('auth')
194
178
  .description('Extract tokens from Slack desktop app')
195
179
  .option('--pretty', 'Pretty print JSON output')
196
180
  .option('--debug', 'Show debug output for troubleshooting')
197
- .action(extractAction)
181
+ .action(extractAction),
198
182
  )
199
183
  .addCommand(
200
184
  new Command('logout')
201
185
  .description('Logout from workspace')
202
186
  .argument('[workspace]', 'Workspace ID')
203
187
  .option('--pretty', 'Pretty print JSON output')
204
- .action(logoutAction)
188
+ .action(logoutAction),
205
189
  )
206
190
  .addCommand(
207
191
  new Command('status')
208
192
  .description('Show authentication status')
209
193
  .option('--pretty', 'Pretty print JSON output')
210
- .action(statusAction)
194
+ .action(statusAction),
211
195
  )
@@ -1,25 +1,16 @@
1
1
  import { Command } from 'commander'
2
- import { handleError } from '../../../shared/utils/error-handler'
3
- import { formatOutput } from '../../../shared/utils/output'
2
+ import { handleError } from '@/shared/utils/error-handler'
3
+ import { formatOutput } from '@/shared/utils/output'
4
4
  import { SlackClient } from '../client'
5
5
  import { CredentialManager } from '../credential-manager'
6
6
 
7
- async function listAction(options: {
8
- type?: string
9
- includeArchived?: boolean
10
- pretty?: boolean
11
- }): Promise<void> {
7
+ async function listAction(options: { type?: string; includeArchived?: boolean; pretty?: boolean }): Promise<void> {
12
8
  try {
13
9
  const credManager = new CredentialManager()
14
10
  const workspace = await credManager.getWorkspace()
15
11
 
16
12
  if (!workspace) {
17
- console.log(
18
- formatOutput(
19
- { error: 'No current workspace set. Run "auth extract" first.' },
20
- options.pretty
21
- )
22
- )
13
+ console.log(formatOutput({ error: 'No current workspace set. Run "auth extract" first.' }, options.pretty))
23
14
  process.exit(1)
24
15
  }
25
16
 
@@ -60,12 +51,7 @@ async function infoAction(channel: string, options: { pretty?: boolean }): Promi
60
51
  const workspace = await credManager.getWorkspace()
61
52
 
62
53
  if (!workspace) {
63
- console.log(
64
- formatOutput(
65
- { error: 'No current workspace set. Run "auth extract" first.' },
66
- options.pretty
67
- )
68
- )
54
+ console.log(formatOutput({ error: 'No current workspace set. Run "auth extract" first.' }, options.pretty))
69
55
  process.exit(1)
70
56
  }
71
57
 
@@ -89,21 +75,13 @@ async function infoAction(channel: string, options: { pretty?: boolean }): Promi
89
75
  }
90
76
  }
91
77
 
92
- async function historyAction(
93
- channel: string,
94
- options: { limit?: number; pretty?: boolean }
95
- ): Promise<void> {
78
+ async function historyAction(channel: string, options: { limit?: number; pretty?: boolean }): Promise<void> {
96
79
  try {
97
80
  const credManager = new CredentialManager()
98
81
  const workspace = await credManager.getWorkspace()
99
82
 
100
83
  if (!workspace) {
101
- console.log(
102
- formatOutput(
103
- { error: 'No current workspace set. Run "auth extract" first.' },
104
- options.pretty
105
- )
106
- )
84
+ console.log(formatOutput({ error: 'No current workspace set. Run "auth extract" first.' }, options.pretty))
107
85
  process.exit(1)
108
86
  }
109
87
 
@@ -134,14 +112,14 @@ export const channelCommand = new Command('channel')
134
112
  .option('--type <public|private|dm>', 'Filter by channel type')
135
113
  .option('--include-archived', 'Include archived channels')
136
114
  .option('--pretty', 'Pretty print JSON output')
137
- .action(listAction)
115
+ .action(listAction),
138
116
  )
139
117
  .addCommand(
140
118
  new Command('info')
141
119
  .description('Get channel info')
142
120
  .argument('<channel>', 'Channel ID or name')
143
121
  .option('--pretty', 'Pretty print JSON output')
144
- .action(infoAction)
122
+ .action(infoAction),
145
123
  )
146
124
  .addCommand(
147
125
  new Command('history')
@@ -154,5 +132,5 @@ export const channelCommand = new Command('channel')
154
132
  limit: parseInt(options.limit, 10),
155
133
  pretty: options.pretty,
156
134
  })
157
- })
135
+ }),
158
136
  )
@@ -1,25 +1,16 @@
1
1
  import { Command } from 'commander'
2
- import { handleError } from '../../../shared/utils/error-handler'
3
- import { formatOutput } from '../../../shared/utils/output'
2
+ import { handleError } from '@/shared/utils/error-handler'
3
+ import { formatOutput } from '@/shared/utils/output'
4
4
  import { SlackClient } from '../client'
5
5
  import { CredentialManager } from '../credential-manager'
6
6
 
7
- async function listAction(options: {
8
- limit?: number
9
- cursor?: string
10
- pretty?: boolean
11
- }): Promise<void> {
7
+ async function listAction(options: { limit?: number; cursor?: string; pretty?: boolean }): Promise<void> {
12
8
  try {
13
9
  const credManager = new CredentialManager()
14
10
  const workspace = await credManager.getWorkspace()
15
11
 
16
12
  if (!workspace) {
17
- console.log(
18
- formatOutput(
19
- { error: 'No current workspace set. Run "auth extract" first.' },
20
- options.pretty
21
- )
22
- )
13
+ console.log(formatOutput({ error: 'No current workspace set. Run "auth extract" first.' }, options.pretty))
23
14
  process.exit(1)
24
15
  }
25
16
 
@@ -58,5 +49,5 @@ export const draftsCommand = new Command('drafts').description('Drafts commands'
58
49
  cursor: options.cursor,
59
50
  pretty: options.pretty,
60
51
  })
61
- })
52
+ }),
62
53
  )