agent-messenger 1.4.0 → 1.6.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.
Files changed (111) hide show
  1. package/.claude-plugin/README.md +38 -14
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.github/workflows/ci.yml +3 -0
  4. package/CONTRIBUTING.md +24 -1
  5. package/README.md +12 -8
  6. package/dist/package.json +1 -1
  7. package/dist/src/platforms/discord/cli.d.ts.map +1 -1
  8. package/dist/src/platforms/discord/cli.js +8 -1
  9. package/dist/src/platforms/discord/cli.js.map +1 -1
  10. package/dist/src/platforms/discord/commands/file.d.ts.map +1 -1
  11. package/dist/src/platforms/discord/commands/file.js +13 -7
  12. package/dist/src/platforms/discord/commands/file.js.map +1 -1
  13. package/dist/src/platforms/discord/commands/friend.d.ts.map +1 -1
  14. package/dist/src/platforms/discord/commands/friend.js +30 -30
  15. package/dist/src/platforms/discord/commands/friend.js.map +1 -1
  16. package/dist/src/platforms/discord/commands/index.d.ts +7 -0
  17. package/dist/src/platforms/discord/commands/index.d.ts.map +1 -1
  18. package/dist/src/platforms/discord/commands/index.js +7 -0
  19. package/dist/src/platforms/discord/commands/index.js.map +1 -1
  20. package/dist/src/platforms/discord/commands/snapshot.d.ts.map +1 -1
  21. package/dist/src/platforms/discord/commands/snapshot.js +1 -2
  22. package/dist/src/platforms/discord/commands/snapshot.js.map +1 -1
  23. package/dist/src/platforms/slack/commands/file.d.ts.map +1 -1
  24. package/dist/src/platforms/slack/commands/file.js +10 -4
  25. package/dist/src/platforms/slack/commands/file.js.map +1 -1
  26. package/dist/src/platforms/slack/commands/sections.d.ts.map +1 -1
  27. package/dist/src/platforms/slack/commands/sections.js +5 -6
  28. package/dist/src/platforms/slack/commands/sections.js.map +1 -1
  29. package/dist/src/platforms/slack/commands/snapshot.d.ts.map +1 -1
  30. package/dist/src/platforms/slack/commands/snapshot.js +1 -2
  31. package/dist/src/platforms/slack/commands/snapshot.js.map +1 -1
  32. package/dist/src/platforms/slack/commands/user.js +8 -8
  33. package/dist/src/platforms/slackbot/commands/reaction.js +2 -2
  34. package/dist/src/platforms/slackbot/commands/reaction.js.map +1 -1
  35. package/dist/src/platforms/teams/cli.d.ts.map +1 -1
  36. package/dist/src/platforms/teams/cli.js +7 -1
  37. package/dist/src/platforms/teams/cli.js.map +1 -1
  38. package/dist/src/platforms/teams/commands/auth.d.ts +3 -0
  39. package/dist/src/platforms/teams/commands/auth.d.ts.map +1 -1
  40. package/dist/src/platforms/teams/commands/auth.js +208 -107
  41. package/dist/src/platforms/teams/commands/auth.js.map +1 -1
  42. package/dist/src/platforms/teams/commands/channel.js +9 -9
  43. package/dist/src/platforms/teams/commands/channel.js.map +1 -1
  44. package/dist/src/platforms/teams/commands/file.js +21 -21
  45. package/dist/src/platforms/teams/commands/file.js.map +1 -1
  46. package/dist/src/platforms/teams/commands/message.js +12 -12
  47. package/dist/src/platforms/teams/commands/message.js.map +1 -1
  48. package/dist/src/platforms/teams/commands/reaction.js +6 -6
  49. package/dist/src/platforms/teams/commands/reaction.js.map +1 -1
  50. package/dist/src/platforms/teams/commands/snapshot.d.ts.map +1 -1
  51. package/dist/src/platforms/teams/commands/snapshot.js +6 -6
  52. package/dist/src/platforms/teams/commands/snapshot.js.map +1 -1
  53. package/dist/src/platforms/teams/commands/team.d.ts.map +1 -1
  54. package/dist/src/platforms/teams/commands/team.js +21 -25
  55. package/dist/src/platforms/teams/commands/team.js.map +1 -1
  56. package/dist/src/platforms/teams/commands/user.js +9 -9
  57. package/dist/src/platforms/teams/commands/user.js.map +1 -1
  58. package/dist/src/platforms/teams/credential-manager.d.ts +15 -2
  59. package/dist/src/platforms/teams/credential-manager.d.ts.map +1 -1
  60. package/dist/src/platforms/teams/credential-manager.js +110 -28
  61. package/dist/src/platforms/teams/credential-manager.js.map +1 -1
  62. package/dist/src/platforms/teams/ensure-auth.d.ts.map +1 -1
  63. package/dist/src/platforms/teams/ensure-auth.js +46 -16
  64. package/dist/src/platforms/teams/ensure-auth.js.map +1 -1
  65. package/dist/src/platforms/teams/token-extractor.d.ts +8 -2
  66. package/dist/src/platforms/teams/token-extractor.d.ts.map +1 -1
  67. package/dist/src/platforms/teams/token-extractor.js +36 -24
  68. package/dist/src/platforms/teams/token-extractor.js.map +1 -1
  69. package/dist/src/platforms/teams/types.d.ts +121 -0
  70. package/dist/src/platforms/teams/types.d.ts.map +1 -1
  71. package/dist/src/platforms/teams/types.js +16 -0
  72. package/dist/src/platforms/teams/types.js.map +1 -1
  73. package/e2e/README.md +1 -1
  74. package/package.json +1 -1
  75. package/skills/agent-discord/SKILL.md +5 -0
  76. package/skills/agent-slack/SKILL.md +11 -17
  77. package/skills/agent-teams/SKILL.md +21 -24
  78. package/skills/agent-teams/references/common-patterns.md +63 -49
  79. package/src/platforms/discord/cli.ts +14 -0
  80. package/src/platforms/discord/commands/file.ts +13 -7
  81. package/src/platforms/discord/commands/friend.ts +34 -34
  82. package/src/platforms/discord/commands/index.ts +7 -0
  83. package/src/platforms/discord/commands/snapshot.ts +1 -2
  84. package/src/platforms/slack/commands/file.ts +12 -4
  85. package/src/platforms/slack/commands/sections.ts +8 -9
  86. package/src/platforms/slack/commands/snapshot.ts +1 -2
  87. package/src/platforms/slack/commands/user.ts +8 -8
  88. package/src/platforms/slackbot/commands/reaction.ts +2 -2
  89. package/src/platforms/teams/cli.ts +7 -0
  90. package/src/platforms/teams/commands/auth.test.ts +6 -5
  91. package/src/platforms/teams/commands/auth.ts +283 -120
  92. package/src/platforms/teams/commands/channel.test.ts +10 -4
  93. package/src/platforms/teams/commands/channel.ts +9 -9
  94. package/src/platforms/teams/commands/file.test.ts +9 -3
  95. package/src/platforms/teams/commands/file.ts +21 -21
  96. package/src/platforms/teams/commands/message.test.ts +9 -3
  97. package/src/platforms/teams/commands/message.ts +12 -12
  98. package/src/platforms/teams/commands/reaction.test.ts +9 -3
  99. package/src/platforms/teams/commands/reaction.ts +6 -6
  100. package/src/platforms/teams/commands/snapshot.ts +6 -6
  101. package/src/platforms/teams/commands/team.test.ts +19 -12
  102. package/src/platforms/teams/commands/team.ts +22 -28
  103. package/src/platforms/teams/commands/user.ts +9 -9
  104. package/src/platforms/teams/credential-manager.test.ts +30 -24
  105. package/src/platforms/teams/credential-manager.ts +106 -31
  106. package/src/platforms/teams/ensure-auth.test.ts +125 -26
  107. package/src/platforms/teams/ensure-auth.ts +47 -15
  108. package/src/platforms/teams/token-extractor.test.ts +116 -85
  109. package/src/platforms/teams/token-extractor.ts +65 -97
  110. package/src/platforms/teams/types.test.ts +31 -13
  111. package/src/platforms/teams/types.ts +45 -0
@@ -100,22 +100,28 @@ export async function infoAction(channelId: string, fileId: string, options: { p
100
100
  }
101
101
 
102
102
  export const fileCommand = new Command('file')
103
- .description('file commands')
103
+ .description('File commands')
104
104
  .addCommand(
105
105
  new Command('upload')
106
- .description('upload file to channel')
107
- .argument('<channel>', 'channel ID')
106
+ .description('Upload file to channel')
107
+ .argument('<channel-id>', 'Channel ID')
108
108
  .argument('<path>', 'file path')
109
109
  .option('--filename <name>', 'override filename')
110
+ .option('--pretty', 'Pretty print JSON output')
110
111
  .action(uploadAction),
111
112
  )
112
113
  .addCommand(
113
- new Command('list').description('list files in channel').argument('<channel>', 'channel ID').action(listAction),
114
+ new Command('list')
115
+ .description('List files in channel')
116
+ .argument('<channel-id>', 'Channel ID')
117
+ .option('--pretty', 'Pretty print JSON output')
118
+ .action(listAction),
114
119
  )
115
120
  .addCommand(
116
121
  new Command('info')
117
- .description('show file details')
118
- .argument('<channel>', 'channel ID')
119
- .argument('<file>', 'file ID')
122
+ .description('Show file details')
123
+ .argument('<channel-id>', 'Channel ID')
124
+ .argument('<file-id>', 'File ID')
125
+ .option('--pretty', 'Pretty print JSON output')
120
126
  .action(infoAction),
121
127
  )
@@ -1,43 +1,43 @@
1
1
  import { Command } from 'commander'
2
+ import { handleError } from '@/shared/utils/error-handler'
3
+ import { formatOutput } from '@/shared/utils/output'
2
4
  import { DiscordClient } from '../client'
3
5
  import { DiscordCredentialManager } from '../credential-manager'
4
6
 
5
- export const friendCommand = new Command('friend').description('Manage Discord relationships (friends)').addCommand(
6
- new Command('list')
7
- .description('List all relationships')
8
- .option('--pretty', 'Pretty print output')
9
- .action(async (options) => {
10
- const credManager = new DiscordCredentialManager()
11
- const config = await credManager.load()
7
+ async function listAction(options: { pretty?: boolean }): Promise<void> {
8
+ try {
9
+ const credManager = new DiscordCredentialManager()
10
+ const config = await credManager.load()
12
11
 
13
- if (!config.token) {
14
- throw new Error('No Discord token found. Run auth extract first.')
15
- }
12
+ if (!config.token) {
13
+ console.log(formatOutput({ error: 'Not authenticated. Run "auth extract" first.' }, options.pretty))
14
+ process.exit(1)
15
+ }
16
16
 
17
- const client = new DiscordClient(config.token)
17
+ const client = new DiscordClient(config.token)
18
+ const relationships = await client.getRelationships()
18
19
 
19
- const relationships = await client.getRelationships()
20
+ const output = relationships.map((rel) => ({
21
+ user: {
22
+ id: rel.user.id,
23
+ username: rel.user.username,
24
+ global_name: rel.user.global_name,
25
+ },
26
+ type: rel.type,
27
+ nickname: rel.nickname || null,
28
+ }))
20
29
 
21
- if (options.pretty) {
22
- const typeNames: Record<number, string> = {
23
- 1: 'Friend',
24
- 2: 'Blocked',
25
- 3: 'Incoming Request',
26
- 4: 'Outgoing Request',
27
- }
30
+ console.log(formatOutput(output, options.pretty))
31
+ } catch (error) {
32
+ handleError(error as Error)
33
+ }
34
+ }
28
35
 
29
- console.log(`\nRelationships (${relationships.length}):\n`)
30
- for (const rel of relationships) {
31
- const displayName = rel.user.global_name || rel.user.username
32
- const nickname = rel.nickname ? ` (${rel.nickname})` : ''
33
- const type = typeNames[rel.type] || `Type ${rel.type}`
34
- console.log(` ${displayName}${nickname} - ${type}`)
35
- console.log(` ID: ${rel.user.id}`)
36
- console.log(` Username: ${rel.user.username}`)
37
- console.log()
38
- }
39
- } else {
40
- console.log(JSON.stringify(relationships, null, 2))
41
- }
42
- }),
43
- )
36
+ export const friendCommand = new Command('friend')
37
+ .description('Friend commands')
38
+ .addCommand(
39
+ new Command('list')
40
+ .description('List all relationships')
41
+ .option('--pretty', 'Pretty print JSON output')
42
+ .action(listAction),
43
+ )
@@ -1,8 +1,15 @@
1
1
  export { authCommand } from './auth'
2
2
  export { channelCommand } from './channel'
3
+ export { dmCommand } from './dm'
3
4
  export { fileCommand } from './file'
5
+ export { friendCommand } from './friend'
6
+ export { memberCommand } from './member'
7
+ export { mentionCommand } from './mention'
4
8
  export { messageCommand } from './message'
9
+ export { noteCommand } from './note'
10
+ export { profileCommand } from './profile'
5
11
  export { reactionCommand } from './reaction'
6
12
  export { serverCommand } from './server'
7
13
  export { snapshotCommand } from './snapshot'
14
+ export { threadCommand } from './thread'
8
15
  export { userCommand } from './user'
@@ -86,8 +86,7 @@ export async function snapshotAction(options: {
86
86
  }
87
87
  }
88
88
 
89
- export const snapshotCommand = new Command()
90
- .name('snapshot')
89
+ export const snapshotCommand = new Command('snapshot')
91
90
  .description('Get comprehensive server state for AI agents')
92
91
  .option('--channels-only', 'Include only channels (exclude messages and members)')
93
92
  .option('--users-only', 'Include only members (exclude channels and messages)')
@@ -117,19 +117,27 @@ async function infoAction(fileId: string, options: { pretty?: boolean }): Promis
117
117
  }
118
118
 
119
119
  export const fileCommand = new Command('file')
120
- .description('file commands')
120
+ .description('File commands')
121
121
  .addCommand(
122
122
  new Command('upload')
123
- .description('upload file to channel')
123
+ .description('Upload file to channel')
124
124
  .argument('<channel>', 'channel ID or name')
125
125
  .argument('<path>', 'file path')
126
126
  .option('--filename <name>', 'override filename')
127
+ .option('--pretty', 'Pretty print JSON output')
127
128
  .action(uploadAction),
128
129
  )
129
130
  .addCommand(
130
131
  new Command('list')
131
- .description('list files in workspace')
132
+ .description('List files in workspace')
132
133
  .option('--channel <id>', 'filter by channel')
134
+ .option('--pretty', 'Pretty print JSON output')
133
135
  .action(listAction),
134
136
  )
135
- .addCommand(new Command('info').description('show file details').argument('<file>', 'file ID').action(infoAction))
137
+ .addCommand(
138
+ new Command('info')
139
+ .description('Show file details')
140
+ .argument('<file>', 'file ID')
141
+ .option('--pretty', 'Pretty print JSON output')
142
+ .action(infoAction),
143
+ )
@@ -32,12 +32,11 @@ async function listAction(options: { pretty?: boolean }): Promise<void> {
32
32
  }
33
33
  }
34
34
 
35
- const sections = new Command('sections').description('Manage Slack channel sections (sidebar folders)')
36
-
37
- sections
38
- .command('list')
39
- .description('List all channel sections')
40
- .option('--pretty', 'Pretty print output')
41
- .action(listAction)
42
-
43
- export const sectionsCommand = sections
35
+ export const sectionsCommand = new Command('sections')
36
+ .description('Sidebar section commands')
37
+ .addCommand(
38
+ new Command('list')
39
+ .description('List all channel sections')
40
+ .option('--pretty', 'Pretty print JSON output')
41
+ .action(listAction),
42
+ )
@@ -93,8 +93,7 @@ async function snapshotAction(options: {
93
93
  }
94
94
  }
95
95
 
96
- export const snapshotCommand = new Command()
97
- .name('snapshot')
96
+ export const snapshotCommand = new Command('snapshot')
98
97
  .description('Get comprehensive workspace state for AI agents')
99
98
  .option('--channels-only', 'Include only channels (exclude messages and users)')
100
99
  .option('--users-only', 'Include only users (exclude channels and messages)')
@@ -17,12 +17,12 @@ async function getClient(pretty?: boolean): Promise<SlackClient | null> {
17
17
  }
18
18
 
19
19
  export const userCommand = new Command('user')
20
- .description('user commands')
20
+ .description('User commands')
21
21
  .addCommand(
22
22
  new Command('list')
23
- .description('list workspace users')
24
- .option('--include-bots', 'include bot users')
25
- .option('--pretty', 'pretty-print JSON output')
23
+ .description('List workspace users')
24
+ .option('--include-bots', 'Include bot users')
25
+ .option('--pretty', 'Pretty print JSON output')
26
26
  .action(async (options) => {
27
27
  try {
28
28
  const client = await getClient(options.pretty)
@@ -51,9 +51,9 @@ export const userCommand = new Command('user')
51
51
  )
52
52
  .addCommand(
53
53
  new Command('info')
54
- .description('show user details')
54
+ .description('Show user details')
55
55
  .argument('<user>', 'user ID or username')
56
- .option('--pretty', 'pretty-print JSON output')
56
+ .option('--pretty', 'Pretty print JSON output')
57
57
  .action(async (userArg, options) => {
58
58
  try {
59
59
  const client = await getClient(options.pretty)
@@ -80,8 +80,8 @@ export const userCommand = new Command('user')
80
80
  )
81
81
  .addCommand(
82
82
  new Command('me')
83
- .description('show current authenticated user')
84
- .option('--pretty', 'pretty-print JSON output')
83
+ .description('Show current authenticated user')
84
+ .option('--pretty', 'Pretty print JSON output')
85
85
  .action(async (options) => {
86
86
  try {
87
87
  const client = await getClient(options.pretty)
@@ -33,7 +33,7 @@ export const reactionCommand = new Command('reaction')
33
33
  new Command('add')
34
34
  .description('Add a reaction to a message')
35
35
  .argument('<channel>', 'Channel ID or name')
36
- .argument('<timestamp>', 'Message timestamp')
36
+ .argument('<ts>', 'Message timestamp')
37
37
  .argument('<emoji>', 'Emoji name (with or without colons)')
38
38
  .option('--bot <id>', 'Use specific bot')
39
39
  .option('--pretty', 'Pretty print JSON output')
@@ -43,7 +43,7 @@ export const reactionCommand = new Command('reaction')
43
43
  new Command('remove')
44
44
  .description('Remove a reaction from a message')
45
45
  .argument('<channel>', 'Channel ID or name')
46
- .argument('<timestamp>', 'Message timestamp')
46
+ .argument('<ts>', 'Message timestamp')
47
47
  .argument('<emoji>', 'Emoji name (with or without colons)')
48
48
  .option('--bot <id>', 'Use specific bot')
49
49
  .option('--pretty', 'Pretty print JSON output')
@@ -13,7 +13,9 @@ import {
13
13
  teamCommand,
14
14
  userCommand,
15
15
  } from './commands'
16
+ import { TeamsCredentialManager } from './credential-manager'
16
17
  import { ensureTeamsAuth } from './ensure-auth'
18
+ import type { TeamsAccountType } from './types'
17
19
 
18
20
  function isAuthCommand(command: CommandType): boolean {
19
21
  let cmd: CommandType | null = command
@@ -32,9 +34,14 @@ program
32
34
  .version(pkg.version)
33
35
  .option('--pretty', 'Pretty-print JSON output')
34
36
  .option('--team <id>', 'Use specific team')
37
+ .option('--account <type>', 'Use specific account (work or personal)')
35
38
 
36
39
  program.hook('preAction', async (_thisCommand, actionCommand) => {
37
40
  if (isAuthCommand(actionCommand)) return
41
+ const opts = program.opts()
42
+ if (opts.account) {
43
+ TeamsCredentialManager.accountOverride = opts.account as TeamsAccountType
44
+ }
38
45
  await ensureTeamsAuth()
39
46
  })
40
47
 
@@ -12,9 +12,9 @@ let credManagerClearCredentialsSpy: ReturnType<typeof spyOn>
12
12
  let credManagerIsTokenExpiredSpy: ReturnType<typeof spyOn>
13
13
 
14
14
  beforeEach(() => {
15
- extractorExtractSpy = spyOn(TeamsTokenExtractor.prototype, 'extract').mockResolvedValue({
16
- token: 'test-skype-token-123',
17
- })
15
+ extractorExtractSpy = spyOn(TeamsTokenExtractor.prototype, 'extract').mockResolvedValue([
16
+ { token: 'test-skype-token-123', accountType: 'work' as const },
17
+ ])
18
18
 
19
19
  clientTestAuthSpy = spyOn(TeamsClient.prototype, 'testAuth').mockResolvedValue({
20
20
  id: 'user-123',
@@ -51,8 +51,9 @@ afterEach(() => {
51
51
  test('extract: calls TeamsTokenExtractor', async () => {
52
52
  const extractor = new TeamsTokenExtractor()
53
53
  const result = await extractor.extract()
54
- expect(result).toBeDefined()
55
- expect(result?.token).toBe('test-skype-token-123')
54
+ expect(result).toHaveLength(1)
55
+ expect(result[0].token).toBe('test-skype-token-123')
56
+ expect(result[0].accountType).toBe('work')
56
57
  })
57
58
 
58
59
  test('extract: validates token with TeamsClient', async () => {